UNPKG

matrix-react-sdk

Version:
152 lines (144 loc) 19.4 kB
"use strict"; 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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