Files: 03ba4f6100e6c42a83ad6c770c69bb63a5d6fd7b / views.js
16026 bytesRaw
1 | var pull = require('pull-stream') |
2 | var human = require('human-time') |
3 | var sbot = require('./scuttlebot') |
4 | var hyperscroll = require('hyperscroll') |
5 | var hyperfile = require('hyperfile') |
6 | var dataurl = require('dataurl-') |
7 | var More = require('pull-more') |
8 | var stream = require('hyperloadmore/stream') |
9 | var h = require('hyperscript') |
10 | var render = require('./render') |
11 | var ref = require('ssb-ref') |
12 | var client = require('ssb-client') |
13 | |
14 | var Next = require('pull-next-query') |
15 | |
16 | var config = require('./config')() |
17 | |
18 | var tools = require('./tools') |
19 | var avatar = require('./avatar') |
20 | var id = require('./keys').id |
21 | |
22 | var ssbKeys = require('ssb-keys') |
23 | var keys = require('./keys') |
24 | |
25 | var checkInvite = require('./invite') |
26 | |
27 | var compose = require('./compose') |
28 | |
29 | var about = function () { |
30 | var screen = document.getElementById('screen') |
31 | |
32 | var about = require('./about') |
33 | |
34 | var content = h('div.content', about) |
35 | |
36 | screen.appendChild(hyperscroll(content)) |
37 | } |
38 | |
39 | var privateStream = function () { |
40 | var content = h('div.content') |
41 | var screen = document.getElementById('screen') |
42 | screen.appendChild(hyperscroll(content)) |
43 | |
44 | function createStream (opts) { |
45 | return pull( |
46 | More(sbot.createLogStream, opts), |
47 | pull.filter(function (msg) { |
48 | return 'string' == typeof msg.value.content |
49 | }), |
50 | pull.filter(function (msg) { |
51 | var unboxed = ssbKeys.unbox(msg.value.content, keys) |
52 | if (unboxed) { |
53 | msg.value.content = unboxed |
54 | msg.value.private = true |
55 | return msg |
56 | } |
57 | }), |
58 | pull.map(function (msg) { |
59 | return render(msg) |
60 | }) |
61 | ) |
62 | } |
63 | |
64 | pull( |
65 | createStream({old: false, limit: 1000}), |
66 | stream.top(content) |
67 | ) |
68 | |
69 | pull( |
70 | createStream({reverse: true, live: false, limit: 1000}), |
71 | stream.bottom(content) |
72 | ) |
73 | } |
74 | |
75 | var queueStream = function () { |
76 | var content = h('div.content') |
77 | var screen = document.getElementById('screen') |
78 | screen.appendChild(hyperscroll(content)) |
79 | |
80 | pull( |
81 | sbot.query({query: [{$filter: { value: {author: id, content: {type: 'queue'}}}}]}), |
82 | pull.drain(function (msg) { |
83 | if (msg.value) { |
84 | if (ref.isMsg(msg.value.content.message)) { |
85 | if (msg.value.content.queue == true) { |
86 | sbot.get(msg.value.content.message, function (err, data) { |
87 | if (data) { |
88 | var message = {} |
89 | message.value = data |
90 | message.key = msg.value.content.message |
91 | content.appendChild(render(message)) |
92 | } |
93 | }) |
94 | } |
95 | if (msg.value.content.queue == false) { |
96 | setTimeout(function () { |
97 | var gotIt = document.getElementById(msg.value.content.message.substring(0,44)) |
98 | if (gotIt != null) { |
99 | gotIt.outerHTML = '' |
100 | } |
101 | }, 100) |
102 | } |
103 | } |
104 | } |
105 | }) |
106 | ) |
107 | } |
108 | |
109 | var mentionsStream = function () { |
110 | var content = h('div.content') |
111 | |
112 | var screen = document.getElementById('screen') |
113 | |
114 | screen.appendChild(hyperscroll(content)) |
115 | |
116 | function createStream (opts) { |
117 | return pull( |
118 | Next(sbot.backlinks, opts, ['value', 'timestamp']), |
119 | pull.map(function (msg) { |
120 | if (msg.value.private == true) return h('div.private') |
121 | return render(msg) |
122 | }) |
123 | ) |
124 | } |
125 | |
126 | pull( |
127 | createStream({ |
128 | limit: 10, |
129 | reverse: true, |
130 | index: 'DTA', |
131 | live: false, |
132 | query: [{$filter: {dest: id}}] |
133 | }), |
134 | stream.bottom(content) |
135 | ) |
136 | |
137 | pull( |
138 | createStream({ |
139 | limit: 10, |
140 | old: false, |
141 | index: 'DTA', |
142 | live: true, |
143 | query: [{$filter: {dest: id}}] |
144 | }), |
145 | stream.top(content) |
146 | ) |
147 | } |
148 | |
149 | var userStream = function (src) { |
150 | var content = h('div.content') |
151 | var screen = document.getElementById('screen') |
152 | screen.appendChild(hyperscroll(content)) |
153 | function createStream (opts) { |
154 | return pull( |
155 | More(sbot.userStream, opts, ['value', 'sequence']), |
156 | pull.map(function (msg) { |
157 | return render(h('div', msg)) |
158 | }) |
159 | ) |
160 | } |
161 | |
162 | pull( |
163 | createStream({old: false, limit: 10, id: src}), |
164 | stream.top(content) |
165 | ) |
166 | |
167 | pull( |
168 | createStream({reverse: true, live: false, limit: 10, id: src}), |
169 | stream.bottom(content) |
170 | ) |
171 | |
172 | var profile = h('div.content#profile', h('div.message')) |
173 | |
174 | if (screen.firstChild.firstChild) { |
175 | screen.firstChild.insertBefore(profile, screen.firstChild.firstChild) |
176 | } else { |
177 | screen.firstChild.appendChild(profile) |
178 | } |
179 | |
180 | var name = avatar.name(src) |
181 | |
182 | var editname = h('span', |
183 | avatar.name(src), |
184 | h('button.btn', 'New name', { |
185 | onclick: function () { |
186 | var nameput = h('input', {placeholder: name.textContent}) |
187 | var nameedit = |
188 | h('span', nameput, |
189 | h('button.btn', 'Preview', { |
190 | onclick: function () { |
191 | if (nameput.value[0] != '@') |
192 | tobename = nameput.value |
193 | else |
194 | tobename = nameput.value.substring(1, 100) |
195 | var newname = h('span', h('a', {href: '#' + src}, '@' + tobename), h('button.btn', 'Publish', { |
196 | onclick: function () { |
197 | var donename = h('span', h('a', {href: '#' + src}, '@' + tobename)) |
198 | sbot.publish({type: 'about', about: src, name: tobename}) |
199 | localStorage[src + 'name'] = tobename |
200 | newname.parentNode.replaceChild(donename, newname) |
201 | } |
202 | })) |
203 | nameedit.parentNode.replaceChild(newname, nameedit) |
204 | } |
205 | }) |
206 | ) |
207 | editname.parentNode.replaceChild(nameedit, editname) |
208 | } |
209 | }) |
210 | ) |
211 | |
212 | var editimage = h('span', |
213 | h('button.btn', 'New image', { |
214 | onclick: function () { |
215 | var upload = |
216 | h('span', |
217 | hyperfile.asDataURL(function (data) { |
218 | if(data) { |
219 | //img.src = data |
220 | var _data = dataurl.parse(data) |
221 | pull( |
222 | pull.once(_data.data), |
223 | sbot.addblob(function (err, hash) { |
224 | if(err) return alert(err.stack) |
225 | selected = { |
226 | link: hash, |
227 | size: _data.data.length, |
228 | type: _data.mimetype |
229 | } |
230 | }) |
231 | ) |
232 | } |
233 | }), |
234 | h('button.btn', 'Preview image', { |
235 | onclick: function() { |
236 | if (selected) { |
237 | console.log(selected) |
238 | var oldImage = document.getElementById('profileImage') |
239 | var newImage = h('span.avatar--medium', h('img', {src: config.blobsUrl + selected.link})) |
240 | var publish = h('button.btn', 'Publish image', { |
241 | onclick: function () { |
242 | sbot.publish({ |
243 | type: 'about', |
244 | about: src, |
245 | image: selected |
246 | }, function (err, published) { |
247 | console.log(published) |
248 | }) |
249 | } |
250 | }) |
251 | upload.parentNode.replaceChild(publish, upload) |
252 | oldImage.parentNode.replaceChild(newImage, oldImage) |
253 | } |
254 | /*if(selected) { |
255 | api.message_confirm({ |
256 | type: 'about', |
257 | about: id, |
258 | image: selected |
259 | }) |
260 | } else { alert('select an image before hitting preview')}*/ |
261 | } |
262 | }) |
263 | ) |
264 | editimage.parentNode.replaceChild(upload, editimage) |
265 | } |
266 | }) |
267 | ) |
268 | |
269 | var avatars = h('div.avatars', |
270 | h('a', {href: '#' + src}, |
271 | h('span.avatar--medium#profileImage', avatar.image(src)), |
272 | editname, |
273 | h('br'), |
274 | editimage |
275 | ) |
276 | ) |
277 | |
278 | pull( |
279 | sbot.userStream({id: src, reverse: false, limit: 1}), |
280 | pull.drain(function (msg) { |
281 | var howlong = h('span', h('br'), ' arrived ', human(new Date(msg.value.timestamp))) |
282 | avatars.appendChild(howlong) |
283 | console.log(msg) |
284 | }) |
285 | ) |
286 | |
287 | |
288 | var buttons = h('div.buttons') |
289 | |
290 | profile.firstChild.appendChild(avatars) |
291 | profile.firstChild.appendChild(buttons) |
292 | buttons.appendChild(tools.mute(src)) |
293 | |
294 | var writeMessage = h('button.btn', 'Public message ', avatar.name(src), { |
295 | onclick: function () { |
296 | opts = {} |
297 | opts.type = 'post' |
298 | opts.mentions = '[' + name.textContent + '](' + src + ')' |
299 | var composer = h('div#composer', h('div.message', compose(opts))) |
300 | profile.appendChild(composer) |
301 | } |
302 | }) |
303 | |
304 | var writePrivate = h('button.btn', 'Private message ', avatar.name(src), { |
305 | onclick: function () { |
306 | opts = {} |
307 | opts.type = 'post' |
308 | opts.mentions = '[' + name.textContent + '](' + src + ')' |
309 | opts.recps = [src, id] |
310 | var composer = h('div#composer', h('div.message', compose(opts))) |
311 | profile.appendChild(composer) |
312 | } |
313 | }) |
314 | |
315 | buttons.appendChild(writeMessage) |
316 | buttons.appendChild(writePrivate) |
317 | buttons.appendChild(tools.follow(src)) |
318 | |
319 | buttons.appendChild(h('button.btn', 'Generate follows', { |
320 | onclick: function () { |
321 | profile.firstChild.appendChild(tools.getFollowing(src)) |
322 | profile.firstChild.appendChild(tools.getFollowers(src)) |
323 | } |
324 | })) |
325 | |
326 | buttons.appendChild(h('button.btn', 'Generate blocks', { |
327 | onclick: function () { |
328 | profile.firstChild.appendChild(tools.getBlocks(src)) |
329 | profile.firstChild.appendChild(tools.getBlocked(src)) |
330 | } |
331 | })) |
332 | |
333 | |
334 | } |
335 | |
336 | var privateMsg = function (src) { |
337 | var content = h('div.content') |
338 | var screen = document.getElementById('screen') |
339 | screen.appendChild(hyperscroll(content)) |
340 | |
341 | sbot.get(src, function (err, data) { |
342 | if (err) { |
343 | var message = h('div.message', 'Missing message!') |
344 | content.appendChild(message) |
345 | } |
346 | if (data) { |
347 | console.log(data) |
348 | data.value = data |
349 | data.key = src |
350 | |
351 | content.appendChild(render(data)) |
352 | } |
353 | |
354 | }) |
355 | } |
356 | |
357 | var msgThread = function (src) { |
358 | |
359 | var content = h('div.content') |
360 | var screen = document.getElementById('screen') |
361 | screen.appendChild(hyperscroll(content)) |
362 | |
363 | pull( |
364 | sbot.query({query: [{$filter: { value: { content: {root: src}, timestamp: { $gt: 1 }}}}], live: true}), |
365 | pull.drain(function (msg) { |
366 | if (msg.value) { |
367 | content.appendChild(render(msg)) |
368 | } |
369 | }) |
370 | ) |
371 | |
372 | |
373 | sbot.get(src, function (err, data) { |
374 | if (err) { |
375 | var message = h('div.message', 'Missing message!') |
376 | content.appendChild(message) |
377 | } |
378 | if (data) { |
379 | data.value = data |
380 | data.key = src |
381 | console.log(data) |
382 | var rootMsg = render(data) |
383 | |
384 | if (content.firstChild) { |
385 | content.insertBefore(rootMsg, content.firstChild) |
386 | } else { |
387 | content.appendChild(rootMsg) |
388 | } |
389 | if (data.value.content.type == 'git-repo') { |
390 | pull( |
391 | sbot.backlinks({query: [{$filter: {value: {content: {type: 'git-update'}}, dest: src}}]}), |
392 | pull.drain(function (msg) { |
393 | if (msg.value) { |
394 | content.appendChild(render(msg)) |
395 | } |
396 | }) |
397 | ) |
398 | } |
399 | |
400 | } |
401 | }) |
402 | } |
403 | |
404 | var keyPage = function () { |
405 | var screen = document.getElementById('screen') |
406 | |
407 | var importKey = h('textarea.import', {placeholder: 'Import a new public/private key', name: 'textarea', style: 'width: 97%; height: 100px;'}) |
408 | |
409 | var content = h('div.content', |
410 | h('div.message#key', |
411 | h('h1', 'Your Key'), |
412 | h('p', {innerHTML: 'Your public/private key is: <pre><code>' + localStorage[config.caps.shs + '/secret'] + '</code></pre>'}, |
413 | h('button.btn', {onclick: function (e){ |
414 | localStorage[config.caps.shs +'/secret'] = '' |
415 | alert('Your public/private key has been deleted') |
416 | e.preventDefault() |
417 | location.hash = "" |
418 | location.reload() |
419 | }}, 'Delete Key') |
420 | ), |
421 | h('hr'), |
422 | h('form', |
423 | importKey, |
424 | h('button.btn', {onclick: function (e){ |
425 | if(importKey.value) { |
426 | localStorage[config.caps.shs + '/secret'] = importKey.value.replace(/\s+/g, ' ') |
427 | e.preventDefault() |
428 | alert('Your public/private key has been updated') |
429 | } |
430 | location.hash = "" |
431 | location.reload() |
432 | }}, 'Import key'), |
433 | ) |
434 | ) |
435 | ) |
436 | |
437 | screen.appendChild(hyperscroll(content)) |
438 | } |
439 | |
440 | function everythingStream () { |
441 | |
442 | var screen = document.getElementById('screen') |
443 | var content = h('div.content') |
444 | |
445 | screen.appendChild(hyperscroll(content)) |
446 | |
447 | function createStream (opts) { |
448 | return pull( |
449 | Next(sbot.query, opts, ['value', 'timestamp']), |
450 | pull.map(function (msg) { |
451 | if (msg.value) { |
452 | if (msg.value.timestamp > Date.now()) { |
453 | return h('div.future') |
454 | } else { |
455 | return render(msg) |
456 | } |
457 | } |
458 | }) |
459 | ) |
460 | } |
461 | |
462 | pull( |
463 | createStream({ |
464 | limit: 10, |
465 | reverse: true, |
466 | live: false, |
467 | query: [{$filter: { value: { timestamp: { $gt: 0 }}}}] |
468 | }), |
469 | stream.bottom(content) |
470 | ) |
471 | |
472 | pull( |
473 | createStream({ |
474 | limit: 10, |
475 | old: false, |
476 | live: true, |
477 | query: [{$filter: { value: { timestamp: { $gt: 0 }}}}] |
478 | }), |
479 | stream.top(content) |
480 | ) |
481 | } |
482 | |
483 | function backchannel () { |
484 | |
485 | var screen = document.getElementById('screen') |
486 | var content = h('div.content') |
487 | |
488 | screen.appendChild(hyperscroll(content)) |
489 | |
490 | var chatbox = h('input', {placeholder: 'Backchannel'}) |
491 | |
492 | var chat = h('div.content') |
493 | |
494 | var publish = h('button.btn', 'Publish', { |
495 | onclick: function () { |
496 | if (chatbox.value) { |
497 | var content = { |
498 | text: chatbox.value, |
499 | type: 'scat_message' |
500 | } |
501 | sbot.publish(content, function (err, msg) { |
502 | if (err) throw err |
503 | chatbox.value = '' |
504 | console.log('Published!', msg) |
505 | }) |
506 | } |
507 | } |
508 | }) |
509 | |
510 | chat.appendChild(h('div.message', chatbox, publish)) |
511 | |
512 | if (screen.firstChild.firstChild) { |
513 | screen.firstChild.insertBefore(chat, screen.firstChild.firstChild) |
514 | } else { |
515 | screen.firstChild.appendChild(chat) |
516 | } |
517 | |
518 | function createStream (opts) { |
519 | return pull( |
520 | Next(sbot.query, opts, ['value', 'timestamp']), |
521 | pull.map(function (msg) { |
522 | if (msg.value) { |
523 | return render(msg) |
524 | } |
525 | }) |
526 | ) |
527 | } |
528 | |
529 | pull( |
530 | createStream({ |
531 | limit: 10, |
532 | reverse: true, |
533 | live: false, |
534 | query: [{$filter: { value: { content: {type: 'scat_message'}, timestamp: { $gt: 0 }}}}] |
535 | }), |
536 | stream.bottom(content) |
537 | ) |
538 | |
539 | pull( |
540 | createStream({ |
541 | limit: 10, |
542 | old: false, |
543 | live: true, |
544 | query: [{$filter: { value: { content: {type: 'scat_message'}, timestamp: { $gt: 0 }}}}] |
545 | }), |
546 | stream.top(content) |
547 | ) |
548 | } |
549 | |
550 | function search (src) { |
551 | console.log('search' + src) |
552 | |
553 | var content = h('div.content') |
554 | var screen = document.getElementById('screen') |
555 | screen.appendChild(hyperscroll(content)) |
556 | |
557 | pull( |
558 | sbot.search.query({query: src, limit: 100}), |
559 | pull.drain(function (search) { |
560 | content.appendChild(render(search)) |
561 | }) |
562 | ) |
563 | |
564 | } |
565 | |
566 | function hash () { |
567 | return window.location.hash.substring(1) |
568 | } |
569 | |
570 | module.exports = function () { |
571 | var src = hash() |
572 | console.log(src) |
573 | |
574 | if (src.substring(52, 59) == '?unbox=') { |
575 | privateMsg(src) |
576 | } else if (ref.isFeed(src)) { |
577 | userStream(src) |
578 | } else if (ref.isMsg(src)) { |
579 | msgThread(src) |
580 | } else if (src == 'mentions') { |
581 | mentionsStream() |
582 | } else if (src == 'queue') { |
583 | queueStream() |
584 | } else if (src == 'about') { |
585 | about() |
586 | } else if (src == 'backchannel') { |
587 | backchannel() |
588 | } else if (src == 'private') { |
589 | privateStream() |
590 | } else if (src == 'key') { |
591 | keyPage() |
592 | } else if (src[0] == '?' || (src[0] == '#')) { |
593 | if (src[0] == '#') |
594 | search(src.split('%20').join(' ')) |
595 | else |
596 | search(src.substr(1).split('%20').join(' ')) |
597 | } else { |
598 | everythingStream() |
599 | checkInvite() |
600 | } |
601 | |
602 | } |
603 |
Built with git-ssb-web