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