diff --git a/src/config/settings.py b/src/config/settings.py index 87d06942..c263547e 100644 --- a/src/config/settings.py +++ b/src/config/settings.py @@ -357,6 +357,10 @@ class Keys: previous_unread = ["Alt+Shift+U"] next_unread = ["Alt+U"] + # Switch to the room with the oldest/latest unread message. + oldest_unread = ["Ctrl+Shift+U"] + latest_unread = ["Ctrl+U"] + # Switch to the previous/next room with highlighted messages in the # list. What causes a highlight is controlled by push rules # (editable in GUI account settings): by default, this includes @@ -364,6 +368,11 @@ class Keys: previous_highlight = ["Alt+Shift+M"] next_highlight = ["Alt+M"] + # Switch to the room with the oldest/latest unread message, + # but only rooms with highlights are considered. + oldest_highlight = ["Ctrl+Shift+M"] + latest_highlight = ["Ctrl+M"] + class AtIndex: # Switch to room number X in the current account. # Each property is a list of keybinds for the room number X: diff --git a/src/gui/MainPane/RoomList.qml b/src/gui/MainPane/RoomList.qml index 905ec1a0..7e09f929 100644 --- a/src/gui/MainPane/RoomList.qml +++ b/src/gui/MainPane/RoomList.qml @@ -104,10 +104,10 @@ HListView { } function cycleUnreadRooms(forward=true, highlights=false) { - const prop = highlights ? "highlights" : "unreads" - const local_prop = highlights ? "highlights" : "local_unreads" - const start = currentIndex === -1 ? 0 : currentIndex - let index = start + const prop = highlights ? "highlights": "unreads" + const localProp = highlights ? "highlights": "local_unreads" + const start = currentIndex === -1 ? 0: currentIndex + let index = start while (true) { index += forward ? 1 : -1 @@ -122,13 +122,43 @@ HListView { const item = model.get(index) - if (item.type === "Room" && (item[prop] || item[local_prop])) { + if (item.type === "Room" && (item[prop] || item[localProp])) { currentIndex = index return true } } } + // Find latest highlight or unread. If oldest=true, find oldest instead. + function latestUnreadRoom(oldest=false, highlights=false) { + const prop = highlights ? "highlights": "unreads" + const localProp = highlights ? "highlights": "local_unreads" + + // When highlights=true, we don't actually find the latest highlight, + // but instead, the latest unread among all the highlighted rooms. + + let max = null + let maxEvent = null + + for (let i = 0; i < model.count; i++) { + const item = model.get(i) + + if ( + item.type === "Room" && + (item[prop] || item[localProp]) && + (max === null || item.last_event_date < maxEvent === oldest) + ) { + max = i + maxEvent = item.last_event_date + } + } + + if (max === null) return false // No unreads found + + currentIndex = max + return true + } + function startCorrectItemSearch() { correctTimer.start() } @@ -285,6 +315,26 @@ HListView { onActivated: cycleUnreadRooms(true, true) && showItemLimiter.restart() } + HShortcut { + sequences: window.settings.Keys.Rooms.latest_unread + onActivated: latestUnreadRoom(false) && showItemLimiter.restart() + } + + HShortcut { + sequences: window.settings.Keys.Rooms.oldest_unread + onActivated: latestUnreadRoom(true) && showItemLimiter.restart() + } + + HShortcut { + sequences: window.settings.Keys.Rooms.latest_highlight + onActivated: latestUnreadRoom(false, true) && showItemLimiter.restart() + } + + HShortcut { + sequences: window.settings.Keys.Rooms.oldest_highlight + onActivated: latestUnreadRoom(true, true) && showItemLimiter.restart() + } + Instantiator { model: Object.keys(window.settings.Keys.Accounts.AtIndex) delegate: Loader {