git ssb

16+

Dominic / patchbay



Tree: 563a47e65cc3a33e94dbc286e9b78d81a1b2d623

Files: 563a47e65cc3a33e94dbc286e9b78d81a1b2d623 / router / html / page / thread.js

3369 bytesRaw
1var { h } = require('mutant')
2const nest = require('depnest')
3const pull = require('pull-stream')
4const sort = require('ssb-sort')
5const ref = require('ssb-ref')
6
7exports.gives = nest('router.html.page')
8
9exports.needs = nest({
10 // 'feed.pull.public': 'first',
11 'keys.sync.id': 'first',
12 'main.html.scroller': 'first',
13 message: {
14 html: {
15 compose: 'first',
16 render: 'first'
17 },
18 'async.name': 'first',
19 'sync.unbox': 'first'
20 },
21 sbot: {
22 'async.get': 'first',
23 'pull.links': 'first'
24 }
25})
26
27exports.create = function (api) {
28 return nest('router.html.page', threadPage)
29
30 function threadPage (id) {
31 if (!ref.isMsg(id)) return
32
33 var meta = {
34 type: 'post',
35 root: id,
36 branch: id // mutated when thread is loaded.
37 }
38 const composer = api.message.html.compose({
39 meta,
40 placeholder: 'Write a reply',
41 shrink: false
42 })
43 const { container, content } = api.main.html.scroller({ append: composer })
44 api.message.async.name(id, (err, name) => {
45 if (err) throw err
46 container.title = name
47 })
48
49 // TODO rewrite with obs
50 pull(
51 api.sbot.pull.links({ rel: 'root', dest: id, keys: true, old: false }),
52 pull.drain(msg => loadThread(), () => {}) // redraw thread
53 )
54
55 function loadThread () {
56 getThread(id, (err, thread) => {
57 if (err) return content.appendChild(h('pre', err.stack))
58
59 // would probably be better keep an id for each message element
60 // (i.e. message key) and then update it if necessary.
61 // also, it may have moved (say, if you received a missing message)
62 content.innerHTML = ''
63
64 // decrypt
65 thread = thread.map(msg => {
66 return typeof msg.value.content === 'string'
67 ? api.message.sync.unbox(msg)
68 : msg
69 })
70
71 sort(thread)
72 .map(api.message.html.render)
73 .filter(Boolean)
74 .forEach(el => content.appendChild(el))
75
76 var branches = sort.heads(thread)
77 meta.branch = branches.length > 1 ? branches : branches[0]
78 meta.root = thread[0].value.content.root || thread[0].key
79 meta.channel = thread[0].value.content.channel
80
81 // TODO - re-enable with channel-picker
82 // if (meta.channel) {
83 // const channelInput = composer.querySelector('input')
84 // channelInput.value = `#${meta.channel}`
85 // channelInput.disabled = true
86 // }
87
88 const priv = thread[0].value['private']
89 const recps = thread[0].value.content.recps
90 if (priv) {
91 if (recps) meta.recps = recps
92 else meta.recps = [thread[0].value.author, api.keys.sync.id()]
93 }
94 })
95 }
96
97 loadThread()
98
99 return container
100 }
101
102 function getThread (root, cb) {
103 // in this case, it's inconvienent that panel only takes
104 // a stream. maybe it would be better to accept an array?
105
106 api.sbot.async.get(root, (err, value) => {
107 if (err) return cb(err)
108
109 var msg = { key: root, value }
110 // if (value.content.root) return getThread(value.content.root, cb)
111
112 pull(
113 api.sbot.pull.links({ rel: 'root', dest: root, values: true, keys: true }),
114 pull.collect((err, ary) => {
115 if (err) return cb(err)
116 ary.unshift(msg)
117
118 cb(null, ary)
119 })
120 )
121 })
122 }
123}
124
125

Built with git-ssb-web