UNPKG

matrix-react-sdk

Version:
244 lines (228 loc) 36.1 kB
"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+IHtcbiAgICAgICAgaWYgKCF0aGlzLm1hdHJpeENsaWVudCkgcmV0dXJuO1xuICAgICAgICB0aGlzLm1hdHJpeENsaWVudC5vbihSb29tRXZlbnQuTG9jYWxFY2hvVXBkYXRlZCwgdGhpcy5vbkxvY2FsRWNob1VwZGF0ZWQpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhc3luYyBvbk5vdFJlYWR5KCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoIXRoaXMubWF0cml4Q2xpZW50KSByZXR1cm47XG4gICAgICAgIHRoaXMubWF0cml4Q2xpZW50Lm9mZihSb29tRXZlbnQuTG9jYWxFY2hvVXBkYXRlZCwgdGhpcy5vbkxvY2FsRWNob1VwZGF0ZWQpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBvbkxvY2FsRWNob1VwZGF0ZWQgPSBhc3luYyAoZXY6IE1hdHJpeEV2ZW50LCByb29tOiBSb29tKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIGlmICghdGhpcy5wcmV2aWV3cy5oYXMocm9vbS5yb29tSWQpKSByZXR1cm47XG4gICAgICAgIGF3YWl0IHRoaXMuZ2VuZXJhdGVQcmV2aWV3KHJvb20sIFRBR19BTlkpO1xuICAgIH07XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBUUEsSUFBQUEsT0FBQSxHQUFBQyxPQUFBO0FBQ0EsSUFBQUMsTUFBQSxHQUFBRCxPQUFBO0FBR0EsSUFBQUUscUJBQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLFdBQUEsR0FBQUMsc0JBQUEsQ0FBQUosT0FBQTtBQUNBLElBQUFLLG9CQUFBLEdBQUFMLE9BQUE7QUFDQSxJQUFBTSxzQkFBQSxHQUFBTixPQUFBO0FBRUEsSUFBQU8sNkJBQUEsR0FBQVAsT0FBQTtBQUNBLElBQUFRLDZCQUFBLEdBQUFSLE9BQUE7QUFDQSxJQUFBUyxzQkFBQSxHQUFBVCxPQUFBO0FBQ0EsSUFBQVUsb0JBQUEsR0FBQVYsT0FBQTtBQUNBLElBQUFXLHFCQUFBLEdBQUFYLE9BQUE7QUFDQSxJQUFBWSxXQUFBLEdBQUFaLE9BQUE7QUFFQSxJQUFBYSxlQUFBLEdBQUFiLE9BQUE7QUFDQSxJQUFBYyxzQkFBQSxHQUFBZCxPQUFBO0FBQ0EsSUFBQWUsZ0JBQUEsR0FBQVgsc0JBQUEsQ0FBQUosT0FBQTtBQUFvRCxJQUFBZ0Isb0JBQUE7QUExQnBEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBc0JBO0FBQ0E7QUFDQSxNQUFNQyxvQkFBb0IsR0FBRyxzQkFBc0I7QUFFbkQsTUFBTUMsUUFNTCxHQUFHO0VBQ0EsZ0JBQWdCLEVBQUU7SUFDZEMsT0FBTyxFQUFFLEtBQUs7SUFDZEMsU0FBUyxFQUFFLElBQUlDLHdDQUFtQixDQUFDO0VBQ3ZDLENBQUM7RUFDRCxlQUFlLEVBQUU7SUFDYkYsT0FBTyxFQUFFLEtBQUs7SUFDZEMsU0FBUyxFQUFFLElBQUlFLDBEQUE0QixDQUFDO0VBQ2hELENBQUM7RUFDRCxlQUFlLEVBQUU7SUFDYkgsT0FBTyxFQUFFLEtBQUs7SUFDZEMsU0FBUyxFQUFFLElBQUlHLDBEQUE0QixDQUFDO0VBQ2hELENBQUM7RUFDRCxlQUFlLEVBQUU7SUFDYkosT0FBTyxFQUFFLEtBQUs7SUFDZEMsU0FBUyxFQUFFLElBQUlJLDRDQUFxQixDQUFDO0VBQ3pDLENBQUM7RUFDRCxXQUFXLEVBQUU7SUFDVEwsT0FBTyxFQUFFLEtBQUs7SUFDZEMsU0FBUyxFQUFFLElBQUlLLHdDQUFtQixDQUFDO0VBQ3ZDLENBQUM7RUFDRCxZQUFZLEVBQUU7SUFDVk4sT0FBTyxFQUFFLEtBQUs7SUFDZEMsU0FBUyxFQUFFLElBQUlNLDBDQUFvQixDQUFDO0VBQ3hDLENBQUM7RUFDRCxDQUFDQyxvQkFBWSxDQUFDQyxJQUFJLEdBQUc7SUFDakJULE9BQU8sRUFBRSxLQUFLO0lBQ2RDLFNBQVMsRUFBRSxJQUFJUyw0Q0FBcUIsQ0FBQztFQUN6QyxDQUFDO0VBQ0QsQ0FBQ0Ysb0JBQVksQ0FBQ0csT0FBTyxHQUFHO0lBQ3BCWCxPQUFPLEVBQUUsS0FBSztJQUNkQyxTQUFTLEVBQUUsSUFBSVMsNENBQXFCLENBQUM7RUFDekMsQ0FBQztFQUNELENBQUNFLDJDQUEyQixHQUFHO0lBQzNCWixPQUFPLEVBQUUsSUFBSTtJQUNiQyxTQUFTLEVBQUUsSUFBSVksNENBQXFCLENBQUM7RUFDekM7QUFDSixDQUFDOztBQUVEO0FBQ0EsTUFBTUMsb0JBQW9CLEdBQUcsRUFBRTs7QUFFL0I7O0FBQ2dDO0FBQ2hDLE1BQU1DLE9BQWdCLEdBQUcsZUFBZTtBQVl4QyxNQUFNQyxhQUFhLEdBQUlDLEtBQWtCLElBQWM7RUFDbkQ7RUFDQSxJQUFJQSxLQUFLLENBQUNDLFlBQVksRUFBRSxPQUFPLEtBQUs7RUFFcEMsTUFBTUMsTUFBTSxHQUFHRixLQUFLLENBQUNHLFNBQVMsQ0FBQyxDQUFDOztFQUVoQztFQUNBLElBQUksQ0FBQ0QsTUFBTSxFQUFFLE9BQU8sS0FBSztFQUV6QixNQUFNRSxRQUFRLEdBQUdKLEtBQUssQ0FBQ0ssV0FBVyxDQUFDLENBQUM7RUFFcEMsSUFDSSxDQUFDLENBQUNELFFBQVEsSUFDVkEsUUFBUSxDQUFDRSxRQUFRLEtBQUtDLG9CQUFZLENBQUNDLFVBQVUsSUFDN0NKLFFBQVEsQ0FBQ0ssUUFBUSxLQUFLUCxNQUFNLENBQUNRLFNBQVMsRUFBRUMsS0FBSyxDQUFDLENBQUMsRUFDakQ7SUFDRTtJQUNBLE9BQU8sS0FBSztFQUNoQjtFQUVBLE9BQU8sSUFBSTtBQUNmLENBQUM7QUFFRCxNQUFNQyxnQkFBZ0IsR0FBR0EsQ0FBQ0MsSUFBWSxFQUFFYixLQUFrQixLQUFxQjtFQUMzRSxPQUFPO0lBQ0hBLEtBQUs7SUFDTGEsSUFBSTtJQUNKZCxhQUFhLEVBQUVBLGFBQWEsQ0FBQ0MsS0FBSztFQUN0QyxDQUFDO0FBQ0wsQ0FBQztBQUVNLE1BQU1jLG1CQUFtQixTQUFTQywwQ0FBb0IsQ0FBUztFQU9sRTtBQUNKO0FBQ0E7RUFDSSxPQUFjQyxZQUFZQSxDQUFBLEVBQXdCO0lBQzlDLE9BQU8sSUFBSUYsbUJBQW1CLENBQUMsQ0FBQztFQUNwQzs7RUFFQTs7RUFHUUcsV0FBV0EsQ0FBQSxFQUFHO0lBQ2xCLEtBQUssQ0FBQ0MsbUJBQWlCLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFBQyxJQUFBQyxnQkFBQSxDQUFBQyxPQUFBLG9CQUhkLElBQUlDLEdBQUcsQ0FBc0QsQ0FBQztJQUFBLElBQUFGLGdCQUFBLENBQUFDLE9BQUEsOEJBZ0psRCxPQUFPRSxFQUFlLEVBQUVDLElBQVUsS0FBb0I7TUFDakYsSUFBSSxDQUFDLElBQUksQ0FBQ0MsUUFBUSxDQUFDQyxHQUFHLENBQUNGLElBQUksQ0FBQ0csTUFBTSxDQUFDLEVBQUU7TUFDckMsTUFBTSxJQUFJLENBQUNDLGVBQWUsQ0FBQ0osSUFBSSxFQUFFekIsT0FBTyxDQUFDO0lBQzdDLENBQUM7RUEvSUQ7RUFFQSxXQUFrQjhCLFFBQVFBLENBQUEsRUFBd0I7SUFDOUMsT0FBT2QsbUJBQW1CLENBQUNlLGdCQUFnQjtFQUMvQztFQUVBLE9BQWNDLDBCQUEwQkEsQ0FBQ1AsSUFBVSxFQUFVO0lBQ3pELE9BQU8sR0FBRzFDLG9CQUFvQixJQUFJMEMsSUFBSSxFQUFFRyxNQUFNLEVBQUU7RUFDcEQ7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksTUFBYUssaUJBQWlCQSxDQUFDUixJQUFVLEVBQUVTLE9BQWMsRUFBa0M7SUFDdkYsSUFBSSxDQUFDVCxJQUFJLEVBQUUsT0FBTyxJQUFJLENBQUMsQ0FBQzs7SUFFeEIsSUFBSSxDQUFDLElBQUksQ0FBQ0MsUUFBUSxDQUFDQyxHQUFHLENBQUNGLElBQUksQ0FBQ0csTUFBTSxDQUFDLEVBQUUsTUFBTSxJQUFJLENBQUNDLGVBQWUsQ0FBQ0osSUFBSSxFQUFFUyxPQUFPLENBQUM7SUFFOUUsTUFBTVIsUUFBUSxHQUFHLElBQUksQ0FBQ0EsUUFBUSxDQUFDUyxHQUFHLENBQUNWLElBQUksQ0FBQ0csTUFBTSxDQUFDO0lBQy9DLElBQUksQ0FBQ0YsUUFBUSxFQUFFLE9BQU8sSUFBSTtJQUUxQixJQUFJQSxRQUFRLENBQUNDLEdBQUcsQ0FBQ08sT0FBTyxDQUFDLEVBQUU7TUFDdkIsT0FBT1IsUUFBUSxDQUFDUyxHQUFHLENBQUNELE9BQU8sQ0FBQztJQUNoQztJQUNBLE9BQU9SLFFBQVEsQ0FBQ1MsR0FBRyxDQUFDbkMsT0FBTyxDQUFDLElBQUksSUFBSTtFQUN4QztFQUVPb0MsdUJBQXVCQSxDQUFDbEMsS0FBa0IsRUFBVTtJQUN2RCxNQUFNbUMsVUFBVSxHQUFHckQsUUFBUSxDQUFDa0IsS0FBSyxDQUFDb0MsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUM1QyxPQUFPRCxVQUFVLEVBQUVuRCxTQUFTLENBQUNxRCxVQUFVLENBQUNyQyxLQUFLLEVBQUVzQyxTQUFTLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRTtFQUN6RTtFQUVBLE1BQWNYLGVBQWVBLENBQUNKLElBQVUsRUFBRWdCLEtBQWEsRUFBaUI7SUFDcEUsTUFBTUMsTUFBTSxHQUFHLENBQUMsR0FBR2pCLElBQUksQ0FBQ2tCLGVBQWUsQ0FBQyxDQUFDLENBQUNDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsR0FBR25CLElBQUksQ0FBQ29CLGdCQUFnQixDQUFDLENBQUMsQ0FBQzs7SUFFbEY7SUFDQXBCLElBQUksQ0FBQ3FCLFVBQVUsQ0FBQyxDQUFDLENBQUNDLE9BQU8sQ0FBRTNDLE1BQWMsSUFBVztNQUNoRCxNQUFNNEMsU0FBUyxHQUFHNUMsTUFBTSxDQUFDNEMsU0FBUyxDQUFDLENBQUM7TUFDcEMsSUFBSUEsU0FBUyxFQUFFTixNQUFNLENBQUNPLElBQUksQ0FBQ0QsU0FBUyxDQUFDO0lBQ3pDLENBQUMsQ0FBQzs7SUFFRjtJQUNBTixNQUFNLENBQUNRLElBQUksQ0FBQyxDQUFDQyxDQUFjLEVBQUVDLENBQWMsS0FBSztNQUM1QyxPQUFPRCxDQUFDLENBQUNFLEtBQUssQ0FBQyxDQUFDLEdBQUdELENBQUMsQ0FBQ0MsS0FBSyxDQUFDLENBQUM7SUFDaEMsQ0FBQyxDQUFDO0lBRUYsSUFBSSxDQUFDWCxNQUFNLEVBQUUsT0FBTyxDQUFDOztJQUVyQixJQUFJWSxHQUFHLEdBQUcsSUFBSSxDQUFDNUIsUUFBUSxDQUFDUyxHQUFHLENBQUNWLElBQUksQ0FBQ0csTUFBTSxDQUFDO0lBQ3hDLElBQUksQ0FBQzBCLEdBQUcsRUFBRTtNQUNOQSxHQUFHLEdBQUcsSUFBSS9CLEdBQUcsQ0FBeUMsQ0FBQztNQUN2RCxJQUFJLENBQUNHLFFBQVEsQ0FBQzZCLEdBQUcsQ0FBQzlCLElBQUksQ0FBQ0csTUFBTSxFQUFFMEIsR0FBRyxDQUFDO0lBQ3ZDOztJQUVBO0lBQ0EsSUFBSSxDQUFDQSxHQUFHLENBQUMzQixHQUFHLENBQUMzQixPQUFPLENBQUMsRUFBRXNELEdBQUcsQ0FBQ0MsR0FBRyxDQUFDdkQsT0FBTyxFQUFFLElBQUksQ0FBQztJQUM3QyxJQUFJeUMsS0FBSyxJQUFJLENBQUNhLEdBQUcsQ0FBQzNCLEdBQUcsQ0FBQ2MsS0FBSyxDQUFDLEVBQUVhLEdBQUcsQ0FBQ0MsR0FBRyxDQUFDZCxLQUFLLEVBQUUsSUFBSSxDQUFDO0lBRWxELElBQUllLE9BQU8sR0FBRyxLQUFLO0lBQ25CLEtBQUssSUFBSUMsQ0FBQyxHQUFHZixNQUFNLENBQUNnQixNQUFNLEdBQUcsQ0FBQyxFQUFFRCxDQUFDLElBQUksQ0FBQyxFQUFFQSxDQUFDLEVBQUUsRUFBRTtNQUN6QyxJQUFJQSxDQUFDLEtBQUtmLE1BQU0sQ0FBQ2dCLE1BQU0sR0FBRzNELG9CQUFvQixFQUFFO1FBQzVDO1FBQ0E7TUFDSjtNQUVBLE1BQU1HLEtBQUssR0FBR3dDLE1BQU0sQ0FBQ2UsQ0FBQyxDQUFDO01BRXZCLE1BQU0sSUFBSSxDQUFDRSxZQUFZLEVBQUVDLG9CQUFvQixDQUFDMUQsS0FBSyxDQUFDO01BQ3BELE1BQU0yRCxVQUFVLEdBQUcsSUFBQUMsd0JBQWUsRUFBQzVELEtBQUssQ0FBQztNQUN6QyxJQUFJMkQsVUFBVSxFQUFFO01BQ2hCLE1BQU14QixVQUFVLEdBQUdyRCxRQUFRLENBQUNrQixLQUFLLENBQUNvQyxPQUFPLENBQUMsQ0FBQyxDQUFDO01BQzVDLElBQUksQ0FBQ0QsVUFBVSxFQUFFO01BQ2pCLElBQUlBLFVBQVUsQ0FBQ3BELE9BQU8sSUFBSSxJQUFBOEUsd0JBQWlCLEVBQUM3RCxLQUFLLENBQUM4RCxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUU7TUFFbEUsTUFBTUMsY0FBYyxHQUFHNUIsVUFBVSxDQUFDbkQsU0FBUyxDQUFDcUQsVUFBVSxDQUFDckMsS0FBSyxDQUFDO01BQzdELElBQUksQ0FBQytELGNBQWMsRUFBRSxTQUFTLENBQUM7O01BRS9CVCxPQUFPLEdBQUdBLE9BQU8sSUFBSVMsY0FBYyxLQUFLWCxHQUFHLENBQUNuQixHQUFHLENBQUNuQyxPQUFPLENBQUMsRUFBRWUsSUFBSTtNQUM5RHVDLEdBQUcsQ0FBQ0MsR0FBRyxDQUFDdkQsT0FBTyxFQUFFYyxnQkFBZ0IsQ0FBQ21ELGNBQWMsRUFBRS9ELEtBQUssQ0FBQyxDQUFDO01BRXpELE1BQU1nRSxjQUFjLEdBQUdDLEtBQUssQ0FBQ0MsSUFBSSxDQUFDZCxHQUFHLENBQUNlLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQ0MsTUFBTSxDQUFFQyxDQUFDLElBQUtBLENBQUMsS0FBS3ZFLE9BQU8sQ0FBQyxDQUFDLENBQUM7TUFDNUUsS0FBSyxNQUFNd0UsUUFBUSxJQUFJTixjQUFjLEVBQUU7UUFDbkMsTUFBTU8sU0FBUyxHQUFHRCxRQUFRLEtBQUt4RSxPQUFPLEdBQUd3QyxTQUFTLEdBQUdnQyxRQUFRO1FBQzdELE1BQU1FLE9BQU8sR0FBR3JDLFVBQVUsQ0FBQ25ELFNBQVMsQ0FBQ3FELFVBQVUsQ0FBQ3JDLEtBQUssRUFBRXVFLFNBQVMsQ0FBQztRQUVqRSxJQUFJQyxPQUFPLEtBQUtULGNBQWMsRUFBRTtVQUM1QlQsT0FBTyxHQUFHQSxPQUFPLElBQUlTLGNBQWMsS0FBS1gsR0FBRyxDQUFDbkIsR0FBRyxDQUFDcUMsUUFBUSxDQUFDLEVBQUV6RCxJQUFJO1VBQy9EdUMsR0FBRyxDQUFDcUIsTUFBTSxDQUFDSCxRQUFRLENBQUM7UUFDeEIsQ0FBQyxNQUFNO1VBQ0hoQixPQUFPLEdBQUdBLE9BQU8sSUFBSWtCLE9BQU8sS0FBS3BCLEdBQUcsQ0FBQ25CLEdBQUcsQ0FBQ3FDLFFBQVEsQ0FBQyxFQUFFekQsSUFBSTtVQUN4RHVDLEdBQUcsQ0FBQ0MsR0FBRyxDQUFDaUIsUUFBUSxFQUFFRSxPQUFPLEdBQUc1RCxnQkFBZ0IsQ0FBQ21ELGNBQWMsRUFBRS9ELEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQztRQUMvRTtNQUNKO01BRUEsSUFBSXNELE9BQU8sRUFBRTtRQUNUO1FBQ0EsSUFBSSxDQUFDOUIsUUFBUSxDQUFDNkIsR0FBRyxDQUFDOUIsSUFBSSxDQUFDRyxNQUFNLEVBQUUwQixHQUFHLENBQUM7UUFDbkMsSUFBSSxDQUFDc0IsSUFBSSxDQUFDQyx3QkFBWSxFQUFFLElBQUksQ0FBQztRQUM3QixJQUFJLENBQUNELElBQUksQ0FBQzVELG1CQUFtQixDQUFDZ0IsMEJBQTBCLENBQUNQLElBQUksQ0FBQyxFQUFFQSxJQUFJLENBQUM7TUFDekU7TUFDQSxPQUFPLENBQUM7SUFDWjs7SUFFQTtJQUNBLElBQUksQ0FBQ0MsUUFBUSxDQUFDNkIsR0FBRyxDQUFDOUIsSUFBSSxDQUFDRyxNQUFNLEVBQUUsSUFBSUwsR0FBRyxDQUF5QyxDQUFDLENBQUM7SUFDakYsSUFBSSxDQUFDcUQsSUFBSSxDQUFDQyx3QkFBWSxFQUFFLElBQUksQ0FBQztJQUM3QixJQUFJLENBQUNELElBQUksQ0FBQzVELG1CQUFtQixDQUFDZ0IsMEJBQTBCLENBQUNQLElBQUksQ0FBQyxFQUFFQSxJQUFJLENBQUM7RUFDekU7RUFFQSxNQUFnQnFELFFBQVFBLENBQUNDLE9BQXNCLEVBQWlCO0lBQzVELElBQUksQ0FBQyxJQUFJLENBQUNwQixZQUFZLEVBQUU7SUFFeEIsSUFBSW9CLE9BQU8sQ0FBQ0MsTUFBTSxLQUFLLDZCQUE2QixJQUFJRCxPQUFPLENBQUNDLE1BQU0sS0FBSywrQkFBK0IsRUFBRTtNQUN4RyxNQUFNOUUsS0FBSyxHQUFHNkUsT0FBTyxDQUFDN0UsS0FBSyxDQUFDLENBQUM7TUFDN0IsTUFBTTBCLE1BQU0sR0FBRzFCLEtBQUssQ0FBQytFLFNBQVMsQ0FBQyxDQUFDO01BQ2hDLE1BQU1DLGlCQUFpQixHQUFHSCxPQUFPLENBQUNJLGNBQWMsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDSixPQUFPLENBQUNLLFdBQVc7TUFFdkYsSUFBSSxDQUFDeEQsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDRixRQUFRLENBQUNDLEdBQUcsQ0FBQ0MsTUFBTSxDQUFDLElBQUlzRCxpQkFBaUIsRUFBRTtNQUVoRSxNQUFNekQsSUFBSSxHQUFHLElBQUksQ0FBQ2tDLFlBQVksQ0FBQzBCLE9BQU8sQ0FBQ3pELE1BQU0sQ0FBQztNQUU5QyxJQUFJLENBQUNILElBQUksRUFBRTtNQUVYLE1BQU0sSUFBSSxDQUFDSSxlQUFlLENBQUNKLElBQUksRUFBRXpCLE9BQU8sQ0FBQztJQUM3QztFQUNKO0VBRUEsTUFBZ0JzRixPQUFPQSxDQUFBLEVBQWtCO0lBQ3JDLElBQUksQ0FBQyxJQUFJLENBQUMzQixZQUFZLEVBQUU7SUFDeEIsSUFBSSxDQUFDQSxZQUFZLENBQUM0QixFQUFFLENBQUNDLGlCQUFTLENBQUNDLGdCQUFnQixFQUFFLElBQUksQ0FBQ0Msa0JBQWtCLENBQUM7RUFDN0U7RUFFQSxNQUFnQkMsVUFBVUEsQ0FBQSxFQUFrQjtJQUN4QyxJQUFJLENBQUMsSUFBSSxDQUFDaEMsWUFBWSxFQUFFO0lBQ3hCLElBQUksQ0FBQ0EsWUFBWSxDQUFDaUMsR0FBRyxDQUFDSixpQkFBUyxDQUFDQyxnQkFBZ0IsRUFBRSxJQUFJLENBQUNDLGtCQUFrQixDQUFDO0VBQzlFO0FBTUo7QUFBQ0csT0FBQSxDQUFBN0UsbUJBQUEsR0FBQUEsbUJBQUE7QUFBQWxDLG9CQUFBLEdBbktZa0MsbUJBQW1CO0FBQUEsSUFBQUssZ0JBQUEsQ0FBQUMsT0FBQSxFQUFuQk4sbUJBQW1CLHNCQUNlLENBQUMsTUFBTTtFQUM5QyxNQUFNYyxRQUFRLEdBQUcsSUFBSWQsb0JBQW1CLENBQUMsQ0FBQztFQUMxQ2MsUUFBUSxDQUFDZ0UsS0FBSyxDQUFDLENBQUM7RUFDaEIsT0FBT2hFLFFBQVE7QUFDbkIsQ0FBQyxFQUFFLENBQUMiLCJpZ25vcmVMaXN0IjpbXX0=