Files: fea2881ae175c88bac926fcff65d32598742e9a1 / app / html / thread.js
2834 bytesRaw
1 | const nest = require('depnest') |
2 | const { h, Array: MutantArray, map, computed, when, throttle } = require('mutant') |
3 | const get = require('lodash/get') |
4 | |
5 | // TODO - rename threadPrivate |
6 | exports.gives = nest('app.html.thread') |
7 | |
8 | exports.needs = nest({ |
9 | 'about.html.avatar': 'first', |
10 | 'feed.obs.thread': 'first', |
11 | 'keys.sync.id': 'first', |
12 | 'message.html.markdown': 'first', |
13 | 'message.html.timeago': 'first', |
14 | 'unread.sync.markRead': 'first', |
15 | 'unread.sync.isUnread': 'first' |
16 | }) |
17 | |
18 | exports.create = (api) => { |
19 | return nest('app.html.thread', function (thread) { |
20 | // catch any code that still uses this the old way... |
21 | if (typeof thread === 'string') throw new Error('thread should be observable') |
22 | const myId = api.keys.sync.id() |
23 | const chunkedMessages = buildChunkedMessages(thread.messages) |
24 | |
25 | const threadView = h('Thread', |
26 | map(chunkedMessages, chunk => { |
27 | const author = computed([chunk], chunk => get(chunk, '[0].value.author')) |
28 | |
29 | return author() === myId |
30 | ? h('div.my-chunk', [ |
31 | h('Avatar -small'), |
32 | h('div.msgs', map(chunk, msg => { |
33 | return h('div.msg-row', [ |
34 | h('div.spacer'), |
35 | message(msg), |
36 | api.message.html.timeago(msg) |
37 | ]) |
38 | })) |
39 | ]) |
40 | : h('div.other-chunk', [ |
41 | when(author, api.about.html.avatar(author()), 'small'), |
42 | h('div.msgs', map(chunk, msg => { |
43 | return h('div.msg-row', [ |
44 | message(msg), |
45 | h('div.spacer'), |
46 | api.message.html.timeago(msg) |
47 | ]) |
48 | })) |
49 | ]) |
50 | }) |
51 | ) |
52 | |
53 | function message (msg) { |
54 | const raw = get(msg, 'value.content.text') |
55 | var unread = api.unread.sync.isUnread(msg) ? ' -unread' : '' |
56 | api.unread.sync.markRead(msg) |
57 | return h('div.msg' + unread, api.message.html.markdown(raw)) |
58 | } |
59 | |
60 | threadView.subject = computed(thread.messages, msgs => { |
61 | return get(msgs, '[0].value.content.subject') |
62 | }) |
63 | return threadView |
64 | }) |
65 | } |
66 | |
67 | function buildChunkedMessages (messagesObs) { |
68 | return computed(throttle(messagesObs, 200), msgs => { |
69 | var chunkedMessages = MutantArray() |
70 | |
71 | var _chunk = null |
72 | var _lastMsg = null |
73 | |
74 | msgs.forEach(msg => { |
75 | const text = get(msg, 'value.content.text') |
76 | if (!text) return |
77 | |
78 | if (!_lastMsg || !isSameAuthor(_lastMsg, msg)) { |
79 | createNewChunk(msg) |
80 | } else { |
81 | _chunk.push(msg) |
82 | } |
83 | |
84 | _lastMsg = msg |
85 | }) |
86 | |
87 | function createNewChunk (msg) { |
88 | const newChunk = MutantArray() |
89 | newChunk.push(msg) |
90 | chunkedMessages.push(newChunk) |
91 | _chunk = newChunk |
92 | } |
93 | |
94 | return chunkedMessages |
95 | }) |
96 | } |
97 | |
98 | function isSameAuthor (msgA, msgB) { |
99 | // TODO (mix) use lodash/get |
100 | return msgA.value.author === msgB.value.author |
101 | } |
102 |
Built with git-ssb-web