matrix-react-sdk
Version:
SDK for matrix.org using React
687 lines (662 loc) • 105 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.RoomViewStore = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var utils = _interopRequireWildcard(require("matrix-js-sdk/src/utils"));
var _matrix = require("matrix-js-sdk/src/matrix");
var _types = require("matrix-js-sdk/src/types");
var _logger = require("matrix-js-sdk/src/logger");
var _events = _interopRequireDefault(require("events"));
var _RoomViewLifecycle = require("@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle");
var _MatrixClientPeg = require("../MatrixClientPeg");
var _Modal = _interopRequireDefault(require("../Modal"));
var _languageHandler = require("../languageHandler");
var _RoomAliasCache = require("../RoomAliasCache");
var _actions = require("../dispatcher/actions");
var _promise = require("../utils/promise");
var _RoomContext = require("../contexts/RoomContext");
var _DMRoomMap = _interopRequireDefault(require("../utils/DMRoomMap"));
var _spaces = require("./spaces");
var _ErrorDialog = _interopRequireDefault(require("../components/views/dialogs/ErrorDialog"));
var _SettingsStore = _interopRequireDefault(require("../settings/SettingsStore"));
var _RoomUpgrade = require("../utils/RoomUpgrade");
var _AsyncStore = require("./AsyncStore");
var _CallStore = require("./CallStore");
var _voiceBroadcast = require("../voice-broadcast");
var _showCantStartACallDialog = require("../voice-broadcast/utils/showCantStartACallDialog");
var _pauseNonLiveBroadcastFromOtherRoom = require("../voice-broadcast/utils/pauseNonLiveBroadcastFromOtherRoom");
var _ModuleRunner = require("../modules/ModuleRunner");
var _notifications = require("../utils/notifications");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /*
Copyright 2024 New Vector Ltd.
Copyright 2019-2022 The Matrix.org Foundation C.I.C.
Copyright 2017, 2018 New Vector Ltd
Copyright 2017 Vector Creations Ltd
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
const NUM_JOIN_RETRY = 5;
const INITIAL_STATE = {
joining: false,
joinError: null,
roomId: null,
threadId: null,
subscribingRoomId: null,
initialEventId: null,
initialEventPixelOffset: null,
isInitialEventHighlighted: false,
initialEventScrollIntoView: true,
roomAlias: null,
roomLoading: false,
roomLoadError: null,
replyingToEvent: null,
shouldPeek: false,
viaServers: [],
wasContextSwitch: false,
viewingCall: false,
promptAskToJoin: false,
viewRoomOpts: {
buttons: []
}
};
/**
* A class for storing application state for RoomView.
*/
class RoomViewStore extends _events.default {
constructor(dis, stores) {
super();
// initialize state as a copy of the initial state. We need to copy else one RVS can talk to
// another RVS via INITIAL_STATE as they share the same underlying object. Mostly relevant for tests.
(0, _defineProperty2.default)(this, "state", utils.deepCopy(INITIAL_STATE));
(0, _defineProperty2.default)(this, "dis", void 0);
(0, _defineProperty2.default)(this, "dispatchToken", void 0);
(0, _defineProperty2.default)(this, "onCurrentBroadcastRecordingChanged", recording => {
if (recording === null) {
const room = this.stores.client?.getRoom(this.state.roomId || undefined);
if (room) {
this.doMaybeSetCurrentVoiceBroadcastPlayback(room);
}
}
});
this.stores = stores;
this.resetDispatcher(dis);
this.stores.voiceBroadcastRecordingsStore.addListener(_voiceBroadcast.VoiceBroadcastRecordingsStoreEvent.CurrentChanged, this.onCurrentBroadcastRecordingChanged);
}
addRoomListener(roomId, fn) {
this.on(roomId, fn);
}
removeRoomListener(roomId, fn) {
this.off(roomId, fn);
}
emitForRoom(roomId, isActive) {
this.emit(roomId, isActive);
}
setState(newState) {
// If values haven't changed, there's nothing to do.
// This only tries a shallow comparison, so unchanged objects will slip
// through, but that's probably okay for now.
let stateChanged = false;
for (const key of Object.keys(newState)) {
if (this.state[key] !== newState[key]) {
stateChanged = true;
break;
}
}
if (!stateChanged) {
return;
}
if (newState.viewingCall) {
// Pause current broadcast, if any
this.stores.voiceBroadcastPlaybacksStore.getCurrent()?.pause();
if (this.stores.voiceBroadcastRecordingsStore.getCurrent()) {
(0, _showCantStartACallDialog.showCantStartACallDialog)();
newState.viewingCall = false;
}
}
const lastRoomId = this.state.roomId;
this.state = Object.assign(this.state, newState);
if (lastRoomId !== this.state.roomId) {
if (lastRoomId) this.emitForRoom(lastRoomId, false);
if (this.state.roomId) this.emitForRoom(this.state.roomId, true);
// Fired so we can reduce dependency on event emitters to this store, which is relatively
// central to the application and can easily cause import cycles.
this.dis?.dispatch({
action: _actions.Action.ActiveRoomChanged,
oldRoomId: lastRoomId,
newRoomId: this.state.roomId
});
}
this.emit(_AsyncStore.UPDATE_EVENT);
}
doMaybeSetCurrentVoiceBroadcastPlayback(room) {
if (!this.stores.client) return;
(0, _voiceBroadcast.doMaybeSetCurrentVoiceBroadcastPlayback)(room, this.stores.client, this.stores.voiceBroadcastPlaybacksStore, this.stores.voiceBroadcastRecordingsStore);
}
onRoomStateEvents(event) {
const roomId = event.getRoomId?.();
// no room or not current room
if (!roomId || roomId !== this.state.roomId) return;
const room = this.stores.client?.getRoom(roomId);
if (room) {
this.doMaybeSetCurrentVoiceBroadcastPlayback(room);
}
}
onDispatch(payload) {
// eslint-disable-line @typescript-eslint/naming-convention
switch (payload.action) {
// view_room:
// - room_alias: '#somealias:matrix.org'
// - room_id: '!roomid123:matrix.org'
// - event_id: '$213456782:matrix.org'
// - event_offset: 100
// - highlighted: true
case _actions.Action.ViewRoom:
this.viewRoom(payload);
break;
case _actions.Action.ViewThread:
this.viewThread(payload);
break;
// for these events blank out the roomId as we are no longer in the RoomView
case "view_welcome_page":
case _actions.Action.ViewHomePage:
this.setState({
roomId: null,
roomAlias: null,
viaServers: [],
wasContextSwitch: false,
viewingCall: false
});
(0, _voiceBroadcast.doClearCurrentVoiceBroadcastPlaybackIfStopped)(this.stores.voiceBroadcastPlaybacksStore);
break;
case "MatrixActions.RoomState.events":
this.onRoomStateEvents(payload.event);
break;
case _actions.Action.ViewRoomError:
this.viewRoomError(payload);
break;
case "will_join":
this.setState({
joining: true
});
break;
case "cancel_join":
this.setState({
joining: false
});
break;
// join_room:
// - opts: options for joinRoom
case _actions.Action.JoinRoom:
this.joinRoom(payload);
break;
case _actions.Action.JoinRoomError:
this.joinRoomError(payload);
break;
case _actions.Action.JoinRoomReady:
{
if (this.state.roomId === payload.roomId) {
this.setState({
shouldPeek: false
});
}
(0, _RoomUpgrade.awaitRoomDownSync)(_MatrixClientPeg.MatrixClientPeg.safeGet(), payload.roomId).then(room => {
const numMembers = room.getJoinedMemberCount();
const roomSize = numMembers > 1000 ? "MoreThanAThousand" : numMembers > 100 ? "OneHundredAndOneToAThousand" : numMembers > 10 ? "ElevenToOneHundred" : numMembers > 2 ? "ThreeToTen" : numMembers > 1 ? "Two" : "One";
this.stores.posthogAnalytics.trackEvent({
eventName: "JoinedRoom",
trigger: payload.metricsTrigger,
roomSize,
isDM: !!_DMRoomMap.default.shared().getUserIdForRoomId(room.roomId),
isSpace: room.isSpaceRoom()
});
});
break;
}
case "on_client_not_viable":
case _actions.Action.OnLoggedOut:
this.reset();
break;
case "reply_to_event":
// Thread timeline view handles its own reply-to-state
if (_RoomContext.TimelineRenderingType.Thread !== payload.context) {
// If currently viewed room does not match the room in which we wish to reply then change rooms this
// can happen when performing a search across all rooms. Persist the data from this event for both
// room and search timeline rendering types, search will get auto-closed by RoomView at this time.
if (payload.event && payload.event.getRoomId() !== this.state.roomId) {
this.dis?.dispatch({
action: _actions.Action.ViewRoom,
room_id: payload.event.getRoomId(),
replyingToEvent: payload.event,
metricsTrigger: undefined // room doesn't change
});
} else {
this.setState({
replyingToEvent: payload.event
});
}
}
break;
case _actions.Action.PromptAskToJoin:
{
this.setState({
promptAskToJoin: true
});
break;
}
case _actions.Action.SubmitAskToJoin:
{
this.submitAskToJoin(payload);
break;
}
case _actions.Action.CancelAskToJoin:
{
this.cancelAskToJoin(payload);
break;
}
case _actions.Action.RoomLoaded:
{
this.setViewRoomOpts();
break;
}
}
}
async viewRoom(payload) {
if (payload.room_id) {
const room = _MatrixClientPeg.MatrixClientPeg.safeGet().getRoom(payload.room_id);
if (payload.metricsTrigger !== null && payload.room_id !== this.state.roomId) {
let activeSpace;
if (this.stores.spaceStore.activeSpace === _spaces.MetaSpace.Home) {
activeSpace = "Home";
} else if ((0, _spaces.isMetaSpace)(this.stores.spaceStore.activeSpace)) {
activeSpace = "Meta";
} else {
activeSpace = this.stores.spaceStore.activeSpaceRoom?.getJoinRule() === _matrix.JoinRule.Public ? "Public" : "Private";
}
this.stores.posthogAnalytics.trackEvent({
eventName: "ViewRoom",
trigger: payload.metricsTrigger,
viaKeyboard: payload.metricsViaKeyboard,
isDM: !!_DMRoomMap.default.shared().getUserIdForRoomId(payload.room_id),
isSpace: room?.isSpaceRoom(),
activeSpace
});
}
if (_SettingsStore.default.getValue("feature_sliding_sync") && this.state.roomId !== payload.room_id) {
if (this.state.subscribingRoomId && this.state.subscribingRoomId !== payload.room_id) {
// unsubscribe from this room, but don't await it as we don't care when this gets done.
this.stores.slidingSyncManager.setRoomVisible(this.state.subscribingRoomId, false);
}
this.setState({
subscribingRoomId: payload.room_id,
roomId: payload.room_id,
initialEventId: null,
initialEventPixelOffset: null,
initialEventScrollIntoView: true,
roomAlias: null,
roomLoading: true,
roomLoadError: null,
viaServers: payload.via_servers,
wasContextSwitch: payload.context_switch,
viewingCall: payload.view_call ?? false
});
// set this room as the room subscription. We need to await for it as this will fetch
// all room state for this room, which is required before we get the state below.
await this.stores.slidingSyncManager.setRoomVisible(payload.room_id, true);
// Whilst we were subscribing another room was viewed, so stop what we're doing and
// unsubscribe
if (this.state.subscribingRoomId !== payload.room_id) {
this.stores.slidingSyncManager.setRoomVisible(payload.room_id, false);
return;
}
// Re-fire the payload: we won't re-process it because the prev room ID == payload room ID now
this.dis?.dispatch(_objectSpread({}, payload));
return;
}
const newState = {
roomId: payload.room_id,
roomAlias: payload.room_alias ?? null,
initialEventId: payload.event_id ?? null,
isInitialEventHighlighted: payload.highlighted ?? false,
initialEventScrollIntoView: payload.scroll_into_view ?? true,
roomLoading: false,
roomLoadError: null,
// should peek by default
shouldPeek: payload.should_peek === undefined ? true : payload.should_peek,
// have we sent a join request for this room and are waiting for a response?
joining: payload.joining || false,
// Reset replyingToEvent because we don't want cross-room because bad UX
replyingToEvent: null,
viaServers: payload.via_servers ?? [],
wasContextSwitch: payload.context_switch ?? false,
skipLobby: payload.skipLobby,
viewingCall: payload.view_call ?? (payload.room_id === this.state.roomId ? this.state.viewingCall : _CallStore.CallStore.instance.getActiveCall(payload.room_id) !== null)
};
// Allow being given an event to be replied to when switching rooms but sanity check its for this room
if (payload.replyingToEvent?.getRoomId() === payload.room_id) {
newState.replyingToEvent = payload.replyingToEvent;
} else if (this.state.replyingToEvent?.getRoomId() === payload.room_id) {
// if the reply-to matches the desired room, e.g visiting a permalink then maintain replyingToEvent
// See https://github.com/vector-im/element-web/issues/21462
newState.replyingToEvent = this.state.replyingToEvent;
}
this.setState(newState);
if (payload.auto_join) {
this.dis?.dispatch(_objectSpread(_objectSpread({}, payload), {}, {
action: _actions.Action.JoinRoom,
roomId: payload.room_id,
metricsTrigger: payload.metricsTrigger
}));
}
if (room) {
(0, _pauseNonLiveBroadcastFromOtherRoom.pauseNonLiveBroadcastFromOtherRoom)(room, this.stores.voiceBroadcastPlaybacksStore);
this.doMaybeSetCurrentVoiceBroadcastPlayback(room);
await (0, _notifications.setMarkedUnreadState)(room, _MatrixClientPeg.MatrixClientPeg.safeGet(), false);
}
} else if (payload.room_alias) {
// Try the room alias to room ID navigation cache first to avoid
// blocking room navigation on the homeserver.
let roomId = (0, _RoomAliasCache.getCachedRoomIDForAlias)(payload.room_alias);
if (!roomId) {
// Room alias cache miss, so let's ask the homeserver. Resolve the alias
// and then do a second dispatch with the room ID acquired.
this.setState({
roomId: null,
initialEventId: null,
initialEventPixelOffset: null,
isInitialEventHighlighted: false,
initialEventScrollIntoView: true,
roomAlias: payload.room_alias,
roomLoading: true,
roomLoadError: null,
viaServers: payload.via_servers,
wasContextSwitch: payload.context_switch,
viewingCall: payload.view_call ?? false,
skipLobby: payload.skipLobby
});
try {
const result = await _MatrixClientPeg.MatrixClientPeg.safeGet().getRoomIdForAlias(payload.room_alias);
(0, _RoomAliasCache.storeRoomAliasInCache)(payload.room_alias, result.room_id);
roomId = result.room_id;
} catch (err) {
_logger.logger.error("RVS failed to get room id for alias: ", err);
this.dis?.dispatch({
action: _actions.Action.ViewRoomError,
room_id: null,
room_alias: payload.room_alias,
err: err instanceof _matrix.MatrixError ? err : undefined
});
return;
}
}
// Re-fire the payload with the newly found room_id
this.dis?.dispatch(_objectSpread(_objectSpread({}, payload), {}, {
room_id: roomId
}));
}
}
viewThread(payload) {
this.setState({
threadId: payload.thread_id
});
}
viewRoomError(payload) {
this.setState({
roomId: payload.room_id,
roomAlias: payload.room_alias,
roomLoading: false,
roomLoadError: payload.err
});
}
async joinRoom(payload) {
this.setState({
joining: true
});
// take a copy of roomAlias & roomId as they may change by the time the join is complete
const {
roomAlias,
roomId = payload.roomId
} = this.state;
const address = roomAlias || roomId;
const viaServers = this.state.viaServers || [];
try {
const cli = _MatrixClientPeg.MatrixClientPeg.safeGet();
await (0, _promise.retry)(() => cli.joinRoom(address, _objectSpread({
viaServers
}, payload.opts || {})), NUM_JOIN_RETRY, err => {
// if we received a Gateway timeout or Cloudflare timeout then retry
return err.httpStatus === 504 || err.httpStatus === 524;
});
// We do *not* clear the 'joining' flag because the Room object and/or our 'joined' member event may not
// have come down the sync stream yet, and that's the point at which we'd consider the user joined to the
// room.
this.dis?.dispatch({
action: _actions.Action.JoinRoomReady,
roomId: roomId,
metricsTrigger: payload.metricsTrigger
});
} catch (err) {
this.dis?.dispatch({
action: _actions.Action.JoinRoomError,
roomId,
err,
canAskToJoin: payload.canAskToJoin
});
if (payload.canAskToJoin) {
this.dis?.dispatch({
action: _actions.Action.PromptAskToJoin
});
}
}
}
getInvitingUserId(roomId) {
const cli = _MatrixClientPeg.MatrixClientPeg.safeGet();
const room = cli.getRoom(roomId);
if (room?.getMyMembership() === _types.KnownMembership.Invite) {
const myMember = room.getMember(cli.getSafeUserId());
const inviteEvent = myMember ? myMember.events.member : null;
return inviteEvent?.getSender();
}
}
showJoinRoomError(err, roomId) {
let description = err.message ? err.message : JSON.stringify(err);
_logger.logger.log("Failed to join room:", description);
if (err.name === "ConnectionError") {
description = (0, _languageHandler._t)("room|error_join_connection");
} else if (err.errcode === "M_INCOMPATIBLE_ROOM_VERSION") {
description = /*#__PURE__*/_react.default.createElement("div", null, (0, _languageHandler._t)("room|error_join_incompatible_version_1"), /*#__PURE__*/_react.default.createElement("br", null), (0, _languageHandler._t)("room|error_join_incompatible_version_2"));
} else if (err.httpStatus === 404) {
const invitingUserId = this.getInvitingUserId(roomId);
// provide a better error message for invites
if (invitingUserId) {
// if the inviting user is on the same HS, there can only be one cause: they left.
if (invitingUserId.endsWith(`:${_MatrixClientPeg.MatrixClientPeg.safeGet().getDomain()}`)) {
description = (0, _languageHandler._t)("room|error_join_404_invite_same_hs");
} else {
description = (0, _languageHandler._t)("room|error_join_404_invite");
}
}
// provide a more detailed error than "No known servers" when attempting to
// join using a room ID and no via servers
if (roomId === this.state.roomId && this.state.viaServers.length === 0) {
description = /*#__PURE__*/_react.default.createElement("div", null, (0, _languageHandler._t)("room|error_join_404_1"), /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement("br", null), (0, _languageHandler._t)("room|error_join_404_2"));
}
}
_Modal.default.createDialog(_ErrorDialog.default, {
title: (0, _languageHandler._t)("room|error_join_title"),
description
});
}
joinRoomError(payload) {
this.setState({
joining: false,
joinError: payload.err
});
if (payload.err && !payload.canAskToJoin) {
this.showJoinRoomError(payload.err, payload.roomId);
}
}
reset() {
this.state = Object.assign({}, INITIAL_STATE);
}
/**
* Reset which dispatcher should be used to listen for actions. The old dispatcher will be
* unregistered.
* @param dis The new dispatcher to use.
*/
resetDispatcher(dis) {
if (this.dispatchToken) {
this.dis?.unregister(this.dispatchToken);
}
this.dis = dis;
if (dis) {
// Some tests mock the dispatcher file resulting in an empty defaultDispatcher
// so rather than dying here, just ignore it. When we no longer mock files like this,
// we should remove the null check.
this.dispatchToken = this.dis.register(this.onDispatch.bind(this));
}
}
// The room ID of the room currently being viewed
getRoomId() {
return this.state.roomId;
}
getThreadId() {
return this.state.threadId;
}
// The event to scroll to when the room is first viewed
getInitialEventId() {
return this.state.initialEventId;
}
// Whether to highlight the initial event
isInitialEventHighlighted() {
return this.state.isInitialEventHighlighted;
}
// Whether to avoid jumping to the initial event
initialEventScrollIntoView() {
return this.state.initialEventScrollIntoView;
}
// The room alias of the room (or null if not originally specified in view_room)
getRoomAlias() {
return this.state.roomAlias;
}
// Whether the current room is loading (true whilst resolving an alias)
isRoomLoading() {
return this.state.roomLoading;
}
// Any error that has occurred during loading
getRoomLoadError() {
return this.state.roomLoadError;
}
// True if we're expecting the user to be joined to the room currently being
// viewed. Note that this is left true after the join request has finished,
// since we should still consider a join to be in progress until the room
// & member events come down the sync.
//
// This flag remains true after the room has been successfully joined,
// (this store doesn't listen for the appropriate member events)
// so you should always observe the joined state from the member event
// if a room object is present.
// ie. The correct logic is:
// if (room) {
// if (myMember.membership == 'joined') {
// // user is joined to the room
// } else {
// // Not joined
// }
// } else {
// if (this.stores.roomViewStore.isJoining()) {
// // show spinner
// } else {
// // show join prompt
// }
// }
isJoining() {
return this.state.joining;
}
// Any error that has occurred during joining
getJoinError() {
return this.state.joinError;
}
// The mxEvent if one is currently being replied to/quoted
getQuotingEvent() {
return this.state.replyingToEvent;
}
shouldPeek() {
return this.state.shouldPeek;
}
getWasContextSwitch() {
return this.state.wasContextSwitch;
}
isViewingCall() {
return this.state.viewingCall;
}
skipCallLobby() {
return this.state.skipLobby;
}
/**
* Gets the current state of the 'promptForAskToJoin' property.
*
* @returns {boolean} The value of the 'promptForAskToJoin' property.
*/
promptAskToJoin() {
return this.state.promptAskToJoin;
}
/**
* Submits a request to join a room by sending a knock request.
*
* @param {SubmitAskToJoinPayload} payload - The payload containing information to submit the request.
* @returns {void}
*/
submitAskToJoin(payload) {
_MatrixClientPeg.MatrixClientPeg.safeGet().knockRoom(payload.roomId, _objectSpread({
viaServers: this.state.viaServers
}, payload.opts)).catch(err => _Modal.default.createDialog(_ErrorDialog.default, {
title: (0, _languageHandler._t)("room|error_join_title"),
description: err.httpStatus === 403 ? (0, _languageHandler._t)("room|error_join_403") : err.message
})).finally(() => this.setState({
promptAskToJoin: false
}));
}
/**
* Cancels a request to join a room by sending a leave request.
*
* @param {CancelAskToJoinPayload} payload - The payload containing information to cancel the request.
* @returns {void}
*/
cancelAskToJoin(payload) {
_MatrixClientPeg.MatrixClientPeg.safeGet().leave(payload.roomId).catch(err => _Modal.default.createDialog(_ErrorDialog.default, {
title: (0, _languageHandler._t)("room|error_cancel_knock_title"),
description: err.message
}));
}
/**
* Gets the current state of the 'viewRoomOpts' property.
*
* @returns {ViewRoomOpts} The value of the 'viewRoomOpts' property.
*/
getViewRoomOpts() {
return this.state.viewRoomOpts;
}
/**
* Invokes the view room lifecycle to set the view room options.
*
* @returns {void}
*/
setViewRoomOpts() {
const viewRoomOpts = {
buttons: []
};
_ModuleRunner.ModuleRunner.instance.invoke(_RoomViewLifecycle.RoomViewLifecycle.ViewRoom, viewRoomOpts, this.getRoomId());
this.setState({
viewRoomOpts
});
}
}
exports.RoomViewStore = RoomViewStore;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsInV0aWxzIiwiX2ludGVyb3BSZXF1aXJlV2lsZGNhcmQiLCJfbWF0cml4IiwiX3R5cGVzIiwiX2xvZ2dlciIsIl9ldmVudHMiLCJfUm9vbVZpZXdMaWZlY3ljbGUiLCJfTWF0cml4Q2xpZW50UGVnIiwiX01vZGFsIiwiX2xhbmd1YWdlSGFuZGxlciIsIl9Sb29tQWxpYXNDYWNoZSIsIl9hY3Rpb25zIiwiX3Byb21pc2UiLCJfUm9vbUNvbnRleHQiLCJfRE1Sb29tTWFwIiwiX3NwYWNlcyIsIl9FcnJvckRpYWxvZyIsIl9TZXR0aW5nc1N0b3JlIiwiX1Jvb21VcGdyYWRlIiwiX0FzeW5jU3RvcmUiLCJfQ2FsbFN0b3JlIiwiX3ZvaWNlQnJvYWRjYXN0IiwiX3Nob3dDYW50U3RhcnRBQ2FsbERpYWxvZyIsIl9wYXVzZU5vbkxpdmVCcm9hZGNhc3RGcm9tT3RoZXJSb29tIiwiX01vZHVsZVJ1bm5lciIsIl9ub3RpZmljYXRpb25zIiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiaGFzIiwiZ2V0IiwibiIsIl9fcHJvdG9fXyIsImEiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsInUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJpIiwic2V0Iiwib3duS2V5cyIsImtleXMiLCJnZXRPd25Qcm9wZXJ0eVN5bWJvbHMiLCJvIiwiZmlsdGVyIiwiZW51bWVyYWJsZSIsInB1c2giLCJhcHBseSIsIl9vYmplY3RTcHJlYWQiLCJhcmd1bWVudHMiLCJsZW5ndGgiLCJmb3JFYWNoIiwiX2RlZmluZVByb3BlcnR5MiIsImdldE93blByb3BlcnR5RGVzY3JpcHRvcnMiLCJkZWZpbmVQcm9wZXJ0aWVzIiwiTlVNX0pPSU5fUkVUUlkiLCJJTklUSUFMX1NUQVRFIiwiam9pbmluZyIsImpvaW5FcnJvciIsInJvb21JZCIsInRocmVhZElkIiwic3Vic2NyaWJpbmdSb29tSWQiLCJpbml0aWFsRXZlbnRJZCIsImluaXRpYWxFdmVudFBpeGVsT2Zmc2V0IiwiaXNJbml0aWFsRXZlbnRIaWdobGlnaHRlZCIsImluaXRpYWxFdmVudFNjcm9sbEludG9WaWV3Iiwicm9vbUFsaWFzIiwicm9vbUxvYWRpbmciLCJyb29tTG9hZEVycm9yIiwicmVwbHlpbmdUb0V2ZW50Iiwic2hvdWxkUGVlayIsInZpYVNlcnZlcnMiLCJ3YXNDb250ZXh0U3dpdGNoIiwidmlld2luZ0NhbGwiLCJwcm9tcHRBc2tUb0pvaW4iLCJ2aWV3Um9vbU9wdHMiLCJidXR0b25zIiwiUm9vbVZpZXdTdG9yZSIsIkV2ZW50RW1pdHRlciIsImNvbnN0cnVjdG9yIiwiZGlzIiwic3RvcmVzIiwiZGVlcENvcHkiLCJyZWNvcmRpbmciLCJyb29tIiwiY2xpZW50IiwiZ2V0Um9vbSIsInN0YXRlIiwidW5kZWZpbmVkIiwiZG9NYXliZVNldEN1cnJlbnRWb2ljZUJyb2FkY2FzdFBsYXliYWNrIiwicmVzZXREaXNwYXRjaGVyIiwidm9pY2VCcm9hZGNhc3RSZWNvcmRpbmdzU3RvcmUiLCJhZGRMaXN0ZW5lciIsIlZvaWNlQnJvYWRjYXN0UmVjb3JkaW5nc1N0b3JlRXZlbnQiLCJDdXJyZW50Q2hhbmdlZCIsIm9uQ3VycmVudEJyb2FkY2FzdFJlY29yZGluZ0NoYW5nZWQiLCJhZGRSb29tTGlzdGVuZXIiLCJmbiIsIm9uIiwicmVtb3ZlUm9vbUxpc3RlbmVyIiwib2ZmIiwiZW1pdEZvclJvb20iLCJpc0FjdGl2ZSIsImVtaXQiLCJzZXRTdGF0ZSIsIm5ld1N0YXRlIiwic3RhdGVDaGFuZ2VkIiwia2V5Iiwidm9pY2VCcm9hZGNhc3RQbGF5YmFja3NTdG9yZSIsImdldEN1cnJlbnQiLCJwYXVzZSIsInNob3dDYW50U3RhcnRBQ2FsbERpYWxvZyIsImxhc3RSb29tSWQiLCJhc3NpZ24iLCJkaXNwYXRjaCIsImFjdGlvbiIsIkFjdGlvbiIsIkFjdGl2ZVJvb21DaGFuZ2VkIiwib2xkUm9vbUlkIiwibmV3Um9vbUlkIiwiVVBEQVRFX0VWRU5UIiwib25Sb29tU3RhdGVFdmVudHMiLCJldmVudCIsImdldFJvb21JZCIsIm9uRGlzcGF0Y2giLCJwYXlsb2FkIiwiVmlld1Jvb20iLCJ2aWV3Um9vbSIsIlZpZXdUaHJlYWQiLCJ2aWV3VGhyZWFkIiwiVmlld0hvbWVQYWdlIiwiZG9DbGVhckN1cnJlbnRWb2ljZUJyb2FkY2FzdFBsYXliYWNrSWZTdG9wcGVkIiwiVmlld1Jvb21FcnJvciIsInZpZXdSb29tRXJyb3IiLCJKb2luUm9vbSIsImpvaW5Sb29tIiwiSm9pblJvb21FcnJvciIsImpvaW5Sb29tRXJyb3IiLCJKb2luUm9vbVJlYWR5IiwiYXdhaXRSb29tRG93blN5bmMiLCJNYXRyaXhDbGllbnRQZWciLCJzYWZlR2V0IiwidGhlbiIsIm51bU1lbWJlcnMiLCJnZXRKb2luZWRNZW1iZXJDb3VudCIsInJvb21TaXplIiwicG9zdGhvZ0FuYWx5dGljcyIsInRyYWNrRXZlbnQiLCJldmVudE5hbWUiLCJ0cmlnZ2VyIiwibWV0cmljc1RyaWdnZXIiLCJpc0RNIiwiRE1Sb29tTWFwIiwic2hhcmVkIiwiZ2V0VXNlcklkRm9yUm9vbUlkIiwiaXNTcGFjZSIsImlzU3BhY2VSb29tIiwiT25Mb2dnZWRPdXQiLCJyZXNldCIsIlRpbWVsaW5lUmVuZGVyaW5nVHlwZSIsIlRocmVhZCIsImNvbnRleHQiLCJyb29tX2lkIiwiUHJvbXB0QXNrVG9Kb2luIiwiU3VibWl0QXNrVG9Kb2luIiwic3VibWl0QXNrVG9Kb2luIiwiQ2FuY2VsQXNrVG9Kb2luIiwiY2FuY2VsQXNrVG9Kb2luIiwiUm9vbUxvYWRlZCIsInNldFZpZXdSb29tT3B0cyIsImFjdGl2ZVNwYWNlIiwic3BhY2VTdG9yZSIsIk1ldGFTcGFjZSIsIkhvbWUiLCJpc01ldGFTcGFjZSIsImFjdGl2ZVNwYWNlUm9vbSIsImdldEpvaW5SdWxlIiwiSm9pblJ1bGUiLCJQdWJsaWMiLCJ2aWFLZXlib2FyZCIsIm1ldHJpY3NWaWFLZXlib2FyZCIsIlNldHRpbmdzU3RvcmUiLCJnZXRWYWx1ZSIsInNsaWRpbmdTeW5jTWFuYWdlciIsInNldFJvb21WaXNpYmxlIiwidmlhX3NlcnZlcnMiLCJjb250ZXh0X3N3aXRjaCIsInZpZXdfY2FsbCIsInJvb21fYWxpYXMiLCJldmVudF9pZCIsImhpZ2hsaWdodGVkIiwic2Nyb2xsX2ludG9fdmlldyIsInNob3VsZF9wZWVrIiwic2tpcExvYmJ5IiwiQ2FsbFN0b3JlIiwiaW5zdGFuY2UiLCJnZXRBY3RpdmVDYWxsIiwiYXV0b19qb2luIiwicGF1c2VOb25MaXZlQnJvYWRjYXN0RnJvbU90aGVyUm9vbSIsInNldE1hcmtlZFVucmVhZFN0YXRlIiwiZ2V0Q2FjaGVkUm9vbUlERm9yQWxpYXMiLCJyZXN1bHQiLCJnZXRSb29tSWRGb3JBbGlhcyIsInN0b3JlUm9vbUFsaWFzSW5DYWNoZSIsImVyciIsImxvZ2dlciIsImVycm9yIiwiTWF0cml4RXJyb3IiLCJ0aHJlYWRfaWQiLCJhZGRyZXNzIiwiY2xpIiwicmV0cnkiLCJvcHRzIiwiaHR0cFN0YXR1cyIsImNhbkFza1RvSm9pbiIsImdldEludml0aW5nVXNlcklkIiwiZ2V0TXlNZW1iZXJzaGlwIiwiS25vd25NZW1iZXJzaGlwIiwiSW52aXRlIiwibXlNZW1iZXIiLCJnZXRNZW1iZXIiLCJnZXRTYWZlVXNlcklkIiwiaW52aXRlRXZlbnQiLCJldmVudHMiLCJtZW1iZXIiLCJnZXRTZW5kZXIiLCJzaG93Sm9pblJvb21FcnJvciIsImRlc2NyaXB0aW9uIiwibWVzc2FnZSIsIkpTT04iLCJzdHJpbmdpZnkiLCJsb2ciLCJuYW1lIiwiX3QiLCJlcnJjb2RlIiwiY3JlYXRlRWxlbWVudCIsImludml0aW5nVXNlcklkIiwiZW5kc1dpdGgiLCJnZXREb21haW4iLCJNb2RhbCIsImNyZWF0ZURpYWxvZyIsIkVycm9yRGlhbG9nIiwidGl0bGUiLCJkaXNwYXRjaFRva2VuIiwidW5yZWdpc3RlciIsInJlZ2lzdGVyIiwiYmluZCIsImdldFRocmVhZElkIiwiZ2V0SW5pdGlhbEV2ZW50SWQiLCJnZXRSb29tQWxpYXMiLCJpc1Jvb21Mb2FkaW5nIiwiZ2V0Um9vbUxvYWRFcnJvciIsImlzSm9pbmluZyIsImdldEpvaW5FcnJvciIsImdldFF1b3RpbmdFdmVudCIsImdldFdhc0NvbnRleHRTd2l0Y2giLCJpc1ZpZXdpbmdDYWxsIiwic2tpcENhbGxMb2JieSIsImtub2NrUm9vbSIsImNhdGNoIiwiZmluYWxseSIsImxlYXZlIiwiZ2V0Vmlld1Jvb21PcHRzIiwiTW9kdWxlUnVubmVyIiwiaW52b2tlIiwiUm9vbVZpZXdMaWZlY3ljbGUiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0b3Jlcy9Sb29tVmlld1N0b3JlLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAxOS0yMDIyIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5Db3B5cmlnaHQgMjAxNywgMjAxOCBOZXcgVmVjdG9yIEx0ZFxuQ29weXJpZ2h0IDIwMTcgVmVjdG9yIENyZWF0aW9ucyBMdGRcblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0LCB7IFJlYWN0Tm9kZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0ICogYXMgdXRpbHMgZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL3V0aWxzXCI7XG5pbXBvcnQgeyBNYXRyaXhFcnJvciwgSm9pblJ1bGUsIFJvb20sIE1hdHJpeEV2ZW50IH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgS25vd25NZW1iZXJzaGlwIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL3R5cGVzXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5pbXBvcnQgeyBWaWV3Um9vbSBhcyBWaWV3Um9vbUV2ZW50IH0gZnJvbSBcIkBtYXRyaXgtb3JnL2FuYWx5dGljcy1ldmVudHMvdHlwZXMvdHlwZXNjcmlwdC9WaWV3Um9vbVwiO1xuaW1wb3J0IHsgSm9pbmVkUm9vbSBhcyBKb2luZWRSb29tRXZlbnQgfSBmcm9tIFwiQG1hdHJpeC1vcmcvYW5hbHl0aWNzLWV2ZW50cy90eXBlcy90eXBlc2NyaXB0L0pvaW5lZFJvb21cIjtcbmltcG9ydCB7IE9wdGlvbmFsIH0gZnJvbSBcIm1hdHJpeC1ldmVudHMtc2RrXCI7XG5pbXBvcnQgRXZlbnRFbWl0dGVyIGZyb20gXCJldmVudHNcIjtcbmltcG9ydCB7IFJvb21WaWV3TGlmZWN5Y2xlLCBWaWV3Um9vbU9wdHMgfSBmcm9tIFwiQG1hdHJpeC1vcmcvcmVhY3Qtc2RrLW1vZHVsZS1hcGkvbGliL2xpZmVjeWNsZXMvUm9vbVZpZXdMaWZlY3ljbGVcIjtcblxuaW1wb3J0IHsgTWF0cml4RGlzcGF0Y2hlciB9IGZyb20gXCIuLi9kaXNwYXRjaGVyL2Rpc3BhdGNoZXJcIjtcbmltcG9ydCB7IE1hdHJpeENsaWVudFBlZyB9IGZyb20gXCIuLi9NYXRyaXhDbGllbnRQZWdcIjtcbmltcG9ydCBNb2RhbCBmcm9tIFwiLi4vTW9kYWxcIjtcbmltcG9ydCB7IF90IH0gZnJvbSBcIi4uL2xhbmd1YWdlSGFuZGxlclwiO1xuaW1wb3J0IHsgZ2V0Q2FjaGVkUm9vbUlERm9yQWxpYXMsIHN0b3JlUm9vbUFsaWFzSW5DYWNoZSB9IGZyb20gXCIuLi9Sb29tQWxpYXNDYWNoZVwiO1xuaW1wb3J0IHsgQWN0aW9uIH0gZnJvbSBcIi4uL2Rpc3BhdGNoZXIvYWN0aW9uc1wiO1xuaW1wb3J0IHsgcmV0cnkgfSBmcm9tIFwiLi4vdXRpbHMvcHJvbWlzZVwiO1xuaW1wb3J0IHsgVGltZWxpbmVSZW5kZXJpbmdUeXBlIH0gZnJvbSBcIi4uL2NvbnRleHRzL1Jvb21Db250ZXh0XCI7XG5pbXBvcnQgeyBWaWV3Um9vbVBheWxvYWQgfSBmcm9tIFwiLi4vZGlzcGF0Y2hlci9wYXlsb2Fkcy9WaWV3Um9vbVBheWxvYWRcIjtcbmltcG9ydCBETVJvb21NYXAgZnJvbSBcIi4uL3V0aWxzL0RNUm9vbU1hcFwiO1xuaW1wb3J0IHsgaXNNZXRhU3BhY2UsIE1ldGFTcGFjZSB9IGZyb20gXCIuL3NwYWNlc1wiO1xuaW1wb3J0IHsgSm9pblJvb21QYXlsb2FkIH0gZnJvbSBcIi4uL2Rpc3BhdGNoZXIvcGF5bG9hZHMvSm9pblJvb21QYXlsb2FkXCI7XG5pbXBvcnQgeyBKb2luUm9vbVJlYWR5UGF5bG9hZCB9IGZyb20gXCIuLi9kaXNwYXRjaGVyL3BheWxvYWRzL0pvaW5Sb29tUmVhZHlQYXlsb2FkXCI7XG5pbXBvcnQgeyBKb2luUm9vbUVycm9yUGF5bG9hZCB9IGZyb20gXCIuLi9kaXNwYXRjaGVyL3BheWxvYWRzL0pvaW5Sb29tRXJyb3JQYXlsb2FkXCI7XG5pbXBvcnQgeyBWaWV3Um9vbUVycm9yUGF5bG9hZCB9IGZyb20gXCIuLi9kaXNwYXRjaGVyL3BheWxvYWRzL1ZpZXdSb29tRXJyb3JQYXlsb2FkXCI7XG5pbXBvcnQgRXJyb3JEaWFsb2cgZnJvbSBcIi4uL2NvbXBvbmVudHMvdmlld3MvZGlhbG9ncy9FcnJvckRpYWxvZ1wiO1xuaW1wb3J0IHsgQWN0aXZlUm9vbUNoYW5nZWRQYXlsb2FkIH0gZnJvbSBcIi4uL2Rpc3BhdGNoZXIvcGF5bG9hZHMvQWN0aXZlUm9vbUNoYW5nZWRQYXlsb2FkXCI7XG5pbXBvcnQgU2V0dGluZ3NTdG9yZSBmcm9tIFwiLi4vc2V0dGluZ3MvU2V0dGluZ3NTdG9yZVwiO1xuaW1wb3J0IHsgYXdhaXRSb29tRG93blN5bmMgfSBmcm9tIFwiLi4vdXRpbHMvUm9vbVVwZ3JhZGVcIjtcbmltcG9ydCB7IFVQREFURV9FVkVOVCB9IGZyb20gXCIuL0FzeW5jU3RvcmVcIjtcbmltcG9ydCB7IFNka0NvbnRleHRDbGFzcyB9IGZyb20gXCIuLi9jb250ZXh0cy9TREtDb250ZXh0XCI7XG5pbXBvcnQgeyBDYWxsU3RvcmUgfSBmcm9tIFwiLi9DYWxsU3RvcmVcIjtcbmltcG9ydCB7IFRocmVhZFBheWxvYWQgfSBmcm9tIFwiLi4vZGlzcGF0Y2hlci9wYXlsb2Fkcy9UaHJlYWRQYXlsb2FkXCI7XG5pbXBvcnQge1xuICAgIGRvQ2xlYXJDdXJyZW50Vm9pY2VCcm9hZGNhc3RQbGF5YmFja0lmU3RvcHBlZCxcbiAgICBkb01heWJlU2V0Q3VycmVudFZvaWNlQnJvYWRjYXN0UGxheWJhY2ssXG4gICAgVm9pY2VCcm9hZGNhc3RSZWNvcmRpbmcsXG4gICAgVm9pY2VCcm9hZGNhc3RSZWNvcmRpbmdzU3RvcmVFdmVudCxcbn0gZnJvbSBcIi4uL3ZvaWNlLWJyb2FkY2FzdFwiO1xuaW1wb3J0IHsgSVJvb21TdGF0ZUV2ZW50c0FjdGlvblBheWxvYWQgfSBmcm9tIFwiLi4vYWN0aW9ucy9NYXRyaXhBY3Rpb25DcmVhdG9yc1wiO1xuaW1wb3J0IHsgc2hvd0NhbnRTdGFydEFDYWxsRGlhbG9nIH0gZnJvbSBcIi4uL3ZvaWNlLWJyb2FkY2FzdC91dGlscy9zaG93Q2FudFN0YXJ0QUNhbGxEaWFsb2dcIjtcbmltcG9ydCB7IHBhdXNlTm9uTGl2ZUJyb2FkY2FzdEZyb21PdGhlclJvb20gfSBmcm9tIFwiLi4vdm9pY2UtYnJvYWRjYXN0L3V0aWxzL3BhdXNlTm9uTGl2ZUJyb2FkY2FzdEZyb21PdGhlclJvb21cIjtcbmltcG9ydCB7IEFjdGlvblBheWxvYWQgfSBmcm9tIFwiLi4vZGlzcGF0Y2hlci9wYXlsb2Fkc1wiO1xuaW1wb3J0IHsgQ2FuY2VsQXNrVG9Kb2luUGF5bG9hZCB9IGZyb20gXCIuLi9kaXNwYXRjaGVyL3BheWxvYWRzL0NhbmNlbEFza1RvSm9pblBheWxvYWRcIjtcbmltcG9ydCB7IFN1Ym1pdEFza1RvSm9pblBheWxvYWQgfSBmcm9tIFwiLi4vZGlzcGF0Y2hlci9wYXlsb2Fkcy9TdWJtaXRBc2tUb0pvaW5QYXlsb2FkXCI7XG5pbXBvcnQgeyBNb2R1bGVSdW5uZXIgfSBmcm9tIFwiLi4vbW9kdWxlcy9Nb2R1bGVSdW5uZXJcIjtcbmltcG9ydCB7IHNldE1hcmtlZFVucmVhZFN0YXRlIH0gZnJvbSBcIi4uL3V0aWxzL25vdGlmaWNhdGlvbnNcIjtcblxuY29uc3QgTlVNX0pPSU5fUkVUUlkgPSA1O1xuXG5pbnRlcmZhY2UgU3RhdGUge1xuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgd2UncmUgam9pbmluZyB0aGUgY3VycmVudGx5IHZpZXdlZCAoc2VlIGlzSm9pbmluZygpKVxuICAgICAqL1xuICAgIGpvaW5pbmc6IGJvb2xlYW47XG4gICAgLyoqXG4gICAgICogQW55IGVycm9yIHRoYXQgaGFzIG9jY3VycmVkIGR1cmluZyBqb2luaW5nXG4gICAgICovXG4gICAgam9pbkVycm9yOiBFcnJvciB8IG51bGw7XG4gICAgLyoqXG4gICAgICogVGhlIElEIG9mIHRoZSByb29tIGN1cnJlbnRseSBiZWluZyB2aWV3ZWRcbiAgICAgKi9cbiAgICByb29tSWQ6IHN0cmluZyB8IG51bGw7XG4gICAgLyoqXG4gICAgICogVGhlIElEIG9mIHRoZSB0aHJlYWQgY3VycmVudGx5IGJlaW5nIHZpZXdlZFxuICAgICAqL1xuICAgIHRocmVhZElkOiBzdHJpbmcgfCBudWxsO1xuICAgIC8qKlxuICAgICAqIFRoZSBJRCBvZiB0aGUgcm9vbSBiZWluZyBzdWJzY3JpYmVkIHRvIChpbiBTbGlkaW5nIFN5bmMpXG4gICAgICovXG4gICAgc3Vic2NyaWJpbmdSb29tSWQ6IHN0cmluZyB8IG51bGw7XG4gICAgLyoqXG4gICAgICogVGhlIGV2ZW50IHRvIHNjcm9sbCB0byB3aGVuIHRoZSByb29tIGlzIGZpcnN0IHZpZXdlZFxuICAgICAqL1xuICAgIGluaXRpYWxFdmVudElkOiBzdHJpbmcgfCBudWxsO1xuICAgIGluaXRpYWxFdmVudFBpeGVsT2Zmc2V0OiBudW1iZXIgfCBudWxsO1xuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdG8gaGlnaGxpZ2h0IHRoZSBpbml0aWFsIGV2ZW50XG4gICAgICovXG4gICAgaXNJbml0aWFsRXZlbnRIaWdobGlnaHRlZDogYm9vbGVhbjtcbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRvIHNjcm9sbCB0aGUgaW5pdGlhbCBldmVudCBpbnRvIHZpZXdcbiAgICAgKi9cbiAgICBpbml0aWFsRXZlbnRTY3JvbGxJbnRvVmlldzogYm9vbGVhbjtcbiAgICAvKipcbiAgICAgKiBUaGUgYWxpYXMgb2YgdGhlIHJvb20gKG9yIG51bGwgaWYgbm90IG9yaWdpbmFsbHkgc3BlY2lmaWVkIGluIHZpZXdfcm9vbSlcbiAgICAgKi9cbiAgICByb29tQWxpYXM6IHN0cmluZyB8IG51bGw7XG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgY3VycmVudCByb29tIGlzIGxvYWRpbmdcbiAgICAgKi9cbiAgICByb29tTG9hZGluZzogYm9vbGVhbjtcbiAgICAvKipcbiAgICAgKiBBbnkgZXJyb3IgdGhhdCBoYXMgb2NjdXJyZWQgZHVyaW5nIGxvYWRpbmdcbiAgICAgKi9cbiAgICByb29tTG9hZEVycm9yOiBNYXRyaXhFcnJvciB8IG51bGw7XG4gICAgcmVwbHlpbmdUb0V2ZW50OiBNYXRyaXhFdmVudCB8IG51bGw7XG4gICAgc2hvdWxkUGVlazogYm9vbGVhbjtcbiAgICB2aWFTZXJ2ZXJzOiBzdHJpbmdbXTtcbiAgICB3YXNDb250ZXh0U3dpdGNoOiBib29sZWFuO1xuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgd2UncmUgdmlld2luZyBhIGNhbGwgb3IgY2FsbCBsb2JieSBpbiB0aGlzIHJvb21cbiAgICAgKi9cbiAgICB2aWV3aW5nQ2FsbDogYm9vbGVhbjtcbiAgICAvKipcbiAgICAgKiBJZiB3ZSB3YW50IHRoZSBjYWxsIHRvIHNraXAgdGhlIGxvYmJ5IGFuZCBpbW1lZGlhdGVseSBqb2luXG4gICAgICovXG4gICAgc2tpcExvYmJ5PzogYm9vbGVhbjtcblxuICAgIHByb21wdEFza1RvSm9pbjogYm9vbGVhbjtcblxuICAgIHZpZXdSb29tT3B0czogVmlld1Jvb21PcHRzO1xufVxuXG5jb25zdCBJTklUSUFMX1NUQVRFOiBTdGF0ZSA9IHtcbiAgICBqb2luaW5nOiBmYWxzZSxcbiAgICBqb2luRXJyb3I6IG51bGwsXG4gICAgcm9vbUlkOiBudWxsLFxuICAgIHRocmVhZElkOiBudWxsLFxuICAgIHN1YnNjcmliaW5nUm9vbUlkOiBudWxsLFxuICAgIGluaXRpYWxFdmVudElkOiBudWxsLFxuICAgIGluaXRpYWxFdmVudFBpeGVsT2Zmc2V0OiBudWxsLFxuICAgIGlzSW5pdGlhbEV2ZW50SGlnaGxpZ2h0ZWQ6IGZhbHNlLFxuICAgIGluaXRpYWxFdmVudFNjcm9sbEludG9WaWV3OiB0cnVlLFxuICAgIHJvb21BbGlhczogbnVsbCxcbiAgICByb29tTG9hZGluZzogZmFsc2UsXG4gICAgcm9vbUxvYWRFcnJvcjogbnVsbCxcbiAgICByZXBseWluZ1RvRXZlbnQ6IG51bGwsXG4gICAgc2hvdWxkUGVlazogZmFsc2UsXG4gICAgdmlhU2VydmVyczogW10sXG4gICAgd2FzQ29udGV4dFN3aXRjaDogZmFsc2UsXG4gICAgdmlld2luZ0NhbGw6IGZhbHNlLFxuICAgIHByb21wdEFza1RvSm9pbjogZmFsc2UsXG4gICAgdmlld1Jvb21PcHRzOiB7IGJ1dHRvbnM6IFtdIH0sXG59O1xuXG50eXBlIExpc3RlbmVyID0gKGlzQWN0aXZlOiBib29sZWFuKSA9PiB2b2lkO1xuXG4vKipcbiAqIEEgY2xhc3MgZm9yIHN0b3JpbmcgYXBwbGljYXRpb24gc3RhdGUgZm9yIFJvb21WaWV3LlxuICovXG5leHBvcnQgY2xhc3MgUm9vbVZpZXdTdG9yZSBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gICAgLy8gaW5pdGlhbGl6ZSBzdGF0ZSBhcyBhIGNvcHkgb2YgdGhlIGluaXRpYWwgc3RhdGUuIFdlIG5lZWQgdG8gY29weSBlbHNlIG9uZSBSVlMgY2FuIHRhbGsgdG9cbiAgICAvLyBhbm90aGVyIFJWUyB2aWEgSU5JVElBTF9TVEFURSBhcyB0aGV5IHNoYXJlIHRoZSBzYW1lIHVuZGVybHlpbmcgb2JqZWN0LiBNb3N0bHkgcmVsZXZhbnQgZm9yIHRlc3RzLlxuICAgIHByaXZhdGUgc3RhdGUgPSB1dGlscy5kZWVwQ29weShJTklUSUFMX1NUQVRFKTtcblxuICAgIHByaXZhdGUgZGlzPzogTWF0cml4RGlzcGF0Y2hlcjtcbiAgICBwcml2YXRlIGRpc3BhdGNoVG9rZW4/OiBzdHJpbmc7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IoXG4gICAgICAgIGRpczogTWF0cml4RGlzcGF0Y2hlcixcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBzdG9yZXM6IFNka0NvbnRleHRDbGFzcyxcbiAgICApIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5yZXNldERpc3BhdGNoZXIoZGlzKTtcbiAgICAgICAgdGhpcy5zdG9yZXMudm9pY2VCcm9hZGNhc3RSZWNvcmRpbmdzU3RvcmUuYWRkTGlzdGVuZXIoXG4gICAgICAgICAgICBWb2ljZUJyb2FkY2FzdFJlY29yZGluZ3NTdG9yZUV2ZW50LkN1cnJlbnRDaGFuZ2VkLFxuICAgICAgICAgICAgdGhpcy5vbkN1cnJlbnRCcm9hZGNhc3RSZWNvcmRpbmdDaGFuZ2VkLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBhZGRSb29tTGlzdGVuZXIocm9vbUlkOiBzdHJpbmcsIGZuOiBMaXN0ZW5lcik6IHZvaWQge1xuICAgICAgICB0aGlzLm9uKHJvb21JZCwgZm4pO1xuICAgIH1cblxuICAgIHB1YmxpYyByZW1vdmVSb29tTGlzdGVuZXIocm9vbUlkOiBzdHJpbmcsIGZuOiBMaXN0ZW5lcik6IHZvaWQge1xuICAgICAgICB0aGlzLm9mZihyb29tSWQsIGZuKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGVtaXRGb3JSb29tKHJvb21JZDogc3RyaW5nLCBpc0FjdGl2ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmVtaXQocm9vbUlkLCBpc0FjdGl2ZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkN1cnJlbnRCcm9hZGNhc3RSZWNvcmRpbmdDaGFuZ2VkID0gKHJlY29yZGluZzogVm9pY2VCcm9hZGNhc3RSZWNvcmRpbmcgfCBudWxsKTogdm9pZCA9PiB7XG4gICAgICAgIGlmIChyZWNvcmRpbmcgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGNvbnN0IHJvb20gPSB0aGlzLnN0b3Jlcy5jbGllbnQ/LmdldFJvb20odGhpcy5zdGF0ZS5yb29tSWQgfHwgdW5kZWZpbmVkKTtcblxuICAgICAgICAgICAgaWYgKHJvb20pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRvTWF5YmVTZXRDdXJyZW50Vm9pY2VCcm9hZGNhc3RQbGF5YmFjayhyb29tKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBwcml2YXRlIHNldFN0YXRlKG5ld1N0YXRlOiBQYXJ0aWFsPFN0YXRlPik6IHZvaWQge1xuICAgICAgICAvLyBJZiB2YWx1ZXMgaGF2ZW4ndCBjaGFuZ2VkLCB0aGVyZSdzIG5vdGhpbmcgdG8gZG8uXG4gICAgICAgIC8vIFRoaXMgb25seSB0cmllcyBhIHNoYWxsb3cgY29tcGFyaXNvbiwgc28gdW5jaGFuZ2VkIG9iamVjdHMgd2lsbCBzbGlwXG4gICAgICAgIC8vIHRocm91Z2gsIGJ1dCB0aGF0J3MgcHJvYmFibHkgb2theSBmb3Igbm93LlxuICAgICAgICBsZXQgc3RhdGVDaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKG5ld1N0YXRlKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGVba2V5IGFzIGtleW9mIFN0YXRlXSAhPT0gbmV3U3RhdGVba2V5IGFzIGtleW9mIFN0YXRlXSkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFzdGF0ZUNoYW5nZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChuZXdTdGF0ZS52aWV3aW5nQ2FsbCkge1xuICAgICAgICAgICAgLy8gUGF1c2UgY3VycmVudCBicm9hZGNhc3QsIGlmIGFueVxuICAgICAgICAgICAgdGhpcy5zdG9yZXMudm9pY2VCcm9hZGNhc3RQbGF5YmFja3NTdG9yZS5nZXRDdXJyZW50KCk/LnBhdXNlKCk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnN0b3Jlcy52b2ljZUJyb2FkY2FzdFJlY29yZGluZ3NTdG9yZS5nZXRDdXJyZW50KCkpIHtcbiAgICAgICAgICAgICAgICBzaG93Q2FudFN0YXJ0QUNhbGxEaWFsb2coKTtcbiAgICAgICAgICAgICAgICBuZXdTdGF0ZS52aWV3aW5nQ2FsbCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbGFzdFJvb21JZCA9IHRoaXMuc3RhdGUucm9vbUlkO1xuICAgICAgICB0aGlzLnN0YXRlID0gT2JqZWN0LmFzc2lnbih0aGlzLnN0YXRlLCBuZXdTdGF0ZSk7XG4gICAgICAgIGlmIChsYXN0Um9vbUlkICE9PSB0aGlzLnN0YXRlLnJvb21JZCkge1xuICAgICAgICAgICAgaWYgKGxhc3RSb29tSWQpIHRoaXMuZW1pdEZvclJvb20obGFzdFJvb21JZCwgZmFsc2UpO1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUucm9vbUlkKSB0aGlzLmVtaXRGb3JSb29tKHRoaXMuc3RhdGUucm9vbUlkLCB0cnVlKTtcblxuICAgICAgICAgICAgLy8gRmlyZWQgc28gd2UgY2FuIHJlZHVjZSBkZXBlbmRlbmN5IG9uIGV2ZW50IGVtaXR0ZXJzIHRvIHRoaXMgc3RvcmUsIHdoaWNoIGlzIHJlbGF0aXZlbHlcbiAgICAgICAgICAgIC8vIGNlbnRyYWwgdG8gdGhlIGFwcGxpY2F0aW9uIGFuZCBjYW4gZWFzaWx5IGNhdXNlIGltcG9ydCBjeWNsZXMuXG4gICAgICAgICAgICB0aGlzLmRpcz8uZGlzcGF0Y2g8QWN0aXZlUm9vbUNoYW5nZWRQYXlsb2FkPih7XG4gICAgICAgICAgICAgICAgYWN0aW9uOiBBY3Rpb24uQWN0aXZlUm9vbUNoYW5nZWQsXG4gICAgICAgICAgICAgICAgb2xkUm9vbUlkOiBsYXN0Um9vbUlkLFxuICAgICAgICAgICAgICAgIG5ld1Jvb21JZDogdGhpcy5zdGF0ZS5yb29tSWQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZW1pdChVUERBVEVfRVZFTlQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZG9NYXliZVNldEN1cnJlbnRWb2ljZUJyb2FkY2FzdFBsYXliYWNrKHJvb206IFJvb20pOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnN0b3Jlcy5jbGllbnQpIHJldHVybjtcbiAgICAgICAgZG9NYXliZVNldEN1cnJlbnRWb2ljZUJyb2FkY2FzdFBsYXliYWNrKFxuICAgICAgICAgICAgcm9vbSxcbiAgICAgICAgICAgIHRoaXMuc3RvcmVzLmNsaWVudCxcbiAgICAgICAgICAgIHRoaXMuc3RvcmVzLnZvaWNlQnJvYWRjYXN0UGxheWJhY2tzU3RvcmUsXG4gICAgICAgICAgICB0aGlzLnN0b3Jlcy52b2ljZUJyb2FkY2FzdFJlY29yZGluZ3NTdG9yZSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uUm9vbVN0YXRlRXZlbnRzKGV2ZW50OiBNYXRyaXhFdmVudCk6IHZvaWQge1xuICAgICAgICBjb25zdCByb29tSWQgPSBldmVudC5nZXRSb29tSWQ/LigpO1xuXG4gICAgICAgIC8vIG5vIHJvb20gb3Igbm90IGN1cnJlbnQgcm9vbVxuICAgICAgICBpZiAoIXJvb21JZCB8fCByb29tSWQgIT09IHRoaXMuc3RhdGUucm9vbUlkKSByZXR1cm47XG5cbiAgICAgICAgY29uc3Qgcm9vbSA9IHRoaXMuc3RvcmVzLmNsaWVudD8uZ2V0Um9vbShyb29tSWQpO1xuXG4gICAgICAgIGlmIChyb29tKSB7XG4gICAgICAgICAgICB0aGlzLmRvTWF5YmVTZXRDdXJyZW50Vm9pY2VCcm9hZGNhc3RQbGF5YmFjayhyb29tKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25EaXNwYXRjaChwYXlsb2FkOiBBY3Rpb25QYXlsb2FkKTogdm9pZCB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXG4gICAgICAgIHN3aXRjaCAocGF5bG9hZC5hY3Rpb24pIHtcbiAgICAgICAgICAgIC8vIHZpZXdfcm9vbTpcbiAgICAgICAgICAgIC8vICAgICAgLSByb29tX2FsaWFzOiAgICcjc29tZWFsaWFzOm1hdHJpeC5vcmcnXG4gICAgICAgICAgICAvLyAgICAgIC0gcm9vbV9pZDogICAgICAnIXJvb21pZDEyMzptYXRyaXgub3JnJ1xuICAgICAgICAgICAgLy8gICAgICAtIGV2ZW50X2lkOiAgICAgJyQyMTM0NTY3ODI6bWF0cml4Lm9yZydcbiAgICAgICAgICAgIC8vICAgICAgLSBldmVudF9vZmZzZXQ6IDEwMFxuICAgICAgICAgICAgLy8gICAgICAtIGhpZ2hsaWdodGVkOiAgdHJ1ZVxuICAgICAgICAgICAgY2FzZSBBY3Rpb24uVmlld1Jvb206XG4gICAgICAgICAgICAgICAgdGhpcy52aWV3Um9vbShwYXlsb2FkIGFzIFZpZXdSb29tUGF5bG9hZCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEFjdGlvbi5WaWV3VGhyZWFkOlxuICAgICAgICAgICAgICAgIHRoaXMudmlld1RocmVhZChwYXlsb2FkIGFzIFRocmVhZFBheWxvYWQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgLy8gZm9yIHRoZXNlIGV2ZW50cyBibGFuayBvdXQgdGhlIHJvb21JZCBhcyB3ZSBhcmUgbm8gbG9uZ2VyIGluIHRoZSBSb29tVmlld1xuICAgICAgICAgICAgY2FzZSBcInZpZXdfd2VsY29tZV9wYWdlXCI6XG4gICAgICAgICAgICBjYXNlIEFjdGlvbi5WaWV3SG9tZVBhZ2U6XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgICAgIHJvb21JZDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgcm9vbUFsaWFzOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICB2aWFTZXJ2ZXJzOiBbXSxcbiAgICAgICAgICAgICAgICAgICAgd2FzQ29udGV4dFN3aXRjaDogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIHZpZXdpbmdDYWxsOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBkb0NsZWFyQ3VycmVudFZvaWNlQnJvYWRjYXN0UGxheWJhY2tJZlN0b3BwZWQodGhpcy5zdG9yZXMudm9pY2VCcm9hZGNhc3RQbGF5YmFja3NTdG9yZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiTWF0cml4QWN0aW9ucy5Sb29tU3RhdGUuZXZlbnRzXCI6XG4gICAgICAgICAgICAgICAgdGhpcy5vblJvb21TdGF0ZUV2ZW50cygocGF5bG9hZCBhcyBJUm9vbVN0YXRlRXZlbnRzQWN0aW9uUGF5bG9hZCkuZXZlbnQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBY3Rpb24uVmlld1Jvb21FcnJvcjpcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdSb29tRXJyb3IocGF5bG9hZCBhcyBWaWV3Um9vbUVycm9yUGF5bG9hZCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwid2lsbF9qb2luXCI6XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgICAgIGpvaW5pbmc6IHRydWUsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiY2FuY2VsX2pvaW5cIjpcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICAgICAgam9pbmluZzogZmFsc2UsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAvLyBqb2luX3Jvb206XG4gICAgICAgICAgICAvLyAgICAgIC0gb3B0czogb3B0aW9ucyBmb3Igam9pblJvb21cbiAgICAgICAgICAgIGNhc2UgQWN0aW9uLkpvaW5Sb29tOlxuICAgICAgICAgICAgICAgIHRoaXMuam9pblJvb20ocGF5bG9hZCBhcyBKb2luUm9vbVBheWxvYWQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBY3Rpb24uSm9pblJvb21FcnJvcjpcbiAgICAgICAgICAgICAgICB0aGlzLmpvaW5Sb29tRXJyb3IocGF5bG9hZCBhcyBKb2luUm9vbUVycm9yUGF5bG9hZCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEFjdGlvbi5Kb2luUm9vbVJlYWR5OiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUucm9vbUlkID09PSBwYXlsb2FkLnJvb21JZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgc2hvdWxkUGVlazogZmFsc2UgfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgYXdhaXRSb29tRG93blN5bmMoTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKSwgcGF5bG9hZC5yb29tSWQpLnRoZW4oKHJvb20pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbnVtTWVtYmVycyA9IHJvb20uZ2V0Sm9pbmVkTWVtYmVyQ291bnQoKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgcm9vbVNpemUgPVxuICAgICAgICAgICAgICAgICAgICAgICAgbnVtTWVtYmVycyA+IDEwMDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IFwiTW9yZVRoYW5BVGhvdXNhbmRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogbnVtTWVtYmVycyA+IDEwMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBcIk9uZUh1bmRyZWRBbmRPbmVUb0FUaG91c2FuZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IG51bU1lbWJlcnMgPiAxMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IFwiRWxldmVuVG9PbmVIdW5kcmVkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBudW1NZW1iZXJzID4gMlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gXCJUaHJlZVRvVGVuXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IG51bU1lbWJlcnMgPiAxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IFwiVHdvXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogXCJPbmVcIjtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0b3Jlcy5wb3N0aG9nQW5hbHl0aWNzLnRyYWNrRXZlbnQ8Sm9pbmVkUm9vbUV2ZW50Pih7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudE5hbWU6IFwiSm9pbmVkUm9vbVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlcjogcG