From 052aca31195a5ce768f34daeacc6eac30c107666 Mon Sep 17 00:00:00 2001 From: Josh Perez <60019601+josh-signal@users.noreply.github.com> Date: Tue, 9 May 2023 11:52:03 -0400 Subject: [PATCH] Enhance super tab --- _locales/en/messages.json | 4 + ts/background.ts | 98 +++++++++++-------------- ts/components/CompositionInput.tsx | 1 + ts/components/LeftPane.tsx | 1 + ts/components/MainHeader.tsx | 3 +- ts/components/SearchInput.tsx | 2 +- ts/components/ShortcutGuide.tsx | 11 ++- ts/components/conversation/Timeline.tsx | 9 +++ 8 files changed, 69 insertions(+), 60 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 19da046d85..54e173e3ee 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -5182,6 +5182,10 @@ "messageformat": "(draft)", "description": "Text shown in left pane as preview for conversation with saved a saved draft message" }, + "icu:Keyboard--focus-most-recent-message": { + "messageformat": "Focus oldest unread or last message", + "description": "Shown in shortcuts guide" + }, "Keyboard--navigate-by-section": { "message": "Navigate by section", "description": "(deleted 03/29/2023) Shown in the shortcuts guide" diff --git a/ts/background.ts b/ts/background.ts index 5cf5e60018..a122a2de74 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -1354,13 +1354,15 @@ export async function startApp(): Promise { } // Super tab :) - if (commandOrCtrl && key === 'F6') { + if ( + (commandOrCtrl && key === 'F6') || + (commandOrCtrl && !shiftKey && (key === 't' || key === 'T')) + ) { window.enterKeyboardMode(); const focusedElement = document.activeElement; const targets: Array = Array.from( document.querySelectorAll('[data-supertab="true"]') ); - const focusedIndex = targets.findIndex(target => { if (!target || !focusedElement) { return false; @@ -1394,65 +1396,30 @@ export async function startApp(): Promise { } } - targets[index] - .querySelectorAll(focusableSelectors.join(','))[0] - ?.focus(); - } + const node = targets[index]; + const firstFocusableElement = node.querySelectorAll( + focusableSelectors.join(',') + )[0]; - // Navigate by section - if (commandOrCtrl && !shiftKey && (key === 't' || key === 'T')) { - window.enterKeyboardMode(); - const focusedElement = document.activeElement; - - const targets: Array = [ - document.querySelector('.module-main-header .module-avatar-button'), - document.querySelector( - '.module-left-pane__header__contents__back-button' - ), - document.querySelector('.LeftPaneSearchInput__input'), - document.querySelector('.module-main-header__compose-icon'), - document.querySelector( - '.module-left-pane__compose-search-form__input' - ), - document.querySelector( - '.module-conversation-list__item--contact-or-conversation' - ), - document.querySelector('.module-search-results'), - document.querySelector('.CompositionArea .ql-editor'), - ]; - const focusedIndex = targets.findIndex(target => { - if (!target || !focusedElement) { - return false; - } - - if (target === focusedElement) { - return true; - } - - if (target.contains(focusedElement)) { - return true; - } - - return false; - }); - const lastIndex = targets.length - 1; - - let index; - if (focusedIndex < 0 || focusedIndex >= lastIndex) { - index = 0; + if (firstFocusableElement) { + firstFocusableElement.focus(); } else { - index = focusedIndex + 1; - } - - while (!targets[index]) { - index += 1; - if (index > lastIndex) { - index = 0; + const nodeInfo = Array.from(node.attributes) + .map(attr => `${attr.name}=${attr.value}`) + .join(','); + log.warn( + `supertab: could not find focus for DOM node ${node.nodeName}<${nodeInfo}>` + ); + window.enterMouseMode(); + const { activeElement } = document; + if ( + activeElement && + 'blur' in activeElement && + typeof activeElement.blur === 'function' + ) { + activeElement.blur(); } } - - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - targets[index]!.focus(); } // Cancel out of keyboard shortcut screen - has first precedence @@ -1611,6 +1578,23 @@ export async function startApp(): Promise { return; } + if ( + conversation && + commandOrCtrl && + !shiftKey && + (key === 'j' || key === 'J') + ) { + window.enterKeyboardMode(); + const item: HTMLElement | null = + document.querySelector( + '.module-last-seen-indicator ~ div .module-message' + ) || + document.querySelector( + '.module-timeline__last-message .module-message' + ); + item?.focus(); + } + // Open all media if ( conversation && diff --git a/ts/components/CompositionInput.tsx b/ts/components/CompositionInput.tsx index 81c70dd0d1..bdb27c61e6 100644 --- a/ts/components/CompositionInput.tsx +++ b/ts/components/CompositionInput.tsx @@ -781,6 +781,7 @@ export function CompositionInput(props: Props): React.ReactElement { {({ ref }) => (
, portalElement )} -
+
{areStoriesEnabled && (