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