diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 030644616..2c7da681b 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1969,6 +1969,10 @@ "message": "Remove all draft attachments", "description": "Shown in the shortcuts guide" }, + "Keyboard--conversation-by-index": { + "message": "Jump to conversation", + "description": "A shortcut allowing direct navigation to conversations 1 to 9 in list" + }, "Keyboard--Key--ctrl": { "message": "Ctrl", "description": "Key shown in shortcut combination in shortcuts guide" @@ -1989,6 +1993,14 @@ "message": "Enter", "description": "Key shown in shortcut combination in shortcuts guide" }, + "Keyboard--Key--tab": { + "message": "Tab", + "description": "Key shown in shortcut combination in shortcuts guide" + }, + "Keyboard--Key--one-to-nine-range": { + "message": "1 to 9", + "description": "Expresses that 1, 2, 3, up to 9 are available shortcut keys" + }, "Keyboard--header": { "message": "Keyboard Shortcuts", "description": "Title header of the keyboard shortcuts guide" diff --git a/js/background.js b/js/background.js index 03ca38c7b..7118d1931 100644 --- a/js/background.js +++ b/js/background.js @@ -702,6 +702,24 @@ } }; + function getConversationByIndex(index) { + const state = store.getState(); + const lists = Signal.State.Selectors.conversations.getLeftPaneLists( + state + ); + const toSearch = state.conversations.showArchived + ? lists.archivedConversations + : lists.conversations; + + const target = toSearch[index]; + + if (target) { + return target.id; + } + + return null; + } + function findConversation(conversationId, direction, unreadOnly) { const state = store.getState(); const lists = Signal.State.Selectors.conversations.getLeftPaneLists( @@ -739,6 +757,18 @@ return null; } + const NUMBERS = { + '1': 1, + '2': 2, + '3': 3, + '4': 4, + '5': 5, + '6': 6, + '7': 7, + '8': 8, + '9': 9, + }; + document.addEventListener('keydown', event => { const { altKey, ctrlKey, key, metaKey, shiftKey } = event; @@ -911,8 +941,24 @@ return; } - // Change currently selected conversation - up/down, to next/previous unread - if (!isSearching && optionOrAlt && !shiftKey && key === 'ArrowUp') { + // Change currently selected conversation by index + if (!isSearching && commandOrCtrl && NUMBERS[key]) { + const targetId = getConversationByIndex(NUMBERS[key] - 1); + + if (targetId) { + window.Whisper.events.trigger('showConversation', targetId); + event.preventDefault(); + event.stopPropagation(); + return; + } + } + + // Change currently selected conversation + // up/previous + if ( + (!isSearching && optionOrAlt && !shiftKey && key === 'ArrowUp') || + (!isSearching && ctrlKey && shiftKey && key === 'Tab') + ) { const unreadOnly = false; const targetId = findConversation( conversation ? conversation.id : null, @@ -927,7 +973,11 @@ return; } } - if (!isSearching && optionOrAlt && !shiftKey && key === 'ArrowDown') { + // down/next + if ( + (!isSearching && optionOrAlt && !shiftKey && key === 'ArrowDown') || + (!isSearching && ctrlKey && key === 'Tab') + ) { const unreadOnly = false; const targetId = findConversation( conversation ? conversation.id : null, @@ -942,6 +992,7 @@ return; } } + // previous unread if (!isSearching && optionOrAlt && shiftKey && key === 'ArrowUp') { const unreadOnly = true; const targetId = findConversation( @@ -957,6 +1008,7 @@ return; } } + // next unread if (!isSearching && optionOrAlt && shiftKey && key === 'ArrowDown') { const unreadOnly = true; const targetId = findConversation( diff --git a/stylesheets/_modules.scss b/stylesheets/_modules.scss index 86d1a08b2..12a78ac93 100644 --- a/stylesheets/_modules.scss +++ b/stylesheets/_modules.scss @@ -7697,11 +7697,15 @@ button.module-image__border-overlay:focus { margin-bottom: 4px; } .module-shortcut-guide__shortcut__key-container { - text-align: right; - margin-right: 4px; margin-bottom: 4px; +} +.module-shortcut-guide__shortcut__key-inner-container { + text-align: right; + margin-top: 4px; + margin-right: 4px; white-space: nowrap; } + .module-shortcut-guide__shortcut__key { display: inline-block; @@ -7709,7 +7713,6 @@ button.module-image__border-overlay:focus { padding: 3px; padding-left: 8px; padding-right: 8px; - margin-top: 4px; margin-left: 4px; height: 30px; diff --git a/ts/components/ShortcutGuide.tsx b/ts/components/ShortcutGuide.tsx index d6b5ae849..4e5017c88 100644 --- a/ts/components/ShortcutGuide.tsx +++ b/ts/components/ShortcutGuide.tsx @@ -15,6 +15,8 @@ type KeyType = | 'optionOrAlt' | 'shift' | 'enter' + | 'tab' + | 'ctrl' | '↑' | '↓' | ',' @@ -33,142 +35,153 @@ type KeyType = | 'T' | 'U' | 'V' - | 'X'; + | 'X' + | '1 to 9'; type ShortcutType = { description: string; - keys: Array; + keys: Array>; }; const NAVIGATION_SHORTCUTS: Array = [ { description: 'Keyboard--navigate-by-section', - keys: ['commandOrCtrl', 'T'], + keys: [['commandOrCtrl', 'T']], }, { description: 'Keyboard--previous-conversation', - keys: ['optionOrAlt', '↑'], + keys: [ + ['optionOrAlt', '↑'], + ['ctrl', 'shift', 'tab'], + ], }, { description: 'Keyboard--next-conversation', - keys: ['optionOrAlt', '↓'], + keys: [ + ['optionOrAlt', '↓'], + ['ctrl', 'tab'], + ], }, { description: 'Keyboard--previous-unread-conversation', - keys: ['optionOrAlt', 'shift', '↑'], + keys: [['optionOrAlt', 'shift', '↑']], }, { description: 'Keyboard--next-unread-conversation', - keys: ['optionOrAlt', 'shift', '↓'], + keys: [['optionOrAlt', 'shift', '↓']], + }, + { + description: 'Keyboard--conversation-by-index', + keys: [['commandOrCtrl', '1 to 9']], }, { description: 'Keyboard--preferences', - keys: ['commandOrCtrl', ','], + keys: [['commandOrCtrl', ',']], }, { description: 'Keyboard--open-conversation-menu', - keys: ['commandOrCtrl', 'shift', 'L'], + keys: [['commandOrCtrl', 'shift', 'L']], }, { description: 'Keyboard--search', - keys: ['commandOrCtrl', 'F'], + keys: [['commandOrCtrl', 'F']], }, { description: 'Keyboard--search-in-conversation', - keys: ['commandOrCtrl', 'shift', 'F'], + keys: [['commandOrCtrl', 'shift', 'F']], }, { description: 'Keyboard--focus-composer', - keys: ['commandOrCtrl', 'shift', 'T'], + keys: [['commandOrCtrl', 'shift', 'T']], }, { description: 'Keyboard--open-all-media-view', - keys: ['commandOrCtrl', 'shift', 'M'], + keys: [['commandOrCtrl', 'shift', 'M']], }, { description: 'Keyboard--open-emoji-chooser', - keys: ['commandOrCtrl', 'shift', 'J'], + keys: [['commandOrCtrl', 'shift', 'J']], }, { description: 'Keyboard--open-sticker-chooser', - keys: ['commandOrCtrl', 'shift', 'S'], + keys: [['commandOrCtrl', 'shift', 'S']], }, { description: 'Keyboard--begin-recording-voice-note', - keys: ['commandOrCtrl', 'shift', 'V'], + keys: [['commandOrCtrl', 'shift', 'V']], }, { description: 'Keyboard--archive-conversation', - keys: ['commandOrCtrl', 'shift', 'A'], + keys: [['commandOrCtrl', 'shift', 'A']], }, { description: 'Keyboard--unarchive-conversation', - keys: ['commandOrCtrl', 'shift', 'U'], + keys: [['commandOrCtrl', 'shift', 'U']], }, { description: 'Keyboard--scroll-to-top', - keys: ['commandOrCtrl', '↑'], + keys: [['commandOrCtrl', '↑']], }, { description: 'Keyboard--scroll-to-bottom', - keys: ['commandOrCtrl', '↓'], + keys: [['commandOrCtrl', '↓']], }, { description: 'Keyboard--close-curent-conversation', - keys: ['commandOrCtrl', 'shift', 'C'], + keys: [['commandOrCtrl', 'shift', 'C']], }, ]; const MESSAGE_SHORTCUTS: Array = [ { description: 'Keyboard--default-message-action', - keys: ['enter'], + keys: [['enter']], }, { description: 'Keyboard--view-details-for-selected-message', - keys: ['commandOrCtrl', 'D'], + keys: [['commandOrCtrl', 'D']], }, { description: 'Keyboard--toggle-reply', - keys: ['commandOrCtrl', 'shift', 'R'], + keys: [['commandOrCtrl', 'shift', 'R']], }, { description: 'Keyboard--toggle-reaction-picker', - keys: ['commandOrCtrl', 'shift', 'E'], + keys: [['commandOrCtrl', 'shift', 'E']], }, { description: 'Keyboard--save-attachment', - keys: ['commandOrCtrl', 'S'], + keys: [['commandOrCtrl', 'S']], }, { description: 'Keyboard--delete-message', - keys: ['commandOrCtrl', 'shift', 'D'], + keys: [['commandOrCtrl', 'shift', 'D']], }, ]; const COMPOSER_SHORTCUTS: Array = [ { description: 'Keyboard--add-newline', - keys: ['shift', 'enter'], + keys: [['shift', 'enter']], }, { description: 'Keyboard--expand-composer', - keys: ['commandOrCtrl', 'shift', 'X'], + keys: [['commandOrCtrl', 'shift', 'X']], }, { description: 'Keyboard--send-in-expanded-composer', - keys: ['commandOrCtrl', 'enter'], + keys: [['commandOrCtrl', 'enter']], }, { description: 'Keyboard--attach-file', - keys: ['commandOrCtrl', 'U'], + keys: [['commandOrCtrl', 'U']], }, { description: 'Keyboard--remove-draft-link-preview', - keys: ['commandOrCtrl', 'P'], + keys: [['commandOrCtrl', 'P']], }, { description: 'Keyboard--remove-draft-attachments', - keys: ['commandOrCtrl', 'shift', 'P'], + keys: [['commandOrCtrl', 'shift', 'P']], }, ]; @@ -253,46 +266,67 @@ function renderShortcut( {i18n(shortcut.description)}
- {shortcut.keys.map((key, mapIndex) => { - let label: string = key; - let isSquare = true; + {shortcut.keys.map((keys, outerIndex) => ( +
+ {keys.map((key, mapIndex) => { + let label: string = key; + let isSquare = true; - if (key === 'commandOrCtrl' && isMacOS) { - label = '⌘'; - } - if (key === 'commandOrCtrl' && !isMacOS) { - label = i18n('Keyboard--Key--ctrl'); - isSquare = false; - } - if (key === 'optionOrAlt' && isMacOS) { - label = i18n('Keyboard--Key--option'); - isSquare = false; - } - if (key === 'optionOrAlt' && !isMacOS) { - label = i18n('Keyboard--Key--alt'); - isSquare = false; - } - if (key === 'shift') { - label = i18n('Keyboard--Key--shift'); - isSquare = false; - } - if (key === 'enter') { - label = i18n('Keyboard--Key--enter'); - isSquare = false; - } + if (key === 'commandOrCtrl' && isMacOS) { + label = '⌘'; + } + if (key === 'commandOrCtrl' && !isMacOS) { + label = i18n('Keyboard--Key--ctrl'); + isSquare = false; + } + if (key === 'optionOrAlt' && isMacOS) { + label = i18n('Keyboard--Key--option'); + isSquare = false; + } + if (key === 'optionOrAlt' && !isMacOS) { + label = i18n('Keyboard--Key--alt'); + isSquare = false; + } + if (key === 'ctrl') { + label = i18n('Keyboard--Key--ctrl'); + isSquare = false; + } + if (key === 'shift') { + label = i18n('Keyboard--Key--shift'); + isSquare = false; + } + if (key === 'enter') { + label = i18n('Keyboard--Key--enter'); + isSquare = false; + } + if (key === 'tab') { + label = i18n('Keyboard--Key--tab'); + isSquare = false; + } + if (key === '1 to 9') { + label = i18n('Keyboard--Key--one-to-nine-range'); + isSquare = false; + } - return ( - - {label} - - ); - })} + return ( + + {label} + + ); + })} +
+ ))}
);