From cd83f12a82dfb40bd2c240410cd27fe5d81f407e Mon Sep 17 00:00:00 2001 From: Jorik Schellekens Date: Mon, 13 Jul 2020 16:11:21 +0100 Subject: [PATCH 1/9] Fix badges for font size 20 --- res/css/views/rooms/_NotificationBadge.scss | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/res/css/views/rooms/_NotificationBadge.scss b/res/css/views/rooms/_NotificationBadge.scss index 521f1dfc20..0e6d442cc1 100644 --- a/res/css/views/rooms/_NotificationBadge.scss +++ b/res/css/views/rooms/_NotificationBadge.scss @@ -48,15 +48,15 @@ limitations under the License. } &.mx_NotificationBadge_2char { - width: 16px; - height: 16px; - border-radius: 16px; + width: $font-16px; + height: $font-16px; + border-radius: $font-16px; } &.mx_NotificationBadge_3char { - width: 26px; - height: 16px; - border-radius: 16px; + width: $font-26px; + height: $font-16px; + border-radius: $font-16px; } // The following is the floating badge From 9a3744ebb25af6f0cb5af007112ba851c33ea51c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 13 Jul 2020 09:54:15 -0600 Subject: [PATCH 2/9] Fix default sorting mechanics for new room list Fixes https://github.com/vector-im/riot-web/issues/14445 --- src/stores/room-list/RoomListStore2.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stores/room-list/RoomListStore2.ts b/src/stores/room-list/RoomListStore2.ts index 8686a3a054..f3a77e765b 100644 --- a/src/stores/room-list/RoomListStore2.ts +++ b/src/stores/room-list/RoomListStore2.ts @@ -30,7 +30,6 @@ import { TagWatcher } from "./TagWatcher"; import RoomViewStore from "../RoomViewStore"; import { Algorithm, LIST_UPDATED_EVENT } from "./algorithms/Algorithm"; import { EffectiveMembership, getEffectiveMembership } from "./membership"; -import { ListLayout } from "./ListLayout"; import { isNullOrUndefined } from "matrix-js-sdk/src/utils"; import RoomListLayoutStore from "./RoomListLayoutStore"; import { MarkedExecution } from "../../utils/MarkedExecution"; @@ -425,7 +424,8 @@ export class RoomListStore2 extends AsyncStore { // logic must match calculateListOrder private calculateTagSorting(tagId: TagID): SortAlgorithm { - const defaultSort = SortAlgorithm.Alphabetic; + const isDefaultRecent = tagId === DefaultTagID.Invite || tagId === DefaultTagID.DM; + const defaultSort = isDefaultRecent ? SortAlgorithm.Recent : SortAlgorithm.Alphabetic; const settingAlphabetical = SettingsStore.getValue("RoomList.orderAlphabetically", null, true); const definedSort = this.getTagSorting(tagId); const storedSort = this.getStoredTagSorting(tagId); From 40ab3e23c6eff9921fbec197f13c3cb9c8d51d87 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 13 Jul 2020 10:09:46 -0600 Subject: [PATCH 3/9] Add a null guard on the client --- .../room-list/algorithms/tag-sorting/RecentAlgorithm.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts b/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts index e7ca94ed95..154fd40b69 100644 --- a/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts +++ b/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts @@ -38,7 +38,11 @@ export class RecentAlgorithm implements IAlgorithm { // actually changed (probably needs to be done higher up?) then we could do an // insertion sort or similar on the limited set of changes. - const myUserId = MatrixClientPeg.get().getUserId(); + // TODO: Don't assume we're using the same client as the peg + let myUserId = ''; + if (MatrixClientPeg.get()) { + myUserId = MatrixClientPeg.get().getUserId(); + } const tsCache: { [roomId: string]: number } = {}; const getLastTs = (r: Room) => { @@ -68,7 +72,6 @@ export class RecentAlgorithm implements IAlgorithm { const ev = r.timeline[i]; if (!ev.getTs()) continue; // skip events that don't have timestamps (tests only?) - // TODO: Don't assume we're using the same client as the peg if (ev.getSender() === myUserId || Unread.eventTriggersUnreadCount(ev)) { return ev.getTs(); } From d2c7a55fa0d0cac3fcd7d68fb14588a24d0bfa30 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 13 Jul 2020 12:00:56 -0600 Subject: [PATCH 4/9] Ensure tag changes (leaving rooms) causes rooms to move between lists Fixes https://github.com/vector-im/riot-web/issues/14442 Turns out that we are so good at moving a room that when it flows through as a TIMELINE update the algorithm no-ops and does nothing, so don't do that. --- src/stores/room-list/algorithms/Algorithm.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/stores/room-list/algorithms/Algorithm.ts b/src/stores/room-list/algorithms/Algorithm.ts index 17e8283c74..a8adaed4d7 100644 --- a/src/stores/room-list/algorithms/Algorithm.ts +++ b/src/stores/room-list/algorithms/Algorithm.ts @@ -698,8 +698,8 @@ export class Algorithm extends EventEmitter { } } + let didTagChange = false; if (cause === RoomUpdateCause.PossibleTagChange) { - let didTagChange = false; const oldTags = this.roomIdsToTags[room.roomId] || []; const newTags = this.getTagsForRoom(room); const diff = arrayDiff(oldTags, newTags); @@ -713,6 +713,11 @@ export class Algorithm extends EventEmitter { if (!algorithm) throw new Error(`No algorithm for ${rmTag}`); await algorithm.handleRoomUpdate(room, RoomUpdateCause.RoomRemoved); this.cachedRooms[rmTag] = algorithm.orderedRooms; + + // Later on we won't update the filtered rooms or sticky room for removed + // tags, so do so now. + this.recalculateFilteredRoomsForTag(rmTag); + this.recalculateStickyRoom(rmTag); } for (const addTag of diff.added) { if (!window.mx_QuietRoomListLogging) { @@ -812,7 +817,7 @@ export class Algorithm extends EventEmitter { return false; } - let changed = false; + let changed = didTagChange; for (const tag of tags) { const algorithm: OrderingAlgorithm = this.algorithms[tag]; if (!algorithm) throw new Error(`No algorithm for ${tag}`); From c9e231c3eb9d8662b4e2fa551408a5a22a527b57 Mon Sep 17 00:00:00 2001 From: Jorik Schellekens Date: Mon, 13 Jul 2020 19:03:31 +0100 Subject: [PATCH 5/9] Add fad --- res/css/views/rooms/_RoomSublist2.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/css/views/rooms/_RoomSublist2.scss b/res/css/views/rooms/_RoomSublist2.scss index 633c33feea..20f836159b 100644 --- a/res/css/views/rooms/_RoomSublist2.scss +++ b/res/css/views/rooms/_RoomSublist2.scss @@ -196,6 +196,8 @@ limitations under the License. // as the box model should be top aligned. Happens in both FF and Chromium display: flex; flex-direction: column; + + mask-image: linear-gradient(0deg, transparent, black 3px); } .mx_RoomSublist2_resizerHandles_showNButton { From 8e982f52ff834e90464d944cf7a22131ee681936 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 13 Jul 2020 12:59:09 -0600 Subject: [PATCH 6/9] Fix extra room tiles being rendered on smaller sublists Fixes https://github.com/vector-im/riot-web/issues/14426 The issue only applies to lists which won't have a 'show less' button, as the lists with the button would have the button's height considered when determining visible tiles. For lists that were under that (1-4 rooms), the show more button wasn't being considered and thus leading to the padding being added rather than subtracted, causing an extra tile to render. By ensuring we include the padding for both show more and show less, we ensure that no extra tiles get rendered and that the cutoff semantics are still present. --- src/components/views/rooms/RoomSublist2.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/RoomSublist2.tsx b/src/components/views/rooms/RoomSublist2.tsx index c22e6cd807..2887b7fa55 100644 --- a/src/components/views/rooms/RoomSublist2.tsx +++ b/src/components/views/rooms/RoomSublist2.tsx @@ -137,9 +137,10 @@ export default class RoomSublist2 extends React.Component { let padding = RESIZE_HANDLE_HEIGHT; // this is used for calculating the max height of the whole container, // and takes into account whether there should be room reserved for the show less button - // when fully expanded. Note that the show more button might still be shown when not fully expanded, - // but in this case it will take the space of a tile and we don't need to reserve space for it. - if (this.numTiles > this.layout.defaultVisibleTiles) { + // when fully expanded. We cannot check against the layout's defaultVisible tile count + // because there are conditions in which we need to know that the 'show more' button + // is present while well under the default tile limit. + if (this.numTiles > this.numVisibleTiles) { padding += SHOW_N_BUTTON_HEIGHT; } return padding; From a8829f09d0ed23dc33148009322cb4019148e35d Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 13 Jul 2020 13:15:44 -0600 Subject: [PATCH 7/9] Ensure RoomListStore2 gets reset when the client becomes invalidated Fixes https://github.com/vector-im/riot-web/issues/14384 We also make use of the new AsyncStore type to handle this more safely. --- src/stores/room-list/RoomListStore2.ts | 48 +++++++------------- test/components/views/rooms/RoomList-test.js | 2 +- 2 files changed, 18 insertions(+), 32 deletions(-) diff --git a/src/stores/room-list/RoomListStore2.ts b/src/stores/room-list/RoomListStore2.ts index f3a77e765b..1be2bae6be 100644 --- a/src/stores/room-list/RoomListStore2.ts +++ b/src/stores/room-list/RoomListStore2.ts @@ -33,6 +33,7 @@ import { EffectiveMembership, getEffectiveMembership } from "./membership"; import { isNullOrUndefined } from "matrix-js-sdk/src/utils"; import RoomListLayoutStore from "./RoomListLayoutStore"; import { MarkedExecution } from "../../utils/MarkedExecution"; +import { AsyncStoreWithClient } from "../AsyncStoreWithClient"; interface IState { tagsEnabled?: boolean; @@ -44,14 +45,13 @@ interface IState { */ export const LISTS_UPDATE_EVENT = "lists_update"; -export class RoomListStore2 extends AsyncStore { +export class RoomListStore2 extends AsyncStoreWithClient { /** * Set to true if you're running tests on the store. Should not be touched in * any other environment. */ public static TEST_MODE = false; - private _matrixClient: MatrixClient; private initialListsGenerated = false; private enabled = false; private algorithm = new Algorithm(); @@ -78,33 +78,30 @@ export class RoomListStore2 extends AsyncStore { return this.algorithm.getOrderedRooms(); } - public get matrixClient(): MatrixClient { - return this._matrixClient; - } - // Intended for test usage public async resetStore() { await this.reset(); this.tagWatcher = new TagWatcher(this); this.filterConditions = []; this.initialListsGenerated = false; - this._matrixClient = null; this.algorithm.off(LIST_UPDATED_EVENT, this.onAlgorithmListUpdated); this.algorithm.off(FILTER_CHANGED, this.onAlgorithmListUpdated); this.algorithm = new Algorithm(); this.algorithm.on(LIST_UPDATED_EVENT, this.onAlgorithmListUpdated); this.algorithm.on(FILTER_CHANGED, this.onAlgorithmListUpdated); + + // Reset state without causing updates as the client will have been destroyed + // and downstream code will throw NPE errors. + await this.reset(null, true); } // Public for test usage. Do not call this. - public async makeReady(client: MatrixClient) { + public async makeReady() { // TODO: Remove with https://github.com/vector-im/riot-web/issues/14367 this.checkEnabled(); if (!this.enabled) return; - this._matrixClient = client; - // Update any settings here, as some may have happened before we were logically ready. // Update any settings here, as some may have happened before we were logically ready. console.log("Regenerating room lists: Startup"); @@ -161,7 +158,15 @@ export class RoomListStore2 extends AsyncStore { if (trigger) this.updateFn.trigger(); } - protected async onDispatch(payload: ActionPayload) { + protected async onReady(): Promise { + await this.makeReady(); + } + + protected async onNotReady(): Promise { + await this.resetStore(); + } + + protected async onAction(payload: ActionPayload) { // When we're running tests we can't reliably use setImmediate out of timing concerns. // As such, we use a more synchronous model. if (RoomListStore2.TEST_MODE) { @@ -175,29 +180,10 @@ export class RoomListStore2 extends AsyncStore { } protected async onDispatchAsync(payload: ActionPayload) { - if (payload.action === 'MatrixActions.sync') { - // Filter out anything that isn't the first PREPARED sync. - if (!(payload.prevState === 'PREPARED' && payload.state !== 'PREPARED')) { - return; - } - - await this.makeReady(payload.matrixClient); - - return; // no point in running the next conditions - they won't match - } - // TODO: Remove this once the RoomListStore becomes default if (!this.enabled) return; - if (payload.action === 'on_client_not_viable' || payload.action === 'on_logged_out') { - // Reset state without causing updates as the client will have been destroyed - // and downstream code will throw NPE errors. - await this.reset(null, true); - this._matrixClient = null; - this.initialListsGenerated = false; // we'll want to regenerate them - } - - // Everything below here requires a MatrixClient or some sort of logical readiness. + // Everything here requires a MatrixClient or some sort of logical readiness. const logicallyReady = this.matrixClient && this.initialListsGenerated; if (!logicallyReady) return; diff --git a/test/components/views/rooms/RoomList-test.js b/test/components/views/rooms/RoomList-test.js index e84f943708..313bd4b77e 100644 --- a/test/components/views/rooms/RoomList-test.js +++ b/test/components/views/rooms/RoomList-test.js @@ -109,7 +109,7 @@ describe('RoomList', () => { client.getRoom = (roomId) => roomMap[roomId]; // Now that everything has been set up, prepare and update the store - await RoomListStore.instance.makeReady(client); + await RoomListStore.instance.makeReady(); done(); }); From eb78b1b328a01fc7a6e2013c10a31e0feba80e6c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 13 Jul 2020 13:18:01 -0600 Subject: [PATCH 8/9] Export the matrix client from the store --- src/stores/room-list/RoomListStore2.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/stores/room-list/RoomListStore2.ts b/src/stores/room-list/RoomListStore2.ts index 1be2bae6be..a3311ce90d 100644 --- a/src/stores/room-list/RoomListStore2.ts +++ b/src/stores/room-list/RoomListStore2.ts @@ -78,6 +78,10 @@ export class RoomListStore2 extends AsyncStoreWithClient { return this.algorithm.getOrderedRooms(); } + public get matrixClient(): MatrixClient { + return super.matrixClient; + } + // Intended for test usage public async resetStore() { await this.reset(); From 19500cf96abd23f761c5e6426da96af7329149ff Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 13 Jul 2020 13:24:02 -0600 Subject: [PATCH 9/9] Allow the tests to force a MatrixClient --- src/stores/room-list/RoomListStore2.ts | 6 +++++- test/components/views/rooms/RoomList-test.js | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/stores/room-list/RoomListStore2.ts b/src/stores/room-list/RoomListStore2.ts index a3311ce90d..d67c728bf0 100644 --- a/src/stores/room-list/RoomListStore2.ts +++ b/src/stores/room-list/RoomListStore2.ts @@ -101,7 +101,11 @@ export class RoomListStore2 extends AsyncStoreWithClient { } // Public for test usage. Do not call this. - public async makeReady() { + public async makeReady(forcedClient?: MatrixClient) { + if (forcedClient) { + super.matrixClient = forcedClient; + } + // TODO: Remove with https://github.com/vector-im/riot-web/issues/14367 this.checkEnabled(); if (!this.enabled) return; diff --git a/test/components/views/rooms/RoomList-test.js b/test/components/views/rooms/RoomList-test.js index 313bd4b77e..e84f943708 100644 --- a/test/components/views/rooms/RoomList-test.js +++ b/test/components/views/rooms/RoomList-test.js @@ -109,7 +109,7 @@ describe('RoomList', () => { client.getRoom = (roomId) => roomMap[roomId]; // Now that everything has been set up, prepare and update the store - await RoomListStore.instance.makeReady(); + await RoomListStore.instance.makeReady(client); done(); });