From 8087f18bf786b7780efbdb0f61fda39e104e3624 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 14 Feb 2020 10:32:42 +0000 Subject: [PATCH 01/15] Remove unused props Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/RoomSubList.js | 2 -- src/components/views/rooms/RoomList.js | 9 --------- 2 files changed, 11 deletions(-) diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js index 600b418fe04..fa2231328c7 100644 --- a/src/components/structures/RoomSubList.js +++ b/src/components/structures/RoomSubList.js @@ -46,8 +46,6 @@ export default class RoomSubList extends React.PureComponent { tagName: PropTypes.string, addRoomLabel: PropTypes.string, - order: PropTypes.string.isRequired, - // passed through to RoomTile and used to highlight room with `!` regardless of notifications count isInvite: PropTypes.bool, diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index f41400ecfc1..ad64ef1a971 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -700,13 +700,11 @@ export default createReactClass({ list: [], extraTiles: this._makeGroupInviteTiles(this.props.searchFilter), label: _t('Community Invites'), - order: "recent", isInvite: true, }, { list: this.state.lists['im.vector.fake.invite'], label: _t('Invites'), - order: "recent", incomingCall: incomingCallIfTaggedAs('im.vector.fake.invite'), isInvite: true, }, @@ -714,14 +712,12 @@ export default createReactClass({ list: this.state.lists['m.favourite'], label: _t('Favourites'), tagName: "m.favourite", - order: "manual", incomingCall: incomingCallIfTaggedAs('m.favourite'), }, { list: this.state.lists['im.vector.fake.direct'], label: _t('Direct Messages'), tagName: "im.vector.fake.direct", - order: "recent", incomingCall: incomingCallIfTaggedAs('im.vector.fake.direct'), onAddRoom: () => {dis.dispatch({action: 'view_create_chat'});}, addRoomLabel: _t("Start chat"), @@ -729,7 +725,6 @@ export default createReactClass({ { list: this.state.lists['im.vector.fake.recent'], label: _t('Rooms'), - order: "recent", incomingCall: incomingCallIfTaggedAs('im.vector.fake.recent'), onAddRoom: () => {dis.dispatch({action: 'view_create_room'});}, }, @@ -744,7 +739,6 @@ export default createReactClass({ key: tagName, label: labelForTagName(tagName), tagName: tagName, - order: "manual", incomingCall: incomingCallIfTaggedAs(tagName), }; }); @@ -754,13 +748,11 @@ export default createReactClass({ list: this.state.lists['m.lowpriority'], label: _t('Low priority'), tagName: "m.lowpriority", - order: "recent", incomingCall: incomingCallIfTaggedAs('m.lowpriority'), }, { list: this.state.lists['im.vector.fake.archived'], label: _t('Historical'), - order: "recent", incomingCall: incomingCallIfTaggedAs('im.vector.fake.archived'), startAsHidden: true, showSpinner: this.state.isLoadingLeftRooms, @@ -770,7 +762,6 @@ export default createReactClass({ list: this.state.lists['m.server_notice'], label: _t('System Alerts'), tagName: "m.lowpriority", - order: "recent", incomingCall: incomingCallIfTaggedAs('m.server_notice'), }, ]); From 932c9b3106e744ae520a75241dc76c3b57520437 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 18 Feb 2020 14:55:12 +0000 Subject: [PATCH 02/15] First attempt alpha room list sorting Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../tabs/user/PreferencesUserSettingsTab.js | 1 + src/i18n/strings/en_EN.json | 5 +- src/settings/Settings.js | 11 +- src/settings/SettingsStore.js | 6 +- .../controllers/RoomListOrderingController.js | 25 +++ src/settings/controllers/SettingController.js | 11 ++ src/stores/RoomListStore.js | 178 ++++++++++++------ 7 files changed, 172 insertions(+), 65 deletions(-) create mode 100644 src/settings/controllers/RoomListOrderingController.js diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js index fea2e8c81f5..b7fb895a9ab 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js @@ -48,6 +48,7 @@ export default class PreferencesUserSettingsTab extends React.Component { ]; static ROOM_LIST_SETTINGS = [ + 'RoomList.orderingAlgorithm', // this has a controller which maps the boolean inputs to algorithms 'RoomList.orderByImportance', 'breadcrumbs', ]; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 7a8642be95b..1f4d9829ad2 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -413,8 +413,9 @@ "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", - "Show recently visited rooms above the room list": "Show recently visited rooms above the room list", + "Order rooms by message activity instead of by name": "Order rooms by message activity instead of by name", + "Show rooms with unread notifications first": "Show rooms with unread notifications first", + "Show shortcuts to recently viewed rooms above the room list": "Show shortcuts to recently viewed rooms above the room list", "Show hidden events in timeline": "Show hidden events in timeline", "Low bandwidth mode": "Low bandwidth mode", "Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)": "Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 936b6512119..87c1526eaaf 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -26,6 +26,7 @@ import CustomStatusController from "./controllers/CustomStatusController"; import ThemeController from './controllers/ThemeController'; import ReloadOnChangeController from "./controllers/ReloadOnChangeController"; import {RIGHT_PANEL_PHASES} from "../stores/RightPanelStorePhases"; +import RoomListOrderingController from "./controllers/RoomListOrderingController"; // These are just a bunch of helper arrays to avoid copy/pasting a bunch of times const LEVELS_ROOM_SETTINGS = ['device', 'room-device', 'room-account', 'account', 'config']; @@ -433,14 +434,20 @@ export const SETTINGS = { deny: [], }, }, + "RoomList.orderingAlgorithm": { + supportedLevels: LEVELS_ACCOUNT_SETTINGS, + displayName: _td("Order rooms by message activity instead of by name"), + default: "recent", // XXX controller maps boolean onto algorithm for future flexibility + controller: new RoomListOrderingController(), + }, "RoomList.orderByImportance": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, - displayName: _td('Order rooms in the room list by most important first instead of most recent'), + displayName: _td("Show rooms with unread notifications first"), default: true, }, "breadcrumbs": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, - displayName: _td("Show recently visited rooms above the room list"), + displayName: _td("Show shortcuts to recently viewed rooms above the room list"), default: true, }, "showHiddenEventsInTimeline": { diff --git a/src/settings/SettingsStore.js b/src/settings/SettingsStore.js index 0122916bc35..897c2521ccb 100644 --- a/src/settings/SettingsStore.js +++ b/src/settings/SettingsStore.js @@ -420,9 +420,13 @@ export default class SettingsStore { throw new Error("User cannot set " + settingName + " at " + level + " in " + roomId); } + const controller = setting.controller; + if (controller) { + value = controller.augmentValue(level, roomId, value); + } + await handler.setValue(settingName, roomId, value); - const controller = setting.controller; if (controller) { controller.onChange(level, roomId, value); } diff --git a/src/settings/controllers/RoomListOrderingController.js b/src/settings/controllers/RoomListOrderingController.js new file mode 100644 index 00000000000..449e21545af --- /dev/null +++ b/src/settings/controllers/RoomListOrderingController.js @@ -0,0 +1,25 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import SettingController from "./SettingController"; + +export default class RoomListOrderingController extends SettingController { + augmentValue(level, roomId, newValue): * { + // currently we expose algorithm as a boolean but store it as a string for future flexibility + // where we may want >2 algorithms available for the user to choose between. + return newValue ? "recent" : "alphabetic"; + } +} diff --git a/src/settings/controllers/SettingController.js b/src/settings/controllers/SettingController.js index a7d0ccf21a8..9327f6ab484 100644 --- a/src/settings/controllers/SettingController.js +++ b/src/settings/controllers/SettingController.js @@ -47,4 +47,15 @@ export default class SettingController { onChange(level, roomId, newValue) { // do nothing by default } + + /** + * Gets the value which should actually get written into the store based on the input value from setValue. + * @param {string} level The level at which the setting has been modified. + * @param {String} roomId The room ID, may be null. + * @param {*} newValue The new value for the setting, may be null. + * @return {*} The value that should be used, may be null. + */ + augmentValue(level, roomId, newValue) { + return newValue; + } } diff --git a/src/stores/RoomListStore.js b/src/stores/RoomListStore.js index a0785cf10ec..e99214dea12 100644 --- a/src/stores/RoomListStore.js +++ b/src/stores/RoomListStore.js @@ -36,29 +36,48 @@ const CATEGORY_GREY = "grey"; // Unread notified messages (not mentions) const CATEGORY_BOLD = "bold"; // Unread messages (not notified, 'Mentions Only' rooms) const CATEGORY_IDLE = "idle"; // Nothing of interest -const CATEGORY_ORDER = [CATEGORY_RED, CATEGORY_GREY, CATEGORY_BOLD, CATEGORY_IDLE]; -const LIST_ORDERS = { - "m.favourite": "manual", - "im.vector.fake.invite": "recent", - "im.vector.fake.recent": "recent", - "im.vector.fake.direct": "recent", - "m.lowpriority": "recent", - "im.vector.fake.archived": "recent", -}; +/** + * Identifier for manual sorting behaviour: sort by the user defined order. + * @type {string} + */ +export const ALGO_MANUAL = "manual"; /** - * Identifier for the "breadcrumb" (or "sort by most important room first") algorithm. - * Includes a provision for keeping the currently open room from flying down the room - * list. + * Identifier for alphabetic sorting behaviour: sort by the room name alphabetically first. * @type {string} */ -const ALGO_IMPORTANCE = "importance"; +export const ALGO_ALPHABETIC = "alphabetic"; /** * Identifier for classic sorting behaviour: sort by the most recent message first. * @type {string} */ -const ALGO_RECENT = "recent"; +export const ALGO_RECENT = "recent"; + +const CATEGORY_ORDER = [CATEGORY_RED, CATEGORY_GREY, CATEGORY_BOLD, CATEGORY_IDLE]; +const getListAlgorithm = (listKey, settingAlgorithm) => { + switch (listKey) { + case "m.favourite": + return ALGO_MANUAL; + case "im.vector.fake.invite": + case "im.vector.fake.recent": + case "im.vector.fake.direct": + case "im.vector.fake.archived": + case "m.lowpriority": + return settingAlgorithm; + default: + return ALGO_MANUAL; // TODO verify this is desired + } +}; + +const knownLists = new Set([ + "m.favourite", + "im.vector.fake.invite", + "im.vector.fake.recent", + "im.vector.fake.direct", + "im.vector.fake.archived", + "m.lowpriority", +]); /** * A class for storing application state for categorising rooms in @@ -76,13 +95,12 @@ class RoomListStore extends Store { /** * Changes the sorting algorithm used by the RoomListStore. * @param {string} algorithm The new algorithm to use. Should be one of the ALGO_* constants. + * @param {boolean} orderImportantFirst Whether to sort by categories of importance */ - updateSortingAlgorithm(algorithm) { + updateSortingAlgorithm(algorithm, orderImportantFirst) { // Dev note: We only have two algorithms at the moment, but it isn't impossible that we want // multiple in the future. Also constants make things slightly clearer. - const byImportance = algorithm === ALGO_IMPORTANCE; - console.log("Updating room sorting algorithm: sortByImportance=" + byImportance); - this._setState({orderRoomsByImportance: byImportance}); + this._setState({algorithm, orderImportantFirst}); // Trigger a resort of the entire list to reflect the change in algorithm this._generateInitialRoomLists(); @@ -106,10 +124,12 @@ class RoomListStore extends Store { presentationLists: defaultLists, // like `lists`, but with arrays of rooms instead ready: false, stickyRoomId: null, - orderRoomsByImportance: true, + algorithm: ALGO_RECENT, + orderImportantFirst: false, }; SettingsStore.monitorSetting('RoomList.orderByImportance', null); + SettingsStore.monitorSetting('RoomList.orderingAlgorithm', null); SettingsStore.monitorSetting('feature_custom_tags', null); } @@ -135,11 +155,17 @@ class RoomListStore extends Store { case 'setting_updated': { if (!logicallyReady) break; - if (payload.settingName === 'RoomList.orderByImportance') { - this.updateSortingAlgorithm(payload.newValue === true ? ALGO_IMPORTANCE : ALGO_RECENT); - } else if (payload.settingName === 'feature_custom_tags') { - this._setState({tagsEnabled: payload.newValue}); - this._generateInitialRoomLists(); // Tags means we have to start from scratch + switch (payload.settingName) { + case "RoomList.orderingAlgorithm": + this.updateSortingAlgorithm(payload.newValue, this._state.orderImportantFirst); + break; + case "RoomList.orderByImportance": + this.updateSortingAlgorithm(this._state.algorithm, payload.newValue); + break; + case "feature_custom_tags": + this._setState({tagsEnabled: payload.newValue}); + this._generateInitialRoomLists(); // Tags means we have to start from scratch + break; } } break; @@ -157,9 +183,9 @@ class RoomListStore extends Store { this._matrixClient = payload.matrixClient; - const algorithm = SettingsStore.getValue("RoomList.orderByImportance") - ? ALGO_IMPORTANCE : ALGO_RECENT; - this.updateSortingAlgorithm(algorithm); + const algorithm = SettingsStore.getValue("RoomList.orderingAlgorithm"); + const orderByImportance = SettingsStore.getValue("RoomList.orderByImportance"); + this.updateSortingAlgorithm(algorithm, orderByImportance); } break; case 'MatrixActions.Room.receipt': { @@ -188,7 +214,8 @@ class RoomListStore extends Store { if (!logicallyReady || !payload.isLiveEvent || !payload.isLiveUnfilteredRoomTimelineEvent || - !this._eventTriggersRecentReorder(payload.event) + !this._eventTriggersRecentReorder(payload.event) || + this._state.algorithm !== ALGO_RECENT ) { break; } @@ -302,7 +329,7 @@ class RoomListStore extends Store { _filterTags(tags) { tags = tags ? Object.keys(tags) : []; if (this._state.tagsEnabled) return tags; - return tags.filter((t) => !!LIST_ORDERS[t]); + return tags.filter((t) => knownLists.has(t)); } _getRecommendedTagsForRoom(room) { @@ -419,9 +446,11 @@ class RoomListStore extends Store { if (changedBoundary) { // If we changed a boundary, then we've gone too far - go to the top of the last // section instead. + console.log("DEBUG changedBoundary", room.name, room, category); newList.splice(desiredCategoryBoundaryIndex, 0, {room, category}); } else { // If we're ordering by timestamp, just insert normally + console.log("DEBUG 11push", room.name, room, category); newList.push({room, category}); } pushedEntry = true; @@ -473,16 +502,19 @@ class RoomListStore extends Store { // Speed optimization: Don't do complicated math if we don't have to. if (!shouldHaveRoom) { + console.log("DEBUG A"); listsClone[key] = this._state.lists[key].filter((e) => e.room.roomId !== room.roomId); - } else if (LIST_ORDERS[key] !== 'recent') { + } else if (getListAlgorithm(key, this._state.algorithm) === ALGO_MANUAL) { // Manually ordered tags are sorted later, so for now we'll just clone the tag // and add our room if needed listsClone[key] = this._state.lists[key].filter((e) => e.room.roomId !== room.roomId); + console.log("DEBUG push", room.name, room, category); listsClone[key].push({room, category}); insertedIntoTags.push(key); } else { listsClone[key] = []; + console.log("DEBUG slot"); const pushedEntry = this._slotRoomIntoList( room, category, key, this._state.lists[key], listsClone[key], lastTimestamp); @@ -529,16 +561,23 @@ class RoomListStore extends Store { console.warn(`!! List for tag ${targetTag} does not exist - creating`); listsClone[targetTag] = []; } + console.log("DEBUG123", room.name, room, category); listsClone[targetTag].splice(0, 0, {room, category}); } } + console.log("DEBUG targetTags", targetTags); + // Sort the favourites before we set the clone for (const tag of Object.keys(listsClone)) { - if (LIST_ORDERS[tag] === 'recent') continue; // skip recents (pre-sorted) + if (getListAlgorithm(tag, this._state.algorithm) !== ALGO_MANUAL) continue; // skip recents (pre-sorted) + console.log("DEBUG applying manual sort to", tag); listsClone[tag].sort(this._getManualComparator(tag)); } + console.log("DEBUG setting lists=listsClone", + this._state.lists["im.vector.fake.recent"].map(e => e.room.name), + listsClone["im.vector.fake.recent"].map(e => e.room.name)); this._setState({lists: listsClone}); } @@ -585,8 +624,10 @@ class RoomListStore extends Store { // Default to an arbitrary category for tags which aren't ordered by recents let category = CATEGORY_IDLE; - if (LIST_ORDERS[tagName] === 'recent') category = this._calculateCategory(room); - lists[tagName].push({room, category: category}); + if (getListAlgorithm(tagName, this._state.algorithm) !== ALGO_MANUAL) { + category = this._calculateCategory(room); + } + lists[tagName].push({room, category}); } } else if (dmRoomMap.getUserIdForRoomId(room.roomId)) { // "Direct Message" rooms (that we're still in and that aren't otherwise tagged) @@ -605,33 +646,41 @@ class RoomListStore extends Store { // cache only needs to survive the sort operation below and should not be implemented outside // of this function, otherwise the room lists will almost certainly be out of date and wrong. const latestEventTsCache = {}; // roomId => timestamp + const tsOfNewestEventFn = (room) => { + if (!room) return Number.MAX_SAFE_INTEGER; // Should only happen in tests + + if (latestEventTsCache[room.roomId]) { + return latestEventTsCache[room.roomId]; + } + + const ts = this._tsOfNewestEvent(room); + latestEventTsCache[room.roomId] = ts; + return ts; + }; Object.keys(lists).forEach((listKey) => { let comparator; - switch (LIST_ORDERS[listKey]) { - case "recent": + console.log("DEBUG sorting", listKey, "using", getListAlgorithm(listKey, this._state.algorithm)); + switch (getListAlgorithm(listKey, this._state.algorithm)) { + case ALGO_RECENT: comparator = (entryA, entryB) => { - return this._recentsComparator(entryA, entryB, (room) => { - if (!room) return Number.MAX_SAFE_INTEGER; // Should only happen in tests - - if (latestEventTsCache[room.roomId]) { - return latestEventTsCache[room.roomId]; - } - - const ts = this._tsOfNewestEvent(room); - latestEventTsCache[room.roomId] = ts; - return ts; - }); + return this._recentsComparator(entryA, entryB, tsOfNewestEventFn); }; break; - case "manual": + case ALGO_ALPHABETIC: + comparator = (entryA, entryB) => this._alphabeticComparator(entryA, entryB); + break; + case ALGO_MANUAL: default: comparator = this._getManualComparator(listKey); break; } - lists[listKey].sort(comparator); + console.log("DEBUG before", listKey, lists[listKey].map(e => e.room.name)); + lists[listKey].sort(comparator); // TODO inline the common CATEGORY comparator here? + console.log("DEBUG after", listKey, lists[listKey].map(e => e.room.name)); }); + console.log("DEBUG setting lists after comparator"); this._setState({ lists, ready: true, // Ready to receive updates to ordering @@ -668,7 +717,7 @@ class RoomListStore extends Store { } _calculateCategory(room) { - if (!this._state.orderRoomsByImportance) { + if (!this._state.orderImportantFirst) { // 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 @@ -689,26 +738,35 @@ class RoomListStore extends Store { } _recentsComparator(entryA, entryB, tsOfNewestEventFn) { - const roomA = entryA.room; - const roomB = entryB.room; - const categoryA = entryA.category; - const categoryB = entryB.category; - - if (categoryA !== categoryB) { - const idxA = CATEGORY_ORDER.indexOf(categoryA); - const idxB = CATEGORY_ORDER.indexOf(categoryB); + console.trace("DEBUG recents"); + if (entryA.category !== entryB.category) { + const idxA = CATEGORY_ORDER.indexOf(entryA.category); + const idxB = CATEGORY_ORDER.indexOf(entryB.category); if (idxA > idxB) return 1; if (idxA < idxB) return -1; return 0; // Technically not possible } - const timestampA = tsOfNewestEventFn(roomA); - const timestampB = tsOfNewestEventFn(roomB); + const timestampA = tsOfNewestEventFn(entryA.room); + const timestampB = tsOfNewestEventFn(entryB.room); return timestampB - timestampA; } + _alphabeticComparator(entryA, entryB) { + if (entryA.category !== entryB.category) { + const idxA = CATEGORY_ORDER.indexOf(entryA.category); + const idxB = CATEGORY_ORDER.indexOf(entryB.category); + if (idxA > idxB) return 1; + if (idxA < idxB) return -1; + return 0; // Technically not possible + } + + // console.log("DEBUG alphabetic, same category", JSON.stringify(entryA.room.name), JSON.stringify(entryB.room.name), this._lexicographicalComparator(entryA.room, entryB.room)); + return this._lexicographicalComparator(entryA.room, entryB.room); + } + _lexicographicalComparator(roomA, roomB) { - return roomA.name > roomB.name ? 1 : -1; + return roomA.name.localeCompare(roomB.name); } _getManualComparator(tagName, optimisticRequest) { From d70a9bd001c9ec85074bc9bb2f3b741148dea7a6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 19 Feb 2020 14:39:36 +0000 Subject: [PATCH 03/15] small tweaks, still not working reliably Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/settings/Settings.js | 2 +- src/settings/controllers/RoomListOrderingController.js | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 87c1526eaaf..2b7dc706231 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -437,7 +437,7 @@ export const SETTINGS = { "RoomList.orderingAlgorithm": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, displayName: _td("Order rooms by message activity instead of by name"), - default: "recent", // XXX controller maps boolean onto algorithm for future flexibility + default: "recent", // controller maps boolean onto algorithm for future flexibility to >2 algorithms controller: new RoomListOrderingController(), }, "RoomList.orderByImportance": { diff --git a/src/settings/controllers/RoomListOrderingController.js b/src/settings/controllers/RoomListOrderingController.js index 449e21545af..7c55e607fc5 100644 --- a/src/settings/controllers/RoomListOrderingController.js +++ b/src/settings/controllers/RoomListOrderingController.js @@ -22,4 +22,14 @@ export default class RoomListOrderingController extends SettingController { // where we may want >2 algorithms available for the user to choose between. return newValue ? "recent" : "alphabetic"; } + + getValueOverride(level: string, roomId: String, calculatedValue: *, calculatedAtLevel: string): * { + switch (calculatedValue) { + case "alphabetic": + return false; + case "recent": + default: + return true; + } + } } From a6edc34e9758295832baa49b03776aa0699b8d27 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 19 Feb 2020 14:52:00 +0000 Subject: [PATCH 04/15] Iterate things Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../tabs/user/PreferencesUserSettingsTab.js | 2 +- src/settings/Settings.js | 6 +- src/settings/SettingsStore.js | 6 +- .../controllers/RoomListOrderingController.js | 35 -------- src/stores/RoomListStore.js | 84 +++++++------------ 5 files changed, 35 insertions(+), 98 deletions(-) delete mode 100644 src/settings/controllers/RoomListOrderingController.js diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js index b7fb895a9ab..09b9151ddc9 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js @@ -48,7 +48,7 @@ export default class PreferencesUserSettingsTab extends React.Component { ]; static ROOM_LIST_SETTINGS = [ - 'RoomList.orderingAlgorithm', // this has a controller which maps the boolean inputs to algorithms + 'RoomList.orderByRecents', 'RoomList.orderByImportance', 'breadcrumbs', ]; diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 2b7dc706231..b35301f124e 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -26,7 +26,6 @@ import CustomStatusController from "./controllers/CustomStatusController"; import ThemeController from './controllers/ThemeController'; import ReloadOnChangeController from "./controllers/ReloadOnChangeController"; import {RIGHT_PANEL_PHASES} from "../stores/RightPanelStorePhases"; -import RoomListOrderingController from "./controllers/RoomListOrderingController"; // These are just a bunch of helper arrays to avoid copy/pasting a bunch of times const LEVELS_ROOM_SETTINGS = ['device', 'room-device', 'room-account', 'account', 'config']; @@ -434,11 +433,10 @@ export const SETTINGS = { deny: [], }, }, - "RoomList.orderingAlgorithm": { + "RoomList.orderByRecents": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, displayName: _td("Order rooms by message activity instead of by name"), - default: "recent", // controller maps boolean onto algorithm for future flexibility to >2 algorithms - controller: new RoomListOrderingController(), + default: true, }, "RoomList.orderByImportance": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, diff --git a/src/settings/SettingsStore.js b/src/settings/SettingsStore.js index 897c2521ccb..0122916bc35 100644 --- a/src/settings/SettingsStore.js +++ b/src/settings/SettingsStore.js @@ -420,13 +420,9 @@ export default class SettingsStore { throw new Error("User cannot set " + settingName + " at " + level + " in " + roomId); } - const controller = setting.controller; - if (controller) { - value = controller.augmentValue(level, roomId, value); - } - await handler.setValue(settingName, roomId, value); + const controller = setting.controller; if (controller) { controller.onChange(level, roomId, value); } diff --git a/src/settings/controllers/RoomListOrderingController.js b/src/settings/controllers/RoomListOrderingController.js deleted file mode 100644 index 7c55e607fc5..00000000000 --- a/src/settings/controllers/RoomListOrderingController.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import SettingController from "./SettingController"; - -export default class RoomListOrderingController extends SettingController { - augmentValue(level, roomId, newValue): * { - // currently we expose algorithm as a boolean but store it as a string for future flexibility - // where we may want >2 algorithms available for the user to choose between. - return newValue ? "recent" : "alphabetic"; - } - - getValueOverride(level: string, roomId: String, calculatedValue: *, calculatedAtLevel: string): * { - switch (calculatedValue) { - case "alphabetic": - return false; - case "recent": - default: - return true; - } - } -} diff --git a/src/stores/RoomListStore.js b/src/stores/RoomListStore.js index e99214dea12..3c6171f272a 100644 --- a/src/stores/RoomListStore.js +++ b/src/stores/RoomListStore.js @@ -56,6 +56,8 @@ export const ALGO_RECENT = "recent"; const CATEGORY_ORDER = [CATEGORY_RED, CATEGORY_GREY, CATEGORY_BOLD, CATEGORY_IDLE]; const getListAlgorithm = (listKey, settingAlgorithm) => { + // apply manual sorting only to m.favourite, otherwise respect the global setting + // all the known tags are listed explicitly here to simplify future changes switch (listKey) { case "m.favourite": return ALGO_MANUAL; @@ -64,9 +66,8 @@ const getListAlgorithm = (listKey, settingAlgorithm) => { case "im.vector.fake.direct": case "im.vector.fake.archived": case "m.lowpriority": - return settingAlgorithm; default: - return ALGO_MANUAL; // TODO verify this is desired + return settingAlgorithm; } }; @@ -129,7 +130,7 @@ class RoomListStore extends Store { }; SettingsStore.monitorSetting('RoomList.orderByImportance', null); - SettingsStore.monitorSetting('RoomList.orderingAlgorithm', null); + SettingsStore.monitorSetting('RoomList.orderByRecents', null); SettingsStore.monitorSetting('feature_custom_tags', null); } @@ -156,8 +157,9 @@ class RoomListStore extends Store { if (!logicallyReady) break; switch (payload.settingName) { - case "RoomList.orderingAlgorithm": - this.updateSortingAlgorithm(payload.newValue, this._state.orderImportantFirst); + case "RoomList.orderByRecents": + this.updateSortingAlgorithm(payload.newValue ? ALGO_RECENT : ALGO_ALPHABETIC, + this._state.orderImportantFirst); break; case "RoomList.orderByImportance": this.updateSortingAlgorithm(this._state.algorithm, payload.newValue); @@ -183,9 +185,9 @@ class RoomListStore extends Store { this._matrixClient = payload.matrixClient; - const algorithm = SettingsStore.getValue("RoomList.orderingAlgorithm"); + const orderByRecents = SettingsStore.getValue("RoomList.orderByRecents"); const orderByImportance = SettingsStore.getValue("RoomList.orderByImportance"); - this.updateSortingAlgorithm(algorithm, orderByImportance); + this.updateSortingAlgorithm(orderByRecents ? ALGO_RECENT : ALGO_ALPHABETIC, orderByImportance); } break; case 'MatrixActions.Room.receipt': { @@ -446,11 +448,9 @@ class RoomListStore extends Store { if (changedBoundary) { // If we changed a boundary, then we've gone too far - go to the top of the last // section instead. - console.log("DEBUG changedBoundary", room.name, room, category); newList.splice(desiredCategoryBoundaryIndex, 0, {room, category}); } else { // If we're ordering by timestamp, just insert normally - console.log("DEBUG 11push", room.name, room, category); newList.push({room, category}); } pushedEntry = true; @@ -502,19 +502,16 @@ class RoomListStore extends Store { // Speed optimization: Don't do complicated math if we don't have to. if (!shouldHaveRoom) { - console.log("DEBUG A"); listsClone[key] = this._state.lists[key].filter((e) => e.room.roomId !== room.roomId); - } else if (getListAlgorithm(key, this._state.algorithm) === ALGO_MANUAL) { + } else if (getListAlgorithm(key, this._state.algorithm) === ALGO_MANUAL || !this._state.orderImportantFirst) { // Manually ordered tags are sorted later, so for now we'll just clone the tag // and add our room if needed listsClone[key] = this._state.lists[key].filter((e) => e.room.roomId !== room.roomId); - console.log("DEBUG push", room.name, room, category); listsClone[key].push({room, category}); insertedIntoTags.push(key); } else { listsClone[key] = []; - console.log("DEBUG slot"); const pushedEntry = this._slotRoomIntoList( room, category, key, this._state.lists[key], listsClone[key], lastTimestamp); @@ -561,23 +558,16 @@ class RoomListStore extends Store { console.warn(`!! List for tag ${targetTag} does not exist - creating`); listsClone[targetTag] = []; } - console.log("DEBUG123", room.name, room, category); listsClone[targetTag].splice(0, 0, {room, category}); } } - console.log("DEBUG targetTags", targetTags); - // Sort the favourites before we set the clone for (const tag of Object.keys(listsClone)) { if (getListAlgorithm(tag, this._state.algorithm) !== ALGO_MANUAL) continue; // skip recents (pre-sorted) - console.log("DEBUG applying manual sort to", tag); listsClone[tag].sort(this._getManualComparator(tag)); } - console.log("DEBUG setting lists=listsClone", - this._state.lists["im.vector.fake.recent"].map(e => e.room.name), - listsClone["im.vector.fake.recent"].map(e => e.room.name)); this._setState({lists: listsClone}); } @@ -660,27 +650,36 @@ class RoomListStore extends Store { Object.keys(lists).forEach((listKey) => { let comparator; - console.log("DEBUG sorting", listKey, "using", getListAlgorithm(listKey, this._state.algorithm)); switch (getListAlgorithm(listKey, this._state.algorithm)) { case ALGO_RECENT: - comparator = (entryA, entryB) => { - return this._recentsComparator(entryA, entryB, tsOfNewestEventFn); - }; + comparator = (entryA, entryB) => this._recentsComparator(entryA, entryB, tsOfNewestEventFn); break; case ALGO_ALPHABETIC: - comparator = (entryA, entryB) => this._alphabeticComparator(entryA, entryB); + comparator = this._lexicographicalComparator; break; case ALGO_MANUAL: default: comparator = this._getManualComparator(listKey); break; } - console.log("DEBUG before", listKey, lists[listKey].map(e => e.room.name)); - lists[listKey].sort(comparator); // TODO inline the common CATEGORY comparator here? - console.log("DEBUG after", listKey, lists[listKey].map(e => e.room.name)); + + if (this._state.orderImportantFirst) { + lists[listKey].sort((entryA, entryB) => { + if (entryA.category !== entryB.category) { + const idxA = CATEGORY_ORDER.indexOf(entryA.category); + const idxB = CATEGORY_ORDER.indexOf(entryB.category); + if (idxA > idxB) return 1; + if (idxA < idxB) return -1; + return 0; // Technically not possible + } + return comparator(entryA, entryB); + }); + } else { + // skip the category comparison even though it should no-op when orderImportantFirst disabled + lists[listKey].sort(comparator); + } }); - console.log("DEBUG setting lists after comparator"); this._setState({ lists, ready: true, // Ready to receive updates to ordering @@ -739,34 +738,13 @@ class RoomListStore extends Store { _recentsComparator(entryA, entryB, tsOfNewestEventFn) { console.trace("DEBUG recents"); - if (entryA.category !== entryB.category) { - const idxA = CATEGORY_ORDER.indexOf(entryA.category); - const idxB = CATEGORY_ORDER.indexOf(entryB.category); - if (idxA > idxB) return 1; - if (idxA < idxB) return -1; - return 0; // Technically not possible - } - const timestampA = tsOfNewestEventFn(entryA.room); const timestampB = tsOfNewestEventFn(entryB.room); return timestampB - timestampA; } - _alphabeticComparator(entryA, entryB) { - if (entryA.category !== entryB.category) { - const idxA = CATEGORY_ORDER.indexOf(entryA.category); - const idxB = CATEGORY_ORDER.indexOf(entryB.category); - if (idxA > idxB) return 1; - if (idxA < idxB) return -1; - return 0; // Technically not possible - } - - // console.log("DEBUG alphabetic, same category", JSON.stringify(entryA.room.name), JSON.stringify(entryB.room.name), this._lexicographicalComparator(entryA.room, entryB.room)); - return this._lexicographicalComparator(entryA.room, entryB.room); - } - - _lexicographicalComparator(roomA, roomB) { - return roomA.name.localeCompare(roomB.name); + _lexicographicalComparator(entryA, entryB) { + return entryA.room.name.localeCompare(entryB.room.name); } _getManualComparator(tagName, optimisticRequest) { @@ -791,7 +769,7 @@ class RoomListStore extends Store { return -1; } - return a === b ? this._lexicographicalComparator(roomA, roomB) : (a > b ? 1 : -1); + return a === b ? this._lexicographicalComparator(entryA, entryB) : (a > b ? 1 : -1); }; } From d1503d8a65c0a985863c26c8daefa3e192c0c05c Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 19 Feb 2020 14:55:49 +0000 Subject: [PATCH 05/15] fix edge case Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/stores/RoomListStore.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/stores/RoomListStore.js b/src/stores/RoomListStore.js index 3c6171f272a..02dd04bda9b 100644 --- a/src/stores/RoomListStore.js +++ b/src/stores/RoomListStore.js @@ -474,6 +474,12 @@ class RoomListStore extends Store { _setRoomCategory(room, category) { if (!room) return; // This should only happen in tests + if (!this._state.orderImportantFirst) { + // XXX bail here early to avoid https://github.com/vector-im/riot-web/issues/9216 + // this may mean that category updates are missed whilst not ordering by importance first + return; + } + const listsClone = {}; // Micro optimization: Support lazily loading the last timestamp in a room From 5a31b308cd3b017984d45e558415643b37c23a35 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 19 Feb 2020 15:09:05 +0000 Subject: [PATCH 06/15] remove unused clause Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/stores/RoomListStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/RoomListStore.js b/src/stores/RoomListStore.js index 02dd04bda9b..5f2ed0f1b79 100644 --- a/src/stores/RoomListStore.js +++ b/src/stores/RoomListStore.js @@ -509,7 +509,7 @@ class RoomListStore extends Store { // Speed optimization: Don't do complicated math if we don't have to. if (!shouldHaveRoom) { listsClone[key] = this._state.lists[key].filter((e) => e.room.roomId !== room.roomId); - } else if (getListAlgorithm(key, this._state.algorithm) === ALGO_MANUAL || !this._state.orderImportantFirst) { + } else if (getListAlgorithm(key, this._state.algorithm) === ALGO_MANUAL) { // Manually ordered tags are sorted later, so for now we'll just clone the tag // and add our room if needed listsClone[key] = this._state.lists[key].filter((e) => e.room.roomId !== room.roomId); From f074e858634d3e459a9318ffa319506c256322aa Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 19 Feb 2020 16:35:05 +0000 Subject: [PATCH 07/15] tidy up Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/stores/RoomListStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/RoomListStore.js b/src/stores/RoomListStore.js index 5f2ed0f1b79..8467b0be58f 100644 --- a/src/stores/RoomListStore.js +++ b/src/stores/RoomListStore.js @@ -55,6 +55,7 @@ export const ALGO_ALPHABETIC = "alphabetic"; export const ALGO_RECENT = "recent"; const CATEGORY_ORDER = [CATEGORY_RED, CATEGORY_GREY, CATEGORY_BOLD, CATEGORY_IDLE]; + const getListAlgorithm = (listKey, settingAlgorithm) => { // apply manual sorting only to m.favourite, otherwise respect the global setting // all the known tags are listed explicitly here to simplify future changes @@ -743,7 +744,6 @@ class RoomListStore extends Store { } _recentsComparator(entryA, entryB, tsOfNewestEventFn) { - console.trace("DEBUG recents"); const timestampA = tsOfNewestEventFn(entryA.room); const timestampB = tsOfNewestEventFn(entryB.room); return timestampB - timestampA; From 3ad8b6e9ccd221aef9bb1a38fd875549981a39d1 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Feb 2020 23:05:08 +0000 Subject: [PATCH 08/15] Use RoomList.orderAlphabetically as the inverse of RoomList.orderByRecents for migration Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../settings/tabs/user/PreferencesUserSettingsTab.js | 2 +- src/settings/Settings.js | 5 +++-- src/stores/RoomListStore.js | 10 +++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js index 09b9151ddc9..ba6695ecf14 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js @@ -48,7 +48,7 @@ export default class PreferencesUserSettingsTab extends React.Component { ]; static ROOM_LIST_SETTINGS = [ - 'RoomList.orderByRecents', + 'RoomList.orderAlphabetically', 'RoomList.orderByImportance', 'breadcrumbs', ]; diff --git a/src/settings/Settings.js b/src/settings/Settings.js index b35301f124e..e384aa8f0f2 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -433,10 +433,11 @@ export const SETTINGS = { deny: [], }, }, - "RoomList.orderByRecents": { + "RoomList.orderAlphabetically": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, - displayName: _td("Order rooms by message activity instead of by name"), + displayName: _td("Order rooms alphabetically by name instead of by recent activity"), default: true, + invertedSettingName: "RoomList.orderByRecents", }, "RoomList.orderByImportance": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, diff --git a/src/stores/RoomListStore.js b/src/stores/RoomListStore.js index e0d60c3eacd..30b523d35d9 100644 --- a/src/stores/RoomListStore.js +++ b/src/stores/RoomListStore.js @@ -133,8 +133,8 @@ class RoomListStore extends Store { orderImportantFirst: false, }; + SettingsStore.monitorSetting('RoomList.orderAlphabetically', null); SettingsStore.monitorSetting('RoomList.orderByImportance', null); - SettingsStore.monitorSetting('RoomList.orderByRecents', null); SettingsStore.monitorSetting('feature_custom_tags', null); } @@ -161,8 +161,8 @@ class RoomListStore extends Store { if (!logicallyReady) break; switch (payload.settingName) { - case "RoomList.orderByRecents": - this.updateSortingAlgorithm(payload.newValue ? ALGO_RECENT : ALGO_ALPHABETIC, + case "RoomList.orderAlphabetically": + this.updateSortingAlgorithm(payload.newValue ? ALGO_ALPHABETIC : ALGO_RECENT, this._state.orderImportantFirst); break; case "RoomList.orderByImportance": @@ -189,9 +189,9 @@ class RoomListStore extends Store { this._matrixClient = payload.matrixClient; - const orderByRecents = SettingsStore.getValue("RoomList.orderByRecents"); const orderByImportance = SettingsStore.getValue("RoomList.orderByImportance"); - this.updateSortingAlgorithm(orderByRecents ? ALGO_RECENT : ALGO_ALPHABETIC, orderByImportance); + const orderAlphabetically = SettingsStore.getValue("RoomList.orderAlphabetically"); + this.updateSortingAlgorithm(orderAlphabetically ? ALGO_ALPHABETIC : ALGO_RECENT, orderByImportance); } break; case 'MatrixActions.Room.receipt': { From ed650d5b9052158acc3c1fac69cd91f221417308 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Feb 2020 23:07:43 +0000 Subject: [PATCH 09/15] Move Room List preferences section to be first Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../tabs/user/PreferencesUserSettingsTab.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js index ba6695ecf14..2b8abafdb45 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js @@ -25,6 +25,12 @@ import * as sdk from "../../../../.."; import PlatformPeg from "../../../../../PlatformPeg"; export default class PreferencesUserSettingsTab extends React.Component { + static ROOM_LIST_SETTINGS = [ + 'RoomList.orderAlphabetically', + 'RoomList.orderByImportance', + 'breadcrumbs', + ]; + static COMPOSER_SETTINGS = [ 'MessageComposerInput.autoReplaceEmoji', 'MessageComposerInput.suggestEmoji', @@ -47,12 +53,6 @@ export default class PreferencesUserSettingsTab extends React.Component { 'showImages', ]; - static ROOM_LIST_SETTINGS = [ - 'RoomList.orderAlphabetically', - 'RoomList.orderByImportance', - 'breadcrumbs', - ]; - static ADVANCED_SETTINGS = [ 'alwaysShowEncryptionIcons', 'Pill.shouldShowPillAvatar', @@ -174,15 +174,15 @@ export default class PreferencesUserSettingsTab extends React.Component {
{_t("Preferences")}
+ {_t("Room list")} + {this._renderGroup(PreferencesUserSettingsTab.ROOM_LIST_SETTINGS)} + {_t("Composer")} {this._renderGroup(PreferencesUserSettingsTab.COMPOSER_SETTINGS)} {_t("Timeline")} {this._renderGroup(PreferencesUserSettingsTab.TIMELINE_SETTINGS)} - {_t("Room list")} - {this._renderGroup(PreferencesUserSettingsTab.ROOM_LIST_SETTINGS)} - {_t("Advanced")} {this._renderGroup(PreferencesUserSettingsTab.ADVANCED_SETTINGS)} {minimizeToTrayOption} From cada584c2569f722cce6c44c90812575c4740953 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Feb 2020 23:09:34 +0000 Subject: [PATCH 10/15] i18n Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index e1cf61c5fed..0994b955aba 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -414,7 +414,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 by message activity instead of by name": "Order rooms by message activity instead of by name", + "Order rooms alphabetically by name instead of by recent activity": "Order rooms alphabetically by name instead of by recent activity", "Show rooms with unread notifications first": "Show rooms with unread notifications first", "Show shortcuts to recently viewed rooms above the room list": "Show shortcuts to recently viewed rooms above the room list", "Show hidden events in timeline": "Show hidden events in timeline", @@ -775,9 +775,9 @@ "Always show the window menu bar": "Always show the window menu bar", "Show tray icon and minimize window to it on close": "Show tray icon and minimize window to it on close", "Preferences": "Preferences", + "Room list": "Room list", "Composer": "Composer", "Timeline": "Timeline", - "Room list": "Room list", "Autocomplete delay (ms)": "Autocomplete delay (ms)", "Read Marker lifetime (ms)": "Read Marker lifetime (ms)", "Read Marker off-screen lifetime (ms)": "Read Marker off-screen lifetime (ms)", From 6a66c4162bb84e9fbf30f7df669d2b98f629c001 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Feb 2020 23:16:27 +0000 Subject: [PATCH 11/15] Space preference sections out more significantly to make the section headers obvious Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../tabs/user/_PreferencesUserSettingsTab.scss | 10 ++++++++-- .../settings/tabs/user/PreferencesUserSettingsTab.js | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss b/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss index d003e175d99..aaa929604d2 100644 --- a/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss @@ -14,6 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_PreferencesUserSettingsTab .mx_Field { - @mixin mx_Settings_fullWidthField; +.mx_PreferencesUserSettingsTab { + .mx_Field { + @mixin mx_Settings_fullWidthField; + } + + .mx_SettingsTab_section { + margin-top: 30px; + } } diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js index 2b8abafdb45..8df65e65902 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js @@ -176,13 +176,19 @@ export default class PreferencesUserSettingsTab extends React.Component {
{_t("Room list")} {this._renderGroup(PreferencesUserSettingsTab.ROOM_LIST_SETTINGS)} +
+
{_t("Composer")} {this._renderGroup(PreferencesUserSettingsTab.COMPOSER_SETTINGS)} +
+
{_t("Timeline")} {this._renderGroup(PreferencesUserSettingsTab.TIMELINE_SETTINGS)} +
+
{_t("Advanced")} {this._renderGroup(PreferencesUserSettingsTab.ADVANCED_SETTINGS)} {minimizeToTrayOption} From 1875bf4bfe938ecc9573ad2d54aedf8df25e76a2 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Feb 2020 23:18:01 +0000 Subject: [PATCH 12/15] remove the first preference section's margin Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../views/settings/tabs/user/_PreferencesUserSettingsTab.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss b/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss index aaa929604d2..be0af9123bd 100644 --- a/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss @@ -20,6 +20,6 @@ limitations under the License. } .mx_SettingsTab_section { - margin-top: 30px; + margin-bottom: 30px; } } From f036f0bd8362f0664c1d55ed6ec7820f9dbe6f08 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Feb 2020 23:19:05 +0000 Subject: [PATCH 13/15] Fix copy Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 2 +- src/settings/Settings.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 0994b955aba..f5209f8e18c 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -414,7 +414,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 alphabetically by name instead of by recent activity": "Order rooms alphabetically by name instead of by recent activity", + "Order rooms by name": "Order rooms by name", "Show rooms with unread notifications first": "Show rooms with unread notifications first", "Show shortcuts to recently viewed rooms above the room list": "Show shortcuts to recently viewed rooms above the room list", "Show hidden events in timeline": "Show hidden events in timeline", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index e384aa8f0f2..87602f866ce 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -435,7 +435,7 @@ export const SETTINGS = { }, "RoomList.orderAlphabetically": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, - displayName: _td("Order rooms alphabetically by name instead of by recent activity"), + displayName: _td("Order rooms by name"), default: true, invertedSettingName: "RoomList.orderByRecents", }, From 75c593b2f4891e84fe208238078b47a85bf29a07 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Feb 2020 23:19:50 +0000 Subject: [PATCH 14/15] get rid of unused stuff Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/settings/Settings.js | 1 - src/settings/controllers/SettingController.js | 11 ----------- 2 files changed, 12 deletions(-) diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 87602f866ce..4687b57b3b4 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -437,7 +437,6 @@ export const SETTINGS = { supportedLevels: LEVELS_ACCOUNT_SETTINGS, displayName: _td("Order rooms by name"), default: true, - invertedSettingName: "RoomList.orderByRecents", }, "RoomList.orderByImportance": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, diff --git a/src/settings/controllers/SettingController.js b/src/settings/controllers/SettingController.js index 9327f6ab484..a7d0ccf21a8 100644 --- a/src/settings/controllers/SettingController.js +++ b/src/settings/controllers/SettingController.js @@ -47,15 +47,4 @@ export default class SettingController { onChange(level, roomId, newValue) { // do nothing by default } - - /** - * Gets the value which should actually get written into the store based on the input value from setValue. - * @param {string} level The level at which the setting has been modified. - * @param {String} roomId The room ID, may be null. - * @param {*} newValue The new value for the setting, may be null. - * @return {*} The value that should be used, may be null. - */ - augmentValue(level, roomId, newValue) { - return newValue; - } } From e0fdfa1c1c25d9a178575030fa044584240c4a8d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Feb 2020 23:21:37 +0000 Subject: [PATCH 15/15] fix default value for alphabetic sorting setting Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/settings/Settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 4687b57b3b4..b77fb392e9d 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -436,7 +436,7 @@ export const SETTINGS = { "RoomList.orderAlphabetically": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, displayName: _td("Order rooms by name"), - default: true, + default: false, }, "RoomList.orderByImportance": { supportedLevels: LEVELS_ACCOUNT_SETTINGS,