matrix-react-sdk
Version:
SDK for matrix.org using React
568 lines (463 loc) • 74.6 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _languageHandler = require("../../../languageHandler");
var _SdkConfig = _interopRequireDefault(require("../../../SdkConfig"));
var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher"));
var _RoomInvite = require("../../../RoomInvite");
var _ratelimitedfunc = _interopRequireDefault(require("../../../ratelimitedfunc"));
var _MatrixClientPeg = require("../../../MatrixClientPeg");
var sdk = _interopRequireWildcard(require("../../../index"));
var _CommunityPrototypeStore = require("../../../stores/CommunityPrototypeStore");
var _BaseCard = _interopRequireDefault(require("../right_panel/BaseCard"));
var _RightPanelStorePhases = require("../../../stores/RightPanelStorePhases");
var _RoomAvatar = _interopRequireDefault(require("../avatars/RoomAvatar"));
var _RoomName = _interopRequireDefault(require("../elements/RoomName"));
var _replaceableComponent = require("../../../utils/replaceableComponent");
var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore"));
var _dec, _class, _temp;
const INITIAL_LOAD_NUM_MEMBERS = 30;
const INITIAL_LOAD_NUM_INVITED = 5;
const SHOW_MORE_INCREMENT = 100; // Regex applied to filter our punctuation in member names before applying sort, to fuzzy it a little
// matches all ASCII punctuation: !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
const SORT_REGEX = /[\x21-\x2F\x3A-\x40\x5B-\x60\x7B-\x7E]+/g;
let MemberList = (_dec = (0, _replaceableComponent.replaceableComponent)("views.rooms.MemberList"), _dec(_class = (_temp = class MemberList extends _react.default.Component {
constructor(props) {
super(props);
(0, _defineProperty2.default)(this, "onUserPresenceChange", (event, user) => {
// Attach a SINGLE listener for global presence changes then locate the
// member tile and re-render it. This is more efficient than every tile
// ever attaching their own listener.
const tile = this.refs[user.userId]; // console.log(`Got presence update for ${user.userId}. hasTile=${!!tile}`);
if (tile) {
this._updateList(); // reorder the membership list
}
});
(0, _defineProperty2.default)(this, "onRoom", room => {
if (room.roomId !== this.props.roomId) {
return;
} // We listen for room events because when we accept an invite
// we need to wait till the room is fully populated with state
// before refreshing the member list else we get a stale list.
this._showMembersAccordingToMembershipWithLL();
});
(0, _defineProperty2.default)(this, "onMyMembership", (room, membership, oldMembership) => {
if (room.roomId === this.props.roomId && membership === "join") {
this._showMembersAccordingToMembershipWithLL();
}
});
(0, _defineProperty2.default)(this, "onRoomStateMember", (ev, state, member) => {
if (member.roomId !== this.props.roomId) {
return;
}
this._updateList();
});
(0, _defineProperty2.default)(this, "onRoomMemberName", (ev, member) => {
if (member.roomId !== this.props.roomId) {
return;
}
this._updateList();
});
(0, _defineProperty2.default)(this, "onRoomStateEvent", (event, state) => {
if (event.getRoomId() === this.props.roomId && event.getType() === "m.room.third_party_invite") {
this._updateList();
}
});
(0, _defineProperty2.default)(this, "_updateList", (0, _ratelimitedfunc.default)(() => {
this._updateListNow();
}, 500));
(0, _defineProperty2.default)(this, "_createOverflowTileJoined", (overflowCount, totalCount) => {
return this._createOverflowTile(overflowCount, totalCount, this._showMoreJoinedMemberList);
});
(0, _defineProperty2.default)(this, "_createOverflowTileInvited", (overflowCount, totalCount) => {
return this._createOverflowTile(overflowCount, totalCount, this._showMoreInvitedMemberList);
});
(0, _defineProperty2.default)(this, "_createOverflowTile", (overflowCount, totalCount, onClick) => {
// For now we'll pretend this is any entity. It should probably be a separate tile.
const EntityTile = sdk.getComponent("rooms.EntityTile");
const BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
const text = (0, _languageHandler._t)("and %(count)s others...", {
count: overflowCount
});
return /*#__PURE__*/_react.default.createElement(EntityTile, {
className: "mx_EntityTile_ellipsis",
avatarJsx: /*#__PURE__*/_react.default.createElement(BaseAvatar, {
url: require("../../../../res/img/ellipsis.svg"),
name: "...",
width: 36,
height: 36
}),
name: text,
presenceState: "online",
suppressOnHover: true,
onClick: onClick
});
});
(0, _defineProperty2.default)(this, "_showMoreJoinedMemberList", () => {
this.setState({
truncateAtJoined: this.state.truncateAtJoined + SHOW_MORE_INCREMENT
});
});
(0, _defineProperty2.default)(this, "_showMoreInvitedMemberList", () => {
this.setState({
truncateAtInvited: this.state.truncateAtInvited + SHOW_MORE_INCREMENT
});
});
(0, _defineProperty2.default)(this, "memberSort", (memberA, memberB) => {
// order by presence, with "active now" first.
// ...and then by power level
// ...and then by last active
// ...and then alphabetically.
// We could tiebreak instead by "last recently spoken in this room" if we wanted to.
// console.log(`Comparing userA=${this.memberString(memberA)} userB=${this.memberString(memberB)}`);
const userA = memberA.user;
const userB = memberB.user; // if (!userA) console.log("!! MISSING USER FOR A-SIDE: " + memberA.name + " !!");
// if (!userB) console.log("!! MISSING USER FOR B-SIDE: " + memberB.name + " !!");
if (!userA && !userB) return 0;
if (userA && !userB) return -1;
if (!userA && userB) return 1; // First by presence
if (this._showPresence) {
const convertPresence = p => p === 'unavailable' ? 'online' : p;
const presenceIndex = p => {
const order = ['active', 'online', 'offline'];
const idx = order.indexOf(convertPresence(p));
return idx === -1 ? order.length : idx; // unknown states at the end
};
const idxA = presenceIndex(userA.currentlyActive ? 'active' : userA.presence);
const idxB = presenceIndex(userB.currentlyActive ? 'active' : userB.presence); // console.log(`userA_presenceGroup=${idxA} userB_presenceGroup=${idxB}`);
if (idxA !== idxB) {
// console.log("Comparing on presence group - returning");
return idxA - idxB;
}
} // Second by power level
if (memberA.powerLevel !== memberB.powerLevel) {
// console.log("Comparing on power level - returning");
return memberB.powerLevel - memberA.powerLevel;
} // Third by last active
if (this._showPresence && userA.getLastActiveTs() !== userB.getLastActiveTs()) {
// console.log("Comparing on last active timestamp - returning");
return userB.getLastActiveTs() - userA.getLastActiveTs();
} // Fourth by name (alphabetical)
const nameA = (memberA.name[0] === '@' ? memberA.name.substr(1) : memberA.name).replace(SORT_REGEX, "");
const nameB = (memberB.name[0] === '@' ? memberB.name.substr(1) : memberB.name).replace(SORT_REGEX, ""); // console.log(`Comparing userA_name=${nameA} against userB_name=${nameB} - returning`);
return nameA.localeCompare(nameB, {
ignorePunctuation: true,
sensitivity: "base"
});
});
(0, _defineProperty2.default)(this, "onSearchQueryChanged", searchQuery => {
this.setState({
searchQuery,
filteredJoinedMembers: this._filterMembers(this.state.members, 'join', searchQuery),
filteredInvitedMembers: this._filterMembers(this.state.members, 'invite', searchQuery)
});
});
(0, _defineProperty2.default)(this, "_onPending3pidInviteClick", inviteEvent => {
_dispatcher.default.dispatch({
action: 'view_3pid_invite',
event: inviteEvent
});
});
(0, _defineProperty2.default)(this, "_getChildrenJoined", (start, end) => this._makeMemberTiles(this.state.filteredJoinedMembers.slice(start, end)));
(0, _defineProperty2.default)(this, "_getChildCountJoined", () => this.state.filteredJoinedMembers.length);
(0, _defineProperty2.default)(this, "_getChildrenInvited", (start, end) => {
let targets = this.state.filteredInvitedMembers;
if (end > this.state.filteredInvitedMembers.length) {
targets = targets.concat(this._getPending3PidInvites());
}
return this._makeMemberTiles(targets.slice(start, end));
});
(0, _defineProperty2.default)(this, "_getChildCountInvited", () => {
return this.state.filteredInvitedMembers.length + (this._getPending3PidInvites() || []).length;
});
(0, _defineProperty2.default)(this, "onInviteButtonClick", () => {
if (_MatrixClientPeg.MatrixClientPeg.get().isGuest()) {
_dispatcher.default.dispatch({
action: 'require_registration'
});
return;
} // call AddressPickerDialog
_dispatcher.default.dispatch({
action: 'view_invite',
roomId: this.props.roomId
});
});
const cli = _MatrixClientPeg.MatrixClientPeg.get();
if (cli.hasLazyLoadMembersEnabled()) {
// show an empty list
this.state = this._getMembersState([]);
} else {
this.state = this._getMembersState(this.roomMembers());
}
cli.on("Room", this.onRoom); // invites & joining after peek
const enablePresenceByHsUrl = _SdkConfig.default.get()["enable_presence_by_hs_url"];
const hsUrl = _MatrixClientPeg.MatrixClientPeg.get().baseUrl;
this._showPresence = true;
if (enablePresenceByHsUrl && enablePresenceByHsUrl[hsUrl] !== undefined) {
this._showPresence = enablePresenceByHsUrl[hsUrl];
}
} // eslint-disable-next-line camelcase
UNSAFE_componentWillMount() {
const cli = _MatrixClientPeg.MatrixClientPeg.get();
this._mounted = true;
if (cli.hasLazyLoadMembersEnabled()) {
this._showMembersAccordingToMembershipWithLL();
cli.on("Room.myMembership", this.onMyMembership);
} else {
this._listenForMembersChanges();
}
}
_listenForMembersChanges() {
const cli = _MatrixClientPeg.MatrixClientPeg.get();
cli.on("RoomState.members", this.onRoomStateMember);
cli.on("RoomMember.name", this.onRoomMemberName);
cli.on("RoomState.events", this.onRoomStateEvent); // We listen for changes to the lastPresenceTs which is essentially
// listening for all presence events (we display most of not all of
// the information contained in presence events).
cli.on("User.lastPresenceTs", this.onUserPresenceChange);
cli.on("User.presence", this.onUserPresenceChange);
cli.on("User.currentlyActive", this.onUserPresenceChange); // cli.on("Room.timeline", this.onRoomTimeline);
}
componentWillUnmount() {
this._mounted = false;
const cli = _MatrixClientPeg.MatrixClientPeg.get();
if (cli) {
cli.removeListener("RoomState.members", this.onRoomStateMember);
cli.removeListener("RoomMember.name", this.onRoomMemberName);
cli.removeListener("Room.myMembership", this.onMyMembership);
cli.removeListener("RoomState.events", this.onRoomStateEvent);
cli.removeListener("Room", this.onRoom);
cli.removeListener("User.lastPresenceTs", this.onUserPresenceChange);
cli.removeListener("User.presence", this.onUserPresenceChange);
cli.removeListener("User.currentlyActive", this.onUserPresenceChange);
} // cancel any pending calls to the rate_limited_funcs
this._updateList.cancelPendingCall();
}
/**
* If lazy loading is enabled, either:
* show a spinner and load the members if the user is joined,
* or show the members available so far if the user is invited
*/
async _showMembersAccordingToMembershipWithLL() {
const cli = _MatrixClientPeg.MatrixClientPeg.get();
if (cli.hasLazyLoadMembersEnabled()) {
const cli = _MatrixClientPeg.MatrixClientPeg.get();
const room = cli.getRoom(this.props.roomId);
const membership = room && room.getMyMembership();
if (membership === "join") {
this.setState({
loading: true
});
try {
await room.loadMembersIfNeeded();
} catch (ex) {
/* already logged in RoomView */
}
if (this._mounted) {
this.setState(this._getMembersState(this.roomMembers()));
this._listenForMembersChanges();
}
} else {
// show the members we already have loaded
this.setState(this._getMembersState(this.roomMembers()));
}
}
}
_getMembersState(members) {
// set the state after determining _showPresence to make sure it's
// taken into account while rerendering
return {
loading: false,
members: members,
filteredJoinedMembers: this._filterMembers(members, 'join'),
filteredInvitedMembers: this._filterMembers(members, 'invite'),
// ideally we'd size this to the page height, but
// in practice I find that a little constraining
truncateAtJoined: INITIAL_LOAD_NUM_MEMBERS,
truncateAtInvited: INITIAL_LOAD_NUM_INVITED,
searchQuery: ""
};
}
_updateListNow() {
// console.log("Updating memberlist");
const newState = {
loading: false,
members: this.roomMembers()
};
newState.filteredJoinedMembers = this._filterMembers(newState.members, 'join', this.state.searchQuery);
newState.filteredInvitedMembers = this._filterMembers(newState.members, 'invite', this.state.searchQuery);
this.setState(newState);
}
getMembersWithUser() {
if (!this.props.roomId) return [];
const cli = _MatrixClientPeg.MatrixClientPeg.get();
const room = cli.getRoom(this.props.roomId);
if (!room) return [];
const allMembers = Object.values(room.currentState.members);
allMembers.forEach(function (member) {
// work around a race where you might have a room member object
// before the user object exists. This may or may not cause
// https://github.com/vector-im/vector-web/issues/186
if (member.user === null) {
member.user = cli.getUser(member.userId);
} // XXX: this user may have no lastPresenceTs value!
// the right solution here is to fix the race rather than leave it as 0
});
return allMembers;
}
roomMembers() {
const allMembers = this.getMembersWithUser();
const filteredAndSortedMembers = allMembers.filter(m => {
return m.membership === 'join' || m.membership === 'invite';
});
filteredAndSortedMembers.sort(this.memberSort);
return filteredAndSortedMembers;
}
memberString(member) {
if (!member) {
return "(null)";
} else {
const u = member.user;
return "(" + member.name + ", " + member.powerLevel + ", " + (u ? u.lastActiveAgo : "<null>") + ", " + (u ? u.getLastActiveTs() : "<null>") + ", " + (u ? u.currentlyActive : "<null>") + ", " + (u ? u.presence : "<null>") + ")";
}
} // returns negative if a comes before b,
// returns 0 if a and b are equivalent in ordering
// returns positive if a comes after b.
_filterMembers(members, membership, query) {
return members.filter(m => {
if (query) {
query = query.toLowerCase();
const matchesName = m.name.toLowerCase().indexOf(query) !== -1;
const matchesId = m.userId.toLowerCase().indexOf(query) !== -1;
if (!matchesName && !matchesId) {
return false;
}
}
return m.membership === membership;
});
}
_getPending3PidInvites() {
// include 3pid invites (m.room.third_party_invite) state events.
// The HS may have already converted these into m.room.member invites so
// we shouldn't add them if the 3pid invite state key (token) is in the
// member invite (content.third_party_invite.signed.token)
const room = _MatrixClientPeg.MatrixClientPeg.get().getRoom(this.props.roomId);
if (room) {
return room.currentState.getStateEvents("m.room.third_party_invite").filter(function (e) {
if (!(0, _RoomInvite.isValid3pidInvite)(e)) return false; // discard all invites which have a m.room.member event since we've
// already added them.
const memberEvent = room.currentState.getInviteForThreePidToken(e.getStateKey());
if (memberEvent) return false;
return true;
});
}
}
_makeMemberTiles(members) {
const MemberTile = sdk.getComponent("rooms.MemberTile");
const EntityTile = sdk.getComponent("rooms.EntityTile");
return members.map(m => {
if (m.userId) {
// Is a Matrix invite
return /*#__PURE__*/_react.default.createElement(MemberTile, {
key: m.userId,
member: m,
ref: m.userId,
showPresence: this._showPresence
});
} else {
// Is a 3pid invite
return /*#__PURE__*/_react.default.createElement(EntityTile, {
key: m.getStateKey(),
name: m.getContent().display_name,
suppressOnHover: true,
onClick: () => this._onPending3pidInviteClick(m)
});
}
});
}
render() {
if (this.state.loading) {
const Spinner = sdk.getComponent("elements.Spinner");
return /*#__PURE__*/_react.default.createElement(_BaseCard.default, {
className: "mx_MemberList",
onClose: this.props.onClose,
previousPhase: _RightPanelStorePhases.RightPanelPhases.RoomSummary
}, /*#__PURE__*/_react.default.createElement(Spinner, null));
}
const SearchBox = sdk.getComponent('structures.SearchBox');
const TruncatedList = sdk.getComponent("elements.TruncatedList");
const cli = _MatrixClientPeg.MatrixClientPeg.get();
const room = cli.getRoom(this.props.roomId);
let inviteButton;
if (room && room.getMyMembership() === 'join') {
const canInvite = room.canInvite(cli.getUserId());
let inviteButtonText = (0, _languageHandler._t)("Invite to this room");
const chat = _CommunityPrototypeStore.CommunityPrototypeStore.instance.getSelectedCommunityGeneralChat();
if (chat && chat.roomId === this.props.roomId) {
inviteButtonText = (0, _languageHandler._t)("Invite to this community");
} else if (_SettingsStore.default.getValue("feature_spaces") && room.isSpaceRoom()) {
inviteButtonText = (0, _languageHandler._t)("Invite to this space");
}
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
inviteButton = /*#__PURE__*/_react.default.createElement(AccessibleButton, {
className: "mx_MemberList_invite",
onClick: this.onInviteButtonClick,
disabled: !canInvite
}, /*#__PURE__*/_react.default.createElement("span", null, inviteButtonText));
}
let invitedHeader;
let invitedSection;
if (this._getChildCountInvited() > 0) {
invitedHeader = /*#__PURE__*/_react.default.createElement("h2", null, (0, _languageHandler._t)("Invited"));
invitedSection = /*#__PURE__*/_react.default.createElement(TruncatedList, {
className: "mx_MemberList_section mx_MemberList_invited",
truncateAt: this.state.truncateAtInvited,
createOverflowElement: this._createOverflowTileInvited,
getChildren: this._getChildrenInvited,
getChildCount: this._getChildCountInvited
});
}
const footer = /*#__PURE__*/_react.default.createElement(SearchBox, {
className: "mx_MemberList_query mx_textinput_icon mx_textinput_search",
placeholder: (0, _languageHandler._t)('Filter room members'),
onSearch: this.onSearchQueryChanged
});
let previousPhase = _RightPanelStorePhases.RightPanelPhases.RoomSummary; // We have no previousPhase for when viewing a MemberList from a Space
let scopeHeader;
if (_SettingsStore.default.getValue("feature_spaces") && room?.isSpaceRoom()) {
previousPhase = undefined;
scopeHeader = /*#__PURE__*/_react.default.createElement("div", {
className: "mx_RightPanel_scopeHeader"
}, /*#__PURE__*/_react.default.createElement(_RoomAvatar.default, {
room: room,
height: 32,
width: 32
}), /*#__PURE__*/_react.default.createElement(_RoomName.default, {
room: room
}));
}
return /*#__PURE__*/_react.default.createElement(_BaseCard.default, {
className: "mx_MemberList",
header: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, scopeHeader, inviteButton),
footer: footer,
onClose: this.props.onClose,
previousPhase: previousPhase
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_MemberList_wrapper"
}, /*#__PURE__*/_react.default.createElement(TruncatedList, {
className: "mx_MemberList_section mx_MemberList_joined",
truncateAt: this.state.truncateAtJoined,
createOverflowElement: this._createOverflowTileJoined,
getChildren: this._getChildrenJoined,
getChildCount: this._getChildCountJoined
}), invitedHeader, invitedSection));
}
}, _temp)) || _class);
exports.default = MemberList;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL3Jvb21zL01lbWJlckxpc3QuanMiXSwibmFtZXMiOlsiSU5JVElBTF9MT0FEX05VTV9NRU1CRVJTIiwiSU5JVElBTF9MT0FEX05VTV9JTlZJVEVEIiwiU0hPV19NT1JFX0lOQ1JFTUVOVCIsIlNPUlRfUkVHRVgiLCJNZW1iZXJMaXN0IiwiUmVhY3QiLCJDb21wb25lbnQiLCJjb25zdHJ1Y3RvciIsInByb3BzIiwiZXZlbnQiLCJ1c2VyIiwidGlsZSIsInJlZnMiLCJ1c2VySWQiLCJfdXBkYXRlTGlzdCIsInJvb20iLCJyb29tSWQiLCJfc2hvd01lbWJlcnNBY2NvcmRpbmdUb01lbWJlcnNoaXBXaXRoTEwiLCJtZW1iZXJzaGlwIiwib2xkTWVtYmVyc2hpcCIsImV2Iiwic3RhdGUiLCJtZW1iZXIiLCJnZXRSb29tSWQiLCJnZXRUeXBlIiwiX3VwZGF0ZUxpc3ROb3ciLCJvdmVyZmxvd0NvdW50IiwidG90YWxDb3VudCIsIl9jcmVhdGVPdmVyZmxvd1RpbGUiLCJfc2hvd01vcmVKb2luZWRNZW1iZXJMaXN0IiwiX3Nob3dNb3JlSW52aXRlZE1lbWJlckxpc3QiLCJvbkNsaWNrIiwiRW50aXR5VGlsZSIsInNkayIsImdldENvbXBvbmVudCIsIkJhc2VBdmF0YXIiLCJ0ZXh0IiwiY291bnQiLCJyZXF1aXJlIiwic2V0U3RhdGUiLCJ0cnVuY2F0ZUF0Sm9pbmVkIiwidHJ1bmNhdGVBdEludml0ZWQiLCJtZW1iZXJBIiwibWVtYmVyQiIsInVzZXJBIiwidXNlckIiLCJfc2hvd1ByZXNlbmNlIiwiY29udmVydFByZXNlbmNlIiwicCIsInByZXNlbmNlSW5kZXgiLCJvcmRlciIsImlkeCIsImluZGV4T2YiLCJsZW5ndGgiLCJpZHhBIiwiY3VycmVudGx5QWN0aXZlIiwicHJlc2VuY2UiLCJpZHhCIiwicG93ZXJMZXZlbCIsImdldExhc3RBY3RpdmVUcyIsIm5hbWVBIiwibmFtZSIsInN1YnN0ciIsInJlcGxhY2UiLCJuYW1lQiIsImxvY2FsZUNvbXBhcmUiLCJpZ25vcmVQdW5jdHVhdGlvbiIsInNlbnNpdGl2aXR5Iiwic2VhcmNoUXVlcnkiLCJmaWx0ZXJlZEpvaW5lZE1lbWJlcnMiLCJfZmlsdGVyTWVtYmVycyIsIm1lbWJlcnMiLCJmaWx0ZXJlZEludml0ZWRNZW1iZXJzIiwiaW52aXRlRXZlbnQiLCJkaXMiLCJkaXNwYXRjaCIsImFjdGlvbiIsInN0YXJ0IiwiZW5kIiwiX21ha2VNZW1iZXJUaWxlcyIsInNsaWNlIiwidGFyZ2V0cyIsImNvbmNhdCIsIl9nZXRQZW5kaW5nM1BpZEludml0ZXMiLCJNYXRyaXhDbGllbnRQZWciLCJnZXQiLCJpc0d1ZXN0IiwiY2xpIiwiaGFzTGF6eUxvYWRNZW1iZXJzRW5hYmxlZCIsIl9nZXRNZW1iZXJzU3RhdGUiLCJyb29tTWVtYmVycyIsIm9uIiwib25Sb29tIiwiZW5hYmxlUHJlc2VuY2VCeUhzVXJsIiwiU2RrQ29uZmlnIiwiaHNVcmwiLCJiYXNlVXJsIiwidW5kZWZpbmVkIiwiVU5TQUZFX2NvbXBvbmVudFdpbGxNb3VudCIsIl9tb3VudGVkIiwib25NeU1lbWJlcnNoaXAiLCJfbGlzdGVuRm9yTWVtYmVyc0NoYW5nZXMiLCJvblJvb21TdGF0ZU1lbWJlciIsIm9uUm9vbU1lbWJlck5hbWUiLCJvblJvb21TdGF0ZUV2ZW50Iiwib25Vc2VyUHJlc2VuY2VDaGFuZ2UiLCJjb21wb25lbnRXaWxsVW5tb3VudCIsInJlbW92ZUxpc3RlbmVyIiwiY2FuY2VsUGVuZGluZ0NhbGwiLCJnZXRSb29tIiwiZ2V0TXlNZW1iZXJzaGlwIiwibG9hZGluZyIsImxvYWRNZW1iZXJzSWZOZWVkZWQiLCJleCIsIm5ld1N0YXRlIiwiZ2V0TWVtYmVyc1dpdGhVc2VyIiwiYWxsTWVtYmVycyIsIk9iamVjdCIsInZhbHVlcyIsImN1cnJlbnRTdGF0ZSIsImZvckVhY2giLCJnZXRVc2VyIiwiZmlsdGVyZWRBbmRTb3J0ZWRNZW1iZXJzIiwiZmlsdGVyIiwibSIsInNvcnQiLCJtZW1iZXJTb3J0IiwibWVtYmVyU3RyaW5nIiwidSIsImxhc3RBY3RpdmVBZ28iLCJxdWVyeSIsInRvTG93ZXJDYXNlIiwibWF0Y2hlc05hbWUiLCJtYXRjaGVzSWQiLCJnZXRTdGF0ZUV2ZW50cyIsImUiLCJtZW1iZXJFdmVudCIsImdldEludml0ZUZvclRocmVlUGlkVG9rZW4iLCJnZXRTdGF0ZUtleSIsIk1lbWJlclRpbGUiLCJtYXAiLCJnZXRDb250ZW50IiwiZGlzcGxheV9uYW1lIiwiX29uUGVuZGluZzNwaWRJbnZpdGVDbGljayIsInJlbmRlciIsIlNwaW5uZXIiLCJvbkNsb3NlIiwiUmlnaHRQYW5lbFBoYXNlcyIsIlJvb21TdW1tYXJ5IiwiU2VhcmNoQm94IiwiVHJ1bmNhdGVkTGlzdCIsImludml0ZUJ1dHRvbiIsImNhbkludml0ZSIsImdldFVzZXJJZCIsImludml0ZUJ1dHRvblRleHQiLCJjaGF0IiwiQ29tbXVuaXR5UHJvdG90eXBlU3RvcmUiLCJpbnN0YW5jZSIsImdldFNlbGVjdGVkQ29tbXVuaXR5R2VuZXJhbENoYXQiLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJpc1NwYWNlUm9vbSIsIkFjY2Vzc2libGVCdXR0b24iLCJvbkludml0ZUJ1dHRvbkNsaWNrIiwiaW52aXRlZEhlYWRlciIsImludml0ZWRTZWN0aW9uIiwiX2dldENoaWxkQ291bnRJbnZpdGVkIiwiX2NyZWF0ZU92ZXJmbG93VGlsZUludml0ZWQiLCJfZ2V0Q2hpbGRyZW5JbnZpdGVkIiwiZm9vdGVyIiwib25TZWFyY2hRdWVyeUNoYW5nZWQiLCJwcmV2aW91c1BoYXNlIiwic2NvcGVIZWFkZXIiLCJfY3JlYXRlT3ZlcmZsb3dUaWxlSm9pbmVkIiwiX2dldENoaWxkcmVuSm9pbmVkIiwiX2dldENoaWxkQ291bnRKb2luZWQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFrQkE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7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M0M7QUFFZSxNQUFBLFdBQVcsRUFBRSxLQUFLQyxrQkFGakM7QUFHZSxNQUFBLGFBQWEsRUFBRSxLQUFLQztBQUhuQyxNQURKLEVBS01YLGFBTE4sRUFNTUMsY0FOTixDQVZHLENBQVA7QUFtQkg7O0FBL2RtRCxDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDE1LCAyMDE2IE9wZW5NYXJrZXQgTHRkXG5Db3B5cmlnaHQgMjAxNyBWZWN0b3IgQ3JlYXRpb25zIEx0ZFxuQ29weXJpZ2h0IDIwMTcsIDIwMTggTmV3IFZlY3RvciBMdGRcblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4qL1xuXG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IHsgX3QgfSBmcm9tICcuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXInO1xuaW1wb3J0IFNka0NvbmZpZyBmcm9tICcuLi8uLi8uLi9TZGtDb25maWcnO1xuaW1wb3J0IGRpcyBmcm9tICcuLi8uLi8uLi9kaXNwYXRjaGVyL2Rpc3BhdGNoZXInO1xuaW1wb3J0IHtpc1ZhbGlkM3BpZEludml0ZX0gZnJvbSBcIi4uLy4uLy4uL1Jvb21JbnZpdGVcIjtcbmltcG9ydCByYXRlX2xpbWl0ZWRfZnVuYyBmcm9tIFwiLi4vLi4vLi4vcmF0ZWxpbWl0ZWRmdW5jXCI7XG5pbXBvcnQge01hdHJpeENsaWVudFBlZ30gZnJvbSBcIi4uLy4uLy4uL01hdHJpeENsaWVudFBlZ1wiO1xuaW1wb3J0ICogYXMgc2RrIGZyb20gXCIuLi8uLi8uLi9pbmRleFwiO1xuaW1wb3J0IHtDb21tdW5pdHlQcm90b3R5cGVTdG9yZX0gZnJvbSBcIi4uLy4uLy4uL3N0b3Jlcy9Db21tdW5pdHlQcm90b3R5cGVTdG9yZVwiO1xuaW1wb3J0IEJhc2VDYXJkIGZyb20gXCIuLi9yaWdodF9wYW5lbC9CYXNlQ2FyZFwiO1xuaW1wb3J0IHtSaWdodFBhbmVsUGhhc2VzfSBmcm9tIFwiLi4vLi4vLi4vc3RvcmVzL1JpZ2h0UGFuZWxTdG9yZVBoYXNlc1wiO1xuaW1wb3J0IFJvb21BdmF0YXIgZnJvbSBcIi4uL2F2YXRhcnMvUm9vbUF2YXRhclwiO1xuaW1wb3J0IFJvb21OYW1lIGZyb20gXCIuLi9lbGVtZW50cy9Sb29tTmFtZVwiO1xuaW1wb3J0IHtyZXBsYWNlYWJsZUNvbXBvbmVudH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL3JlcGxhY2VhYmxlQ29tcG9uZW50XCI7XG5pbXBvcnQgU2V0dGluZ3NTdG9yZSBmcm9tIFwiLi4vLi4vLi4vc2V0dGluZ3MvU2V0dGluZ3NTdG9yZVwiO1xuXG5jb25zdCBJTklUSUFMX0xPQURfTlVNX01FTUJFUlMgPSAzMDtcbmNvbnN0IElOSVRJQUxfTE9BRF9OVU1fSU5WSVRFRCA9IDU7XG5jb25zdCBTSE9XX01PUkVfSU5DUkVNRU5UID0gMTAwO1xuXG4vLyBSZWdleCBhcHBsaWVkIHRvIGZpbHRlciBvdXIgcHVuY3R1YXRpb24gaW4gbWVtYmVyIG5hbWVzIGJlZm9yZSBhcHBseWluZyBzb3J0LCB0byBmdXp6eSBpdCBhIGxpdHRsZVxuLy8gbWF0Y2hlcyBhbGwgQVNDSUkgcHVuY3R1YXRpb246ICFcIiMkJSYnKCkqKywtLi86Ozw9Pj9AW1xcXV5fYHt8fX5cbmNvbnN0IFNPUlRfUkVHRVggPSAvW1xceDIxLVxceDJGXFx4M0EtXFx4NDBcXHg1Qi1cXHg2MFxceDdCLVxceDdFXSsvZztcblxuQHJlcGxhY2VhYmxlQ29tcG9uZW50KFwidmlld3Mucm9vbXMuTWVtYmVyTGlzdFwiKVxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTWVtYmVyTGlzdCBleHRlbmRzIFJlYWN0LkNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICAgICAgc3VwZXIocHJvcHMpO1xuXG4gICAgICAgIGNvbnN0IGNsaSA9IE1hdHJpeENsaWVudFBlZy5nZXQoKTtcbiAgICAgICAgaWYgKGNsaS5oYXNMYXp5TG9hZE1lbWJlcnNFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIC8vIHNob3cgYW4gZW1wdHkgbGlzdFxuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IHRoaXMuX2dldE1lbWJlcnNTdGF0ZShbXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gdGhpcy5fZ2V0TWVtYmVyc1N0YXRlKHRoaXMucm9vbU1lbWJlcnMoKSk7XG4gICAgICAgIH1cblxuICAgICAgICBjbGkub24oXCJSb29tXCIsIHRoaXMub25Sb29tKTsgLy8gaW52aXRlcyAmIGpvaW5pbmcgYWZ0ZXIgcGVla1xuICAgICAgICBjb25zdCBlbmFibGVQcmVzZW5jZUJ5SHNVcmwgPSBTZGtDb25maWcuZ2V0KClbXCJlbmFibGVfcHJlc2VuY2VfYnlfaHNfdXJsXCJdO1xuICAgICAgICBjb25zdCBoc1VybCA9IE1hdHJpeENsaWVudFBlZy5nZXQoKS5iYXNlVXJsO1xuICAgICAgICB0aGlzLl9zaG93UHJlc2VuY2UgPSB0cnVlO1xuICAgICAgICBpZiAoZW5hYmxlUHJlc2VuY2VCeUhzVXJsICYmIGVuYWJsZVByZXNlbmNlQnlIc1VybFtoc1VybF0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5fc2hvd1ByZXNlbmNlID0gZW5hYmxlUHJlc2VuY2VCeUhzVXJsW2hzVXJsXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjYW1lbGNhc2VcbiAgICBVTlNBRkVfY29tcG9uZW50V2lsbE1vdW50KCkge1xuICAgICAgICBjb25zdCBjbGkgPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCk7XG4gICAgICAgIHRoaXMuX21vdW50ZWQgPSB0cnVlO1xuICAgICAgICBpZiAoY2xpLmhhc0xhenlMb2FkTWVtYmVyc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5fc2hvd01lbWJlcnNBY2NvcmRpbmdUb01lbWJlcnNoaXBXaXRoTEwoKTtcbiAgICAgICAgICAgIGNsaS5vbihcIlJvb20ubXlNZW1iZXJzaGlwXCIsIHRoaXMub25NeU1lbWJlcnNoaXApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fbGlzdGVuRm9yTWVtYmVyc0NoYW5nZXMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIF9saXN0ZW5Gb3JNZW1iZXJzQ2hhbmdlcygpIHtcbiAgICAgICAgY29uc3QgY2xpID0gTWF0cml4Q2xpZW50UGVnLmdldCgpO1xuICAgICAgICBjbGkub24oXCJSb29tU3RhdGUubWVtYmVyc1wiLCB0aGlzLm9uUm9vbVN0YXRlTWVtYmVyKTtcbiAgICAgICAgY2xpLm9uKFwiUm9vbU1lbWJlci5uYW1lXCIsIHRoaXMub25Sb29tTWVtYmVyTmFtZSk7XG4gICAgICAgIGNsaS5vbihcIlJvb21TdGF0ZS5ldmVudHNcIiwgdGhpcy5vblJvb21TdGF0ZUV2ZW50KTtcbiAgICAgICAgLy8gV2UgbGlzdGVuIGZvciBjaGFuZ2VzIHRvIHRoZSBsYXN0UHJlc2VuY2VUcyB3aGljaCBpcyBlc3NlbnRpYWxseVxuICAgICAgICAvLyBsaXN0ZW5pbmcgZm9yIGFsbCBwcmVzZW5jZSBldmVudHMgKHdlIGRpc3BsYXkgbW9zdCBvZiBub3QgYWxsIG9mXG4gICAgICAgIC8vIHRoZSBpbmZvcm1hdGlvbiBjb250YWluZWQgaW4gcHJlc2VuY2UgZXZlbnRzKS5cbiAgICAgICAgY2xpLm9uKFwiVXNlci5sYXN0UHJlc2VuY2VUc1wiLCB0aGlzLm9uVXNlclByZXNlbmNlQ2hhbmdlKTtcbiAgICAgICAgY2xpLm9uKFwiVXNlci5wcmVzZW5jZVwiLCB0aGlzLm9uVXNlclByZXNlbmNlQ2hhbmdlKTtcbiAgICAgICAgY2xpLm9u