my fork of the bluesky client
1import React from 'react'
2
3import {useDialogStateContext} from '#/state/dialogs'
4import {useLightbox} from '#/state/lightbox'
5import {useModals} from '#/state/modals'
6import {useSession} from '#/state/session'
7import {useIsDrawerOpen} from '#/state/shell/drawer-open'
8import {useComposerControls} from './'
9
10/**
11 * Based on {@link https://github.com/jaywcjlove/hotkeys-js/blob/b0038773f3b902574f22af747f3bb003a850f1da/src/index.js#L51C1-L64C2}
12 */
13function shouldIgnore(event: KeyboardEvent) {
14 const target: any = event.target || event.srcElement
15 if (!target) return false
16 const {tagName} = target
17 if (!tagName) return false
18 const isInput =
19 tagName === 'INPUT' &&
20 ![
21 'checkbox',
22 'radio',
23 'range',
24 'button',
25 'file',
26 'reset',
27 'submit',
28 'color',
29 ].includes(target.type)
30 // ignore: isContentEditable === 'true', <input> and <textarea> when readOnly state is false, <select>
31 if (
32 target.isContentEditable ||
33 ((isInput || tagName === 'TEXTAREA' || tagName === 'SELECT') &&
34 !target.readOnly)
35 ) {
36 return true
37 }
38 return false
39}
40
41export function useComposerKeyboardShortcut() {
42 const {openComposer} = useComposerControls()
43 const {openDialogs} = useDialogStateContext()
44 const {isModalActive} = useModals()
45 const {activeLightbox} = useLightbox()
46 const isDrawerOpen = useIsDrawerOpen()
47 const {hasSession} = useSession()
48
49 React.useEffect(() => {
50 if (!hasSession) {
51 return
52 }
53
54 function handler(event: KeyboardEvent) {
55 if (shouldIgnore(event)) return
56 if (
57 openDialogs?.current.size > 0 ||
58 isModalActive ||
59 activeLightbox ||
60 isDrawerOpen
61 )
62 return
63 if (event.key === 'n' || event.key === 'N') {
64 openComposer({})
65 }
66 }
67 document.addEventListener('keydown', handler)
68 return () => document.removeEventListener('keydown', handler)
69 }, [
70 openComposer,
71 isModalActive,
72 openDialogs,
73 activeLightbox,
74 isDrawerOpen,
75 hasSession,
76 ])
77}