git ssb

0+

alanz / patchwork



forked from Matt McKegg / patchwork

Tree: fc374df20b48a0ac407ed90137c2abf612c63a9e

Files: fc374df20b48a0ac407ed90137c2abf612c63a9e / modules / page / html / render / message.js

3925 bytesRaw
1var { h, when, map, Proxy, Struct, Value, computed } = require('mutant')
2var nest = require('depnest')
3var ref = require('ssb-ref')
4var AnchorHook = require('../../../../lib/anchor-hook')
5
6exports.needs = nest({
7 'keys.sync.id': 'first',
8 'feed.obs.thread': 'first',
9 'message.sync.unbox': 'first',
10 'message.html': {
11 render: 'first',
12 compose: 'first'
13 },
14 'sbot.async.get': 'first',
15 'intl.sync.i18n': 'first',
16 'message.html.missing': 'first'
17})
18
19exports.gives = nest('page.html.render')
20
21exports.create = function (api) {
22 const i18n = api.intl.sync.i18n
23 return nest('page.html.render', function (id) {
24 if (!ref.isMsg(id)) return
25 var loader = h('div', {className: 'Loading -large'})
26
27 var result = Proxy(loader)
28 var anchor = Value()
29
30 var meta = Struct({
31 type: 'post',
32 root: Proxy(id),
33 branch: Proxy(id),
34 channel: Value(undefined),
35 recps: Value(undefined)
36 })
37
38 var compose = api.message.html.compose({
39 meta,
40 isPrivate: when(meta.recps, true),
41 shrink: false,
42 hooks: [
43 AnchorHook('reply', anchor, (el) => el.focus())
44 ],
45 placeholder: when(meta.recps, i18n('Write a private reply'), i18n('Write a public reply'))
46 })
47
48 api.sbot.async.get(id, (err, value) => {
49 if (err) {
50 return result.set(h('PageHeading', [
51 h('h1', i18n('Cannot load thead'))
52 ]))
53 }
54
55 if (typeof value.content === 'string') {
56 value = api.message.sync.unbox(value)
57 }
58
59 if (!value) {
60 return result.set(h('PageHeading', [
61 h('h1', i18n('Cannot display message.'))
62 ]))
63 }
64
65 // what happens in private stays in private!
66 meta.recps.set(value.content.recps)
67
68 var isReply = !!value.content.root
69 var thread = api.feed.obs.thread(id, {branch: isReply})
70
71 meta.channel.set(value.content.channel)
72 meta.root.set(value.content.root || thread.rootId)
73
74 // if root thread, reply to last post
75 meta.branch.set(isReply ? thread.branchId : thread.lastId)
76
77 var container = h('Thread', [
78 h('div.messages', [
79 when(thread.branchId, h('a.full', {href: thread.rootId, anchor: id}, [i18n('View full thread')])),
80 map(thread.messages, (msg) => {
81 return computed([msg, thread.previousKey(msg)], (msg, previousId) => {
82 return h('div', {
83 hooks: [AnchorHook(msg.key, anchor, showContext)]
84 }, [
85 msg.key !== id ? api.message.html.missing(last(msg.value.content.branch), msg) : null,
86 api.message.html.render(msg, {
87 pageId: id,
88 previousId,
89 includeForks: msg.key !== id,
90 includeReferences: true
91 })
92 ])
93 })
94 }, {
95 maxTime: 5,
96 idle: true
97 })
98 ]),
99 compose
100 ])
101 result.set(when(thread.sync, container, loader))
102 })
103
104 var view = h('div', {className: 'SplitView'}, [
105 h('div.main', [
106 result
107 ])
108 ])
109
110 view.setAnchor = function (value) {
111 anchor.set(value)
112 }
113
114 return view
115 })
116}
117
118function showContext (element) {
119 var scrollParent = getScrollParent(element)
120 if (scrollParent) {
121 // ensure context is visible
122 scrollParent.scrollTop = Math.max(0, scrollParent.scrollTop - 100)
123 }
124}
125
126function getScrollParent (element) {
127 while (element.parentNode) {
128 if (element.parentNode.scrollTop > 10 && isScroller(element.parentNode)) {
129 return element.parentNode
130 } else {
131 element = element.parentNode
132 }
133 }
134}
135
136function isScroller (element) {
137 var value = window.getComputedStyle(element)['overflow-y']
138 return (value === 'auto' || value === 'scroll')
139}
140
141function last (array) {
142 if (Array.isArray(array)) {
143 return array[array.length - 1]
144 } else {
145 return array
146 }
147}
148

Built with git-ssb-web