git ssb

10+

Matt McKegg / patchwork



Tree: 99aead0a4c4797532b2986ba64d8c30f3d3c5993

Files: 99aead0a4c4797532b2986ba64d8c30f3d3c5993 / modules / feed-summary.js

5881 bytesRaw
1var Value = require('@mmckegg/mutant/value')
2var h = require('@mmckegg/mutant/html-element')
3var when = require('@mmckegg/mutant/when')
4var computed = require('@mmckegg/mutant/computed')
5var MutantArray = require('@mmckegg/mutant/array')
6var Abortable = require('pull-abortable')
7var Scroller = require('../lib/pull-scroll')
8var FeedSummary = require('../lib/feed-summary')
9var onceTrue = require('../lib/once-true')
10
11var m = require('../lib/h')
12
13var pull = require('pull-stream')
14
15var plugs = require('patchbay/plugs')
16var message_render = plugs.first(exports.message_render = [])
17var message_link = plugs.first(exports.message_link = [])
18var person = plugs.first(exports.person = [])
19var many_people = plugs.first(exports.many_people = [])
20var people_names = plugs.first(exports.people_names = [])
21var sbot_get = plugs.first(exports.sbot_get = [])
22var get_id = plugs.first(exports.get_id = [])
23
24exports.feed_summary = function (getStream, prefix, opts) {
25 var sync = Value(false)
26 var updates = Value(0)
27
28 var filter = opts && opts.filter
29 var bumpFilter = opts && opts.bumpFilter
30 var windowSize = opts && opts.windowSize
31 var waitFor = opts && opts.waitFor || true
32
33 var updateLoader = m('a Notifier -loader', {
34 href: '#',
35 'ev-click': refresh
36 }, [
37 'Show ',
38 h('strong', [updates]), ' ',
39 when(computed(updates, a => a === 1), 'update', 'updates')
40 ])
41
42 var content = h('div.column.scroller__content')
43
44 var scrollElement = h('div.column.scroller', {
45 style: {
46 'overflow': 'auto'
47 }
48 }, [
49 h('div.scroller__wrapper', [
50 prefix, content
51 ])
52 ])
53
54 setTimeout(refresh, 10)
55
56 onceTrue(waitFor, () => {
57 pull(
58 getStream({old: false}),
59 pull.drain((item) => {
60 var type = item && item.value && item.value.content.type
61 if (type && type !== 'vote') {
62 if (item.value && item.value.author === get_id() && !updates()) {
63 return refresh()
64 }
65 if (filter) {
66 var update = (item.value.content.type === 'post' && item.value.content.root) ? {
67 type: 'message',
68 messageId: item.value.content.root,
69 channel: item.value.content.channel
70 } : {
71 type: 'message',
72 author: item.value.author,
73 channel: item.value.content.channel,
74 messageId: item.key
75 }
76
77 ensureAuthor(update, (err, update) => {
78 if (!err) {
79 if (filter(update)) {
80 updates.set(updates() + 1)
81 }
82 }
83 })
84 } else {
85 updates.set(updates() + 1)
86 }
87 }
88 })
89 )
90 })
91
92 var abortLastFeed = null
93
94 var result = MutantArray([
95 when(updates, updateLoader),
96 when(sync, scrollElement, m('Loading -large'))
97 ])
98
99 result.reload = refresh
100 result.pendingUpdates = updates
101
102 return result
103
104 // scoped
105
106 function refresh () {
107 if (abortLastFeed) {
108 abortLastFeed()
109 }
110 updates.set(0)
111 sync.set(false)
112 content.innerHTML = ''
113
114 var abortable = Abortable()
115 abortLastFeed = abortable.abort
116
117 pull(
118 FeedSummary(getStream, {windowSize, bumpFilter}, () => {
119 sync.set(true)
120 }),
121 pull.asyncMap(ensureAuthor),
122 pull.filter((item) => {
123 if (filter) {
124 return filter(item)
125 } else {
126 return true
127 }
128 }),
129 abortable,
130 Scroller(scrollElement, content, renderItem, false, false)
131 )
132 }
133}
134
135function ensureAuthor (item, cb) {
136 if (item.type === 'message' && !item.message) {
137 sbot_get(item.messageId, (_, value) => {
138 if (value) {
139 item.author = value.author
140 }
141 cb(null, item)
142 })
143 } else {
144 cb(null, item)
145 }
146}
147
148function renderItem (item) {
149 if (item.type === 'message') {
150 var meta = null
151 var previousId = item.messageId
152 var replies = item.replies.slice(-4).map((msg) => {
153 var result = message_render(msg, {inContext: true, inSummary: true, previousId})
154 previousId = msg.key
155 return result
156 })
157 var renderedMessage = item.message ? message_render(item.message, {inContext: true}) : null
158 if (renderedMessage) {
159 if (item.lastUpdateType === 'reply' && item.repliesFrom.size) {
160 meta = m('div.meta', {
161 title: people_names(item.repliesFrom)
162 }, [
163 many_people(item.repliesFrom), ' replied'
164 ])
165 } else if (item.lastUpdateType === 'dig' && item.digs.size) {
166 meta = m('div.meta', {
167 title: people_names(item.digs)
168 }, [
169 many_people(item.digs), ' dug this message'
170 ])
171 }
172
173 return m('FeedEvent', [
174 meta,
175 renderedMessage,
176 when(replies.length, [
177 when(item.replies.length > replies.length,
178 m('a.full', {href: `#${item.messageId}`}, ['View full thread'])
179 ),
180 m('div.replies', replies)
181 ])
182 ])
183 } else {
184 if (item.lastUpdateType === 'reply' && item.repliesFrom.size) {
185 meta = m('div.meta', {
186 title: people_names(item.repliesFrom)
187 }, [
188 many_people(item.repliesFrom), ' replied to ', message_link(item.messageId)
189 ])
190 } else if (item.lastUpdateType === 'dig' && item.digs.size) {
191 meta = m('div.meta', {
192 title: people_names(item.digs)
193 }, [
194 many_people(item.digs), ' dug ', message_link(item.messageId)
195 ])
196 }
197
198 if (meta || replies.length) {
199 return m('FeedEvent', [
200 meta, m('div.replies', replies)
201 ])
202 }
203 }
204 } else if (item.type === 'follow') {
205 return m('FeedEvent -follow', [
206 m('div.meta', {
207 title: people_names(item.contacts)
208 }, [
209 person(item.id), ' followed ', many_people(item.contacts)
210 ])
211 ])
212 }
213
214 return h('div')
215}
216

Built with git-ssb-web