git ssb

16+

Dominic / patchbay



Tree: 8fde330d9640244a94c068b1f62791019b5b6338

Files: 8fde330d9640244a94c068b1f62791019b5b6338 / app / sync / catch-keyboard-shortcut.js

3263 bytesRaw
1const nest = require('depnest')
2
3exports.gives = nest('app.sync.catchKeyboardShortcut')
4
5exports.needs = nest({
6 'app.html': {
7 searchBar: 'first',
8 tabs: 'first'
9 },
10 'app.sync': {
11 goTo: 'first'
12 }
13})
14
15exports.create = function (api) {
16 return nest('app.sync.catchKeyboardShortcut', catchKeyboardShortcut)
17
18 function catchKeyboardShortcut (root) {
19 var gPressed = false
20
21 var tabs = api.app.html.tabs()
22 var search = api.app.html.searchBar()
23 var goTo = api.app.sync.goTo
24
25 root.addEventListener('keydown', (ev) => {
26 isTextFieldEvent(ev)
27 ? textFieldShortcuts(ev)
28 : genericShortcuts(ev, { tabs, search, goTo })
29 })
30 }
31}
32
33function isTextFieldEvent (ev) {
34 const tag = ev.target.nodeName
35 return (tag === 'INPUT' || tag === 'TEXTAREA')
36}
37
38function textFieldShortcuts (ev) {
39 if (ev.keyCode === 13 && ev.ctrlKey) {
40 ev.target.publish() // expects the textField to have a publish method
41 }
42}
43
44function genericShortcuts (ev, { tabs, goTo, search }) {
45 // Messages
46 if (ev.keyCode === 71) { // gg = scroll to top
47 if (!gPressed) {
48 gPressed = true
49 return
50 }
51 tabs.getCurrent().firstChild.scroll('first')
52 }
53 gPressed = false
54
55 switch (ev.keyCode) {
56
57 // Messages (cont'd)
58 case 74: // j = older
59 return tabs.getCurrent().firstChild.scroll(1)
60 case 75: // k = newer
61 return tabs.getCurrent().firstChild.scroll(-1)
62 case 13: // enter = open
63 return goToMessage(ev, { tabs, goTo })
64 case 79: // o = open
65 return goToMessage(ev, { tabs, goTo })
66 case 192: // ` = toggle raw message view
67 return toggleRawMessage(ev)
68
69 // Tabs
70 case 72: // h = left
71 return tabs.selectRelative(-1)
72 case 76: // l = right
73 return tabs.selectRelative(1)
74 case 88: // x = close
75 if (tabs.selected) {
76 var sel = tabs.selected
77 var i = sel.reduce(function (a, b) { return Math.min(a, b) })
78 tabs.remove(sel)
79 tabs.select(Math.max(i - 1, 0))
80 }
81 return
82
83 // Search
84 case 191: // / = routes search
85 if (ev.shiftKey) search.activate('?', ev)
86 else search.activate('/', ev)
87 return
88 case 50: // @ = mention search
89 if (ev.shiftKey) search.activate('@', ev)
90 return
91 case 51: // # = channel search
92 if (ev.shiftKey) search.activate('#', ev)
93 return
94 case 53: // % = message search
95 if (ev.shiftKey) search.activate('%', ev)
96 return
97 }
98}
99
100function goToMessage (ev, { tabs, goTo }) {
101 const msg = ev.target
102 if (!msg.classList.contains('Message')) return
103
104 const { root, id } = msg.dataset
105 if (!root) return goTo(id)
106
107 goTo(root)
108 setTimeout(() => scrollDownToMessage(id, tabs), 250)
109}
110
111function scrollDownToMessage (id, tabs) {
112 tabs.getCurrent().firstChild.scroll('first')
113 locateKey()
114
115 function locateKey () {
116 const msg = tabs.getCurrent().querySelector(`[data-id='${id}']`)
117 if (msg === null) return setTimeout(locateKey, 100)
118
119 ;(msg.scrollIntoViewIfNeeded || msg.scrollIntoView).call(msg)
120 msg.focus()
121 }
122}
123
124function toggleRawMessage (ev) {
125 const msg = ev.target
126 if (!msg.classList.contains('Message')) return
127
128 // this uses a crudely exported nav api
129 msg.querySelector('.meta .toggle-raw-msg').click()
130}
131
132

Built with git-ssb-web