Bluesky app fork with some witchin' additions 💫

"N" keyboard shortcut to open a new post modal (#5197)

* feat: Add hook on web app to open composer with 'N' keyboard shortcut

* Extract, don't fire open composer if already open

* Ignore interactive elements

---------

Co-authored-by: João Gabriel <joaog@nocorp.io>
Co-authored-by: Hailey <me@haileyok.com>

authored by

Eric Bailey
João Gabriel
Hailey
and committed by
GitHub
d76f9abd cac43127

+52
+3
src/App.web.tsx
··· 35 35 } from '#/state/session' 36 36 import {readLastActiveAccount} from '#/state/session/util' 37 37 import {Provider as ShellStateProvider} from '#/state/shell' 38 + import {useComposerKeyboardShortcut} from '#/state/shell/composer/useComposerKeyboardShortcut' 38 39 import {Provider as LoggedOutViewProvider} from '#/state/shell/logged-out' 39 40 import {Provider as ProgressGuideProvider} from '#/state/shell/progress-guide' 40 41 import {Provider as SelectedFeedProvider} from '#/state/shell/selected-feed' ··· 61 62 const {_} = useLingui() 62 63 useIntentHandler() 63 64 const hasCheckedReferrer = useStarterPackEntry() 65 + 66 + useComposerKeyboardShortcut() 64 67 65 68 // init 66 69 useEffect(() => {
src/state/shell/composer.tsx src/state/shell/composer/index.tsx
+49
src/state/shell/composer/useComposerKeyboardShortcut.tsx
··· 1 + import React from 'react' 2 + 3 + import {useComposerControls} from './' 4 + 5 + /** 6 + * Based on {@link https://github.com/jaywcjlove/hotkeys-js/blob/b0038773f3b902574f22af747f3bb003a850f1da/src/index.js#L51C1-L64C2} 7 + */ 8 + function shouldIgnore(event: KeyboardEvent) { 9 + const target: any = event.target || event.srcElement 10 + if (!target) return false 11 + const {tagName} = target 12 + if (!tagName) return false 13 + const isInput = 14 + tagName === 'INPUT' && 15 + ![ 16 + 'checkbox', 17 + 'radio', 18 + 'range', 19 + 'button', 20 + 'file', 21 + 'reset', 22 + 'submit', 23 + 'color', 24 + ].includes(target.type) 25 + // ignore: isContentEditable === 'true', <input> and <textarea> when readOnly state is false, <select> 26 + if ( 27 + target.isContentEditable || 28 + ((isInput || tagName === 'TEXTAREA' || tagName === 'SELECT') && 29 + !target.readOnly) 30 + ) { 31 + return true 32 + } 33 + return false 34 + } 35 + 36 + export function useComposerKeyboardShortcut() { 37 + const {openComposer} = useComposerControls() 38 + 39 + React.useEffect(() => { 40 + function handler(event: KeyboardEvent) { 41 + if (shouldIgnore(event)) return 42 + if (event.key === 'n' || event.key === 'N') { 43 + openComposer({}) 44 + } 45 + } 46 + document.addEventListener('keydown', handler) 47 + return () => document.removeEventListener('keydown', handler) 48 + }, [openComposer]) 49 + }