git ssb

16+

Dominic / patchbay



Commit 07a1886afcd4ca233680d7d4ac6651449f656039

add basic thread view

mix irving committed on 2/26/2017, 3:20:55 AM
Parent: 4cc0d31d81a81e1f7fa95ad23f2a988b0c941e6d

Files changed

main/html/app.jschanged
router/html/page/thread.jsadded
main/html/app.jsView
@@ -21,11 +21,14 @@
2121 var App = h('App', tabs)
2222 ;['/public', '/private', '/notifications'].forEach(addPage(tabs))
2323 tabs.select(0)
2424
25- catchClick(App, (link, { ctrlKey: change, isExternal }) => {
25+ catchClick(App, (link, { ctrlKey: openBackground, isExternal }) => {
2626 if (tabs.has(link)) tabs.select(link)
27- else addPage(tabs, change)(link)
27+ else {
28+ const changeTab = !openBackground
29+ addPage(tabs, changeTab)(link)
30+ }
2831
2932 // TODO add external-links module
3033 })
3134
@@ -52,11 +55,11 @@
5255 var Url = require('url')
5356
5457 function catchClick (root, cb) {
5558 root.addEventListener('click', (ev) => {
59+ if (ev.defaultPrevented) return // TODO check this is in the right place
5660 ev.preventDefault()
5761 ev.stopPropagation()
58- if (ev.defaultPrevented) return
5962
6063 var anchor = null
6164 for (var n = ev.target; n.parentNode; n = n.parentNode) {
6265 if (n.nodeName === 'A') {
router/html/page/thread.jsView
@@ -1,0 +1,124 @@
1+var { h } = require('mutant')
2+const nest = require('depnest')
3+const pull = require('pull-stream')
4+const sort = require('ssb-sort')
5+const ref = require('ssb-ref')
6+
7+exports.gives = nest('router.html.page')
8+
9+exports.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+
27+exports.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+

Built with git-ssb-web