From b0cc69bca934865e93d759d33bba3850e9f53fda Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 22 Feb 2019 16:57:41 -0700 Subject: [PATCH] Add an option to sort the room list by recents first Fixes https://github.com/vector-im/riot-web/issues/8892 --- .../settings/tabs/PreferencesSettingsTab.js | 7 ++++ src/i18n/strings/en_EN.json | 2 ++ src/settings/Settings.js | 7 +++- src/stores/RoomListStore.js | 34 ++++++++++++++++++- 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/components/views/settings/tabs/PreferencesSettingsTab.js b/src/components/views/settings/tabs/PreferencesSettingsTab.js index d76dc8f3dd..d40e532789 100644 --- a/src/components/views/settings/tabs/PreferencesSettingsTab.js +++ b/src/components/views/settings/tabs/PreferencesSettingsTab.js @@ -44,6 +44,10 @@ export default class PreferencesSettingsTab extends React.Component { 'showDisplaynameChanges', ]; + static ROOM_LIST_SETTINGS = [ + 'RoomList.orderByImportance', + ]; + static ADVANCED_SETTINGS = [ 'alwaysShowEncryptionIcons', 'Pill.shouldShowPillAvatar', @@ -104,6 +108,9 @@ export default class PreferencesSettingsTab extends React.Component { {_t("Timeline")} {this._renderGroup(PreferencesSettingsTab.TIMELINE_SETTINGS)} + {_t("Room list")} + {this._renderGroup(PreferencesSettingsTab.ROOM_LIST_SETTINGS)} + {_t("Advanced")} {this._renderGroup(PreferencesSettingsTab.ADVANCED_SETTINGS)} {autoLaunchOption} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 84c9dacd07..d7c82e23e6 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -306,6 +306,7 @@ "Enable widget screenshots on supported widgets": "Enable widget screenshots on supported widgets", "Prompt before sending invites to potentially invalid matrix IDs": "Prompt before sending invites to potentially invalid matrix IDs", "Show developer tools": "Show developer tools", + "Order rooms in the room list by most important first instead of most recent": "Order rooms in the room list by most important first instead of most recent", "Collecting app version information": "Collecting app version information", "Collecting logs": "Collecting logs", "Uploading report": "Uploading report", @@ -554,6 +555,7 @@ "Preferences": "Preferences", "Composer": "Composer", "Timeline": "Timeline", + "Room list": "Room list", "Autocomplete delay (ms)": "Autocomplete delay (ms)", "To change the room's avatar, you must be a": "To change the room's avatar, you must be a", "To change the room's name, you must be a": "To change the room's name, you must be a", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index cf68fed8ba..e4db12f5ba 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -1,6 +1,6 @@ /* Copyright 2017 Travis Ralston -Copyright 2018 New Vector Ltd +Copyright 2018, 2019 New Vector Ltd. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -340,4 +340,9 @@ export const SETTINGS = { displayName: _td('Show developer tools'), default: false, }, + "RoomList.orderByImportance": { + supportedLevels: LEVELS_ACCOUNT_SETTINGS, + displayName: _td('Order rooms in the room list by most important first instead of most recent'), + default: true, + }, }; diff --git a/src/stores/RoomListStore.js b/src/stores/RoomListStore.js index 0a11c2774a..aec57dedeb 100644 --- a/src/stores/RoomListStore.js +++ b/src/stores/RoomListStore.js @@ -59,6 +59,22 @@ class RoomListStore extends Store { this._recentsComparator = this._recentsComparator.bind(this); } + /** + * Alerts the RoomListStore to a potential change in how room list sorting should + * behave. + * @param {boolean} forceRegeneration True to force a change in the algorithm + */ + updateSortingAlgorithm(forceRegeneration=false) { + const byImportance = SettingsStore.getValue("RoomList.orderByImportance"); + if (byImportance !== this._state.orderRoomsByImportance || forceRegeneration) { + console.log("Updating room sorting algorithm: sortByImportance=" + byImportance); + this._setState({orderRoomsByImportance: byImportance}); + + // Trigger a resort of the entire list to reflect the change in algorithm + this._generateInitialRoomLists(); + } + } + _init() { // Initialise state const defaultLists = { @@ -77,7 +93,10 @@ class RoomListStore extends Store { presentationLists: defaultLists, // like `lists`, but with arrays of rooms instead ready: false, stickyRoomId: null, + orderRoomsByImportance: true, }; + + SettingsStore.monitorSetting('RoomList.orderByImportance', null); } _setState(newState) { @@ -99,6 +118,11 @@ class RoomListStore extends Store { __onDispatch(payload) { const logicallyReady = this._matrixClient && this._state.ready; switch (payload.action) { + case 'setting_updated': { + if (payload.settingName !== 'RoomList.orderByImportance') break; + this.updateSortingAlgorithm(); + } + break; // Initialise state after initial sync case 'MatrixActions.sync': { if (!(payload.prevState !== 'PREPARED' && payload.state === 'PREPARED')) { @@ -106,7 +130,7 @@ class RoomListStore extends Store { } this._matrixClient = payload.matrixClient; - this._generateInitialRoomLists(); + this.updateSortingAlgorithm(/*force=*/true); } break; case 'MatrixActions.Room.receipt': { @@ -517,6 +541,14 @@ class RoomListStore extends Store { } _calculateCategory(room) { + if (!this._state.orderRoomsByImportance) { + // Effectively disable the categorization of rooms if we're supposed to + // be sorting by more recent messages first. This triggers the timestamp + // comparison bit of _setRoomCategory and _recentsComparator instead of + // the category ordering. + return CATEGORY_IDLE; + } + const mentions = room.getUnreadNotificationCount("highlight") > 0; if (mentions) return CATEGORY_RED;