UNPKG

matrix-react-sdk

Version:
174 lines (168 loc) 28.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; exports.isAppWidget = isAppWidget; exports.isVirtualWidget = isVirtualWidget; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _matrix = require("matrix-js-sdk/src/matrix"); var _logger = require("matrix-js-sdk/src/logger"); var _AsyncStoreWithClient = require("./AsyncStoreWithClient"); var _dispatcher = _interopRequireDefault(require("../dispatcher/dispatcher")); var _WidgetEchoStore = _interopRequireDefault(require("../stores/WidgetEchoStore")); var _ActiveWidgetStore = _interopRequireDefault(require("../stores/ActiveWidgetStore")); var _WidgetUtils = _interopRequireDefault(require("../utils/WidgetUtils")); var _AsyncStore = require("./AsyncStore"); var _WidgetStore; /* Copyright 2024 New Vector Ltd. Copyright 2020 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ function isAppWidget(widget) { return "roomId" in widget && typeof widget.roomId === "string"; } function isVirtualWidget(widget) { return widget.eventId === undefined; } // TODO consolidate WidgetEchoStore into this // TODO consolidate ActiveWidgetStore into this class WidgetStore extends _AsyncStoreWithClient.AsyncStoreWithClient { // Key is room ID constructor() { super(_dispatcher.default, {}); (0, _defineProperty2.default)(this, "widgetMap", new Map()); // Key is widget Unique ID (UID) (0, _defineProperty2.default)(this, "roomMap", new Map()); (0, _defineProperty2.default)(this, "onWidgetEchoStoreUpdate", roomId => { this.initRoom(roomId); this.loadRoomWidgets(this.matrixClient?.getRoom(roomId) ?? null); this.emit(_AsyncStore.UPDATE_EVENT, roomId); }); (0, _defineProperty2.default)(this, "onRoom", room => { this.initRoom(room.roomId); this.loadRoomWidgets(room); this.emit(_AsyncStore.UPDATE_EVENT, room.roomId); }); (0, _defineProperty2.default)(this, "onRoomStateEvents", ev => { if (ev.getType() !== "im.vector.modular.widgets") return; // TODO: Support m.widget too const roomId = ev.getRoomId(); this.initRoom(roomId); this.loadRoomWidgets(this.matrixClient?.getRoom(roomId) ?? null); this.emit(_AsyncStore.UPDATE_EVENT, roomId); }); _WidgetEchoStore.default.on("update", this.onWidgetEchoStoreUpdate); } static get instance() { return WidgetStore.internalInstance; } initRoom(roomId) { if (!this.roomMap.has(roomId)) { this.roomMap.set(roomId, { widgets: [] }); } } async onReady() { if (!this.matrixClient) return; this.matrixClient.on(_matrix.ClientEvent.Room, this.onRoom); this.matrixClient.on(_matrix.RoomStateEvent.Events, this.onRoomStateEvents); this.matrixClient.getRooms().forEach(room => { this.loadRoomWidgets(room); }); this.emit(_AsyncStore.UPDATE_EVENT, null); // emit for all rooms } async onNotReady() { if (this.matrixClient) { this.matrixClient.off(_matrix.ClientEvent.Room, this.onRoom); this.matrixClient.off(_matrix.RoomStateEvent.Events, this.onRoomStateEvents); } this.widgetMap = new Map(); this.roomMap = new Map(); await this.reset({}); } // We don't need this, but our contract says we do. async onAction(payload) { return; } generateApps(room) { return _WidgetEchoStore.default.getEchoedRoomWidgets(room.roomId, _WidgetUtils.default.getRoomWidgets(room)).map(ev => { return _WidgetUtils.default.makeAppConfig(ev.getStateKey(), ev.getContent(), ev.getSender(), ev.getRoomId(), ev.getId()); }); } loadRoomWidgets(room) { if (!room) return; const roomInfo = this.roomMap.get(room.roomId) || {}; roomInfo.widgets = []; // first clean out old widgets from the map which originate from this room // otherwise we are out of sync with the rest of the app with stale widget events during removal Array.from(this.widgetMap.values()).forEach(app => { if (app.roomId !== room.roomId) return; // skip - wrong room if (isVirtualWidget(app)) { // virtual widget - keep it roomInfo.widgets.push(app); } else { this.widgetMap.delete(_WidgetUtils.default.getWidgetUid(app)); } }); let edited = false; this.generateApps(room).forEach(app => { // Sanity check for https://github.com/vector-im/element-web/issues/15705 const existingApp = this.widgetMap.get(_WidgetUtils.default.getWidgetUid(app)); if (existingApp) { _logger.logger.warn(`Possible widget ID conflict for ${app.id} - wants to store in room ${app.roomId} ` + `but is currently stored as ${existingApp.roomId} - letting the want win`); } this.widgetMap.set(_WidgetUtils.default.getWidgetUid(app), app); roomInfo.widgets.push(app); edited = true; }); if (edited && !this.roomMap.has(room.roomId)) { this.roomMap.set(room.roomId, roomInfo); } // If a persistent widget is active, check to see if it's just been removed. // If it has, it needs to destroyed otherwise unmounting the node won't kill it const persistentWidgetId = _ActiveWidgetStore.default.instance.getPersistentWidgetId(); if (persistentWidgetId && _ActiveWidgetStore.default.instance.getPersistentRoomId() === room.roomId && !roomInfo.widgets.some(w => w.id === persistentWidgetId)) { _logger.logger.log(`Persistent widget ${persistentWidgetId} removed from room ${room.roomId}: destroying.`); _ActiveWidgetStore.default.instance.destroyPersistentWidget(persistentWidgetId, room.roomId); } this.emit(room.roomId); } get(widgetId, roomId) { return this.widgetMap.get(_WidgetUtils.default.calcWidgetUid(widgetId, roomId)); } getRoom(roomId, initIfNeeded = false) { if (initIfNeeded) this.initRoom(roomId); // internally handles "if needed" return this.roomMap.get(roomId); } getApps(roomId) { const roomInfo = this.getRoom(roomId); return roomInfo?.widgets || []; } addVirtualWidget(widget, roomId) { this.initRoom(roomId); const app = _WidgetUtils.default.makeAppConfig(widget.id, widget, widget.creatorUserId, roomId, undefined); this.widgetMap.set(_WidgetUtils.default.getWidgetUid(app), app); this.roomMap.get(roomId).widgets.push(app); return app; } removeVirtualWidget(widgetId, roomId) { this.widgetMap.delete(_WidgetUtils.default.calcWidgetUid(widgetId, roomId)); const roomApps = this.roomMap.get(roomId); if (roomApps) { roomApps.widgets = roomApps.widgets.filter(app => !(app.id === widgetId && app.roomId === roomId)); } } } exports.default = WidgetStore; _WidgetStore = WidgetStore; (0, _defineProperty2.default)(WidgetStore, "internalInstance", (() => { const instance = new _WidgetStore(); instance.start(); return instance; })()); window.mxWidgetStore = WidgetStore.instance; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0cml4IiwicmVxdWlyZSIsIl9sb2dnZXIiLCJfQXN5bmNTdG9yZVdpdGhDbGllbnQiLCJfZGlzcGF0Y2hlciIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfV2lkZ2V0RWNob1N0b3JlIiwiX0FjdGl2ZVdpZGdldFN0b3JlIiwiX1dpZGdldFV0aWxzIiwiX0FzeW5jU3RvcmUiLCJfV2lkZ2V0U3RvcmUiLCJpc0FwcFdpZGdldCIsIndpZGdldCIsInJvb21JZCIsImlzVmlydHVhbFdpZGdldCIsImV2ZW50SWQiLCJ1bmRlZmluZWQiLCJXaWRnZXRTdG9yZSIsIkFzeW5jU3RvcmVXaXRoQ2xpZW50IiwiY29uc3RydWN0b3IiLCJkZWZhdWx0RGlzcGF0Y2hlciIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJkZWZhdWx0IiwiTWFwIiwiaW5pdFJvb20iLCJsb2FkUm9vbVdpZGdldHMiLCJtYXRyaXhDbGllbnQiLCJnZXRSb29tIiwiZW1pdCIsIlVQREFURV9FVkVOVCIsInJvb20iLCJldiIsImdldFR5cGUiLCJnZXRSb29tSWQiLCJXaWRnZXRFY2hvU3RvcmUiLCJvbiIsIm9uV2lkZ2V0RWNob1N0b3JlVXBkYXRlIiwiaW5zdGFuY2UiLCJpbnRlcm5hbEluc3RhbmNlIiwicm9vbU1hcCIsImhhcyIsInNldCIsIndpZGdldHMiLCJvblJlYWR5IiwiQ2xpZW50RXZlbnQiLCJSb29tIiwib25Sb29tIiwiUm9vbVN0YXRlRXZlbnQiLCJFdmVudHMiLCJvblJvb21TdGF0ZUV2ZW50cyIsImdldFJvb21zIiwiZm9yRWFjaCIsIm9uTm90UmVhZHkiLCJvZmYiLCJ3aWRnZXRNYXAiLCJyZXNldCIsIm9uQWN0aW9uIiwicGF5bG9hZCIsImdlbmVyYXRlQXBwcyIsImdldEVjaG9lZFJvb21XaWRnZXRzIiwiV2lkZ2V0VXRpbHMiLCJnZXRSb29tV2lkZ2V0cyIsIm1hcCIsIm1ha2VBcHBDb25maWciLCJnZXRTdGF0ZUtleSIsImdldENvbnRlbnQiLCJnZXRTZW5kZXIiLCJnZXRJZCIsInJvb21JbmZvIiwiZ2V0IiwiQXJyYXkiLCJmcm9tIiwidmFsdWVzIiwiYXBwIiwicHVzaCIsImRlbGV0ZSIsImdldFdpZGdldFVpZCIsImVkaXRlZCIsImV4aXN0aW5nQXBwIiwibG9nZ2VyIiwid2FybiIsImlkIiwicGVyc2lzdGVudFdpZGdldElkIiwiQWN0aXZlV2lkZ2V0U3RvcmUiLCJnZXRQZXJzaXN0ZW50V2lkZ2V0SWQiLCJnZXRQZXJzaXN0ZW50Um9vbUlkIiwic29tZSIsInciLCJsb2ciLCJkZXN0cm95UGVyc2lzdGVudFdpZGdldCIsIndpZGdldElkIiwiY2FsY1dpZGdldFVpZCIsImluaXRJZk5lZWRlZCIsImdldEFwcHMiLCJhZGRWaXJ0dWFsV2lkZ2V0IiwiY3JlYXRvclVzZXJJZCIsInJlbW92ZVZpcnR1YWxXaWRnZXQiLCJyb29tQXBwcyIsImZpbHRlciIsImV4cG9ydHMiLCJzdGFydCIsIndpbmRvdyIsIm14V2lkZ2V0U3RvcmUiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RvcmVzL1dpZGdldFN0b3JlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDIwIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCB7IFJvb20sIFJvb21TdGF0ZUV2ZW50LCBNYXRyaXhFdmVudCwgQ2xpZW50RXZlbnQgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBJV2lkZ2V0IH0gZnJvbSBcIm1hdHJpeC13aWRnZXQtYXBpXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5cbmltcG9ydCB7IEFjdGlvblBheWxvYWQgfSBmcm9tIFwiLi4vZGlzcGF0Y2hlci9wYXlsb2Fkc1wiO1xuaW1wb3J0IHsgQXN5bmNTdG9yZVdpdGhDbGllbnQgfSBmcm9tIFwiLi9Bc3luY1N0b3JlV2l0aENsaWVudFwiO1xuaW1wb3J0IGRlZmF1bHREaXNwYXRjaGVyIGZyb20gXCIuLi9kaXNwYXRjaGVyL2Rpc3BhdGNoZXJcIjtcbmltcG9ydCBXaWRnZXRFY2hvU3RvcmUgZnJvbSBcIi4uL3N0b3Jlcy9XaWRnZXRFY2hvU3RvcmVcIjtcbmltcG9ydCBBY3RpdmVXaWRnZXRTdG9yZSBmcm9tIFwiLi4vc3RvcmVzL0FjdGl2ZVdpZGdldFN0b3JlXCI7XG5pbXBvcnQgV2lkZ2V0VXRpbHMgZnJvbSBcIi4uL3V0aWxzL1dpZGdldFV0aWxzXCI7XG5pbXBvcnQgeyBVUERBVEVfRVZFTlQgfSBmcm9tIFwiLi9Bc3luY1N0b3JlXCI7XG5cbmludGVyZmFjZSBJU3RhdGUge31cblxuZXhwb3J0IGludGVyZmFjZSBJQXBwIGV4dGVuZHMgSVdpZGdldCB7XG4gICAgXCJyb29tSWRcIjogc3RyaW5nO1xuICAgIFwiZXZlbnRJZFwiPzogc3RyaW5nOyAvLyBub3QgcHJlc2VudCBvbiB2aXJ0dWFsIHdpZGdldHNcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2FtZWxjYXNlXG4gICAgXCJhdmF0YXJfdXJsXCI/OiBzdHJpbmc7IC8vIE1TQzI3NjUgaHR0cHM6Ly9naXRodWIuY29tL21hdHJpeC1vcmcvbWF0cml4LWRvYy9wdWxsLzI3NjVcbiAgICAvLyBXaGV0aGVyIHRoZSB3aWRnZXQgd2FzIGNyZWF0ZWQgZnJvbSBgd2lkZ2V0X2J1aWxkX3VybGAgYW5kIHRodXMgaXMgYSBjYWxsIHdpZGdldCBvZiBzb21lIGtpbmRcbiAgICBcImlvLmVsZW1lbnQubWFuYWdlZF9oeWJyaWRcIj86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0FwcFdpZGdldCh3aWRnZXQ6IElXaWRnZXQgfCBJQXBwKTogd2lkZ2V0IGlzIElBcHAge1xuICAgIHJldHVybiBcInJvb21JZFwiIGluIHdpZGdldCAmJiB0eXBlb2Ygd2lkZ2V0LnJvb21JZCA9PT0gXCJzdHJpbmdcIjtcbn1cbmV4cG9ydCBmdW5jdGlvbiBpc1ZpcnR1YWxXaWRnZXQod2lkZ2V0OiBJQXBwKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHdpZGdldC5ldmVudElkID09PSB1bmRlZmluZWQ7XG59XG5cbmludGVyZmFjZSBJUm9vbVdpZGdldHMge1xuICAgIHdpZGdldHM6IElBcHBbXTtcbn1cblxuLy8gVE9ETyBjb25zb2xpZGF0ZSBXaWRnZXRFY2hvU3RvcmUgaW50byB0aGlzXG4vLyBUT0RPIGNvbnNvbGlkYXRlIEFjdGl2ZVdpZGdldFN0b3JlIGludG8gdGhpc1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2lkZ2V0U3RvcmUgZXh0ZW5kcyBBc3luY1N0b3JlV2l0aENsaWVudDxJU3RhdGU+IHtcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBpbnRlcm5hbEluc3RhbmNlID0gKCgpID0+IHtcbiAgICAgICAgY29uc3QgaW5zdGFuY2UgPSBuZXcgV2lkZ2V0U3RvcmUoKTtcbiAgICAgICAgaW5zdGFuY2Uuc3RhcnQoKTtcbiAgICAgICAgcmV0dXJuIGluc3RhbmNlO1xuICAgIH0pKCk7XG5cbiAgICBwcml2YXRlIHdpZGdldE1hcCA9IG5ldyBNYXA8c3RyaW5nLCBJQXBwPigpOyAvLyBLZXkgaXMgd2lkZ2V0IFVuaXF1ZSBJRCAoVUlEKVxuICAgIHByaXZhdGUgcm9vbU1hcCA9IG5ldyBNYXA8c3RyaW5nLCBJUm9vbVdpZGdldHM+KCk7IC8vIEtleSBpcyByb29tIElEXG5cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlcihkZWZhdWx0RGlzcGF0Y2hlciwge30pO1xuXG4gICAgICAgIFdpZGdldEVjaG9TdG9yZS5vbihcInVwZGF0ZVwiLCB0aGlzLm9uV2lkZ2V0RWNob1N0b3JlVXBkYXRlKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RhdGljIGdldCBpbnN0YW5jZSgpOiBXaWRnZXRTdG9yZSB7XG4gICAgICAgIHJldHVybiBXaWRnZXRTdG9yZS5pbnRlcm5hbEluc3RhbmNlO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW5pdFJvb20ocm9vbUlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnJvb21NYXAuaGFzKHJvb21JZCkpIHtcbiAgICAgICAgICAgIHRoaXMucm9vbU1hcC5zZXQocm9vbUlkLCB7XG4gICAgICAgICAgICAgICAgd2lkZ2V0czogW10sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBhc3luYyBvblJlYWR5KCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIGlmICghdGhpcy5tYXRyaXhDbGllbnQpIHJldHVybjtcbiAgICAgICAgdGhpcy5tYXRyaXhDbGllbnQub24oQ2xpZW50RXZlbnQuUm9vbSwgdGhpcy5vblJvb20pO1xuICAgICAgICB0aGlzLm1hdHJpeENsaWVudC5vbihSb29tU3RhdGVFdmVudC5FdmVudHMsIHRoaXMub25Sb29tU3RhdGVFdmVudHMpO1xuICAgICAgICB0aGlzLm1hdHJpeENsaWVudC5nZXRSb29tcygpLmZvckVhY2goKHJvb206IFJvb20pID0+IHtcbiAgICAgICAgICAgIHRoaXMubG9hZFJvb21XaWRnZXRzKHJvb20pO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5lbWl0KFVQREFURV9FVkVOVCwgbnVsbCk7IC8vIGVtaXQgZm9yIGFsbCByb29tc1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhc3luYyBvbk5vdFJlYWR5KCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIGlmICh0aGlzLm1hdHJpeENsaWVudCkge1xuICAgICAgICAgICAgdGhpcy5tYXRyaXhDbGllbnQub2ZmKENsaWVudEV2ZW50LlJvb20sIHRoaXMub25Sb29tKTtcbiAgICAgICAgICAgIHRoaXMubWF0cml4Q2xpZW50Lm9mZihSb29tU3RhdGVFdmVudC5FdmVudHMsIHRoaXMub25Sb29tU3RhdGVFdmVudHMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMud2lkZ2V0TWFwID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLnJvb21NYXAgPSBuZXcgTWFwKCk7XG4gICAgICAgIGF3YWl0IHRoaXMucmVzZXQoe30pO1xuICAgIH1cblxuICAgIC8vIFdlIGRvbid0IG5lZWQgdGhpcywgYnV0IG91ciBjb250cmFjdCBzYXlzIHdlIGRvLlxuICAgIHByb3RlY3RlZCBhc3luYyBvbkFjdGlvbihwYXlsb2FkOiBBY3Rpb25QYXlsb2FkKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uV2lkZ2V0RWNob1N0b3JlVXBkYXRlID0gKHJvb21JZDogc3RyaW5nKTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMuaW5pdFJvb20ocm9vbUlkKTtcbiAgICAgICAgdGhpcy5sb2FkUm9vbVdpZGdldHModGhpcy5tYXRyaXhDbGllbnQ/LmdldFJvb20ocm9vbUlkKSA/PyBudWxsKTtcbiAgICAgICAgdGhpcy5lbWl0KFVQREFURV9FVkVOVCwgcm9vbUlkKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBnZW5lcmF0ZUFwcHMocm9vbTogUm9vbSk6IElBcHBbXSB7XG4gICAgICAgIHJldHVybiBXaWRnZXRFY2hvU3RvcmUuZ2V0RWNob2VkUm9vbVdpZGdldHMocm9vbS5yb29tSWQsIFdpZGdldFV0aWxzLmdldFJvb21XaWRnZXRzKHJvb20pKS5tYXAoKGV2KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gV2lkZ2V0VXRpbHMubWFrZUFwcENvbmZpZyhcbiAgICAgICAgICAgICAgICBldi5nZXRTdGF0ZUtleSgpISxcbiAgICAgICAgICAgICAgICBldi5nZXRDb250ZW50KCksXG4gICAgICAgICAgICAgICAgZXYuZ2V0U2VuZGVyKCkhLFxuICAgICAgICAgICAgICAgIGV2LmdldFJvb21JZCgpLFxuICAgICAgICAgICAgICAgIGV2LmdldElkKCksXG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWRSb29tV2lkZ2V0cyhyb29tOiBSb29tIHwgbnVsbCk6IHZvaWQge1xuICAgICAgICBpZiAoIXJvb20pIHJldHVybjtcbiAgICAgICAgY29uc3Qgcm9vbUluZm8gPSB0aGlzLnJvb21NYXAuZ2V0KHJvb20ucm9vbUlkKSB8fCA8SVJvb21XaWRnZXRzPnt9O1xuICAgICAgICByb29tSW5mby53aWRnZXRzID0gW107XG5cbiAgICAgICAgLy8gZmlyc3QgY2xlYW4gb3V0IG9sZCB3aWRnZXRzIGZyb20gdGhlIG1hcCB3aGljaCBvcmlnaW5hdGUgZnJvbSB0aGlzIHJvb21cbiAgICAgICAgLy8gb3RoZXJ3aXNlIHdlIGFyZSBvdXQgb2Ygc3luYyB3aXRoIHRoZSByZXN0IG9mIHRoZSBhcHAgd2l0aCBzdGFsZSB3aWRnZXQgZXZlbnRzIGR1cmluZyByZW1vdmFsXG4gICAgICAgIEFycmF5LmZyb20odGhpcy53aWRnZXRNYXAudmFsdWVzKCkpLmZvckVhY2goKGFwcCkgPT4ge1xuICAgICAgICAgICAgaWYgKGFwcC5yb29tSWQgIT09IHJvb20ucm9vbUlkKSByZXR1cm47IC8vIHNraXAgLSB3cm9uZyByb29tXG4gICAgICAgICAgICBpZiAoaXNWaXJ0dWFsV2lkZ2V0KGFwcCkpIHtcbiAgICAgICAgICAgICAgICAvLyB2aXJ0dWFsIHdpZGdldCAtIGtlZXAgaXRcbiAgICAgICAgICAgICAgICByb29tSW5mby53aWRnZXRzLnB1c2goYXBwKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy53aWRnZXRNYXAuZGVsZXRlKFdpZGdldFV0aWxzLmdldFdpZGdldFVpZChhcHApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgbGV0IGVkaXRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmdlbmVyYXRlQXBwcyhyb29tKS5mb3JFYWNoKChhcHApID0+IHtcbiAgICAgICAgICAgIC8vIFNhbml0eSBjaGVjayBmb3IgaHR0cHM6Ly9naXRodWIuY29tL3ZlY3Rvci1pbS9lbGVtZW50LXdlYi9pc3N1ZXMvMTU3MDVcbiAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nQXBwID0gdGhpcy53aWRnZXRNYXAuZ2V0KFdpZGdldFV0aWxzLmdldFdpZGdldFVpZChhcHApKTtcbiAgICAgICAgICAgIGlmIChleGlzdGluZ0FwcCkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICAgICAgICAgICAgICBgUG9zc2libGUgd2lkZ2V0IElEIGNvbmZsaWN0IGZvciAke2FwcC5pZH0gLSB3YW50cyB0byBzdG9yZSBpbiByb29tICR7YXBwLnJvb21JZH0gYCArXG4gICAgICAgICAgICAgICAgICAgICAgICBgYnV0IGlzIGN1cnJlbnRseSBzdG9yZWQgYXMgJHtleGlzdGluZ0FwcC5yb29tSWR9IC0gbGV0dGluZyB0aGUgd2FudCB3aW5gLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMud2lkZ2V0TWFwLnNldChXaWRnZXRVdGlscy5nZXRXaWRnZXRVaWQoYXBwKSwgYXBwKTtcbiAgICAgICAgICAgIHJvb21JbmZvLndpZGdldHMucHVzaChhcHApO1xuICAgICAgICAgICAgZWRpdGVkID0gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChlZGl0ZWQgJiYgIXRoaXMucm9vbU1hcC5oYXMocm9vbS5yb29tSWQpKSB7XG4gICAgICAgICAgICB0aGlzLnJvb21NYXAuc2V0KHJvb20ucm9vbUlkLCByb29tSW5mbyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiBhIHBlcnNpc3RlbnQgd2lkZ2V0IGlzIGFjdGl2ZSwgY2hlY2sgdG8gc2VlIGlmIGl0J3MganVzdCBiZWVuIHJlbW92ZWQuXG4gICAgICAgIC8vIElmIGl0IGhhcywgaXQgbmVlZHMgdG8gZGVzdHJveWVkIG90aGVyd2lzZSB1bm1vdW50aW5nIHRoZSBub2RlIHdvbid0IGtpbGwgaXRcbiAgICAgICAgY29uc3QgcGVyc2lzdGVudFdpZGdldElkID0gQWN0aXZlV2lkZ2V0U3RvcmUuaW5zdGFuY2UuZ2V0UGVyc2lzdGVudFdpZGdldElkKCk7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIHBlcnNpc3RlbnRXaWRnZXRJZCAmJlxuICAgICAgICAgICAgQWN0aXZlV2lkZ2V0U3RvcmUuaW5zdGFuY2UuZ2V0UGVyc2lzdGVudFJvb21JZCgpID09PSByb29tLnJvb21JZCAmJlxuICAgICAgICAgICAgIXJvb21JbmZvLndpZGdldHMuc29tZSgodykgPT4gdy5pZCA9PT0gcGVyc2lzdGVudFdpZGdldElkKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGxvZ2dlci5sb2coYFBlcnNpc3RlbnQgd2lkZ2V0ICR7cGVyc2lzdGVudFdpZGdldElkfSByZW1vdmVkIGZyb20gcm9vbSAke3Jvb20ucm9vbUlkfTogZGVzdHJveWluZy5gKTtcbiAgICAgICAgICAgIEFjdGl2ZVdpZGdldFN0b3JlLmluc3RhbmNlLmRlc3Ryb3lQZXJzaXN0ZW50V2lkZ2V0KHBlcnNpc3RlbnRXaWRnZXRJZCwgcm9vbS5yb29tSWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5lbWl0KHJvb20ucm9vbUlkKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uUm9vbSA9IChyb29tOiBSb29tKTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMuaW5pdFJvb20ocm9vbS5yb29tSWQpO1xuICAgICAgICB0aGlzLmxvYWRSb29tV2lkZ2V0cyhyb29tKTtcbiAgICAgICAgdGhpcy5lbWl0KFVQREFURV9FVkVOVCwgcm9vbS5yb29tSWQpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uUm9vbVN0YXRlRXZlbnRzID0gKGV2OiBNYXRyaXhFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoZXYuZ2V0VHlwZSgpICE9PSBcImltLnZlY3Rvci5tb2R1bGFyLndpZGdldHNcIikgcmV0dXJuOyAvLyBUT0RPOiBTdXBwb3J0IG0ud2lkZ2V0IHRvb1xuICAgICAgICBjb25zdCByb29tSWQgPSBldi5nZXRSb29tSWQoKSE7XG4gICAgICAgIHRoaXMuaW5pdFJvb20ocm9vbUlkKTtcbiAgICAgICAgdGhpcy5sb2FkUm9vbVdpZGdldHModGhpcy5tYXRyaXhDbGllbnQ/LmdldFJvb20ocm9vbUlkKSA/PyBudWxsKTtcbiAgICAgICAgdGhpcy5lbWl0KFVQREFURV9FVkVOVCwgcm9vbUlkKTtcbiAgICB9O1xuXG4gICAgcHVibGljIGdldCh3aWRnZXRJZDogc3RyaW5nLCByb29tSWQ6IHN0cmluZyB8IHVuZGVmaW5lZCk6IElBcHAgfCB1bmRlZmluZWQge1xuICAgICAgICByZXR1cm4gdGhpcy53aWRnZXRNYXAuZ2V0KFdpZGdldFV0aWxzLmNhbGNXaWRnZXRVaWQod2lkZ2V0SWQsIHJvb21JZCkpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRSb29tKHJvb21JZDogc3RyaW5nLCBpbml0SWZOZWVkZWQgPSBmYWxzZSk6IElSb29tV2lkZ2V0cyB7XG4gICAgICAgIGlmIChpbml0SWZOZWVkZWQpIHRoaXMuaW5pdFJvb20ocm9vbUlkKTsgLy8gaW50ZXJuYWxseSBoYW5kbGVzIFwiaWYgbmVlZGVkXCJcbiAgICAgICAgcmV0dXJuIHRoaXMucm9vbU1hcC5nZXQocm9vbUlkKSE7XG4gICAgfVxuXG4gICAgcHVibGljIGdldEFwcHMocm9vbUlkOiBzdHJpbmcpOiBJQXBwW10ge1xuICAgICAgICBjb25zdCByb29tSW5mbyA9IHRoaXMuZ2V0Um9vbShyb29tSWQpO1xuICAgICAgICByZXR1cm4gcm9vbUluZm8/LndpZGdldHMgfHwgW107XG4gICAgfVxuXG4gICAgcHVibGljIGFkZFZpcnR1YWxXaWRnZXQod2lkZ2V0OiBJV2lkZ2V0LCByb29tSWQ6IHN0cmluZyk6IElBcHAge1xuICAgICAgICB0aGlzLmluaXRSb29tKHJvb21JZCk7XG4gICAgICAgIGNvbnN0IGFwcCA9IFdpZGdldFV0aWxzLm1ha2VBcHBDb25maWcod2lkZ2V0LmlkLCB3aWRnZXQsIHdpZGdldC5jcmVhdG9yVXNlcklkLCByb29tSWQsIHVuZGVmaW5lZCk7XG4gICAgICAgIHRoaXMud2lkZ2V0TWFwLnNldChXaWRnZXRVdGlscy5nZXRXaWRnZXRVaWQoYXBwKSwgYXBwKTtcbiAgICAgICAgdGhpcy5yb29tTWFwLmdldChyb29tSWQpIS53aWRnZXRzLnB1c2goYXBwKTtcbiAgICAgICAgcmV0dXJuIGFwcDtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVtb3ZlVmlydHVhbFdpZGdldCh3aWRnZXRJZDogc3RyaW5nLCByb29tSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLndpZGdldE1hcC5kZWxldGUoV2lkZ2V0VXRpbHMuY2FsY1dpZGdldFVpZCh3aWRnZXRJZCwgcm9vbUlkKSk7XG4gICAgICAgIGNvbnN0IHJvb21BcHBzID0gdGhpcy5yb29tTWFwLmdldChyb29tSWQpO1xuICAgICAgICBpZiAocm9vbUFwcHMpIHtcbiAgICAgICAgICAgIHJvb21BcHBzLndpZGdldHMgPSByb29tQXBwcy53aWRnZXRzLmZpbHRlcigoYXBwKSA9PiAhKGFwcC5pZCA9PT0gd2lkZ2V0SWQgJiYgYXBwLnJvb21JZCA9PT0gcm9vbUlkKSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbndpbmRvdy5teFdpZGdldFN0b3JlID0gV2lkZ2V0U3RvcmUuaW5zdGFuY2U7XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFRQSxJQUFBQSxPQUFBLEdBQUFDLE9BQUE7QUFFQSxJQUFBQyxPQUFBLEdBQUFELE9BQUE7QUFHQSxJQUFBRSxxQkFBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsV0FBQSxHQUFBQyxzQkFBQSxDQUFBSixPQUFBO0FBQ0EsSUFBQUssZ0JBQUEsR0FBQUQsc0JBQUEsQ0FBQUosT0FBQTtBQUNBLElBQUFNLGtCQUFBLEdBQUFGLHNCQUFBLENBQUFKLE9BQUE7QUFDQSxJQUFB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