git ssb

0+

ev / minbase



Tree: b62ecd6f843b26f37e70c7b6d65c71db35bbf922

Files: b62ecd6f843b26f37e70c7b6d65c71db35bbf922 / modules / tabs.js

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

Built with git-ssb-web