matrix-react-sdk
Version:
SDK for matrix.org using React
161 lines (152 loc) • 25.7 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _lodash = require("lodash");
var _matrix = require("matrix-js-sdk/src/matrix");
var _types = require("matrix-js-sdk/src/types");
var _MatrixClientPeg = require("../MatrixClientPeg");
var _QueryMatcher = _interopRequireDefault(require("./QueryMatcher"));
var _Components = require("./Components");
var _AutocompleteProvider = _interopRequireDefault(require("./AutocompleteProvider"));
var _languageHandler = require("../languageHandler");
var _Permalinks = require("../utils/permalinks/Permalinks");
var _MemberAvatar = _interopRequireDefault(require("../components/views/avatars/MemberAvatar"));
var _UserIdentifier = _interopRequireDefault(require("../customisations/UserIdentifier"));
/*
Copyright 2024 New Vector Ltd.
Copyright 2018 Michael Telatynski <7t3chguy@gmail.com>
Copyright 2017, 2018 New Vector Ltd
Copyright 2017 Vector Creations Ltd
Copyright 2016 Aviral Dasgupta
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
const USER_REGEX = /\B@\S*/g;
// used when you hit 'tab' - we allow some separator chars at the beginning
// to allow you to tab-complete /mat into /(matthew)
const FORCED_USER_REGEX = /[^/,:; \t\n]\S*/g;
class UserProvider extends _AutocompleteProvider.default {
constructor(_room, renderingType) {
super({
commandRegex: USER_REGEX,
forcedCommandRegex: FORCED_USER_REGEX,
renderingType
});
(0, _defineProperty2.default)(this, "matcher", void 0);
(0, _defineProperty2.default)(this, "users", void 0);
(0, _defineProperty2.default)(this, "room", void 0);
(0, _defineProperty2.default)(this, "onRoomTimeline", (ev, room, toStartOfTimeline, removed, data) => {
if (!room) return; // notification timeline, we'll get this event again with a room specific timeline
if (removed) return;
if (room.roomId !== this.room.roomId) return;
// ignore events from filtered timelines
if (data.timeline.getTimelineSet() !== room.getUnfilteredTimelineSet()) return;
// ignore anything but real-time updates at the end of the room:
// updates from pagination will happen when the paginate completes.
if (toStartOfTimeline || !data || !data.liveEvent) return;
// TODO: lazyload if we have no ev.sender room member?
this.onUserSpoke(ev.sender);
});
(0, _defineProperty2.default)(this, "onRoomStateUpdate", state => {
// ignore updates in other rooms
if (state.roomId !== this.room.roomId) return;
// blow away the users cache
this.users = undefined;
});
this.room = _room;
this.matcher = new _QueryMatcher.default([], {
keys: ["name"],
funcs: [obj => obj.userId.slice(1)],
// index by user id minus the leading '@'
shouldMatchWordsOnly: false
});
_MatrixClientPeg.MatrixClientPeg.safeGet().on(_matrix.RoomEvent.Timeline, this.onRoomTimeline);
_MatrixClientPeg.MatrixClientPeg.safeGet().on(_matrix.RoomStateEvent.Update, this.onRoomStateUpdate);
}
destroy() {
_MatrixClientPeg.MatrixClientPeg.get()?.removeListener(_matrix.RoomEvent.Timeline, this.onRoomTimeline);
_MatrixClientPeg.MatrixClientPeg.get()?.removeListener(_matrix.RoomStateEvent.Update, this.onRoomStateUpdate);
}
async getCompletions(rawQuery, selection, force = false, limit = -1) {
// lazy-load user list into matcher
if (!this.users) this.makeUsers();
const {
command,
range
} = this.getCurrentCommand(rawQuery, selection, force);
const fullMatch = command?.[0];
// Don't search if the query is a single "@"
if (fullMatch && fullMatch !== "@") {
// Don't include the '@' in our search query - it's only used as a way to trigger completion
const query = fullMatch.startsWith("@") ? fullMatch.substring(1) : fullMatch;
return this.matcher.match(query, limit).map(user => {
const description = _UserIdentifier.default.getDisplayUserIdentifier?.(user.userId, {
roomId: this.room.roomId,
withDisplayName: true
});
const displayName = user.name || user.userId || "";
return {
// Length of completion should equal length of text in decorator. draft-js
// relies on the length of the entity === length of the text in the decoration.
completion: user.rawDisplayName,
completionId: user.userId,
type: "user",
suffix: selection.beginning && range.start === 0 ? ": " : " ",
href: (0, _Permalinks.makeUserPermalink)(user.userId),
component: /*#__PURE__*/_react.default.createElement(_Components.PillCompletion, {
title: displayName,
description: description
}, /*#__PURE__*/_react.default.createElement(_MemberAvatar.default, {
member: user,
size: "24px"
})),
range: range
};
});
}
return [];
}
getName() {
return (0, _languageHandler._t)("composer|autocomplete|user_description");
}
makeUsers() {
const events = this.room.getLiveTimeline().getEvents();
const lastSpoken = {};
for (const event of events) {
lastSpoken[event.getSender()] = event.getTs();
}
const currentUserId = _MatrixClientPeg.MatrixClientPeg.safeGet().credentials.userId;
this.users = this.room.getJoinedMembers().filter(({
userId
}) => userId !== currentUserId);
this.users = this.users.concat(this.room.getMembersWithMembership(_types.KnownMembership.Invite));
this.users = (0, _lodash.sortBy)(this.users, member => 1e20 - lastSpoken[member.userId] || 1e20);
this.matcher.setObjects(this.users);
}
onUserSpoke(user) {
if (!this.users) return;
if (!user) return;
if (user.userId === _MatrixClientPeg.MatrixClientPeg.safeGet().getSafeUserId()) return;
// Move the user that spoke to the front of the array
this.users.splice(this.users.findIndex(user2 => user2.userId === user.userId), 1);
this.users = [user, ...this.users];
this.matcher.setObjects(this.users);
}
renderCompletions(completions) {
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_Autocomplete_Completion_container_pill",
role: "presentation",
"aria-label": (0, _languageHandler._t)("composer|autocomplete|user_a11y")
}, completions);
}
shouldForceComplete() {
return true;
}
}
exports.default = UserProvider;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9sb2Rhc2giLCJfbWF0cml4IiwiX3R5cGVzIiwiX01hdHJpeENsaWVudFBlZyIsIl9RdWVyeU1hdGNoZXIiLCJfQ29tcG9uZW50cyIsIl9BdXRvY29tcGxldGVQcm92aWRlciIsIl9sYW5ndWFnZUhhbmRsZXIiLCJfUGVybWFsaW5rcyIsIl9NZW1iZXJBdmF0YXIiLCJfVXNlcklkZW50aWZpZXIiLCJVU0VSX1JFR0VYIiwiRk9SQ0VEX1VTRVJfUkVHRVgiLCJVc2VyUHJvdmlkZXIiLCJBdXRvY29tcGxldGVQcm92aWRlciIsImNvbnN0cnVjdG9yIiwicm9vbSIsInJlbmRlcmluZ1R5cGUiLCJjb21tYW5kUmVnZXgiLCJmb3JjZWRDb21tYW5kUmVnZXgiLCJfZGVmaW5lUHJvcGVydHkyIiwiZGVmYXVsdCIsImV2IiwidG9TdGFydE9mVGltZWxpbmUiLCJyZW1vdmVkIiwiZGF0YSIsInJvb21JZCIsInRpbWVsaW5lIiwiZ2V0VGltZWxpbmVTZXQiLCJnZXRVbmZpbHRlcmVkVGltZWxpbmVTZXQiLCJsaXZlRXZlbnQiLCJvblVzZXJTcG9rZSIsInNlbmRlciIsInN0YXRlIiwidXNlcnMiLCJ1bmRlZmluZWQiLCJtYXRjaGVyIiwiUXVlcnlNYXRjaGVyIiwia2V5cyIsImZ1bmNzIiwib2JqIiwidXNlcklkIiwic2xpY2UiLCJzaG91bGRNYXRjaFdvcmRzT25seSIsIk1hdHJpeENsaWVudFBlZyIsInNhZmVHZXQiLCJvbiIsIlJvb21FdmVudCIsIlRpbWVsaW5lIiwib25Sb29tVGltZWxpbmUiLCJSb29tU3RhdGVFdmVudCIsIlVwZGF0ZSIsIm9uUm9vbVN0YXRlVXBkYXRlIiwiZGVzdHJveSIsImdldCIsInJlbW92ZUxpc3RlbmVyIiwiZ2V0Q29tcGxldGlvbnMiLCJyYXdRdWVyeSIsInNlbGVjdGlvbiIsImZvcmNlIiwibGltaXQiLCJtYWtlVXNlcnMiLCJjb21tYW5kIiwicmFuZ2UiLCJnZXRDdXJyZW50Q29tbWFuZCIsImZ1bGxNYXRjaCIsInF1ZXJ5Iiwic3RhcnRzV2l0aCIsInN1YnN0cmluZyIsIm1hdGNoIiwibWFwIiwidXNlciIsImRlc2NyaXB0aW9uIiwiVXNlcklkZW50aWZpZXJDdXN0b21pc2F0aW9ucyIsImdldERpc3BsYXlVc2VySWRlbnRpZmllciIsIndpdGhEaXNwbGF5TmFtZSIsImRpc3BsYXlOYW1lIiwibmFtZSIsImNvbXBsZXRpb24iLCJyYXdEaXNwbGF5TmFtZSIsImNvbXBsZXRpb25JZCIsInR5cGUiLCJzdWZmaXgiLCJiZWdpbm5pbmciLCJzdGFydCIsImhyZWYiLCJtYWtlVXNlclBlcm1hbGluayIsImNvbXBvbmVudCIsImNyZWF0ZUVsZW1lbnQiLCJQaWxsQ29tcGxldGlvbiIsInRpdGxlIiwibWVtYmVyIiwic2l6ZSIsImdldE5hbWUiLCJfdCIsImV2ZW50cyIsImdldExpdmVUaW1lbGluZSIsImdldEV2ZW50cyIsImxhc3RTcG9rZW4iLCJldmVudCIsImdldFNlbmRlciIsImdldFRzIiwiY3VycmVudFVzZXJJZCIsImNyZWRlbnRpYWxzIiwiZ2V0Sm9pbmVkTWVtYmVycyIsImZpbHRlciIsImNvbmNhdCIsImdldE1lbWJlcnNXaXRoTWVtYmVyc2hpcCIsIktub3duTWVtYmVyc2hpcCIsIkludml0ZSIsInNvcnRCeSIsInNldE9iamVjdHMiLCJnZXRTYWZlVXNlcklkIiwic3BsaWNlIiwiZmluZEluZGV4IiwidXNlcjIiLCJyZW5kZXJDb21wbGV0aW9ucyIsImNvbXBsZXRpb25zIiwiY2xhc3NOYW1lIiwicm9sZSIsInNob3VsZEZvcmNlQ29tcGxldGUiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2F1dG9jb21wbGV0ZS9Vc2VyUHJvdmlkZXIudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDE4IE1pY2hhZWwgVGVsYXR5bnNraSA8N3QzY2hndXlAZ21haWwuY29tPlxuQ29weXJpZ2h0IDIwMTcsIDIwMTggTmV3IFZlY3RvciBMdGRcbkNvcHlyaWdodCAyMDE3IFZlY3RvciBDcmVhdGlvbnMgTHRkXG5Db3B5cmlnaHQgMjAxNiBBdmlyYWwgRGFzZ3VwdGFcblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgc29ydEJ5IH0gZnJvbSBcImxvZGFzaFwiO1xuaW1wb3J0IHtcbiAgICBNYXRyaXhFdmVudCxcbiAgICBSb29tLFxuICAgIFJvb21FdmVudCxcbiAgICBSb29tTWVtYmVyLFxuICAgIFJvb21TdGF0ZSxcbiAgICBSb29tU3RhdGVFdmVudCxcbiAgICBJUm9vbVRpbWVsaW5lRGF0YSxcbn0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgS25vd25NZW1iZXJzaGlwIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL3R5cGVzXCI7XG5cbmltcG9ydCB7IE1hdHJpeENsaWVudFBlZyB9IGZyb20gXCIuLi9NYXRyaXhDbGllbnRQZWdcIjtcbmltcG9ydCBRdWVyeU1hdGNoZXIgZnJvbSBcIi4vUXVlcnlNYXRjaGVyXCI7XG5pbXBvcnQgeyBQaWxsQ29tcGxldGlvbiB9IGZyb20gXCIuL0NvbXBvbmVudHNcIjtcbmltcG9ydCBBdXRvY29tcGxldGVQcm92aWRlciBmcm9tIFwiLi9BdXRvY29tcGxldGVQcm92aWRlclwiO1xuaW1wb3J0IHsgX3QgfSBmcm9tIFwiLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgeyBtYWtlVXNlclBlcm1hbGluayB9IGZyb20gXCIuLi91dGlscy9wZXJtYWxpbmtzL1Blcm1hbGlua3NcIjtcbmltcG9ydCB7IElDb21wbGV0aW9uLCBJU2VsZWN0aW9uUmFuZ2UgfSBmcm9tIFwiLi9BdXRvY29tcGxldGVyXCI7XG5pbXBvcnQgTWVtYmVyQXZhdGFyIGZyb20gXCIuLi9jb21wb25lbnRzL3ZpZXdzL2F2YXRhcnMvTWVtYmVyQXZhdGFyXCI7XG5pbXBvcnQgeyBUaW1lbGluZVJlbmRlcmluZ1R5cGUgfSBmcm9tIFwiLi4vY29udGV4dHMvUm9vbUNvbnRleHRcIjtcbmltcG9ydCBVc2VySWRlbnRpZmllckN1c3RvbWlzYXRpb25zIGZyb20gXCIuLi9jdXN0b21pc2F0aW9ucy9Vc2VySWRlbnRpZmllclwiO1xuXG5jb25zdCBVU0VSX1JFR0VYID0gL1xcQkBcXFMqL2c7XG5cbi8vIHVzZWQgd2hlbiB5b3UgaGl0ICd0YWInIC0gd2UgYWxsb3cgc29tZSBzZXBhcmF0b3IgY2hhcnMgYXQgdGhlIGJlZ2lubmluZ1xuLy8gdG8gYWxsb3cgeW91IHRvIHRhYi1jb21wbGV0ZSAvbWF0IGludG8gLyhtYXR0aGV3KVxuY29uc3QgRk9SQ0VEX1VTRVJfUkVHRVggPSAvW14vLDo7IFxcdFxcbl1cXFMqL2c7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFVzZXJQcm92aWRlciBleHRlbmRzIEF1dG9jb21wbGV0ZVByb3ZpZGVyIHtcbiAgICBwdWJsaWMgbWF0Y2hlcjogUXVlcnlNYXRjaGVyPFJvb21NZW1iZXI+O1xuICAgIHB1YmxpYyB1c2Vycz86IFJvb21NZW1iZXJbXTtcbiAgICBwdWJsaWMgcm9vbTogUm9vbTtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcihyb29tOiBSb29tLCByZW5kZXJpbmdUeXBlPzogVGltZWxpbmVSZW5kZXJpbmdUeXBlKSB7XG4gICAgICAgIHN1cGVyKHtcbiAgICAgICAgICAgIGNvbW1hbmRSZWdleDogVVNFUl9SRUdFWCxcbiAgICAgICAgICAgIGZvcmNlZENvbW1hbmRSZWdleDogRk9SQ0VEX1VTRVJfUkVHRVgsXG4gICAgICAgICAgICByZW5kZXJpbmdUeXBlLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5yb29tID0gcm9vbTtcbiAgICAgICAgdGhpcy5tYXRjaGVyID0gbmV3IFF1ZXJ5TWF0Y2hlcjxSb29tTWVtYmVyPihbXSwge1xuICAgICAgICAgICAga2V5czogW1wibmFtZVwiXSxcbiAgICAgICAgICAgIGZ1bmNzOiBbKG9iaikgPT4gb2JqLnVzZXJJZC5zbGljZSgxKV0sIC8vIGluZGV4IGJ5IHVzZXIgaWQgbWludXMgdGhlIGxlYWRpbmcgJ0AnXG4gICAgICAgICAgICBzaG91bGRNYXRjaFdvcmRzT25seTogZmFsc2UsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkub24oUm9vbUV2ZW50LlRpbWVsaW5lLCB0aGlzLm9uUm9vbVRpbWVsaW5lKTtcbiAgICAgICAgTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5vbihSb29tU3RhdGVFdmVudC5VcGRhdGUsIHRoaXMub25Sb29tU3RhdGVVcGRhdGUpO1xuICAgIH1cblxuICAgIHB1YmxpYyBkZXN0cm95KCk6IHZvaWQge1xuICAgICAgICBNYXRyaXhDbGllbnRQZWcuZ2V0KCk/LnJlbW92ZUxpc3RlbmVyKFJvb21FdmVudC5UaW1lbGluZSwgdGhpcy5vblJvb21UaW1lbGluZSk7XG4gICAgICAgIE1hdHJpeENsaWVudFBlZy5nZXQoKT8ucmVtb3ZlTGlzdGVuZXIoUm9vbVN0YXRlRXZlbnQuVXBkYXRlLCB0aGlzLm9uUm9vbVN0YXRlVXBkYXRlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uUm9vbVRpbWVsaW5lID0gKFxuICAgICAgICBldjogTWF0cml4RXZlbnQsXG4gICAgICAgIHJvb206IFJvb20gfCB1bmRlZmluZWQsXG4gICAgICAgIHRvU3RhcnRPZlRpbWVsaW5lOiBib29sZWFuIHwgdW5kZWZpbmVkLFxuICAgICAgICByZW1vdmVkOiBib29sZWFuLFxuICAgICAgICBkYXRhOiBJUm9vbVRpbWVsaW5lRGF0YSxcbiAgICApOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKCFyb29tKSByZXR1cm47IC8vIG5vdGlmaWNhdGlvbiB0aW1lbGluZSwgd2UnbGwgZ2V0IHRoaXMgZXZlbnQgYWdhaW4gd2l0aCBhIHJvb20gc3BlY2lmaWMgdGltZWxpbmVcbiAgICAgICAgaWYgKHJlbW92ZWQpIHJldHVybjtcbiAgICAgICAgaWYgKHJvb20ucm9vbUlkICE9PSB0aGlzLnJvb20ucm9vbUlkKSByZXR1cm47XG5cbiAgICAgICAgLy8gaWdub3JlIGV2ZW50cyBmcm9tIGZpbHRlcmVkIHRpbWVsaW5lc1xuICAgICAgICBpZiAoZGF0YS50aW1lbGluZS5nZXRUaW1lbGluZVNldCgpICE9PSByb29tLmdldFVuZmlsdGVyZWRUaW1lbGluZVNldCgpKSByZXR1cm47XG5cbiAgICAgICAgLy8gaWdub3JlIGFueXRoaW5nIGJ1dCByZWFsLXRpbWUgdXBkYXRlcyBhdCB0aGUgZW5kIG9mIHRoZSByb29tOlxuICAgICAgICAvLyB1cGRhdGVzIGZyb20gcGFnaW5hdGlvbiB3aWxsIGhhcHBlbiB3aGVuIHRoZSBwYWdpbmF0ZSBjb21wbGV0ZXMuXG4gICAgICAgIGlmICh0b1N0YXJ0T2ZUaW1lbGluZSB8fCAhZGF0YSB8fCAhZGF0YS5saXZlRXZlbnQpIHJldHVybjtcblxuICAgICAgICAvLyBUT0RPOiBsYXp5bG9hZCBpZiB3ZSBoYXZlIG5vIGV2LnNlbmRlciByb29tIG1lbWJlcj9cbiAgICAgICAgdGhpcy5vblVzZXJTcG9rZShldi5zZW5kZXIpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uUm9vbVN0YXRlVXBkYXRlID0gKHN0YXRlOiBSb29tU3RhdGUpOiB2b2lkID0+IHtcbiAgICAgICAgLy8gaWdub3JlIHVwZGF0ZXMgaW4gb3RoZXIgcm9vbXNcbiAgICAgICAgaWYgKHN0YXRlLnJvb21JZCAhPT0gdGhpcy5yb29tLnJvb21JZCkgcmV0dXJuO1xuXG4gICAgICAgIC8vIGJsb3cgYXdheSB0aGUgdXNlcnMgY2FjaGVcbiAgICAgICAgdGhpcy51c2VycyA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgcHVibGljIGFzeW5jIGdldENvbXBsZXRpb25zKFxuICAgICAgICByYXdRdWVyeTogc3RyaW5nLFxuICAgICAgICBzZWxlY3Rpb246IElTZWxlY3Rpb25SYW5nZSxcbiAgICAgICAgZm9yY2UgPSBmYWxzZSxcbiAgICAgICAgbGltaXQgPSAtMSxcbiAgICApOiBQcm9taXNlPElDb21wbGV0aW9uW10+IHtcbiAgICAgICAgLy8gbGF6eS1sb2FkIHVzZXIgbGlzdCBpbnRvIG1hdGNoZXJcbiAgICAgICAgaWYgKCF0aGlzLnVzZXJzKSB0aGlzLm1ha2VVc2VycygpO1xuXG4gICAgICAgIGNvbnN0IHsgY29tbWFuZCwgcmFuZ2UgfSA9IHRoaXMuZ2V0Q3VycmVudENvbW1hbmQocmF3UXVlcnksIHNlbGVjdGlvbiwgZm9yY2UpO1xuXG4gICAgICAgIGNvbnN0IGZ1bGxNYXRjaCA9IGNvbW1hbmQ/LlswXTtcbiAgICAgICAgLy8gRG9uJ3Qgc2VhcmNoIGlmIHRoZSBxdWVyeSBpcyBhIHNpbmdsZSBcIkBcIlxuICAgICAgICBpZiAoZnVsbE1hdGNoICYmIGZ1bGxNYXRjaCAhPT0gXCJAXCIpIHtcbiAgICAgICAgICAgIC8vIERvbid0IGluY2x1ZGUgdGhlICdAJyBpbiBvdXIgc2VhcmNoIHF1ZXJ5IC0gaXQncyBvbmx5IHVzZWQgYXMgYSB3YXkgdG8gdHJpZ2dlciBjb21wbGV0aW9uXG4gICAgICAgICAgICBjb25zdCBxdWVyeSA9IGZ1bGxNYXRjaC5zdGFydHNXaXRoKFwiQFwiKSA/IGZ1bGxNYXRjaC5zdWJzdHJpbmcoMSkgOiBmdWxsTWF0Y2g7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXRjaGVyLm1hdGNoKHF1ZXJ5LCBsaW1pdCkubWFwKCh1c2VyKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVzY3JpcHRpb24gPSBVc2VySWRlbnRpZmllckN1c3RvbWlzYXRpb25zLmdldERpc3BsYXlVc2VySWRlbnRpZmllcj8uKHVzZXIudXNlcklkLCB7XG4gICAgICAgICAgICAgICAgICAgIHJvb21JZDogdGhpcy5yb29tLnJvb21JZCxcbiAgICAgICAgICAgICAgICAgICAgd2l0aERpc3BsYXlOYW1lOiB0cnVlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IGRpc3BsYXlOYW1lID0gdXNlci5uYW1lIHx8IHVzZXIudXNlcklkIHx8IFwiXCI7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTGVuZ3RoIG9mIGNvbXBsZXRpb24gc2hvdWxkIGVxdWFsIGxlbmd0aCBvZiB0ZXh0IGluIGRlY29yYXRvci4gZHJhZnQtanNcbiAgICAgICAgICAgICAgICAgICAgLy8gcmVsaWVzIG9uIHRoZSBsZW5ndGggb2YgdGhlIGVudGl0eSA9PT0gbGVuZ3RoIG9mIHRoZSB0ZXh0IGluIHRoZSBkZWNvcmF0aW9uLlxuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uOiB1c2VyLnJhd0Rpc3BsYXlOYW1lLFxuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSWQ6IHVzZXIudXNlcklkLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInVzZXJcIixcbiAgICAgICAgICAgICAgICAgICAgc3VmZml4OiBzZWxlY3Rpb24uYmVnaW5uaW5nICYmIHJhbmdlIS5zdGFydCA9PT0gMCA/IFwiOiBcIiA6IFwiIFwiLFxuICAgICAgICAgICAgICAgICAgICBocmVmOiBtYWtlVXNlclBlcm1hbGluayh1c2VyLnVzZXJJZCksXG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudDogKFxuICAgICAgICAgICAgICAgICAgICAgICAgPFBpbGxDb21wbGV0aW9uIHRpdGxlPXtkaXNwbGF5TmFtZX0gZGVzY3JpcHRpb249e2Rlc2NyaXB0aW9ufT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8TWVtYmVyQXZhdGFyIG1lbWJlcj17dXNlcn0gc2l6ZT1cIjI0cHhcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9QaWxsQ29tcGxldGlvbj5cbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2U6IHJhbmdlISxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXROYW1lKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBfdChcImNvbXBvc2VyfGF1dG9jb21wbGV0ZXx1c2VyX2Rlc2NyaXB0aW9uXCIpO1xuICAgIH1cblxuICAgIHByaXZhdGUgbWFrZVVzZXJzKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBldmVudHMgPSB0aGlzLnJvb20uZ2V0TGl2ZVRpbWVsaW5lKCkuZ2V0RXZlbnRzKCk7XG4gICAgICAgIGNvbnN0IGxhc3RTcG9rZW46IFJlY29yZDxzdHJpbmcsIG51bWJlcj4gPSB7fTtcblxuICAgICAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGV2ZW50cykge1xuICAgICAgICAgICAgbGFzdFNwb2tlbltldmVudC5nZXRTZW5kZXIoKSFdID0gZXZlbnQuZ2V0VHMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGN1cnJlbnRVc2VySWQgPSBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLmNyZWRlbnRpYWxzLnVzZXJJZDtcbiAgICAgICAgdGhpcy51c2VycyA9IHRoaXMucm9vbS5nZXRKb2luZWRNZW1iZXJzKCkuZmlsdGVyKCh7IHVzZXJJZCB9KSA9PiB1c2VySWQgIT09IGN1cnJlbnRVc2VySWQpO1xuICAgICAgICB0aGlzLnVzZXJzID0gdGhpcy51c2Vycy5jb25jYXQodGhpcy5yb29tLmdldE1lbWJlcnNXaXRoTWVtYmVyc2hpcChLbm93bk1lbWJlcnNoaXAuSW52aXRlKSk7XG5cbiAgICAgICAgdGhpcy51c2VycyA9IHNvcnRCeSh0aGlzLnVzZXJzLCAobWVtYmVyKSA9PiAxZTIwIC0gbGFzdFNwb2tlblttZW1iZXIudXNlcklkXSB8fCAxZTIwKTtcblxuICAgICAgICB0aGlzLm1hdGNoZXIuc2V0T2JqZWN0cyh0aGlzLnVzZXJzKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgb25Vc2VyU3Bva2UodXNlcjogUm9vbU1lbWJlciB8IG51bGwpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnVzZXJzKSByZXR1cm47XG4gICAgICAgIGlmICghdXNlcikgcmV0dXJuO1xuICAgICAgICBpZiAodXNlci51c2VySWQgPT09IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkuZ2V0U2FmZVVzZXJJZCgpKSByZXR1cm47XG5cbiAgICAgICAgLy8gTW92ZSB0aGUgdXNlciB0aGF0IHNwb2tlIHRvIHRoZSBmcm9udCBvZiB0aGUgYXJyYXlcbiAgICAgICAgdGhpcy51c2Vycy5zcGxpY2UoXG4gICAgICAgICAgICB0aGlzLnVzZXJzLmZpbmRJbmRleCgodXNlcjIpID0+IHVzZXIyLnVzZXJJZCA9PT0gdXNlci51c2VySWQpLFxuICAgICAgICAgICAgMSxcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy51c2VycyA9IFt1c2VyLCAuLi50aGlzLnVzZXJzXTtcblxuICAgICAgICB0aGlzLm1hdGNoZXIuc2V0T2JqZWN0cyh0aGlzLnVzZXJzKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVuZGVyQ29tcGxldGlvbnMoY29tcGxldGlvbnM6IFJlYWN0LlJlYWN0Tm9kZVtdKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9BdXRvY29tcGxldGVfQ29tcGxldGlvbl9jb250YWluZXJfcGlsbFwiXG4gICAgICAgICAgICAgICAgcm9sZT1cInByZXNlbnRhdGlvblwiXG4gICAgICAgICAgICAgICAgYXJpYS1sYWJlbD17X3QoXCJjb21wb3NlcnxhdXRvY29tcGxldGV8dXNlcl9hMTF5XCIpfVxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIHtjb21wbGV0aW9uc31cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBzaG91bGRGb3JjZUNvbXBsZXRlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBV0EsSUFBQUEsTUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsT0FBQSxHQUFBRixPQUFBO0FBU0EsSUFBQUcsTUFBQSxHQUFBSCxPQUFBO0FBRUEsSUFBQUksZ0JBQUEsR0FBQUosT0FBQTtBQUNBLElBQUFLLGFBQUEsR0FBQU4sc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFNLFdBQUEsR0FBQU4sT0FBQTtBQUNBLElBQUFPLHFCQUFBLEdBQUFSLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBUSxnQkFBQSxHQUFBUixPQUFBO0FBQ0EsSUFBQVMsV0FBQSxHQUFBVCxPQUFBO0FBRUEsSUFBQVUsYUFBQSxHQUFBWCxzQkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQVcsZUFBQSxHQUFBWixzQkFBQSxDQUFBQyxPQUFBO0FBakNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQTBCQSxNQUFNWSxVQUFVLEdBQUcsU0FBUzs7QUFFNUI7QUFDQTtBQUNBLE1BQU1DLGlCQUFpQixHQUFHLGtCQUFrQjtBQUU3QixNQUFNQyxZQUFZLFNBQVNDLDZCQUFvQixDQUFDO0VBS3BEQyxXQUFXQSxDQUFDQyxLQUFVLEVBQUVDLGFBQXFDLEVBQUU7SUFDbEUsS0FBSyxDQUFDO01BQ0ZDLFlBQVksRUFBRVAsVUFBVTtNQUN4QlEsa0JBQWtCLEVBQUVQLGlCQUFpQjtNQUNyQ0s7SUFDSixDQUFDLENBQUM7SUFBQyxJQUFBRyxnQkFBQSxDQUFBQyxPQUFBO0lBQUEsSUFBQUQsZ0JBQUEsQ0FBQUMsT0FBQTtJQUFBLElBQUFELGdCQUFBLENBQUFDLE9BQUE7SUFBQSxJQUFBRCxnQkFBQSxDQUFB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