git ssb

16+

Dominic / patchbay



Tree: 32aba29b1bd68e4ba002781ccc56db127018f545

Files: 32aba29b1bd68e4ba002781ccc56db127018f545 / modules_core / tabs.js

5813 bytesRaw
1var Tabs = require('hypertabs')
2var h = require('../h')
3var keyscroll = require('../keyscroll')
4var open = require('open-external')
5
6function ancestor (el) {
7 if(!el) return
8 if(el.tagName !== 'A') return ancestor(el.parentElement)
9 return el
10}
11
12exports.needs = {
13 build_scroller: 'first',
14 screen_view: 'first',
15 search_box: 'first',
16 menu: 'first',
17 external_confirm:'first'
18}
19
20exports.gives = 'screen_view'
21
22exports.create = function (api) {
23 return function (path) {
24 if(path !== 'tabs') return
25
26 function setSelected (indexes) {
27 const ids = indexes.map(index => tabs.get(index).content.id)
28 if(search)
29 if(ids.length > 1)
30 search.input.value = 'split('+ids.join(',')+')'
31 else
32 search.input.value = ids[0]
33 }
34
35 const tabs = Tabs(setSelected)
36 const search = api.search_box((path, change) => {
37 if(tabs.has(path)) {
38 tabs.select(path)
39 return true
40 }
41
42 const el = api.screen_view(path)
43 if (!el) return
44
45 if(!el.title) el.title = path
46 el.scroll = keyscroll(el.querySelector('.Scroller .\\.content'))
47 tabs.add(el, change)
48// localStorage.openTabs = JSON.stringify(tabs.tabs)
49 return change
50 })
51
52 // TODO add options to Tabs : e.g. Tabs(setSelected, { append: el })
53 tabs.firstChild.appendChild(
54 h('div.extra', [
55 search,
56 api.menu()
57 ])
58 )
59
60 var saved = []
61 // try { saved = JSON.parse(localStorage.openTabs) }
62 // catch (_) { }
63
64 if(!saved || saved.length < 3)
65 saved = ['/public', '/private', '/notifications', '/data']
66
67 saved.forEach(function (path) {
68 var el = api.screen_view(path)
69 if(!el) return
70 el.id = el.id || path
71 if (!el) return
72 el.scroll = keyscroll(el.querySelector('.Scroller .\\.content'))
73 if(el) tabs.add(el, false, false)
74 })
75
76 tabs.select(0)
77 search.input.value = null // start with an empty field to show placeholder
78
79 //handle link clicks
80 window.onclick = function (ev) {
81 var link = ancestor(ev.target)
82 if(!link) return
83 var path = link.hash.substring(1)
84
85 ev.preventDefault()
86 ev.stopPropagation()
87
88 //let the application handle this link
89 if (link.getAttribute('href') === '#') return
90
91 //open external links.
92 //this ought to be made into something more runcible
93 if(link.href && open.isExternal(link.href)) return api.external_confirm(link.href)
94
95 if(tabs.has(path))
96 return tabs.select(path, !ev.ctrlKey, !!ev.shiftKey)
97
98 var el = api.screen_view(path)
99 if(el) {
100 el.id = el.id || path
101 el.scroll = keyscroll(el.querySelector('.Scroller .\\.content'))
102 tabs.add(el, !ev.ctrlKey, !!ev.shiftKey)
103 // localStorage.openTabs = JSON.stringify(tabs.tabs)
104 }
105
106 return false
107 }
108
109 var gPressed = false
110 window.addEventListener('keydown', function (ev) {
111 if (ev.target.nodeName === 'INPUT' || ev.target.nodeName === 'TEXTAREA')
112 return
113
114 // scroll to top
115 if (ev.keyCode == 71) { // g
116 if (!gPressed) return gPressed = true
117 var el = tabs.get(tabs.selected[0]).firstChild.scroll('first')
118 gPressed = false
119 } else {
120 gPressed = false
121 }
122
123 switch(ev.keyCode) {
124 // scroll through tabs
125 case 72: // h
126 return tabs.selectRelative(-1)
127 case 76: // l
128 return tabs.selectRelative(1)
129
130 // scroll through messages
131 case 74: // j
132 return tabs.get(tabs.selected[0]).firstChild.scroll(1)
133 case 75: // k
134 return tabs.get(tabs.selected[0]).firstChild.scroll(-1)
135
136 // close a tab
137 case 88: // x
138 if (tabs.selected) {
139 var sel = tabs.selected
140 var i = sel.reduce(function (a, b) { return Math.min(a, b) })
141 tabs.remove(sel)
142 tabs.select(Math.max(i-1, 0))
143 }
144 return
145
146 // activate the search field
147 case 191: // /
148 if (ev.shiftKey)
149 search.activate('?', ev)
150 else
151 search.activate('/', ev)
152 return
153
154 // navigate to a feed
155 case 50: // 2
156 if (ev.shiftKey)
157 search.activate('@', ev)
158 return
159
160 // navigate to a channel
161 case 51: // 3
162 if (ev.shiftKey)
163 search.activate('#', ev)
164 return
165
166 // navigate to a message
167 case 53: // 5
168 if (ev.shiftKey)
169 search.activate('%', ev)
170 return
171 }
172 })
173
174 // errors tab
175 var {
176 container: errors,
177 content: errorsContent
178 } = api.build_scroller()
179
180 // remove loader error handler
181 if (window.onError) {
182 window.removeEventListener('error', window.onError)
183 delete window.onError
184 }
185
186 // put errors in a tab
187 window.addEventListener('error', function (ev) {
188 var err = ev.error || ev
189 if(!tabs.has('errors'))
190 tabs.add(errors, false)
191 var el = h('div.message',
192 h('strong', err.message),
193 h('pre', err.stack))
194 if (errorsContent.firstChild)
195 errorsContent.insertBefore(el, errorsContent.firstChild)
196 else
197 errorsContent.appendChild(el)
198 })
199
200 if (process.versions.electron) {
201 window.addEventListener('contextmenu', function (ev) {
202 ev.preventDefault()
203 var remote = require('electron').remote
204 var Menu = remote.Menu
205 var MenuItem = remote.MenuItem
206 var menu = new Menu()
207 menu.append(new MenuItem({
208 label: 'Inspect Element',
209 click: function () {
210 remote.getCurrentWindow().inspectElement(ev.x, ev.y)
211 }
212 }))
213 menu.popup(remote.getCurrentWindow())
214 })
215 }
216
217 return tabs
218 }
219
220}
221

Built with git-ssb-web