matrix-react-sdk
Version:
SDK for matrix.org using React
244 lines (228 loc) • 36.1 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MessagePreviewStore = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _matrix = require("matrix-js-sdk/src/matrix");
var _utils = require("matrix-js-sdk/src/utils");
var _AsyncStoreWithClient = require("../AsyncStoreWithClient");
var _dispatcher = _interopRequireDefault(require("../../dispatcher/dispatcher"));
var _MessageEventPreview = require("./previews/MessageEventPreview");
var _PollStartEventPreview = require("./previews/PollStartEventPreview");
var _LegacyCallInviteEventPreview = require("./previews/LegacyCallInviteEventPreview");
var _LegacyCallAnswerEventPreview = require("./previews/LegacyCallAnswerEventPreview");
var _LegacyCallHangupEvent = require("./previews/LegacyCallHangupEvent");
var _StickerEventPreview = require("./previews/StickerEventPreview");
var _ReactionEventPreview = require("./previews/ReactionEventPreview");
var _AsyncStore = require("../AsyncStore");
var _voiceBroadcast = require("../../voice-broadcast");
var _VoiceBroadcastPreview = require("./previews/VoiceBroadcastPreview");
var _shouldHideEvent = _interopRequireDefault(require("../../shouldHideEvent"));
var _MessagePreviewStore;
/*
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.
*/
// Emitted event for when a room's preview has changed. First argument will the room for which
// the change happened.
const ROOM_PREVIEW_CHANGED = "room_preview_changed";
const PREVIEWS = {
"m.room.message": {
isState: false,
previewer: new _MessageEventPreview.MessageEventPreview()
},
"m.call.invite": {
isState: false,
previewer: new _LegacyCallInviteEventPreview.LegacyCallInviteEventPreview()
},
"m.call.answer": {
isState: false,
previewer: new _LegacyCallAnswerEventPreview.LegacyCallAnswerEventPreview()
},
"m.call.hangup": {
isState: false,
previewer: new _LegacyCallHangupEvent.LegacyCallHangupEvent()
},
"m.sticker": {
isState: false,
previewer: new _StickerEventPreview.StickerEventPreview()
},
"m.reaction": {
isState: false,
previewer: new _ReactionEventPreview.ReactionEventPreview()
},
[_matrix.M_POLL_START.name]: {
isState: false,
previewer: new _PollStartEventPreview.PollStartEventPreview()
},
[_matrix.M_POLL_START.altName]: {
isState: false,
previewer: new _PollStartEventPreview.PollStartEventPreview()
},
[_voiceBroadcast.VoiceBroadcastInfoEventType]: {
isState: true,
previewer: new _VoiceBroadcastPreview.VoiceBroadcastPreview()
}
};
// The maximum number of events we're willing to look back on to get a preview.
const MAX_EVENTS_BACKWARDS = 50;
// type merging ftw
// eslint-disable-line @typescript-eslint/naming-convention
const TAG_ANY = "im.vector.any";
const isThreadReply = event => {
// a thread root event cannot be a thread reply
if (event.isThreadRoot) return false;
const thread = event.getThread();
// it cannot be a thread reply if there is no thread
if (!thread) return false;
const relation = event.getRelation();
if (!!relation && relation.rel_type === _matrix.RelationType.Annotation && relation.event_id === thread.rootEvent?.getId()) {
// annotations on the thread root are not a thread reply
return false;
}
return true;
};
const mkMessagePreview = (text, event) => {
return {
event,
text,
isThreadReply: isThreadReply(event)
};
};
class MessagePreviewStore extends _AsyncStoreWithClient.AsyncStoreWithClient {
/**
* @internal Public for test only
*/
static testInstance() {
return new MessagePreviewStore();
}
// null indicates the preview is empty / irrelevant
constructor() {
super(_dispatcher.default, {});
(0, _defineProperty2.default)(this, "previews", new Map());
(0, _defineProperty2.default)(this, "onLocalEchoUpdated", async (ev, room) => {
if (!this.previews.has(room.roomId)) return;
await this.generatePreview(room, TAG_ANY);
});
}
static get instance() {
return MessagePreviewStore.internalInstance;
}
static getPreviewChangedEventName(room) {
return `${ROOM_PREVIEW_CHANGED}:${room?.roomId}`;
}
/**
* Gets the pre-translated preview for a given room
* @param room The room to get the preview for.
* @param inTagId The tag ID in which the room resides
* @returns The preview, or null if none present.
*/
async getPreviewForRoom(room, inTagId) {
if (!room) return null; // invalid room, just return nothing
if (!this.previews.has(room.roomId)) await this.generatePreview(room, inTagId);
const previews = this.previews.get(room.roomId);
if (!previews) return null;
if (previews.has(inTagId)) {
return previews.get(inTagId);
}
return previews.get(TAG_ANY) ?? null;
}
generatePreviewForEvent(event) {
const previewDef = PREVIEWS[event.getType()];
return previewDef?.previewer.getTextFor(event, undefined, true) ?? "";
}
async generatePreview(room, tagId) {
const events = [...room.getLiveTimeline().getEvents(), ...room.getPendingEvents()];
// add last reply from each thread
room.getThreads().forEach(thread => {
const lastReply = thread.lastReply();
if (lastReply) events.push(lastReply);
});
// sort events from oldest to newest
events.sort((a, b) => {
return a.getTs() - b.getTs();
});
if (!events) return; // should only happen in tests
let map = this.previews.get(room.roomId);
if (!map) {
map = new Map();
this.previews.set(room.roomId, map);
}
// Set the tags so we know what to generate
if (!map.has(TAG_ANY)) map.set(TAG_ANY, null);
if (tagId && !map.has(tagId)) map.set(tagId, null);
let changed = false;
for (let i = events.length - 1; i >= 0; i--) {
if (i === events.length - MAX_EVENTS_BACKWARDS) {
// limit reached - clear the preview by breaking out of the loop
break;
}
const event = events[i];
await this.matrixClient?.decryptEventIfNeeded(event);
const shouldHide = (0, _shouldHideEvent.default)(event);
if (shouldHide) continue;
const previewDef = PREVIEWS[event.getType()];
if (!previewDef) continue;
if (previewDef.isState && (0, _utils.isNullOrUndefined)(event.getStateKey())) continue;
const anyPreviewText = previewDef.previewer.getTextFor(event);
if (!anyPreviewText) continue; // not previewable for some reason
changed = changed || anyPreviewText !== map.get(TAG_ANY)?.text;
map.set(TAG_ANY, mkMessagePreview(anyPreviewText, event));
const tagsToGenerate = Array.from(map.keys()).filter(t => t !== TAG_ANY); // we did the any tag above
for (const genTagId of tagsToGenerate) {
const realTagId = genTagId === TAG_ANY ? undefined : genTagId;
const preview = previewDef.previewer.getTextFor(event, realTagId);
if (preview === anyPreviewText) {
changed = changed || anyPreviewText !== map.get(genTagId)?.text;
map.delete(genTagId);
} else {
changed = changed || preview !== map.get(genTagId)?.text;
map.set(genTagId, preview ? mkMessagePreview(anyPreviewText, event) : null);
}
}
if (changed) {
// We've muted the underlying Map, so just emit that we've changed.
this.previews.set(room.roomId, map);
this.emit(_AsyncStore.UPDATE_EVENT, this);
this.emit(MessagePreviewStore.getPreviewChangedEventName(room), room);
}
return; // we're done
}
// At this point, we didn't generate a preview so clear it
this.previews.set(room.roomId, new Map());
this.emit(_AsyncStore.UPDATE_EVENT, this);
this.emit(MessagePreviewStore.getPreviewChangedEventName(room), room);
}
async onAction(payload) {
if (!this.matrixClient) return;
if (payload.action === "MatrixActions.Room.timeline" || payload.action === "MatrixActions.Event.decrypted") {
const event = payload.event; // TODO: Type out the dispatcher
const roomId = event.getRoomId();
const isHistoricalEvent = payload.hasOwnProperty("isLiveEvent") && !payload.isLiveEvent;
if (!roomId || !this.previews.has(roomId) || isHistoricalEvent) return;
const room = this.matrixClient.getRoom(roomId);
if (!room) return;
await this.generatePreview(room, TAG_ANY);
}
}
async onReady() {
if (!this.matrixClient) return;
this.matrixClient.on(_matrix.RoomEvent.LocalEchoUpdated, this.onLocalEchoUpdated);
}
async onNotReady() {
if (!this.matrixClient) return;
this.matrixClient.off(_matrix.RoomEvent.LocalEchoUpdated, this.onLocalEchoUpdated);
}
}
exports.MessagePreviewStore = MessagePreviewStore;
_MessagePreviewStore = MessagePreviewStore;
(0, _defineProperty2.default)(MessagePreviewStore, "internalInstance", (() => {
const instance = new _MessagePreviewStore();
instance.start();
return instance;
})());
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0cml4IiwicmVxdWlyZSIsIl91dGlscyIsIl9Bc3luY1N0b3JlV2l0aENsaWVudCIsIl9kaXNwYXRjaGVyIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9NZXNzYWdlRXZlbnRQcmV2aWV3IiwiX1BvbGxTdGFydEV2ZW50UHJldmlldyIsIl9MZWdhY3lDYWxsSW52aXRlRXZlbnRQcmV2aWV3IiwiX0xlZ2FjeUNhbGxBbnN3ZXJFdmVudFByZXZpZXciLCJfTGVnYWN5Q2FsbEhhbmd1cEV2ZW50IiwiX1N0aWNrZXJFdmVudFByZXZpZXciLCJfUmVhY3Rpb25FdmVudFByZXZpZXciLCJfQXN5bmNTdG9yZSIsIl92b2ljZUJyb2FkY2FzdCIsIl9Wb2ljZUJyb2FkY2FzdFByZXZpZXciLCJfc2hvdWxkSGlkZUV2ZW50IiwiX01lc3NhZ2VQcmV2aWV3U3RvcmUiLCJST09NX1BSRVZJRVdfQ0hBTkdFRCIsIlBSRVZJRVdTIiwiaXNTdGF0ZSIsInByZXZpZXdlciIsIk1lc3NhZ2VFdmVudFByZXZpZXciLCJMZWdhY3lDYWxsSW52aXRlRXZlbnRQcmV2aWV3IiwiTGVnYWN5Q2FsbEFuc3dlckV2ZW50UHJldmlldyIsIkxlZ2FjeUNhbGxIYW5ndXBFdmVudCIsIlN0aWNrZXJFdmVudFByZXZpZXciLCJSZWFjdGlvbkV2ZW50UHJldmlldyIsIk1fUE9MTF9TVEFSVCIsIm5hbWUiLCJQb2xsU3RhcnRFdmVudFByZXZpZXciLCJhbHROYW1lIiwiVm9pY2VCcm9hZGNhc3RJbmZvRXZlbnRUeXBlIiwiVm9pY2VCcm9hZGNhc3RQcmV2aWV3IiwiTUFYX0VWRU5UU19CQUNLV0FSRFMiLCJUQUdfQU5ZIiwiaXNUaHJlYWRSZXBseSIsImV2ZW50IiwiaXNUaHJlYWRSb290IiwidGhyZWFkIiwiZ2V0VGhyZWFkIiwicmVsYXRpb24iLCJnZXRSZWxhdGlvbiIsInJlbF90eXBlIiwiUmVsYXRpb25UeXBlIiwiQW5ub3RhdGlvbiIsImV2ZW50X2lkIiwicm9vdEV2ZW50IiwiZ2V0SWQiLCJta01lc3NhZ2VQcmV2aWV3IiwidGV4dCIsIk1lc3NhZ2VQcmV2aWV3U3RvcmUiLCJBc3luY1N0b3JlV2l0aENsaWVudCIsInRlc3RJbnN0YW5jZSIsImNvbnN0cnVjdG9yIiwiZGVmYXVsdERpc3BhdGNoZXIiLCJfZGVmaW5lUHJvcGVydHkyIiwiZGVmYXVsdCIsIk1hcCIsImV2Iiwicm9vbSIsInByZXZpZXdzIiwiaGFzIiwicm9vbUlkIiwiZ2VuZXJhdGVQcmV2aWV3IiwiaW5zdGFuY2UiLCJpbnRlcm5hbEluc3RhbmNlIiwiZ2V0UHJldmlld0NoYW5nZWRFdmVudE5hbWUiLCJnZXRQcmV2aWV3Rm9yUm9vbSIsImluVGFnSWQiLCJnZXQiLCJnZW5lcmF0ZVByZXZpZXdGb3JFdmVudCIsInByZXZpZXdEZWYiLCJnZXRUeXBlIiwiZ2V0VGV4dEZvciIsInVuZGVmaW5lZCIsInRhZ0lkIiwiZXZlbnRzIiwiZ2V0TGl2ZVRpbWVsaW5lIiwiZ2V0RXZlbnRzIiwiZ2V0UGVuZGluZ0V2ZW50cyIsImdldFRocmVhZHMiLCJmb3JFYWNoIiwibGFzdFJlcGx5IiwicHVzaCIsInNvcnQiLCJhIiwiYiIsImdldFRzIiwibWFwIiwic2V0IiwiY2hhbmdlZCIsImkiLCJsZW5ndGgiLCJtYXRyaXhDbGllbnQiLCJkZWNyeXB0RXZlbnRJZk5lZWRlZCIsInNob3VsZEhpZGUiLCJzaG91bGRIaWRlRXZlbnQiLCJpc051bGxPclVuZGVmaW5lZCIsImdldFN0YXRlS2V5IiwiYW55UHJldmlld1RleHQiLCJ0YWdzVG9HZW5lcmF0ZSIsIkFycmF5IiwiZnJvbSIsImtleXMiLCJmaWx0ZXIiLCJ0IiwiZ2VuVGFnSWQiLCJyZWFsVGFnSWQiLCJwcmV2aWV3IiwiZGVsZXRlIiwiZW1pdCIsIlVQREFURV9FVkVOVCIsIm9uQWN0aW9uIiwicGF5bG9hZCIsImFjdGlvbiIsImdldFJvb21JZCIsImlzSGlzdG9yaWNhbEV2ZW50IiwiaGFzT3duUHJvcGVydHkiLCJpc0xpdmVFdmVudCIsImdldFJvb20iLCJvblJlYWR5Iiwib24iLCJSb29tRXZlbnQiLCJMb2NhbEVjaG9VcGRhdGVkIiwib25Mb2NhbEVjaG9VcGRhdGVkIiwib25Ob3RSZWFkeSIsIm9mZiIsImV4cG9ydHMiLCJzdGFydCJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zdG9yZXMvcm9vbS1saXN0L01lc3NhZ2VQcmV2aWV3U3RvcmUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMjAgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IHsgUm9vbSwgUmVsYXRpb25UeXBlLCBNYXRyaXhFdmVudCwgVGhyZWFkLCBNX1BPTExfU1RBUlQsIFJvb21FdmVudCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tYXRyaXhcIjtcbmltcG9ydCB7IGlzTnVsbE9yVW5kZWZpbmVkIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL3V0aWxzXCI7XG5cbmltcG9ydCB7IEFjdGlvblBheWxvYWQgfSBmcm9tIFwiLi4vLi4vZGlzcGF0Y2hlci9wYXlsb2Fkc1wiO1xuaW1wb3J0IHsgQXN5bmNTdG9yZVdpdGhDbGllbnQgfSBmcm9tIFwiLi4vQXN5bmNTdG9yZVdpdGhDbGllbnRcIjtcbmltcG9ydCBkZWZhdWx0RGlzcGF0Y2hlciBmcm9tIFwiLi4vLi4vZGlzcGF0Y2hlci9kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBNZXNzYWdlRXZlbnRQcmV2aWV3IH0gZnJvbSBcIi4vcHJldmlld3MvTWVzc2FnZUV2ZW50UHJldmlld1wiO1xuaW1wb3J0IHsgUG9sbFN0YXJ0RXZlbnRQcmV2aWV3IH0gZnJvbSBcIi4vcHJldmlld3MvUG9sbFN0YXJ0RXZlbnRQcmV2aWV3XCI7XG5pbXBvcnQgeyBUYWdJRCB9IGZyb20gXCIuL21vZGVsc1wiO1xuaW1wb3J0IHsgTGVnYWN5Q2FsbEludml0ZUV2ZW50UHJldmlldyB9IGZyb20gXCIuL3ByZXZpZXdzL0xlZ2FjeUNhbGxJbnZpdGVFdmVudFByZXZpZXdcIjtcbmltcG9ydCB7IExlZ2FjeUNhbGxBbnN3ZXJFdmVudFByZXZpZXcgfSBmcm9tIFwiLi9wcmV2aWV3cy9MZWdhY3lDYWxsQW5zd2VyRXZlbnRQcmV2aWV3XCI7XG5pbXBvcnQgeyBMZWdhY3lDYWxsSGFuZ3VwRXZlbnQgfSBmcm9tIFwiLi9wcmV2aWV3cy9MZWdhY3lDYWxsSGFuZ3VwRXZlbnRcIjtcbmltcG9ydCB7IFN0aWNrZXJFdmVudFByZXZpZXcgfSBmcm9tIFwiLi9wcmV2aWV3cy9TdGlja2VyRXZlbnRQcmV2aWV3XCI7XG5pbXBvcnQgeyBSZWFjdGlvbkV2ZW50UHJldmlldyB9IGZyb20gXCIuL3ByZXZpZXdzL1JlYWN0aW9uRXZlbnRQcmV2aWV3XCI7XG5pbXBvcnQgeyBVUERBVEVfRVZFTlQgfSBmcm9tIFwiLi4vQXN5bmNTdG9yZVwiO1xuaW1wb3J0IHsgSVByZXZpZXcgfSBmcm9tIFwiLi9wcmV2aWV3cy9JUHJldmlld1wiO1xuaW1wb3J0IHsgVm9pY2VCcm9hZGNhc3RJbmZvRXZlbnRUeXBlIH0gZnJvbSBcIi4uLy4uL3ZvaWNlLWJyb2FkY2FzdFwiO1xuaW1wb3J0IHsgVm9pY2VCcm9hZGNhc3RQcmV2aWV3IH0gZnJvbSBcIi4vcHJldmlld3MvVm9pY2VCcm9hZGNhc3RQcmV2aWV3XCI7XG5pbXBvcnQgc2hvdWxkSGlkZUV2ZW50IGZyb20gXCIuLi8uLi9zaG91bGRIaWRlRXZlbnRcIjtcblxuLy8gRW1pdHRlZCBldmVudCBmb3Igd2hlbiBhIHJvb20ncyBwcmV2aWV3IGhhcyBjaGFuZ2VkLiBGaXJzdCBhcmd1bWVudCB3aWxsIHRoZSByb29tIGZvciB3aGljaFxuLy8gdGhlIGNoYW5nZSBoYXBwZW5lZC5cbmNvbnN0IFJPT01fUFJFVklFV19DSEFOR0VEID0gXCJyb29tX3ByZXZpZXdfY2hhbmdlZFwiO1xuXG5jb25zdCBQUkVWSUVXUzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICB7XG4gICAgICAgIGlzU3RhdGU6IGJvb2xlYW47XG4gICAgICAgIHByZXZpZXdlcjogSVByZXZpZXc7XG4gICAgfVxuPiA9IHtcbiAgICBcIm0ucm9vbS5tZXNzYWdlXCI6IHtcbiAgICAgICAgaXNTdGF0ZTogZmFsc2UsXG4gICAgICAgIHByZXZpZXdlcjogbmV3IE1lc3NhZ2VFdmVudFByZXZpZXcoKSxcbiAgICB9LFxuICAgIFwibS5jYWxsLmludml0ZVwiOiB7XG4gICAgICAgIGlzU3RhdGU6IGZhbHNlLFxuICAgICAgICBwcmV2aWV3ZXI6IG5ldyBMZWdhY3lDYWxsSW52aXRlRXZlbnRQcmV2aWV3KCksXG4gICAgfSxcbiAgICBcIm0uY2FsbC5hbnN3ZXJcIjoge1xuICAgICAgICBpc1N0YXRlOiBmYWxzZSxcbiAgICAgICAgcHJldmlld2VyOiBuZXcgTGVnYWN5Q2FsbEFuc3dlckV2ZW50UHJldmlldygpLFxuICAgIH0sXG4gICAgXCJtLmNhbGwuaGFuZ3VwXCI6IHtcbiAgICAgICAgaXNTdGF0ZTogZmFsc2UsXG4gICAgICAgIHByZXZpZXdlcjogbmV3IExlZ2FjeUNhbGxIYW5ndXBFdmVudCgpLFxuICAgIH0sXG4gICAgXCJtLnN0aWNrZXJcIjoge1xuICAgICAgICBpc1N0YXRlOiBmYWxzZSxcbiAgICAgICAgcHJldmlld2VyOiBuZXcgU3RpY2tlckV2ZW50UHJldmlldygpLFxuICAgIH0sXG4gICAgXCJtLnJlYWN0aW9uXCI6IHtcbiAgICAgICAgaXNTdGF0ZTogZmFsc2UsXG4gICAgICAgIHByZXZpZXdlcjogbmV3IFJlYWN0aW9uRXZlbnRQcmV2aWV3KCksXG4gICAgfSxcbiAgICBbTV9QT0xMX1NUQVJULm5hbWVdOiB7XG4gICAgICAgIGlzU3RhdGU6IGZhbHNlLFxuICAgICAgICBwcmV2aWV3ZXI6IG5ldyBQb2xsU3RhcnRFdmVudFByZXZpZXcoKSxcbiAgICB9LFxuICAgIFtNX1BPTExfU1RBUlQuYWx0TmFtZV06IHtcbiAgICAgICAgaXNTdGF0ZTogZmFsc2UsXG4gICAgICAgIHByZXZpZXdlcjogbmV3IFBvbGxTdGFydEV2ZW50UHJldmlldygpLFxuICAgIH0sXG4gICAgW1ZvaWNlQnJvYWRjYXN0SW5mb0V2ZW50VHlwZV06IHtcbiAgICAgICAgaXNTdGF0ZTogdHJ1ZSxcbiAgICAgICAgcHJldmlld2VyOiBuZXcgVm9pY2VCcm9hZGNhc3RQcmV2aWV3KCksXG4gICAgfSxcbn07XG5cbi8vIFRoZSBtYXhpbXVtIG51bWJlciBvZiBldmVudHMgd2UncmUgd2lsbGluZyB0byBsb29rIGJhY2sgb24gdG8gZ2V0IGEgcHJldmlldy5cbmNvbnN0IE1BWF9FVkVOVFNfQkFDS1dBUkRTID0gNTA7XG5cbi8vIHR5cGUgbWVyZ2luZyBmdHdcbnR5cGUgVEFHX0FOWSA9IFwiaW0udmVjdG9yLmFueVwiOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxuY29uc3QgVEFHX0FOWTogVEFHX0FOWSA9IFwiaW0udmVjdG9yLmFueVwiO1xuXG5pbnRlcmZhY2UgSVN0YXRlIHtcbiAgICAvLyBFbXB0eSBiZWNhdXNlIHdlIGRvbid0IGFjdHVhbGx5IHVzZSB0aGUgc3RhdGVcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNZXNzYWdlUHJldmlldyB7XG4gICAgZXZlbnQ6IE1hdHJpeEV2ZW50O1xuICAgIGlzVGhyZWFkUmVwbHk6IGJvb2xlYW47XG4gICAgdGV4dDogc3RyaW5nO1xufVxuXG5jb25zdCBpc1RocmVhZFJlcGx5ID0gKGV2ZW50OiBNYXRyaXhFdmVudCk6IGJvb2xlYW4gPT4ge1xuICAgIC8vIGEgdGhyZWFkIHJvb3QgZXZlbnQgY2Fubm90IGJlIGEgdGhyZWFkIHJlcGx5XG4gICAgaWYgKGV2ZW50LmlzVGhyZWFkUm9vdCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgY29uc3QgdGhyZWFkID0gZXZlbnQuZ2V0VGhyZWFkKCk7XG5cbiAgICAvLyBpdCBjYW5ub3QgYmUgYSB0aHJlYWQgcmVwbHkgaWYgdGhlcmUgaXMgbm8gdGhyZWFkXG4gICAgaWYgKCF0aHJlYWQpIHJldHVybiBmYWxzZTtcblxuICAgIGNvbnN0IHJlbGF0aW9uID0gZXZlbnQuZ2V0UmVsYXRpb24oKTtcblxuICAgIGlmIChcbiAgICAgICAgISFyZWxhdGlvbiAmJlxuICAgICAgICByZWxhdGlvbi5yZWxfdHlwZSA9PT0gUmVsYXRpb25UeXBlLkFubm90YXRpb24gJiZcbiAgICAgICAgcmVsYXRpb24uZXZlbnRfaWQgPT09IHRocmVhZC5yb290RXZlbnQ/LmdldElkKClcbiAgICApIHtcbiAgICAgICAgLy8gYW5ub3RhdGlvbnMgb24gdGhlIHRocmVhZCByb290IGFyZSBub3QgYSB0aHJlYWQgcmVwbHlcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xufTtcblxuY29uc3QgbWtNZXNzYWdlUHJldmlldyA9ICh0ZXh0OiBzdHJpbmcsIGV2ZW50OiBNYXRyaXhFdmVudCk6IE1lc3NhZ2VQcmV2aWV3ID0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgICBldmVudCxcbiAgICAgICAgdGV4dCxcbiAgICAgICAgaXNUaHJlYWRSZXBseTogaXNUaHJlYWRSZXBseShldmVudCksXG4gICAgfTtcbn07XG5cbmV4cG9ydCBjbGFzcyBNZXNzYWdlUHJldmlld1N0b3JlIGV4dGVuZHMgQXN5bmNTdG9yZVdpdGhDbGllbnQ8SVN0YXRlPiB7XG4gICAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgaW50ZXJuYWxJbnN0YW5jZSA9ICgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGluc3RhbmNlID0gbmV3IE1lc3NhZ2VQcmV2aWV3U3RvcmUoKTtcbiAgICAgICAgaW5zdGFuY2Uuc3RhcnQoKTtcbiAgICAgICAgcmV0dXJuIGluc3RhbmNlO1xuICAgIH0pKCk7XG5cbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWwgUHVibGljIGZvciB0ZXN0IG9ubHlcbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIHRlc3RJbnN0YW5jZSgpOiBNZXNzYWdlUHJldmlld1N0b3JlIHtcbiAgICAgICAgcmV0dXJuIG5ldyBNZXNzYWdlUHJldmlld1N0b3JlKCk7XG4gICAgfVxuXG4gICAgLy8gbnVsbCBpbmRpY2F0ZXMgdGhlIHByZXZpZXcgaXMgZW1wdHkgLyBpcnJlbGV2YW50XG4gICAgcHJpdmF0ZSBwcmV2aWV3cyA9IG5ldyBNYXA8c3RyaW5nLCBNYXA8VGFnSUQgfCBUQUdfQU5ZLCBNZXNzYWdlUHJldmlldyB8IG51bGw+PigpO1xuXG4gICAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoZGVmYXVsdERpc3BhdGNoZXIsIHt9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RhdGljIGdldCBpbnN0YW5jZSgpOiBNZXNzYWdlUHJldmlld1N0b3JlIHtcbiAgICAgICAgcmV0dXJuIE1lc3NhZ2VQcmV2aWV3U3RvcmUuaW50ZXJuYWxJbnN0YW5jZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RhdGljIGdldFByZXZpZXdDaGFuZ2VkRXZlbnROYW1lKHJvb206IFJvb20pOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gYCR7Uk9PTV9QUkVWSUVXX0NIQU5HRUR9OiR7cm9vbT8ucm9vbUlkfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcHJlLXRyYW5zbGF0ZWQgcHJldmlldyBmb3IgYSBnaXZlbiByb29tXG4gICAgICogQHBhcmFtIHJvb20gVGhlIHJvb20gdG8gZ2V0IHRoZSBwcmV2aWV3IGZvci5cbiAgICAgKiBAcGFyYW0gaW5UYWdJZCBUaGUgdGFnIElEIGluIHdoaWNoIHRoZSByb29tIHJlc2lkZXNcbiAgICAgKiBAcmV0dXJucyBUaGUgcHJldmlldywgb3IgbnVsbCBpZiBub25lIHByZXNlbnQuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGdldFByZXZpZXdGb3JSb29tKHJvb206IFJvb20sIGluVGFnSWQ6IFRhZ0lEKTogUHJvbWlzZTxNZXNzYWdlUHJldmlldyB8IG51bGw+IHtcbiAgICAgICAgaWYgKCFyb29tKSByZXR1cm4gbnVsbDsgLy8gaW52YWxpZCByb29tLCBqdXN0IHJldHVybiBub3RoaW5nXG5cbiAgICAgICAgaWYgKCF0aGlzLnByZXZpZXdzLmhhcyhyb29tLnJvb21JZCkpIGF3YWl0IHRoaXMuZ2VuZXJhdGVQcmV2aWV3KHJvb20sIGluVGFnSWQpO1xuXG4gICAgICAgIGNvbnN0IHByZXZpZXdzID0gdGhpcy5wcmV2aWV3cy5nZXQocm9vbS5yb29tSWQpO1xuICAgICAgICBpZiAoIXByZXZpZXdzKSByZXR1cm4gbnVsbDtcblxuICAgICAgICBpZiAocHJldmlld3MuaGFzKGluVGFnSWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJldmlld3MuZ2V0KGluVGFnSWQpITtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcHJldmlld3MuZ2V0KFRBR19BTlkpID8/IG51bGw7XG4gICAgfVxuXG4gICAgcHVibGljIGdlbmVyYXRlUHJldmlld0ZvckV2ZW50KGV2ZW50OiBNYXRyaXhFdmVudCk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHByZXZpZXdEZWYgPSBQUkVWSUVXU1tldmVudC5nZXRUeXBlKCldO1xuICAgICAgICByZXR1cm4gcHJldmlld0RlZj8ucHJldmlld2VyLmdldFRleHRGb3IoZXZlbnQsIHVuZGVmaW5lZCwgdHJ1ZSkgPz8gXCJcIjtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGdlbmVyYXRlUHJldmlldyhyb29tOiBSb29tLCB0YWdJZD86IFRhZ0lEKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGV2ZW50cyA9IFsuLi5yb29tLmdldExpdmVUaW1lbGluZSgpLmdldEV2ZW50cygpLCAuLi5yb29tLmdldFBlbmRpbmdFdmVudHMoKV07XG5cbiAgICAgICAgLy8gYWRkIGxhc3QgcmVwbHkgZnJvbSBlYWNoIHRocmVhZFxuICAgICAgICByb29tLmdldFRocmVhZHMoKS5mb3JFYWNoKCh0aHJlYWQ6IFRocmVhZCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgY29uc3QgbGFzdFJlcGx5ID0gdGhyZWFkLmxhc3RSZXBseSgpO1xuICAgICAgICAgICAgaWYgKGxhc3RSZXBseSkgZXZlbnRzLnB1c2gobGFzdFJlcGx5KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gc29ydCBldmVudHMgZnJvbSBvbGRlc3QgdG8gbmV3ZXN0XG4gICAgICAgIGV2ZW50cy5zb3J0KChhOiBNYXRyaXhFdmVudCwgYjogTWF0cml4RXZlbnQpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBhLmdldFRzKCkgLSBiLmdldFRzKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICghZXZlbnRzKSByZXR1cm47IC8vIHNob3VsZCBvbmx5IGhhcHBlbiBpbiB0ZXN0c1xuXG4gICAgICAgIGxldCBtYXAgPSB0aGlzLnByZXZpZXdzLmdldChyb29tLnJvb21JZCk7XG4gICAgICAgIGlmICghbWFwKSB7XG4gICAgICAgICAgICBtYXAgPSBuZXcgTWFwPFRhZ0lEIHwgVEFHX0FOWSwgTWVzc2FnZVByZXZpZXcgfCBudWxsPigpO1xuICAgICAgICAgICAgdGhpcy5wcmV2aWV3cy5zZXQocm9vbS5yb29tSWQsIG1hcCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZXQgdGhlIHRhZ3Mgc28gd2Uga25vdyB3aGF0IHRvIGdlbmVyYXRlXG4gICAgICAgIGlmICghbWFwLmhhcyhUQUdfQU5ZKSkgbWFwLnNldChUQUdfQU5ZLCBudWxsKTtcbiAgICAgICAgaWYgKHRhZ0lkICYmICFtYXAuaGFzKHRhZ0lkKSkgbWFwLnNldCh0YWdJZCwgbnVsbCk7XG5cbiAgICAgICAgbGV0IGNoYW5nZWQgPSBmYWxzZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IGV2ZW50cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgaWYgKGkgPT09IGV2ZW50cy5sZW5ndGggLSBNQVhfRVZFTlRTX0JBQ0tXQVJEUykge1xuICAgICAgICAgICAgICAgIC8vIGxpbWl0IHJlYWNoZWQgLSBjbGVhciB0aGUgcHJldmlldyBieSBicmVha2luZyBvdXQgb2YgdGhlIGxvb3BcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgZXZlbnQgPSBldmVudHNbaV07XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMubWF0cml4Q2xpZW50Py5kZWNyeXB0RXZlbnRJZk5lZWRlZChldmVudCk7XG4gICAgICAgICAgICBjb25zdCBzaG91bGRIaWRlID0gc2hvdWxkSGlkZUV2ZW50KGV2ZW50KTtcbiAgICAgICAgICAgIGlmIChzaG91bGRIaWRlKSBjb250aW51ZTtcbiAgICAgICAgICAgIGNvbnN0IHByZXZpZXdEZWYgPSBQUkVWSUVXU1tldmVudC5nZXRUeXBlKCldO1xuICAgICAgICAgICAgaWYgKCFwcmV2aWV3RGVmKSBjb250aW51ZTtcbiAgICAgICAgICAgIGlmIChwcmV2aWV3RGVmLmlzU3RhdGUgJiYgaXNOdWxsT3JVbmRlZmluZWQoZXZlbnQuZ2V0U3RhdGVLZXkoKSkpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICBjb25zdCBhbnlQcmV2aWV3VGV4dCA9IHByZXZpZXdEZWYucHJldmlld2VyLmdldFRleHRGb3IoZXZlbnQpO1xuICAgICAgICAgICAgaWYgKCFhbnlQcmV2aWV3VGV4dCkgY29udGludWU7IC8vIG5vdCBwcmV2aWV3YWJsZSBmb3Igc29tZSByZWFzb25cblxuICAgICAgICAgICAgY2hhbmdlZCA9IGNoYW5nZWQgfHwgYW55UHJldmlld1RleHQgIT09IG1hcC5nZXQoVEFHX0FOWSk/LnRleHQ7XG4gICAgICAgICAgICBtYXAuc2V0KFRBR19BTlksIG1rTWVzc2FnZVByZXZpZXcoYW55UHJldmlld1RleHQsIGV2ZW50KSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHRhZ3NUb0dlbmVyYXRlID0gQXJyYXkuZnJvbShtYXAua2V5cygpKS5maWx0ZXIoKHQpID0+IHQgIT09IFRBR19BTlkpOyAvLyB3ZSBkaWQgdGhlIGFueSB0YWcgYWJvdmVcbiAgICAgICAgICAgIGZvciAoY29uc3QgZ2VuVGFnSWQgb2YgdGFnc1RvR2VuZXJhdGUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWFsVGFnSWQgPSBnZW5UYWdJZCA9PT0gVEFHX0FOWSA/IHVuZGVmaW5lZCA6IGdlblRhZ0lkO1xuICAgICAgICAgICAgICAgIGNvbnN0IHByZXZpZXcgPSBwcmV2aWV3RGVmLnByZXZpZXdlci5nZXRUZXh0Rm9yKGV2ZW50LCByZWFsVGFnSWQpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHByZXZpZXcgPT09IGFueVByZXZpZXdUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5nZWQgPSBjaGFuZ2VkIHx8IGFueVByZXZpZXdUZXh0ICE9PSBtYXAuZ2V0KGdlblRhZ0lkKT8udGV4dDtcbiAgICAgICAgICAgICAgICAgICAgbWFwLmRlbGV0ZShnZW5UYWdJZCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY2hhbmdlZCA9IGNoYW5nZWQgfHwgcHJldmlldyAhPT0gbWFwLmdldChnZW5UYWdJZCk/LnRleHQ7XG4gICAgICAgICAgICAgICAgICAgIG1hcC5zZXQoZ2VuVGFnSWQsIHByZXZpZXcgPyBta01lc3NhZ2VQcmV2aWV3KGFueVByZXZpZXdUZXh0LCBldmVudCkgOiBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjaGFuZ2VkKSB7XG4gICAgICAgICAgICAgICAgLy8gV2UndmUgbXV0ZWQgdGhlIHVuZGVybHlpbmcgTWFwLCBzbyBqdXN0IGVtaXQgdGhhdCB3ZSd2ZSBjaGFuZ2VkLlxuICAgICAgICAgICAgICAgIHRoaXMucHJldmlld3Muc2V0KHJvb20ucm9vbUlkLCBtYXApO1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdChVUERBVEVfRVZFTlQsIHRoaXMpO1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdChNZXNzYWdlUHJldmlld1N0b3JlLmdldFByZXZpZXdDaGFuZ2VkRXZlbnROYW1lKHJvb20pLCByb29tKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjsgLy8gd2UncmUgZG9uZVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQXQgdGhpcyBwb2ludCwgd2UgZGlkbid0IGdlbmVyYXRlIGEgcHJldmlldyBzbyBjbGVhciBpdFxuICAgICAgICB0aGlzLnByZXZpZXdzLnNldChyb29tLnJvb21JZCwgbmV3IE1hcDxUYWdJRCB8IFRBR19BTlksIE1lc3NhZ2VQcmV2aWV3IHwgbnVsbD4oKSk7XG4gICAgICAgIHRoaXMuZW1pdChVUERBVEVfRVZFTlQsIHRoaXMpO1xuICAgICAgICB0aGlzLmVtaXQoTWVzc2FnZVByZXZpZXdTdG9yZS5nZXRQcmV2aWV3Q2hhbmdlZEV2ZW50TmFtZShyb29tKSwgcm9vbSk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFzeW5jIG9uQWN0aW9uKHBheWxvYWQ6IEFjdGlvblBheWxvYWQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKCF0aGlzLm1hdHJpeENsaWVudCkgcmV0dXJuO1xuXG4gICAgICAgIGlmIChwYXlsb2FkLmFjdGlvbiA9PT0gXCJNYXRyaXhBY3Rpb25zLlJvb20udGltZWxpbmVcIiB8fCBwYXlsb2FkLmFjdGlvbiA9PT0gXCJNYXRyaXhBY3Rpb25zLkV2ZW50LmRlY3J5cHRlZFwiKSB7XG4gICAgICAgICAgICBjb25zdCBldmVudCA9IHBheWxvYWQuZXZlbnQ7IC8vIFRPRE86IFR5cGUgb3V0IHRoZSBkaXNwYXRjaGVyXG4gICAgICAgICAgICBjb25zdCByb29tSWQgPSBldmVudC5nZXRSb29tSWQoKTtcbiAgICAgICAgICAgIGNvbnN0IGlzSGlzdG9yaWNhbEV2ZW50ID0gcGF5bG9hZC5oYXNPd25Qcm9wZXJ0eShcImlzTGl2ZUV2ZW50XCIpICYmICFwYXlsb2FkLmlzTGl2ZUV2ZW50O1xuXG4gICAgICAgICAgICBpZiAoIXJvb21JZCB8fCAhdGhpcy5wcmV2aWV3cy5oYXMocm9vbUlkKSB8fCBpc0hpc3RvcmljYWxFdmVudCkgcmV0dXJuO1xuXG4gICAgICAgICAgICBjb25zdCByb29tID0gdGhpcy5tYXRyaXhDbGllbnQuZ2V0Um9vbShyb29tSWQpO1xuXG4gICAgICAgICAgICBpZiAoIXJvb20pIHJldHVybjtcblxuICAgICAgICAgICAgYXdhaXQgdGhpcy5nZW5lcmF0ZVByZXZpZXcocm9vbSwgVEFHX0FOWSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYXN5bmMgb25SZWFkeSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKCF0aGlzLm1hdHJpeENsaWVudCkgcmV0dXJuO1xuICAgICAgICB0aGlzLm1hdHJpeENsaWVudC5vbihSb29tRXZlbnQuTG9jYWxFY2hvVXBkYXRlZCwgdGhpcy5vbkxvY2FsRWNob1VwZGF0ZWQpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhc3luYyBvbk5vdFJlYWR5KCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoIXRoaXMubWF0cml4Q2xpZW50KSByZXR1cm47XG4gICAgICAgIHRoaXMubWF0cml4Q2xpZW50Lm9mZihSb29tRXZlbnQuTG9jYWxFY2hvVXBkYXRlZCwgdGhpcy5vbkxvY2FsRWNob1VwZGF0ZWQpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBvbkxvY2FsRWNob1VwZGF0ZWQgPSBhc3luYyAoZXY6IE1hdHJpeEV2ZW50LCByb29tOiBSb29tKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIGlmICghdGhpcy5wcmV2aWV3cy5oYXMocm9vbS5yb29tSWQpKSByZXR1cm47XG4gICAgICAgIGF3YWl0IHRoaXMuZ2VuZXJhdGVQcmV2aWV3KHJvb20sIFRBR19BTlkpO1xuICAgIH07XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7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