git ssb

16+

Dominic / patchbay



Tree: cf0a874df629bde26e5b4c28ef1e4948274f8d0b

Files: cf0a874df629bde26e5b4c28ef1e4948274f8d0b / app / page / thread.js

2692 bytesRaw
1const { h, Struct, Value, when, map, resolve, onceTrue } = require('mutant')
2const nest = require('depnest')
3const { isFeed } = require('ssb-ref')
4
5exports.gives = nest('app.page.thread')
6
7exports.needs = nest({
8 'about.html.avatar': 'first',
9 'app.html.scroller': 'first',
10 'contact.obs.following': 'first',
11 'feed.obs.thread': 'first',
12 'keys.sync.id': 'first',
13 'message.html.compose': 'first',
14 'message.html.render': 'first',
15 'message.async.name': 'first',
16 'message.sync.unbox': 'first',
17 'sbot.async.get': 'first',
18 'sbot.pull.links': 'first'
19})
20
21exports.create = function (api) {
22 return nest('app.page.thread', threadPage)
23
24 function threadPage (location) {
25 const { key } = location
26
27 const myId = api.keys.sync.id()
28 const ImFollowing = api.contact.obs.following(myId)
29 const { messages, isPrivate, rootId, lastId, channel, recps } = api.feed.obs.thread(key)
30 const meta = Struct({
31 type: 'post',
32 root: rootId,
33 branch: lastId,
34 channel,
35 recps
36 })
37 const contactWarning = Value(false)
38 const header = when(isPrivate, [
39 h('section.recipients', map(recps, r => {
40 const id = isFeed(r) ? r : r.link
41
42 var className
43 if (contactIsTrouble(id)) {
44 className = 'warning'
45 contactWarning.set(true)
46 }
47 return h('div', { className }, api.about.html.avatar(id))
48 })),
49 when(contactWarning,
50 h('section.info -warning', 'There is a person in this thread you do not follow (bordered in red). If you think you know this person it might be worth checking their profile to confirm they are who they say they are.'),
51 h('section.info', 'These are the other participants in this thread. Once a private thread is started you cannot add people to it.')
52 )
53 ])
54 function contactIsTrouble (id) {
55 if (id === myId) return false
56 if (Array.from(ImFollowing()).includes(id)) return false
57 return true
58 }
59
60 const composer = api.message.html.compose({
61 meta,
62 placeholder: 'Write a reply',
63 shrink: false
64 })
65 const content = h('section.content', map(messages, m => {
66 return api.message.html.render(resolve(m), {pageId: key})
67 }))
68 const { container } = api.app.html.scroller({ prepend: header, content, append: composer })
69
70 container.classList.add('Thread')
71 container.title = key
72 api.message.async.name(key, (err, name) => {
73 if (err) throw err
74 container.title = name
75 })
76
77 onceTrue(channel, ch => {
78 const channelInput = composer.querySelector('input')
79 channelInput.value = `#${ch}`
80 channelInput.disabled = true
81 })
82
83 return container
84 }
85}
86

Built with git-ssb-web