From 936c49127d2bb1691399144b08c1b9951f865104 Mon Sep 17 00:00:00 2001 From: miruka Date: Fri, 27 Mar 2020 04:49:01 -0400 Subject: [PATCH] Add keyboard controls for message focus/selection --- src/backend/user_files.py | 10 +++- src/gui/Base/HListView.qml | 23 ++++++++- src/gui/Pages/Chat/Composer.qml | 3 +- src/gui/Pages/Chat/Timeline/EventDelegate.qml | 4 +- src/gui/Pages/Chat/Timeline/EventList.qml | 49 ++++++++++++++++++- 5 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/backend/user_files.py b/src/backend/user_files.py index a5273a74..17ebc659 100644 --- a/src/backend/user_files.py +++ b/src/backend/user_files.py @@ -270,8 +270,14 @@ class UISettings(JSONDataFile): "10": "Alt+0", }, - "unselectAllMessages": ["Escape"], - "clearRoomMessages": ["Ctrl+L"], + "unfocusOrUnselectAllMessages": ["Escape"], + "focusPreviousMessage": ["Ctrl+Up", "Ctrl+K"], + "focusNextMessage": ["Ctrl+Down", "Ctrl+J"], + "toggleSelectMessage": ["Ctrl+Space"], + "selectMessagesUntilHere": ["Ctrl+Shift+Space"], + "debugFocusedMessage": ["Ctrl+D"], + "clearRoomMessages": ["Ctrl+L"], + "sendFile": ["Alt+S"], "sendFileFromPathInClipboard": ["Alt+Shift+S"], diff --git a/src/gui/Base/HListView.qml b/src/gui/Base/HListView.qml index 105b0aed..185f5e6f 100644 --- a/src/gui/Base/HListView.qml +++ b/src/gui/Base/HListView.qml @@ -77,14 +77,12 @@ ListView { function delegatesChecked(...indices) { - print( indices) for (const i of indices) { const model = listView.model.get(i) checkedDelegates[model.id] = model } lastCheckedDelegateIndex = indices.slice(-1)[0] - checkedDelegatesChanged() } @@ -98,6 +96,27 @@ ListView { const model = listView.model.get(i) delete checkedDelegates[model.id] } + + checkedDelegatesChanged() + } + + function toggleCheck(...indices) { + const checkedIndices = [] + + for (const i of indices) { + const model = listView.model.get(i) + + if (model.id in checkedDelegates) { + delete checkedDelegates[model.id] + } else { + checkedDelegates[model.id] = model + checkedIndices.push(i) + } + } + + if (checkedIndices.length > 0) + lastCheckedDelegateIndex = checkedIndices.slice(-1)[0] + checkedDelegatesChanged() } diff --git a/src/gui/Pages/Chat/Composer.qml b/src/gui/Pages/Chat/Composer.qml index c2a53292..3590d00a 100644 --- a/src/gui/Pages/Chat/Composer.qml +++ b/src/gui/Pages/Chat/Composer.qml @@ -205,7 +205,8 @@ Rectangle { if (ev.matches(StandardKey.Copy) && ! area.selectedText && eventList && - eventList.selectedCount) { + (eventList.selectedCount || + eventList.currentIndex !== -1)) { ev.accepted = true eventList.copySelectedDelegates() diff --git a/src/gui/Pages/Chat/Timeline/EventDelegate.qml b/src/gui/Pages/Chat/Timeline/EventDelegate.qml index 187e4488..c684c5fa 100644 --- a/src/gui/Pages/Chat/Timeline/EventDelegate.qml +++ b/src/gui/Pages/Chat/Timeline/EventDelegate.qml @@ -57,6 +57,8 @@ HColumnLayout { combine ? theme.spacing / (compact ? 4 : 2) : theme.spacing * (compact ? 1 : 2) + readonly property alias eventContent: eventContent + // Needed because of eventList's MouseArea which steals the // HSelectableLabel's MouseArea hover events onCursorShapeChanged: eventList.cursorShape = cursorShape @@ -209,7 +211,7 @@ HColumnLayout { qsTr("Copy text") onTriggered: { - if (! eventList.selectedCount) { + if (! eventList.selectedCount && eventList.currentItem === -1){ Clipboard.text = JSON.parse(model.source).body return } diff --git a/src/gui/Pages/Chat/Timeline/EventList.qml b/src/gui/Pages/Chat/Timeline/EventList.qml index 0904e65d..87d7053b 100644 --- a/src/gui/Pages/Chat/Timeline/EventList.qml +++ b/src/gui/Pages/Chat/Timeline/EventList.qml @@ -15,13 +15,51 @@ Rectangle { HShortcut { - sequences: window.settings.keys.unselectAllMessages - onActivated: eventList.checkedDelegates = {} + sequences: window.settings.keys.unfocusOrUnselectAllMessages + onActivated: { + eventList.currentIndex !== -1 ? + eventList.currentIndex = -1 : + eventList.checkedDelegates = {} + } + } + + HShortcut { + sequences: window.settings.keys.focusPreviousMessage + onActivated: eventList.incrementCurrentIndex() + } + + HShortcut { + sequences: window.settings.keys.focusNextMessage + onActivated: + eventList.currentIndex === 0 ? + eventList.currentIndex = -1 : + eventList.decrementCurrentIndex() + } + + HShortcut { + enabled: eventList.currentItem + sequences: window.settings.keys.toggleSelectMessage + onActivated: eventList.toggleCheck(eventList.currentIndex) + } + + HShortcut { + enabled: eventList.currentItem + sequences: window.settings.keys.selectMessagesUntilHere + onActivated: + eventList.delegatesFromLastToHereChecked(eventList.currentIndex) + } + + HShortcut { + enabled: eventList.currentItem + sequences: window.settings.keys.debugFocusedMessage + onActivated: + eventList.currentItem.eventContent.debugConsoleLoader.toggle() } HListView { id: eventList clip: true + keyNavigationWraps: false anchors.fill: parent anchors.leftMargin: theme.spacing @@ -87,6 +125,13 @@ Rectangle { return } + if (! eventList.selectedCount && eventList.currentIndex !== -1) { + Clipboard.text = JSON.parse( + eventList.model.get(eventList.currentIndex).source + ).body + return + } + const contents = [] for (const model of eventList.getSortedCheckedDelegates()) {