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;