git ssb

2+

ev / mvd



Tree: 8430497d3d003bdc4dd1c148e80aef9e226086f4

Files: 8430497d3d003bdc4dd1c148e80aef9e226086f4 / views.js

11365 bytesRaw
1var pull = require('pull-stream')
2var human = require('human-time')
3var sbot = require('./scuttlebot')
4var hyperscroll = require('hyperscroll')
5var More = require('pull-more')
6var stream = require('hyperloadmore/stream')
7var h = require('hyperscript')
8var render = require('./render')
9var ref = require('ssb-ref')
10var client = require('ssb-client')
11
12var Next = require('pull-next-query')
13
14var config = require('./config')()
15
16var tools = require('./tools')
17var avatar = require('./avatar')
18var id = require('./keys').id
19
20var ssbKeys = require('ssb-keys')
21var keys = require('./keys')
22
23var compose = require('./compose')
24
25var about = function () {
26 var screen = document.getElementById('screen')
27
28 var about = require('./about')
29
30 var content = h('div.content', about)
31
32 screen.appendChild(hyperscroll(content))
33}
34
35var privateStream = function () {
36 var content = h('div.content')
37 var screen = document.getElementById('screen')
38 screen.appendChild(hyperscroll(content))
39
40 function createStream (opts) {
41 return pull(
42 More(sbot.createLogStream, opts),
43 pull.filter(function (msg) {
44 return 'string' == typeof msg.value.content
45 }),
46 pull.filter(function (msg) {
47 var unboxed = ssbKeys.unbox(msg.value.content, keys)
48 if (unboxed) {
49 msg.value.content = unboxed
50 msg.value.private = true
51 return msg
52 }
53 }),
54 pull.map(function (msg) {
55 return render(msg)
56 })
57 )
58 }
59
60 pull(
61 createStream({old: false, limit: 1000}),
62 stream.top(content)
63 )
64
65 pull(
66 createStream({reverse: true, live: false, limit: 1000}),
67 stream.bottom(content)
68 )
69}
70
71var mentionsStream = function () {
72 var content = h('div.content')
73
74 var screen = document.getElementById('screen')
75
76 screen.appendChild(hyperscroll(content))
77
78 function createStream (opts) {
79 return pull(
80 Next(sbot.backlinks, opts, ['value', 'timestamp']),
81 pull.map(function (msg) {
82 if (msg.value.private == true) return
83 return render(msg)
84 })
85 )
86 }
87
88 pull(
89 createStream({
90 limit: 10,
91 reverse: true,
92 index: 'DTA',
93 live: false,
94 query: [{$filter: {dest: id}}]
95 }),
96 stream.bottom(content)
97 )
98
99 pull(
100 createStream({
101 limit: 10,
102 old: false,
103 index: 'DTA',
104 live: true,
105 query: [{$filter: {dest: id}}]
106 }),
107 stream.top(content)
108 )
109}
110
111var userStream = function (src) {
112 var content = h('div.content')
113 var screen = document.getElementById('screen')
114 screen.appendChild(hyperscroll(content))
115 function createStream (opts) {
116 return pull(
117 More(sbot.userStream, opts, ['value', 'sequence']),
118 pull.map(function (msg) {
119 return render(msg)
120 })
121 )
122 }
123
124 pull(
125 createStream({old: false, limit: 10, id: src}),
126 stream.top(content)
127 )
128
129 pull(
130 createStream({reverse: true, live: false, limit: 10, id: src}),
131 stream.bottom(content)
132 )
133
134 var profile = h('div.content#profile', h('div.message'))
135
136 if (screen.firstChild.firstChild) {
137 screen.firstChild.insertBefore(profile, screen.firstChild.firstChild)
138 } else {
139 screen.firstChild.appendChild(profile)
140 }
141
142 var avatars = h('div.avatars',
143 h('a', {href: '#' + src},
144 h('span.avatar--medium', avatar.image(src)),
145 avatar.name(src)
146 )
147 )
148
149 pull(
150 sbot.userStream({id: src, reverse: false, limit: 1}),
151 pull.drain(function (msg) {
152 var howlong = h('span', ' arrived ', human(new Date(msg.value.timestamp)))
153 avatars.appendChild(howlong)
154 console.log(msg)
155 })
156 )
157
158 var name = avatar.name(src)
159
160 var buttons = h('div.buttons')
161
162 profile.firstChild.appendChild(avatars)
163 profile.firstChild.appendChild(buttons)
164 buttons.appendChild(tools.mute(src))
165
166 var writeMessage = h('button.btn', 'Public message ', avatar.name(src), {
167 onclick: function () {
168 opts = {}
169 opts.type = 'post'
170 opts.mentions = '[' + name.textContent + '](' + src + ')'
171 var composer = h('div#composer', h('div.message', compose(opts)))
172 profile.appendChild(composer)
173 }
174 })
175
176 var writePrivate = h('button.btn', 'Private message ', avatar.name(src), {
177 onclick: function () {
178 opts = {}
179 opts.type = 'post'
180 opts.mentions = '[' + name.textContent + '](' + src + ')'
181 opts.recps = [src, id]
182 var composer = h('div#composer', h('div.message', compose(opts)))
183 profile.appendChild(composer)
184 }
185 })
186
187 buttons.appendChild(writeMessage)
188 buttons.appendChild(writePrivate)
189 buttons.appendChild(tools.follow(src))
190
191 profile.firstChild.appendChild(tools.getFollowing(src))
192 profile.firstChild.appendChild(tools.getFollowers(src))
193}
194
195var msgThread = function (src) {
196
197 var content = h('div.content')
198 var screen = document.getElementById('screen')
199 screen.appendChild(hyperscroll(content))
200
201 pull(
202 sbot.query({query: [{$filter: { value: { content: {root: src}, timestamp: { $gt: 1 }}}}], live: true}),
203 pull.drain(function (msg) {
204 if (msg.value) {
205 content.appendChild(render(msg))
206 }
207 })
208 )
209
210 sbot.get(src, function (err, data) {
211 if (err) {console.log('could not find message')}
212 data.value = data
213 data.key = src
214 console.log(data)
215 var rootMsg = render(data)
216
217 if (content.firstChild) {
218 content.insertBefore(rootMsg, content.firstChild)
219 } else {
220 content.appendChild(rootMsg)
221 }
222 })
223}
224
225var keyPage = function () {
226 var screen = document.getElementById('screen')
227
228 var importKey = h('textarea.import', {placeholder: 'Import a new public/private key', name: 'textarea', style: 'width: 97%; height: 100px;'})
229
230 var content = h('div.content',
231 h('div.message#key',
232 h('h1', 'Your Key'),
233 h('p', {innerHTML: 'Your public/private key is: <pre><code>' + localStorage[config.caps.shs + '/secret'] + '</code></pre>'},
234 h('button.btn', {onclick: function (e){
235 localStorage[config.caps.shs +'/secret'] = ''
236 alert('Your public/private key has been deleted')
237 e.preventDefault()
238 location.hash = ""
239 location.reload()
240 }}, 'Delete Key')
241 ),
242 h('hr'),
243 h('form',
244 importKey,
245 h('button.btn', {onclick: function (e){
246 if(importKey.value) {
247 localStorage[config.caps.shs + '/secret'] = importKey.value.replace(/\s+/g, ' ')
248 e.preventDefault()
249 alert('Your public/private key has been updated')
250 }
251 location.hash = ""
252 location.reload()
253 }}, 'Import key'),
254 )
255 )
256 )
257
258 screen.appendChild(hyperscroll(content))
259}
260
261function everythingStream () {
262
263 var screen = document.getElementById('screen')
264 var content = h('div.content')
265
266 screen.appendChild(hyperscroll(content))
267
268 function createStream (opts) {
269 return pull(
270 Next(sbot.query, opts, ['value', 'timestamp']),
271 pull.map(function (msg) {
272 if (msg.value) {
273 return render(msg)
274 }
275 })
276 )
277 }
278
279 pull(
280 createStream({
281 limit: 10,
282 reverse: true,
283 live: false,
284 query: [{$filter: { value: { timestamp: { $gt: 0 }}}}]
285 }),
286 stream.bottom(content)
287 )
288
289 pull(
290 createStream({
291 limit: 10,
292 old: false,
293 live: true,
294 query: [{$filter: { value: { timestamp: { $gt: 0 }}}}]
295 }),
296 stream.top(content)
297 )
298}
299
300function backchannel () {
301
302 var screen = document.getElementById('screen')
303 var content = h('div.content')
304
305 screen.appendChild(hyperscroll(content))
306
307 var chatbox = h('input', {placeholder: 'Backchannel'})
308
309 var chat = h('div.content')
310
311 var publish = h('button.btn', 'Publish', {
312 onclick: function () {
313 if (chatbox.value) {
314 var content = {
315 text: chatbox.value,
316 type: 'scat_message'
317 }
318 sbot.publish(content, function (err, msg) {
319 if (err) throw err
320 chatbox.value = ''
321 console.log('Published!', msg)
322 })
323 }
324 }
325 })
326
327 chat.appendChild(h('div.message', chatbox, publish))
328
329 if (screen.firstChild.firstChild) {
330 screen.firstChild.insertBefore(chat, screen.firstChild.firstChild)
331 } else {
332 screen.firstChild.appendChild(chat)
333 }
334
335 function createStream (opts) {
336 return pull(
337 Next(sbot.query, opts, ['value', 'timestamp']),
338 pull.map(function (msg) {
339 if (msg.value) {
340 return render(msg)
341 }
342 })
343 )
344 }
345
346 pull(
347 createStream({
348 limit: 10,
349 reverse: true,
350 live: false,
351 query: [{$filter: { value: { content: {type: 'scat_message'}, timestamp: { $gt: 0 }}}}]
352 }),
353 stream.bottom(content)
354 )
355
356 pull(
357 createStream({
358 limit: 10,
359 old: false,
360 live: true,
361 query: [{$filter: { value: { content: {type: 'scat_message'}, timestamp: { $gt: 0 }}}}]
362 }),
363 stream.top(content)
364 )
365}
366
367
368function hash () {
369 return window.location.hash.substring(1)
370}
371
372module.exports = function () {
373 var src = hash()
374
375 if (ref.isFeed(src)) {
376 userStream(src)
377 } else if (ref.isMsg(src)) {
378 msgThread(src)
379 } else if (src == 'mentions') {
380 mentionsStream()
381 } else if (src == 'about') {
382 about()
383 } else if (src == 'backchannel') {
384 backchannel()
385 } else if (src == 'private') {
386 privateStream()
387 } else if (src == 'key') {
388 keyPage()
389 } else {
390 everythingStream()
391 }
392
393
394 function parseInvite (invite) {
395 return ref.parseInvite(invite)
396 }
397
398 // TODO: this should really only pop up if you have no friends
399 var currentScreen = document.getElementById('screen')
400 var invitebox = h('input', {placeholder: 'Invite Code Here'})
401 invitebox.value = config.invite
402 var invite = h('div.content', h('div.message#inviter',
403 'Hey, no one follows you. Your secure-scuttlebutt feed may not replicate unless a pub follows you. Either ', h('a', {href: '#key'}, 'import your key'), ' or use a pub invite:',
404 h('br'),
405 invitebox,
406 h('button', 'Accept', {onclick: function (e) {
407 var data = parseInvite(invitebox.value)
408 console.log(data)
409 e.preventDefault()
410 //sbot.gossip.connect(data.remote, function (err) {
411
412 //})
413
414 client(keys, {
415 remote: data.invite,
416 caps: config.caps,
417 manifest: {invite: {use: 'async'}, getAddress: 'async'}
418 }, function (err, remotebot) {
419 if (err) throw err
420 remotebot.invite.use({feed: id}, function (_err, msg) {
421 if (msg) {
422 sbot.publish({
423 type: 'contact',
424 contact: data.key,
425 following: true
426 })
427 }
428 })
429 setTimeout(function () {
430 location.hash = '#' + id
431 location.hash = '#'
432 }, 100)
433 })
434 }})
435 ))
436 if (currentScreen.firstChild.firstChild) {
437 currentScreen.firstChild.insertBefore(invite, currentScreen.firstChild.firstChild)
438 } else {
439 currentScreen.firstChild.appendChild(invite)
440 }
441 sbot.friends.get({dest: id}, function (err, follows) {
442 for (var i in follows) {
443 if (follows[i] === true) {
444 var getInvite = document.getElementById('inviter')
445
446 if (getInvite) {
447 getInvite.parentNode.removeChild(getInvite)
448 }
449 }
450 }
451 })
452}
453

Built with git-ssb-web