git ssb

0+

alanz / patchwork



forked from Matt McKegg / patchwork

Tree: edd19ac16c2732b2754c1235d583233b40c3bb00

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

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

Built with git-ssb-web