matrix-react-sdk
Version:
SDK for matrix.org using React
183 lines (173 loc) • 24.5 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MARKED_UNREAD_TYPE_UNSTABLE = exports.MARKED_UNREAD_TYPE_STABLE = void 0;
exports.clearAllNotifications = clearAllNotifications;
exports.clearRoomNotification = clearRoomNotification;
exports.createLocalNotificationSettingsIfNeeded = createLocalNotificationSettingsIfNeeded;
exports.deviceNotificationSettingsKeys = void 0;
exports.getLocalNotificationAccountDataEventType = getLocalNotificationAccountDataEventType;
exports.getMarkedUnreadState = getMarkedUnreadState;
exports.getThreadNotificationLevel = getThreadNotificationLevel;
exports.localNotificationsAreSilenced = localNotificationsAreSilenced;
exports.notificationLevelToIndicator = notificationLevelToIndicator;
exports.setMarkedUnreadState = setMarkedUnreadState;
var _matrix = require("matrix-js-sdk/src/matrix");
var _SettingsStore = _interopRequireDefault(require("../settings/SettingsStore"));
var _NotificationLevel = require("../stores/notifications/NotificationLevel");
var _Unread = require("../Unread");
/*
Copyright 2024 New Vector Ltd.
Copyright 2022 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.
*/
// MSC2867 is not yet spec at time of writing. We read from both stable
// and unstable prefixes and accept the risk that the format may change,
// since the stable prefix is not actually defined yet.
/**
* Unstable identifier for the marked_unread event, per MSC2867
*/
const MARKED_UNREAD_TYPE_UNSTABLE = exports.MARKED_UNREAD_TYPE_UNSTABLE = "com.famedly.marked_unread";
/**
* Stable identifier for the marked_unread event
*/
const MARKED_UNREAD_TYPE_STABLE = exports.MARKED_UNREAD_TYPE_STABLE = "m.marked_unread";
const deviceNotificationSettingsKeys = exports.deviceNotificationSettingsKeys = ["notificationsEnabled", "notificationBodyEnabled", "audioNotificationsEnabled"];
function getLocalNotificationAccountDataEventType(deviceId) {
return `${_matrix.LOCAL_NOTIFICATION_SETTINGS_PREFIX.name}.${deviceId}`;
}
async function createLocalNotificationSettingsIfNeeded(cli) {
if (cli.isGuest()) {
return;
}
const eventType = getLocalNotificationAccountDataEventType(cli.deviceId);
const event = cli.getAccountData(eventType);
// New sessions will create an account data event to signify they support
// remote toggling of push notifications on this device. Default `is_silenced=true`
// For backwards compat purposes, older sessions will need to check settings value
// to determine what the state of `is_silenced`
if (!event) {
// If any of the above is true, we fall in the "backwards compat" case,
// and `is_silenced` will be set to `false`
const isSilenced = !deviceNotificationSettingsKeys.some(key => _SettingsStore.default.getValue(key));
await cli.setAccountData(eventType, {
is_silenced: isSilenced
});
}
}
function localNotificationsAreSilenced(cli) {
const eventType = getLocalNotificationAccountDataEventType(cli.deviceId);
const event = cli.getAccountData(eventType);
return event?.getContent()?.is_silenced ?? false;
}
/**
* Mark a room as read
* @param room
* @param client
* @returns a promise that resolves when the room has been marked as read
*/
async function clearRoomNotification(room, client) {
const lastEvent = room.getLastLiveEvent();
await setMarkedUnreadState(room, client, false);
try {
if (lastEvent) {
const receiptType = _SettingsStore.default.getValue("sendReadReceipts", room.roomId) ? _matrix.ReceiptType.Read : _matrix.ReceiptType.ReadPrivate;
return await client.sendReadReceipt(lastEvent, receiptType, true);
} else {
return {};
}
} finally {
// We've had a lot of stuck unread notifications that in e2ee rooms
// They occur on event decryption when clients try to replicate the logic
//
// This resets the notification on a room, even though no read receipt
// has been sent, particularly useful when the clients has incorrectly
// notified a user.
room.setUnreadNotificationCount(_matrix.NotificationCountType.Highlight, 0);
room.setUnreadNotificationCount(_matrix.NotificationCountType.Total, 0);
for (const thread of room.getThreads()) {
room.setThreadUnreadNotificationCount(thread.id, _matrix.NotificationCountType.Highlight, 0);
room.setThreadUnreadNotificationCount(thread.id, _matrix.NotificationCountType.Total, 0);
}
}
}
/**
* Marks all rooms with an unread counter as read
* @param client The matrix client
* @returns a promise that resolves when all rooms have been marked as read
*/
function clearAllNotifications(client) {
const receiptPromises = client.getRooms().reduce((promises, room) => {
if ((0, _Unread.doesRoomHaveUnreadMessages)(room, true)) {
const promise = clearRoomNotification(room, client);
promises.push(promise);
}
return promises;
}, []);
return Promise.all(receiptPromises);
}
/**
* Gives the marked_unread state of the given room
* @param room The room to check
* @returns - The marked_unread state of the room, or undefined if no explicit state is set.
*/
function getMarkedUnreadState(room) {
const currentStateStable = room.getAccountData(MARKED_UNREAD_TYPE_STABLE)?.getContent()?.unread;
const currentStateUnstable = room.getAccountData(MARKED_UNREAD_TYPE_UNSTABLE)?.getContent()?.unread;
return currentStateStable ?? currentStateUnstable;
}
/**
* Sets the marked_unread state of the given room. This sets some room account data that indicates to
* clients that the user considers this room to be 'unread', but without any actual notifications.
*
* @param room The room to set
* @param client MatrixClient object to use
* @param unread The new marked_unread state of the room
*/
async function setMarkedUnreadState(room, client, unread) {
// if there's no event, treat this as false as we don't need to send the flag to clear it if the event isn't there
const currentState = getMarkedUnreadState(room);
if (Boolean(currentState) !== unread) {
// Assuming MSC2867 passes FCP with no changes, we should update to start writing
// the flag to the stable prefix (or both) and then ultimately use only the
// stable prefix.
await client.setRoomAccountData(room.roomId, MARKED_UNREAD_TYPE_UNSTABLE, {
unread
});
}
}
/**
* A helper to transform a notification color to the what the Compound Icon Button
* expects
*/
function notificationLevelToIndicator(level) {
if (level <= _NotificationLevel.NotificationLevel.None) {
return undefined;
} else if (level <= _NotificationLevel.NotificationLevel.Activity) {
return "default";
} else if (level <= _NotificationLevel.NotificationLevel.Notification) {
return "success";
} else {
return "critical";
}
}
/**
* Return the thread notification level for a room
* @param room
* @returns {NotificationLevel}
*/
function getThreadNotificationLevel(room) {
const notificationCountType = room.threadsAggregateNotificationType;
switch (notificationCountType) {
case _matrix.NotificationCountType.Highlight:
return _NotificationLevel.NotificationLevel.Highlight;
case _matrix.NotificationCountType.Total:
return _NotificationLevel.NotificationLevel.Notification;
default:
return _NotificationLevel.NotificationLevel.Activity;
}
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0cml4IiwicmVxdWlyZSIsIl9TZXR0aW5nc1N0b3JlIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9Ob3RpZmljYXRpb25MZXZlbCIsIl9VbnJlYWQiLCJNQVJLRURfVU5SRUFEX1RZUEVfVU5TVEFCTEUiLCJleHBvcnRzIiwiTUFSS0VEX1VOUkVBRF9UWVBFX1NUQUJMRSIsImRldmljZU5vdGlmaWNhdGlvblNldHRpbmdzS2V5cyIsImdldExvY2FsTm90aWZpY2F0aW9uQWNjb3VudERhdGFFdmVudFR5cGUiLCJkZXZpY2VJZCIsIkxPQ0FMX05PVElGSUNBVElPTl9TRVRUSU5HU19QUkVGSVgiLCJuYW1lIiwiY3JlYXRlTG9jYWxOb3RpZmljYXRpb25TZXR0aW5nc0lmTmVlZGVkIiwiY2xpIiwiaXNHdWVzdCIsImV2ZW50VHlwZSIsImV2ZW50IiwiZ2V0QWNjb3VudERhdGEiLCJpc1NpbGVuY2VkIiwic29tZSIsImtleSIsIlNldHRpbmdzU3RvcmUiLCJnZXRWYWx1ZSIsInNldEFjY291bnREYXRhIiwiaXNfc2lsZW5jZWQiLCJsb2NhbE5vdGlmaWNhdGlvbnNBcmVTaWxlbmNlZCIsImdldENvbnRlbnQiLCJjbGVhclJvb21Ob3RpZmljYXRpb24iLCJyb29tIiwiY2xpZW50IiwibGFzdEV2ZW50IiwiZ2V0TGFzdExpdmVFdmVudCIsInNldE1hcmtlZFVucmVhZFN0YXRlIiwicmVjZWlwdFR5cGUiLCJyb29tSWQiLCJSZWNlaXB0VHlwZSIsIlJlYWQiLCJSZWFkUHJpdmF0ZSIsInNlbmRSZWFkUmVjZWlwdCIsInNldFVucmVhZE5vdGlmaWNhdGlvbkNvdW50IiwiTm90aWZpY2F0aW9uQ291bnRUeXBlIiwiSGlnaGxpZ2h0IiwiVG90YWwiLCJ0aHJlYWQiLCJnZXRUaHJlYWRzIiwic2V0VGhyZWFkVW5yZWFkTm90aWZpY2F0aW9uQ291bnQiLCJpZCIsImNsZWFyQWxsTm90aWZpY2F0aW9ucyIsInJlY2VpcHRQcm9taXNlcyIsImdldFJvb21zIiwicmVkdWNlIiwicHJvbWlzZXMiLCJkb2VzUm9vbUhhdmVVbnJlYWRNZXNzYWdlcyIsInByb21pc2UiLCJwdXNoIiwiUHJvbWlzZSIsImFsbCIsImdldE1hcmtlZFVucmVhZFN0YXRlIiwiY3VycmVudFN0YXRlU3RhYmxlIiwidW5yZWFkIiwiY3VycmVudFN0YXRlVW5zdGFibGUiLCJjdXJyZW50U3RhdGUiLCJCb29sZWFuIiwic2V0Um9vbUFjY291bnREYXRhIiwibm90aWZpY2F0aW9uTGV2ZWxUb0luZGljYXRvciIsImxldmVsIiwiTm90aWZpY2F0aW9uTGV2ZWwiLCJOb25lIiwidW5kZWZpbmVkIiwiQWN0aXZpdHkiLCJOb3RpZmljYXRpb24iLCJnZXRUaHJlYWROb3RpZmljYXRpb25MZXZlbCIsIm5vdGlmaWNhdGlvbkNvdW50VHlwZSIsInRocmVhZHNBZ2dyZWdhdGVOb3RpZmljYXRpb25UeXBlIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL25vdGlmaWNhdGlvbnMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMjIgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IHtcbiAgICBNYXRyaXhDbGllbnQsXG4gICAgTE9DQUxfTk9USUZJQ0FUSU9OX1NFVFRJTkdTX1BSRUZJWCxcbiAgICBOb3RpZmljYXRpb25Db3VudFR5cGUsXG4gICAgUm9vbSxcbiAgICBMb2NhbE5vdGlmaWNhdGlvblNldHRpbmdzLFxuICAgIFJlY2VpcHRUeXBlLFxuICAgIElNYXJrZWRVbnJlYWRFdmVudCxcbn0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgSW5kaWNhdG9ySWNvbiB9IGZyb20gXCJAdmVjdG9yLWltL2NvbXBvdW5kLXdlYlwiO1xuXG5pbXBvcnQgU2V0dGluZ3NTdG9yZSBmcm9tIFwiLi4vc2V0dGluZ3MvU2V0dGluZ3NTdG9yZVwiO1xuaW1wb3J0IHsgTm90aWZpY2F0aW9uTGV2ZWwgfSBmcm9tIFwiLi4vc3RvcmVzL25vdGlmaWNhdGlvbnMvTm90aWZpY2F0aW9uTGV2ZWxcIjtcbmltcG9ydCB7IGRvZXNSb29tSGF2ZVVucmVhZE1lc3NhZ2VzIH0gZnJvbSBcIi4uL1VucmVhZFwiO1xuXG4vLyBNU0MyODY3IGlzIG5vdCB5ZXQgc3BlYyBhdCB0aW1lIG9mIHdyaXRpbmcuIFdlIHJlYWQgZnJvbSBib3RoIHN0YWJsZVxuLy8gYW5kIHVuc3RhYmxlIHByZWZpeGVzIGFuZCBhY2NlcHQgdGhlIHJpc2sgdGhhdCB0aGUgZm9ybWF0IG1heSBjaGFuZ2UsXG4vLyBzaW5jZSB0aGUgc3RhYmxlIHByZWZpeCBpcyBub3QgYWN0dWFsbHkgZGVmaW5lZCB5ZXQuXG5cbi8qKlxuICogVW5zdGFibGUgaWRlbnRpZmllciBmb3IgdGhlIG1hcmtlZF91bnJlYWQgZXZlbnQsIHBlciBNU0MyODY3XG4gKi9cbmV4cG9ydCBjb25zdCBNQVJLRURfVU5SRUFEX1RZUEVfVU5TVEFCTEUgPSBcImNvbS5mYW1lZGx5Lm1hcmtlZF91bnJlYWRcIjtcbi8qKlxuICogU3RhYmxlIGlkZW50aWZpZXIgZm9yIHRoZSBtYXJrZWRfdW5yZWFkIGV2ZW50XG4gKi9cbmV4cG9ydCBjb25zdCBNQVJLRURfVU5SRUFEX1RZUEVfU1RBQkxFID0gXCJtLm1hcmtlZF91bnJlYWRcIjtcblxuZXhwb3J0IGNvbnN0IGRldmljZU5vdGlmaWNhdGlvblNldHRpbmdzS2V5cyA9IFtcbiAgICBcIm5vdGlmaWNhdGlvbnNFbmFibGVkXCIsXG4gICAgXCJub3RpZmljYXRpb25Cb2R5RW5hYmxlZFwiLFxuICAgIFwiYXVkaW9Ob3RpZmljYXRpb25zRW5hYmxlZFwiLFxuXTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldExvY2FsTm90aWZpY2F0aW9uQWNjb3VudERhdGFFdmVudFR5cGUoZGV2aWNlSWQ6IHN0cmluZyB8IG51bGwpOiBzdHJpbmcge1xuICAgIHJldHVybiBgJHtMT0NBTF9OT1RJRklDQVRJT05fU0VUVElOR1NfUFJFRklYLm5hbWV9LiR7ZGV2aWNlSWR9YDtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUxvY2FsTm90aWZpY2F0aW9uU2V0dGluZ3NJZk5lZWRlZChjbGk6IE1hdHJpeENsaWVudCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChjbGkuaXNHdWVzdCgpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZXZlbnRUeXBlID0gZ2V0TG9jYWxOb3RpZmljYXRpb25BY2NvdW50RGF0YUV2ZW50VHlwZShjbGkuZGV2aWNlSWQhKTtcbiAgICBjb25zdCBldmVudCA9IGNsaS5nZXRBY2NvdW50RGF0YShldmVudFR5cGUpO1xuICAgIC8vIE5ldyBzZXNzaW9ucyB3aWxsIGNyZWF0ZSBhbiBhY2NvdW50IGRhdGEgZXZlbnQgdG8gc2lnbmlmeSB0aGV5IHN1cHBvcnRcbiAgICAvLyByZW1vdGUgdG9nZ2xpbmcgb2YgcHVzaCBub3RpZmljYXRpb25zIG9uIHRoaXMgZGV2aWNlLiBEZWZhdWx0IGBpc19zaWxlbmNlZD10cnVlYFxuICAgIC8vIEZvciBiYWNrd2FyZHMgY29tcGF0IHB1cnBvc2VzLCBvbGRlciBzZXNzaW9ucyB3aWxsIG5lZWQgdG8gY2hlY2sgc2V0dGluZ3MgdmFsdWVcbiAgICAvLyB0byBkZXRlcm1pbmUgd2hhdCB0aGUgc3RhdGUgb2YgYGlzX3NpbGVuY2VkYFxuICAgIGlmICghZXZlbnQpIHtcbiAgICAgICAgLy8gSWYgYW55IG9mIHRoZSBhYm92ZSBpcyB0cnVlLCB3ZSBmYWxsIGluIHRoZSBcImJhY2t3YXJkcyBjb21wYXRcIiBjYXNlLFxuICAgICAgICAvLyBhbmQgYGlzX3NpbGVuY2VkYCB3aWxsIGJlIHNldCB0byBgZmFsc2VgXG4gICAgICAgIGNvbnN0IGlzU2lsZW5jZWQgPSAhZGV2aWNlTm90aWZpY2F0aW9uU2V0dGluZ3NLZXlzLnNvbWUoKGtleSkgPT4gU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShrZXkpKTtcblxuICAgICAgICBhd2FpdCBjbGkuc2V0QWNjb3VudERhdGEoZXZlbnRUeXBlLCB7XG4gICAgICAgICAgICBpc19zaWxlbmNlZDogaXNTaWxlbmNlZCxcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbG9jYWxOb3RpZmljYXRpb25zQXJlU2lsZW5jZWQoY2xpOiBNYXRyaXhDbGllbnQpOiBib29sZWFuIHtcbiAgICBjb25zdCBldmVudFR5cGUgPSBnZXRMb2NhbE5vdGlmaWNhdGlvbkFjY291bnREYXRhRXZlbnRUeXBlKGNsaS5kZXZpY2VJZCEpO1xuICAgIGNvbnN0IGV2ZW50ID0gY2xpLmdldEFjY291bnREYXRhKGV2ZW50VHlwZSk7XG4gICAgcmV0dXJuIGV2ZW50Py5nZXRDb250ZW50PExvY2FsTm90aWZpY2F0aW9uU2V0dGluZ3M+KCk/LmlzX3NpbGVuY2VkID8/IGZhbHNlO1xufVxuXG4vKipcbiAqIE1hcmsgYSByb29tIGFzIHJlYWRcbiAqIEBwYXJhbSByb29tXG4gKiBAcGFyYW0gY2xpZW50XG4gKiBAcmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSByb29tIGhhcyBiZWVuIG1hcmtlZCBhcyByZWFkXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjbGVhclJvb21Ob3RpZmljYXRpb24ocm9vbTogUm9vbSwgY2xpZW50OiBNYXRyaXhDbGllbnQpOiBQcm9taXNlPHt9IHwgdW5kZWZpbmVkPiB7XG4gICAgY29uc3QgbGFzdEV2ZW50ID0gcm9vbS5nZXRMYXN0TGl2ZUV2ZW50KCk7XG5cbiAgICBhd2FpdCBzZXRNYXJrZWRVbnJlYWRTdGF0ZShyb29tLCBjbGllbnQsIGZhbHNlKTtcblxuICAgIHRyeSB7XG4gICAgICAgIGlmIChsYXN0RXZlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlY2VpcHRUeXBlID0gU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShcInNlbmRSZWFkUmVjZWlwdHNcIiwgcm9vbS5yb29tSWQpXG4gICAgICAgICAgICAgICAgPyBSZWNlaXB0VHlwZS5SZWFkXG4gICAgICAgICAgICAgICAgOiBSZWNlaXB0VHlwZS5SZWFkUHJpdmF0ZTtcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCBjbGllbnQuc2VuZFJlYWRSZWNlaXB0KGxhc3RFdmVudCwgcmVjZWlwdFR5cGUsIHRydWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgLy8gV2UndmUgaGFkIGEgbG90IG9mIHN0dWNrIHVucmVhZCBub3RpZmljYXRpb25zIHRoYXQgaW4gZTJlZSByb29tc1xuICAgICAgICAvLyBUaGV5IG9jY3VyIG9uIGV2ZW50IGRlY3J5cHRpb24gd2hlbiBjbGllbnRzIHRyeSB0byByZXBsaWNhdGUgdGhlIGxvZ2ljXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFRoaXMgcmVzZXRzIHRoZSBub3RpZmljYXRpb24gb24gYSByb29tLCBldmVuIHRob3VnaCBubyByZWFkIHJlY2VpcHRcbiAgICAgICAgLy8gaGFzIGJlZW4gc2VudCwgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHRoZSBjbGllbnRzIGhhcyBpbmNvcnJlY3RseVxuICAgICAgICAvLyBub3RpZmllZCBhIHVzZXIuXG4gICAgICAgIHJvb20uc2V0VW5yZWFkTm90aWZpY2F0aW9uQ291bnQoTm90aWZpY2F0aW9uQ291bnRUeXBlLkhpZ2hsaWdodCwgMCk7XG4gICAgICAgIHJvb20uc2V0VW5yZWFkTm90aWZpY2F0aW9uQ291bnQoTm90aWZpY2F0aW9uQ291bnRUeXBlLlRvdGFsLCAwKTtcbiAgICAgICAgZm9yIChjb25zdCB0aHJlYWQgb2Ygcm9vbS5nZXRUaHJlYWRzKCkpIHtcbiAgICAgICAgICAgIHJvb20uc2V0VGhyZWFkVW5yZWFkTm90aWZpY2F0aW9uQ291bnQodGhyZWFkLmlkLCBOb3RpZmljYXRpb25Db3VudFR5cGUuSGlnaGxpZ2h0LCAwKTtcbiAgICAgICAgICAgIHJvb20uc2V0VGhyZWFkVW5yZWFkTm90aWZpY2F0aW9uQ291bnQodGhyZWFkLmlkLCBOb3RpZmljYXRpb25Db3VudFR5cGUuVG90YWwsIDApO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIE1hcmtzIGFsbCByb29tcyB3aXRoIGFuIHVucmVhZCBjb3VudGVyIGFzIHJlYWRcbiAqIEBwYXJhbSBjbGllbnQgVGhlIG1hdHJpeCBjbGllbnRcbiAqIEByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIHJvb21zIGhhdmUgYmVlbiBtYXJrZWQgYXMgcmVhZFxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xlYXJBbGxOb3RpZmljYXRpb25zKGNsaWVudDogTWF0cml4Q2xpZW50KTogUHJvbWlzZTxBcnJheTx7fSB8IHVuZGVmaW5lZD4+IHtcbiAgICBjb25zdCByZWNlaXB0UHJvbWlzZXMgPSBjbGllbnQuZ2V0Um9vbXMoKS5yZWR1Y2UoKHByb21pc2VzOiBBcnJheTxQcm9taXNlPHt9IHwgdW5kZWZpbmVkPj4sIHJvb206IFJvb20pID0+IHtcbiAgICAgICAgaWYgKGRvZXNSb29tSGF2ZVVucmVhZE1lc3NhZ2VzKHJvb20sIHRydWUpKSB7XG4gICAgICAgICAgICBjb25zdCBwcm9taXNlID0gY2xlYXJSb29tTm90aWZpY2F0aW9uKHJvb20sIGNsaWVudCk7XG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKHByb21pc2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHByb21pc2VzO1xuICAgIH0sIFtdKTtcblxuICAgIHJldHVybiBQcm9taXNlLmFsbChyZWNlaXB0UHJvbWlzZXMpO1xufVxuXG4vKipcbiAqIEdpdmVzIHRoZSBtYXJrZWRfdW5yZWFkIHN0YXRlIG9mIHRoZSBnaXZlbiByb29tXG4gKiBAcGFyYW0gcm9vbSBUaGUgcm9vbSB0byBjaGVja1xuICogQHJldHVybnMgLSBUaGUgbWFya2VkX3VucmVhZCBzdGF0ZSBvZiB0aGUgcm9vbSwgb3IgdW5kZWZpbmVkIGlmIG5vIGV4cGxpY2l0IHN0YXRlIGlzIHNldC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE1hcmtlZFVucmVhZFN0YXRlKHJvb206IFJvb20pOiBib29sZWFuIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBjdXJyZW50U3RhdGVTdGFibGUgPSByb29tLmdldEFjY291bnREYXRhKE1BUktFRF9VTlJFQURfVFlQRV9TVEFCTEUpPy5nZXRDb250ZW50PElNYXJrZWRVbnJlYWRFdmVudD4oKT8udW5yZWFkO1xuICAgIGNvbnN0IGN1cnJlbnRTdGF0ZVVuc3RhYmxlID0gcm9vbVxuICAgICAgICAuZ2V0QWNjb3VudERhdGEoTUFSS0VEX1VOUkVBRF9UWVBFX1VOU1RBQkxFKVxuICAgICAgICA/LmdldENvbnRlbnQ8SU1hcmtlZFVucmVhZEV2ZW50PigpPy51bnJlYWQ7XG4gICAgcmV0dXJuIGN1cnJlbnRTdGF0ZVN0YWJsZSA/PyBjdXJyZW50U3RhdGVVbnN0YWJsZTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBtYXJrZWRfdW5yZWFkIHN0YXRlIG9mIHRoZSBnaXZlbiByb29tLiBUaGlzIHNldHMgc29tZSByb29tIGFjY291bnQgZGF0YSB0aGF0IGluZGljYXRlcyB0b1xuICogY2xpZW50cyB0aGF0IHRoZSB1c2VyIGNvbnNpZGVycyB0aGlzIHJvb20gdG8gYmUgJ3VucmVhZCcsIGJ1dCB3aXRob3V0IGFueSBhY3R1YWwgbm90aWZpY2F0aW9ucy5cbiAqXG4gKiBAcGFyYW0gcm9vbSBUaGUgcm9vbSB0byBzZXRcbiAqIEBwYXJhbSBjbGllbnQgTWF0cml4Q2xpZW50IG9iamVjdCB0byB1c2VcbiAqIEBwYXJhbSB1bnJlYWQgVGhlIG5ldyBtYXJrZWRfdW5yZWFkIHN0YXRlIG9mIHRoZSByb29tXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZXRNYXJrZWRVbnJlYWRTdGF0ZShyb29tOiBSb29tLCBjbGllbnQ6IE1hdHJpeENsaWVudCwgdW5yZWFkOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gaWYgdGhlcmUncyBubyBldmVudCwgdHJlYXQgdGhpcyBhcyBmYWxzZSBhcyB3ZSBkb24ndCBuZWVkIHRvIHNlbmQgdGhlIGZsYWcgdG8gY2xlYXIgaXQgaWYgdGhlIGV2ZW50IGlzbid0IHRoZXJlXG4gICAgY29uc3QgY3VycmVudFN0YXRlID0gZ2V0TWFya2VkVW5yZWFkU3RhdGUocm9vbSk7XG5cbiAgICBpZiAoQm9vbGVhbihjdXJyZW50U3RhdGUpICE9PSB1bnJlYWQpIHtcbiAgICAgICAgLy8gQXNzdW1pbmcgTVNDMjg2NyBwYXNzZXMgRkNQIHdpdGggbm8gY2hhbmdlcywgd2Ugc2hvdWxkIHVwZGF0ZSB0byBzdGFydCB3cml0aW5nXG4gICAgICAgIC8vIHRoZSBmbGFnIHRvIHRoZSBzdGFibGUgcHJlZml4IChvciBib3RoKSBhbmQgdGhlbiB1bHRpbWF0ZWx5IHVzZSBvbmx5IHRoZVxuICAgICAgICAvLyBzdGFibGUgcHJlZml4LlxuICAgICAgICBhd2FpdCBjbGllbnQuc2V0Um9vbUFjY291bnREYXRhKHJvb20ucm9vbUlkLCBNQVJLRURfVU5SRUFEX1RZUEVfVU5TVEFCTEUsIHsgdW5yZWFkIH0pO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBIGhlbHBlciB0byB0cmFuc2Zvcm0gYSBub3RpZmljYXRpb24gY29sb3IgdG8gdGhlIHdoYXQgdGhlIENvbXBvdW5kIEljb24gQnV0dG9uXG4gKiBleHBlY3RzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBub3RpZmljYXRpb25MZXZlbFRvSW5kaWNhdG9yKFxuICAgIGxldmVsOiBOb3RpZmljYXRpb25MZXZlbCxcbik6IFJlYWN0LkNvbXBvbmVudFByb3BzV2l0aFJlZjx0eXBlb2YgSW5kaWNhdG9ySWNvbj5bXCJpbmRpY2F0b3JcIl0ge1xuICAgIGlmIChsZXZlbCA8PSBOb3RpZmljYXRpb25MZXZlbC5Ob25lKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfSBlbHNlIGlmIChsZXZlbCA8PSBOb3RpZmljYXRpb25MZXZlbC5BY3Rpdml0eSkge1xuICAgICAgICByZXR1cm4gXCJkZWZhdWx0XCI7XG4gICAgfSBlbHNlIGlmIChsZXZlbCA8PSBOb3RpZmljYXRpb25MZXZlbC5Ob3RpZmljYXRpb24pIHtcbiAgICAgICAgcmV0dXJuIFwic3VjY2Vzc1wiO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBcImNyaXRpY2FsXCI7XG4gICAgfVxufVxuXG4vKipcbiAqIFJldHVybiB0aGUgdGhyZWFkIG5vdGlmaWNhdGlvbiBsZXZlbCBmb3IgYSByb29tXG4gKiBAcGFyYW0gcm9vbVxuICogQHJldHVybnMge05vdGlmaWNhdGlvbkxldmVsfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VGhyZWFkTm90aWZpY2F0aW9uTGV2ZWwocm9vbTogUm9vbSk6IE5vdGlmaWNhdGlvbkxldmVsIHtcbiAgICBjb25zdCBub3RpZmljYXRpb25Db3VudFR5cGUgPSByb29tLnRocmVhZHNBZ2dyZWdhdGVOb3RpZmljYXRpb25UeXBlO1xuICAgIHN3aXRjaCAobm90aWZpY2F0aW9uQ291bnRUeXBlKSB7XG4gICAgICAgIGNhc2UgTm90aWZpY2F0aW9uQ291bnRUeXBlLkhpZ2hsaWdodDpcbiAgICAgICAgICAgIHJldHVybiBOb3RpZmljYXRpb25MZXZlbC5IaWdobGlnaHQ7XG4gICAgICAgIGNhc2UgTm90aWZpY2F0aW9uQ291bnRUeXBlLlRvdGFsOlxuICAgICAgICAgICAgcmV0dXJuIE5vdGlmaWNhdGlvbkxldmVsLk5vdGlmaWNhdGlvbjtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBOb3RpZmljYXRpb25MZXZlbC5BY3Rpdml0eTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBUUEs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