From b91026fa895d4aef1627d48864fa9fd2807cc666 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Jul 2020 17:18:01 -0600 Subject: [PATCH] Ensure CustomRoomTagStore doesn't fire useless updates This could in theory cause double rendering of the room list under some conditions. --- src/stores/CustomRoomTagStore.js | 8 ++++++-- src/utils/objects.ts | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/stores/CustomRoomTagStore.js b/src/stores/CustomRoomTagStore.js index 9967708c29..1f24dc589a 100644 --- a/src/stores/CustomRoomTagStore.js +++ b/src/stores/CustomRoomTagStore.js @@ -22,6 +22,7 @@ import SettingsStore from "../settings/SettingsStore"; import RoomListStore, {LISTS_UPDATE_EVENT} from "./room-list/RoomListStore"; import {RoomNotificationStateStore} from "./notifications/RoomNotificationStateStore"; import {isCustomTag} from "./room-list/models"; +import {objectHasDiff} from "../utils/objects"; function commonPrefix(a, b) { const len = Math.min(a.length, b.length); @@ -107,7 +108,10 @@ class CustomRoomTagStore extends EventEmitter { } _onListsUpdated = () => { - this._setState({tags: this._getUpdatedTags()}); + const newTags = this._getUpdatedTags(); + if (!this._state.tags || objectHasDiff(this._state.tags, newTags)) { + this._setState({tags: newTags}); + } }; _onDispatch(payload) { @@ -134,7 +138,7 @@ class CustomRoomTagStore extends EventEmitter { _getUpdatedTags() { if (!SettingsStore.isFeatureEnabled("feature_custom_tags")) { - return; + return {}; // none } const newTagNames = Object.keys(RoomListStore.instance.orderedLists).filter(t => isCustomTag(t)).sort(); diff --git a/src/utils/objects.ts b/src/utils/objects.ts index db8248759d..9dcc41ecd2 100644 --- a/src/utils/objects.ts +++ b/src/utils/objects.ts @@ -72,6 +72,23 @@ export function objectHasValueChange(a: any, b: any): boolean { return arrayHasDiff(aValues, bValues); } +/** + * Determines if any keys were added, removed, or changed between two objects. + * For changes, simple triple equal comparisons are done, not in-depth + * tree checking. + * @param a The first object. Must be defined. + * @param b The second object. Must be defined. + * @returns True if there's a difference between the objects, false otherwise + */ +export function objectHasDiff(a: any, b: any): boolean { + const aKeys = Object.keys(a); + const bKeys = Object.keys(b); + if (arrayHasDiff(aKeys, bKeys)) return true; + + const possibleChanges = arrayUnion(aKeys, bKeys); + return possibleChanges.some(k => a[k] !== b[k]); +} + /** * Determines the keys added, changed, and removed between two objects. * For changes, simple triple equal comparisons are done, not in-depth