matrix-react-sdk
Version:
SDK for matrix.org using React
152 lines (144 loc) • 19.4 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.doesRoomHaveUnreadMessages = doesRoomHaveUnreadMessages;
exports.doesRoomHaveUnreadThreads = doesRoomHaveUnreadThreads;
exports.doesRoomOrThreadHaveUnreadMessages = doesRoomOrThreadHaveUnreadMessages;
exports.eventTriggersUnreadCount = eventTriggersUnreadCount;
var _matrix = require("matrix-js-sdk/src/matrix");
var _logger = require("matrix-js-sdk/src/logger");
var _shouldHideEvent = _interopRequireDefault(require("./shouldHideEvent"));
var _EventTileFactory = require("./events/EventTileFactory");
var _SettingsStore = _interopRequireDefault(require("./settings/SettingsStore"));
var _RoomNotifs = require("./RoomNotifs");
/*
Copyright 2024 New Vector Ltd.
Copyright 2015-2023 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.
*/
/**
* Returns true if this event arriving in a room should affect the room's
* count of unread messages
*
* @param client The Matrix Client instance of the logged-in user
* @param {Object} ev The event
* @returns {boolean} True if the given event should affect the unread message count
*/
function eventTriggersUnreadCount(client, ev) {
if (ev.getSender() === client.getSafeUserId()) {
return false;
}
switch (ev.getType()) {
case _matrix.EventType.RoomMember:
case _matrix.EventType.RoomThirdPartyInvite:
case _matrix.EventType.CallAnswer:
case _matrix.EventType.CallHangup:
case _matrix.EventType.RoomCanonicalAlias:
case _matrix.EventType.RoomServerAcl:
case _matrix.M_BEACON.name:
case _matrix.M_BEACON.altName:
return false;
}
if (ev.isRedacted()) return false;
return (0, _EventTileFactory.haveRendererForEvent)(ev, client, false /* hidden messages should never trigger unread counts anyways */);
}
function doesRoomHaveUnreadMessages(room, includeThreads) {
if (_SettingsStore.default.getValue("feature_sliding_sync")) {
// TODO: https://github.com/vector-im/element-web/issues/23207
// Sliding Sync doesn't support unread indicator dots (yet...)
return false;
}
const toCheck = [room];
if (includeThreads) {
toCheck.push(...room.getThreads());
}
for (const withTimeline of toCheck) {
if (doesTimelineHaveUnreadMessages(room, withTimeline.timeline)) {
// We found an unread, so the room is unread
return true;
}
}
// If we got here then no timelines were found with unread messages.
return false;
}
function doesTimelineHaveUnreadMessages(room, timeline) {
// The room is a space, let's ignore it
if (room.isSpaceRoom()) return false;
const myUserId = room.client.getSafeUserId();
const latestImportantEventId = findLatestImportantEvent(room.client, timeline)?.getId();
if (latestImportantEventId) {
return !room.hasUserReadEvent(myUserId, latestImportantEventId);
} else {
// We couldn't find an important event to check - check the unimportant ones.
const earliestUnimportantEventId = timeline.at(0)?.getId();
if (!earliestUnimportantEventId) {
// There are no events in this timeline - it is uninitialised, so we
// consider it read
return false;
} else if (room.hasUserReadEvent(myUserId, earliestUnimportantEventId)) {
// Some of the unimportant events are read, and there are no
// important ones after them, so we've read everything.
return false;
} else {
// We have events. and none of them are read. We must guess that
// the timeline is unread, because there could be older unread
// important events that we don't have loaded.
_logger.logger.warn("Falling back to unread room because of no read receipt or counting message found", {
roomId: room.roomId,
earliestUnimportantEventId: earliestUnimportantEventId
});
return true;
}
}
}
/**
* Returns true if this room has unread threads.
* @param room The room to check
* @returns {boolean} True if the given room has unread threads
*/
function doesRoomHaveUnreadThreads(room) {
if ((0, _RoomNotifs.getRoomNotifsState)(room.client, room.roomId) === _RoomNotifs.RoomNotifState.Mute) {
// No unread for muted rooms, nor their threads
// NB. This logic duplicated in RoomNotifs.determineUnreadState
return false;
}
for (const thread of room.getThreads()) {
if (doesTimelineHaveUnreadMessages(room, thread.timeline)) {
// We found an unread, so the room has an unread thread
return true;
}
}
// If we got here then no threads were found with unread messages.
return false;
}
function doesRoomOrThreadHaveUnreadMessages(roomOrThread) {
const room = roomOrThread instanceof _matrix.Thread ? roomOrThread.room : roomOrThread;
const events = roomOrThread instanceof _matrix.Thread ? roomOrThread.timeline : room.getLiveTimeline().getEvents();
return doesTimelineHaveUnreadMessages(room, events);
}
/**
* Look backwards through the timeline and find the last event that is
* "important" in the sense of isImportantEvent.
*
* @returns the latest important event, or null if none were found
*/
function findLatestImportantEvent(client, timeline) {
for (let index = timeline.length - 1; index >= 0; index--) {
const event = timeline[index];
if (isImportantEvent(client, event)) {
return event;
}
}
return null;
}
/**
* Given this event does not have a receipt, is it important enough to make
* this room unread?
*/
function isImportantEvent(client, event) {
return !(0, _shouldHideEvent.default)(event) && eventTriggersUnreadCount(client, event);
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0cml4IiwicmVxdWlyZSIsIl9sb2dnZXIiLCJfc2hvdWxkSGlkZUV2ZW50IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9FdmVudFRpbGVGYWN0b3J5IiwiX1NldHRpbmdzU3RvcmUiLCJfUm9vbU5vdGlmcyIsImV2ZW50VHJpZ2dlcnNVbnJlYWRDb3VudCIsImNsaWVudCIsImV2IiwiZ2V0U2VuZGVyIiwiZ2V0U2FmZVVzZXJJZCIsImdldFR5cGUiLCJFdmVudFR5cGUiLCJSb29tTWVtYmVyIiwiUm9vbVRoaXJkUGFydHlJbnZpdGUiLCJDYWxsQW5zd2VyIiwiQ2FsbEhhbmd1cCIsIlJvb21DYW5vbmljYWxBbGlhcyIsIlJvb21TZXJ2ZXJBY2wiLCJNX0JFQUNPTiIsIm5hbWUiLCJhbHROYW1lIiwiaXNSZWRhY3RlZCIsImhhdmVSZW5kZXJlckZvckV2ZW50IiwiZG9lc1Jvb21IYXZlVW5yZWFkTWVzc2FnZXMiLCJyb29tIiwiaW5jbHVkZVRocmVhZHMiLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJ0b0NoZWNrIiwicHVzaCIsImdldFRocmVhZHMiLCJ3aXRoVGltZWxpbmUiLCJkb2VzVGltZWxpbmVIYXZlVW5yZWFkTWVzc2FnZXMiLCJ0aW1lbGluZSIsImlzU3BhY2VSb29tIiwibXlVc2VySWQiLCJsYXRlc3RJbXBvcnRhbnRFdmVudElkIiwiZmluZExhdGVzdEltcG9ydGFudEV2ZW50IiwiZ2V0SWQiLCJoYXNVc2VyUmVhZEV2ZW50IiwiZWFybGllc3RVbmltcG9ydGFudEV2ZW50SWQiLCJhdCIsImxvZ2dlciIsIndhcm4iLCJyb29tSWQiLCJkb2VzUm9vbUhhdmVVbnJlYWRUaHJlYWRzIiwiZ2V0Um9vbU5vdGlmc1N0YXRlIiwiUm9vbU5vdGlmU3RhdGUiLCJNdXRlIiwidGhyZWFkIiwiZG9lc1Jvb21PclRocmVhZEhhdmVVbnJlYWRNZXNzYWdlcyIsInJvb21PclRocmVhZCIsIlRocmVhZCIsImV2ZW50cyIsImdldExpdmVUaW1lbGluZSIsImdldEV2ZW50cyIsImluZGV4IiwibGVuZ3RoIiwiZXZlbnQiLCJpc0ltcG9ydGFudEV2ZW50Iiwic2hvdWxkSGlkZUV2ZW50Il0sInNvdXJjZXMiOlsiLi4vc3JjL1VucmVhZC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAxNS0yMDIzIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCB7IE1fQkVBQ09OLCBSb29tLCBUaHJlYWQsIE1hdHJpeEV2ZW50LCBFdmVudFR5cGUsIE1hdHJpeENsaWVudCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tYXRyaXhcIjtcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9sb2dnZXJcIjtcblxuaW1wb3J0IHNob3VsZEhpZGVFdmVudCBmcm9tIFwiLi9zaG91bGRIaWRlRXZlbnRcIjtcbmltcG9ydCB7IGhhdmVSZW5kZXJlckZvckV2ZW50IH0gZnJvbSBcIi4vZXZlbnRzL0V2ZW50VGlsZUZhY3RvcnlcIjtcbmltcG9ydCBTZXR0aW5nc1N0b3JlIGZyb20gXCIuL3NldHRpbmdzL1NldHRpbmdzU3RvcmVcIjtcbmltcG9ydCB7IFJvb21Ob3RpZlN0YXRlLCBnZXRSb29tTm90aWZzU3RhdGUgfSBmcm9tIFwiLi9Sb29tTm90aWZzXCI7XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoaXMgZXZlbnQgYXJyaXZpbmcgaW4gYSByb29tIHNob3VsZCBhZmZlY3QgdGhlIHJvb20nc1xuICogY291bnQgb2YgdW5yZWFkIG1lc3NhZ2VzXG4gKlxuICogQHBhcmFtIGNsaWVudCBUaGUgTWF0cml4IENsaWVudCBpbnN0YW5jZSBvZiB0aGUgbG9nZ2VkLWluIHVzZXJcbiAqIEBwYXJhbSB7T2JqZWN0fSBldiBUaGUgZXZlbnRcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBnaXZlbiBldmVudCBzaG91bGQgYWZmZWN0IHRoZSB1bnJlYWQgbWVzc2FnZSBjb3VudFxuICovXG5leHBvcnQgZnVuY3Rpb24gZXZlbnRUcmlnZ2Vyc1VucmVhZENvdW50KGNsaWVudDogTWF0cml4Q2xpZW50LCBldjogTWF0cml4RXZlbnQpOiBib29sZWFuIHtcbiAgICBpZiAoZXYuZ2V0U2VuZGVyKCkgPT09IGNsaWVudC5nZXRTYWZlVXNlcklkKCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZXYuZ2V0VHlwZSgpKSB7XG4gICAgICAgIGNhc2UgRXZlbnRUeXBlLlJvb21NZW1iZXI6XG4gICAgICAgIGNhc2UgRXZlbnRUeXBlLlJvb21UaGlyZFBhcnR5SW52aXRlOlxuICAgICAgICBjYXNlIEV2ZW50VHlwZS5DYWxsQW5zd2VyOlxuICAgICAgICBjYXNlIEV2ZW50VHlwZS5DYWxsSGFuZ3VwOlxuICAgICAgICBjYXNlIEV2ZW50VHlwZS5Sb29tQ2Fub25pY2FsQWxpYXM6XG4gICAgICAgIGNhc2UgRXZlbnRUeXBlLlJvb21TZXJ2ZXJBY2w6XG4gICAgICAgIGNhc2UgTV9CRUFDT04ubmFtZTpcbiAgICAgICAgY2FzZSBNX0JFQUNPTi5hbHROYW1lOlxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmIChldi5pc1JlZGFjdGVkKCkpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gaGF2ZVJlbmRlcmVyRm9yRXZlbnQoZXYsIGNsaWVudCwgZmFsc2UgLyogaGlkZGVuIG1lc3NhZ2VzIHNob3VsZCBuZXZlciB0cmlnZ2VyIHVucmVhZCBjb3VudHMgYW55d2F5cyAqLyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkb2VzUm9vbUhhdmVVbnJlYWRNZXNzYWdlcyhyb29tOiBSb29tLCBpbmNsdWRlVGhyZWFkczogYm9vbGVhbik6IGJvb2xlYW4ge1xuICAgIGlmIChTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwiZmVhdHVyZV9zbGlkaW5nX3N5bmNcIikpIHtcbiAgICAgICAgLy8gVE9ETzogaHR0cHM6Ly9naXRodWIuY29tL3ZlY3Rvci1pbS9lbGVtZW50LXdlYi9pc3N1ZXMvMjMyMDdcbiAgICAgICAgLy8gU2xpZGluZyBTeW5jIGRvZXNuJ3Qgc3VwcG9ydCB1bnJlYWQgaW5kaWNhdG9yIGRvdHMgKHlldC4uLilcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IHRvQ2hlY2s6IEFycmF5PFJvb20gfCBUaHJlYWQ+ID0gW3Jvb21dO1xuICAgIGlmIChpbmNsdWRlVGhyZWFkcykge1xuICAgICAgICB0b0NoZWNrLnB1c2goLi4ucm9vbS5nZXRUaHJlYWRzKCkpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qgd2l0aFRpbWVsaW5lIG9mIHRvQ2hlY2spIHtcbiAgICAgICAgaWYgKGRvZXNUaW1lbGluZUhhdmVVbnJlYWRNZXNzYWdlcyhyb29tLCB3aXRoVGltZWxpbmUudGltZWxpbmUpKSB7XG4gICAgICAgICAgICAvLyBXZSBmb3VuZCBhbiB1bnJlYWQsIHNvIHRoZSByb29tIGlzIHVucmVhZFxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBJZiB3ZSBnb3QgaGVyZSB0aGVuIG5vIHRpbWVsaW5lcyB3ZXJlIGZvdW5kIHdpdGggdW5yZWFkIG1lc3NhZ2VzLlxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gZG9lc1RpbWVsaW5lSGF2ZVVucmVhZE1lc3NhZ2VzKHJvb206IFJvb20sIHRpbWVsaW5lOiBBcnJheTxNYXRyaXhFdmVudD4pOiBib29sZWFuIHtcbiAgICAvLyBUaGUgcm9vbSBpcyBhIHNwYWNlLCBsZXQncyBpZ25vcmUgaXRcbiAgICBpZiAocm9vbS5pc1NwYWNlUm9vbSgpKSByZXR1cm4gZmFsc2U7XG5cbiAgICBjb25zdCBteVVzZXJJZCA9IHJvb20uY2xpZW50LmdldFNhZmVVc2VySWQoKTtcbiAgICBjb25zdCBsYXRlc3RJbXBvcnRhbnRFdmVudElkID0gZmluZExhdGVzdEltcG9ydGFudEV2ZW50KHJvb20uY2xpZW50LCB0aW1lbGluZSk/LmdldElkKCk7XG4gICAgaWYgKGxhdGVzdEltcG9ydGFudEV2ZW50SWQpIHtcbiAgICAgICAgcmV0dXJuICFyb29tLmhhc1VzZXJSZWFkRXZlbnQobXlVc2VySWQsIGxhdGVzdEltcG9ydGFudEV2ZW50SWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFdlIGNvdWxkbid0IGZpbmQgYW4gaW1wb3J0YW50IGV2ZW50IHRvIGNoZWNrIC0gY2hlY2sgdGhlIHVuaW1wb3J0YW50IG9uZXMuXG4gICAgICAgIGNvbnN0IGVhcmxpZXN0VW5pbXBvcnRhbnRFdmVudElkID0gdGltZWxpbmUuYXQoMCk/LmdldElkKCk7XG4gICAgICAgIGlmICghZWFybGllc3RVbmltcG9ydGFudEV2ZW50SWQpIHtcbiAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBldmVudHMgaW4gdGhpcyB0aW1lbGluZSAtIGl0IGlzIHVuaW5pdGlhbGlzZWQsIHNvIHdlXG4gICAgICAgICAgICAvLyBjb25zaWRlciBpdCByZWFkXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAocm9vbS5oYXNVc2VyUmVhZEV2ZW50KG15VXNlcklkLCBlYXJsaWVzdFVuaW1wb3J0YW50RXZlbnRJZCkpIHtcbiAgICAgICAgICAgIC8vIFNvbWUgb2YgdGhlIHVuaW1wb3J0YW50IGV2ZW50cyBhcmUgcmVhZCwgYW5kIHRoZXJlIGFyZSBub1xuICAgICAgICAgICAgLy8gaW1wb3J0YW50IG9uZXMgYWZ0ZXIgdGhlbSwgc28gd2UndmUgcmVhZCBldmVyeXRoaW5nLlxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gV2UgaGF2ZSBldmVudHMuIGFuZCBub25lIG9mIHRoZW0gYXJlIHJlYWQuICBXZSBtdXN0IGd1ZXNzIHRoYXRcbiAgICAgICAgICAgIC8vIHRoZSB0aW1lbGluZSBpcyB1bnJlYWQsIGJlY2F1c2UgdGhlcmUgY291bGQgYmUgb2xkZXIgdW5yZWFkXG4gICAgICAgICAgICAvLyBpbXBvcnRhbnQgZXZlbnRzIHRoYXQgd2UgZG9uJ3QgaGF2ZSBsb2FkZWQuXG4gICAgICAgICAgICBsb2dnZXIud2FybihcIkZhbGxpbmcgYmFjayB0byB1bnJlYWQgcm9vbSBiZWNhdXNlIG9mIG5vIHJlYWQgcmVjZWlwdCBvciBjb3VudGluZyBtZXNzYWdlIGZvdW5kXCIsIHtcbiAgICAgICAgICAgICAgICByb29tSWQ6IHJvb20ucm9vbUlkLFxuICAgICAgICAgICAgICAgIGVhcmxpZXN0VW5pbXBvcnRhbnRFdmVudElkOiBlYXJsaWVzdFVuaW1wb3J0YW50RXZlbnRJZCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoaXMgcm9vbSBoYXMgdW5yZWFkIHRocmVhZHMuXG4gKiBAcGFyYW0gcm9vbSBUaGUgcm9vbSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIGdpdmVuIHJvb20gaGFzIHVucmVhZCB0aHJlYWRzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkb2VzUm9vbUhhdmVVbnJlYWRUaHJlYWRzKHJvb206IFJvb20pOiBib29sZWFuIHtcbiAgICBpZiAoZ2V0Um9vbU5vdGlmc1N0YXRlKHJvb20uY2xpZW50LCByb29tLnJvb21JZCkgPT09IFJvb21Ob3RpZlN0YXRlLk11dGUpIHtcbiAgICAgICAgLy8gTm8gdW5yZWFkIGZvciBtdXRlZCByb29tcywgbm9yIHRoZWlyIHRocmVhZHNcbiAgICAgICAgLy8gTkIuIFRoaXMgbG9naWMgZHVwbGljYXRlZCBpbiBSb29tTm90aWZzLmRldGVybWluZVVucmVhZFN0YXRlXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHRocmVhZCBvZiByb29tLmdldFRocmVhZHMoKSkge1xuICAgICAgICBpZiAoZG9lc1RpbWVsaW5lSGF2ZVVucmVhZE1lc3NhZ2VzKHJvb20sIHRocmVhZC50aW1lbGluZSkpIHtcbiAgICAgICAgICAgIC8vIFdlIGZvdW5kIGFuIHVucmVhZCwgc28gdGhlIHJvb20gaGFzIGFuIHVucmVhZCB0aHJlYWRcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gSWYgd2UgZ290IGhlcmUgdGhlbiBubyB0aHJlYWRzIHdlcmUgZm91bmQgd2l0aCB1bnJlYWQgbWVzc2FnZXMuXG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZG9lc1Jvb21PclRocmVhZEhhdmVVbnJlYWRNZXNzYWdlcyhyb29tT3JUaHJlYWQ6IFJvb20gfCBUaHJlYWQpOiBib29sZWFuIHtcbiAgICBjb25zdCByb29tID0gcm9vbU9yVGhyZWFkIGluc3RhbmNlb2YgVGhyZWFkID8gcm9vbU9yVGhyZWFkLnJvb20gOiByb29tT3JUaHJlYWQ7XG4gICAgY29uc3QgZXZlbnRzID0gcm9vbU9yVGhyZWFkIGluc3RhbmNlb2YgVGhyZWFkID8gcm9vbU9yVGhyZWFkLnRpbWVsaW5lIDogcm9vbS5nZXRMaXZlVGltZWxpbmUoKS5nZXRFdmVudHMoKTtcbiAgICByZXR1cm4gZG9lc1RpbWVsaW5lSGF2ZVVucmVhZE1lc3NhZ2VzKHJvb20sIGV2ZW50cyk7XG59XG5cbi8qKlxuICogTG9vayBiYWNrd2FyZHMgdGhyb3VnaCB0aGUgdGltZWxpbmUgYW5kIGZpbmQgdGhlIGxhc3QgZXZlbnQgdGhhdCBpc1xuICogXCJpbXBvcnRhbnRcIiBpbiB0aGUgc2Vuc2Ugb2YgaXNJbXBvcnRhbnRFdmVudC5cbiAqXG4gKiBAcmV0dXJucyB0aGUgbGF0ZXN0IGltcG9ydGFudCBldmVudCwgb3IgbnVsbCBpZiBub25lIHdlcmUgZm91bmRcbiAqL1xuZnVuY3Rpb24gZmluZExhdGVzdEltcG9ydGFudEV2ZW50KGNsaWVudDogTWF0cml4Q2xpZW50LCB0aW1lbGluZTogQXJyYXk8TWF0cml4RXZlbnQ+KTogTWF0cml4RXZlbnQgfCBudWxsIHtcbiAgICBmb3IgKGxldCBpbmRleCA9IHRpbWVsaW5lLmxlbmd0aCAtIDE7IGluZGV4ID49IDA7IGluZGV4LS0pIHtcbiAgICAgICAgY29uc3QgZXZlbnQgPSB0aW1lbGluZVtpbmRleF07XG4gICAgICAgIGlmIChpc0ltcG9ydGFudEV2ZW50KGNsaWVudCwgZXZlbnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gZXZlbnQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogR2l2ZW4gdGhpcyBldmVudCBkb2VzIG5vdCBoYXZlIGEgcmVjZWlwdCwgaXMgaXQgaW1wb3J0YW50IGVub3VnaCB0byBtYWtlXG4gKiB0aGlzIHJvb20gdW5yZWFkP1xuICovXG5mdW5jdGlvbiBpc0ltcG9ydGFudEV2ZW50KGNsaWVudDogTWF0cml4Q2xpZW50LCBldmVudDogTWF0cml4RXZlbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gIXNob3VsZEhpZGVFdmVudChldmVudCkgJiYgZXZlbnRUcmlnZ2Vyc1VucmVhZENvdW50KGNsaWVudCwgZXZlbnQpO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBUUEsSUFBQUEsT0FBQSxHQUFBQyxPQUFBO0FBQ0EsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBRUEsSUFBQUUsZ0JBQUEsR0FBQUMsc0JBQUEsQ0FBQUgsT0FBQTtBQUNBLElBQUFJLGlCQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxjQUFBLEdBQUFGLHNCQUFBLENBQUFILE9BQUE7QUFDQSxJQUFBTSxXQUFBLEdBQUFOLE9BQUE7QUFkQTtB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