git ssb

16+

Dominic / patchbay



Tree: dc2e96d4d0a86072d9393a2d15d786a80cb341ff

Files: dc2e96d4d0a86072d9393a2d15d786a80cb341ff / app / page / thread.js

3679 bytesRaw
1const { h, Struct, Value, when, computed, map, resolve, onceTrue } = require('mutant')
2const nest = require('depnest')
3const get = require('lodash/get')
4const { isFeed } = require('ssb-ref')
5
6exports.gives = nest('app.page.thread')
7
8exports.needs = nest({
9 'about.html.avatar': 'first',
10 'app.html.scroller': 'first',
11 'app.html.tabs': 'first',
12 'app.sync.locationId': 'first',
13 'contact.obs.following': 'first',
14 'feed.obs.thread': 'first',
15 'keys.sync.id': 'first',
16 'message.html.compose': 'first',
17 'message.html.render': 'first',
18 'message.async.name': 'first',
19 'message.sync.unbox': 'first',
20 'sbot.async.get': 'first',
21 'sbot.pull.links': 'first'
22})
23
24exports.create = function (api) {
25 return nest('app.page.thread', threadPage)
26
27 function threadPage (location) {
28 const root = get(location, 'value.content.root', location.key)
29 const msg = location.key
30 if (msg !== root) scrollDownToMessage(msg)
31
32 const myId = api.keys.sync.id()
33 const ImFollowing = api.contact.obs.following(myId)
34 const { messages, isPrivate, rootId, lastId, channel, recps } = api.feed.obs.thread(root)
35 const meta = Struct({
36 type: 'post',
37 root: rootId,
38 branch: lastId,
39 channel,
40 recps
41 })
42 const contactWarning = Value(false)
43 const header = when(isPrivate, [
44 h('section.recipients', map(recps, r => {
45 const id = isFeed(r) ? r : r.link
46
47 var className
48 if (contactIsTrouble(id)) {
49 className = 'warning'
50 contactWarning.set(true)
51 }
52 return h('div', { className }, api.about.html.avatar(id))
53 })),
54 when(contactWarning,
55 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.'),
56 h('section.info', 'These are the other participants in this thread. Once a private thread is started you cannot add people to it.')
57 )
58 ])
59 function contactIsTrouble (id) {
60 if (id === myId) return false
61 if (Array.from(ImFollowing()).includes(id)) return false
62 return true
63 }
64
65 const composer = api.message.html.compose({
66 meta,
67 location,
68 feedIdsInThread: computed(messages, msgs => msgs.map(m => m.value.author)),
69 placeholder: 'Write a reply',
70 shrink: false
71 })
72 const content = h('section.content', map(messages, m => {
73 return api.message.html.render(resolve(m), {pageId: root})
74 }))
75 const { container } = api.app.html.scroller({ prepend: header, content, append: composer })
76
77 container.classList.add('Thread')
78 container.title = msg
79 api.message.async.name(msg, (err, name) => {
80 if (err) throw err
81 container.title = name
82 })
83
84 onceTrue(channel, ch => {
85 const channelInput = composer.querySelector('input')
86 channelInput.value = `#${ch}`
87 channelInput.disabled = true
88 })
89
90 return container
91
92 function scrollDownToMessage (id) {
93 const locationId = api.app.sync.locationId(location)
94 const tabs = api.app.html.tabs()
95 locateKey()
96
97 function locateKey () {
98 // wait till we're on the right page
99 if (tabs.currentPage().id !== locationId) return setTimeout(locateKey, 200)
100
101 if (!tabs.currentPage().scroll) return setTimeout(locateKey, 200)
102
103 tabs.currentPage().scroll('first')
104 const msg = tabs.currentPage().querySelector(`[data-id='${id}']`)
105 if (!msg) return setTimeout(locateKey, 200)
106
107 ;(msg.scrollIntoViewIfNeeded || msg.scrollIntoView).call(msg)
108 msg.focus()
109 }
110 }
111 }
112}
113

Built with git-ssb-web