Files: c6d7f47ac4cd019ab82c6961b892bee7a57ff0a7 / app / html / comments.js
4398 bytesRaw
1 | const nest = require('depnest') |
2 | const { h, Value, map, computed, when, resolve, throttle } = require('mutant') |
3 | const get = require('lodash/get') |
4 | |
5 | exports.gives = nest('app.html.comments') |
6 | |
7 | exports.needs = nest({ |
8 | 'about.html.avatar': 'first', |
9 | 'about.obs.name': 'first', |
10 | 'backlinks.obs.for': 'first', |
11 | 'feed.obs.thread': 'first', |
12 | 'message.html.compose': 'first', |
13 | 'message.html.markdown': 'first', |
14 | 'message.html.timeago': 'first', |
15 | 'message.html.likes': 'first', |
16 | 'unread.sync.markRead': 'first', |
17 | 'unread.sync.isUnread': 'first', |
18 | 'translations.sync.strings': 'first' |
19 | }) |
20 | |
21 | exports.create = (api) => { |
22 | return nest('app.html.comments', comments) |
23 | |
24 | function comments (thread) { |
25 | const strings = api.translations.sync.strings() |
26 | const { messages, channel, lastId: branch } = thread |
27 | |
28 | // TODO - move this up into Patchcore |
29 | const messagesTree = computed(throttle(messages, 200), msgs => { |
30 | return msgs |
31 | .filter(msg => forkOf(msg) === undefined) |
32 | .map(threadMsg => { |
33 | const nestedReplies = msgs.filter(msg => forkOf(msg) === threadMsg.key) |
34 | threadMsg.replies = nestedReplies |
35 | return threadMsg |
36 | }) |
37 | }) |
38 | |
39 | const root = computed(messages, ary => ary[0].key) |
40 | |
41 | const meta = { |
42 | type: 'post', |
43 | root, |
44 | branch, |
45 | channel |
46 | } |
47 | // const twoComposers = computed(messages, messages => { |
48 | // return messages.length > 5 |
49 | // }) |
50 | const { compose } = api.message.html |
51 | |
52 | const feedIdsInThread = computed(thread.messages, msgs => { |
53 | return msgs.map(m => m.value.author) |
54 | }) |
55 | |
56 | return h('Comments', [ |
57 | // when(twoComposers, compose({ meta, shrink: true, canAttach: false })), |
58 | map(messagesTree, msg => Comment(msg, root, branch)), |
59 | compose({ meta, feedIdsInThread, shrink: false, canAttach: true, placeholder: strings.writeComment }) |
60 | ]) |
61 | } |
62 | |
63 | function Comment (msgObs, root, branch) { |
64 | const strings = api.translations.sync.strings() |
65 | const msg = resolve(msgObs) |
66 | |
67 | const raw = get(msg, 'value.content.text') |
68 | var className = api.unread.sync.isUnread(msg) ? ' -unread' : ' -read' |
69 | api.unread.sync.markRead(msg) |
70 | |
71 | if (!get(msg, 'value.content.root')) return |
72 | |
73 | const { author, content } = msg.value |
74 | |
75 | // // TODO - move this upstream into patchcore:feed.obs.thread ?? |
76 | // // OR change strategy to use forks |
77 | // const backlinks = api.backlinks.obs.for(msg.key) |
78 | // const nestedReplies = computed(backlinks, backlinks => { |
79 | // return backlinks.filter(backlinker => { |
80 | // const { type, root } = backlinker.value.content |
81 | // return type === 'post' && root === msg.key |
82 | // }) |
83 | // }) |
84 | |
85 | var nestedReplyCompose = Value(false) |
86 | const toggleCompose = () => nestedReplyCompose.set(!nestedReplyCompose()) |
87 | const nestedReplyComposer = api.message.html.compose({ |
88 | meta: { |
89 | type: 'post', |
90 | root, |
91 | fork: msg.key, |
92 | branch, |
93 | channel: content.channel |
94 | }, |
95 | shrink: false, |
96 | canAttach: true, |
97 | canPreview: false, |
98 | placeholder: strings.writeComment |
99 | }, toggleCompose) |
100 | |
101 | return h('Comment', { className }, [ |
102 | h('div.left', api.about.html.avatar(author, 'tiny')), |
103 | h('div.right', [ |
104 | h('section.context', [ |
105 | h('div.name', api.about.obs.name(author)), |
106 | api.message.html.timeago(msg) |
107 | ]), |
108 | h('section.content', api.message.html.markdown(raw)), |
109 | when(msgObs.replies, |
110 | h('section.replies', |
111 | map(msgObs.replies, NestedComment) |
112 | ) |
113 | ), |
114 | h('section.actions', [ |
115 | h('div.reply', { 'ev-click': toggleCompose }, [ |
116 | h('i.fa.fa-commenting-o') |
117 | ]), |
118 | api.message.html.likes(msg) |
119 | ]), |
120 | when(nestedReplyCompose, nestedReplyComposer) |
121 | ]) |
122 | ]) |
123 | } |
124 | |
125 | function NestedComment (msgObs) { |
126 | const msg = resolve(msgObs) |
127 | const raw = get(msg, 'value.content.text') |
128 | if (!raw) return |
129 | |
130 | const { author } = msg.value |
131 | |
132 | return h('Comment -nested', [ |
133 | h('div.left'), |
134 | h('div.right', [ |
135 | h('section.context', [ |
136 | h('div.name', api.about.obs.name(author)), |
137 | api.message.html.timeago(msg) |
138 | ]), |
139 | h('section.content', api.message.html.markdown(raw)) |
140 | ]) |
141 | ]) |
142 | |
143 | api.message.html.markdown(raw) |
144 | } |
145 | } |
146 | |
147 | function forkOf (msg) { |
148 | return get(msg, 'value.content.fork') |
149 | } |
150 |
Built with git-ssb-web