Files: 791d817894b256f9a26d15c977f65c023036c676 / app / page / blogIndex.js
3397 bytesRaw
1 | const nest = require('depnest') |
2 | const { h } = require('mutant') |
3 | |
4 | const isString = require('lodash/isString') |
5 | const More = require('hypermore') |
6 | const morphdom = require('morphdom') |
7 | const Debounce = require('obv-debounce') |
8 | |
9 | exports.gives = nest('app.page.blogIndex') |
10 | |
11 | exports.needs = nest({ |
12 | 'history.sync.push': 'first', |
13 | 'keys.sync.id': 'first', |
14 | 'translations.sync.strings': 'first', |
15 | 'state.obs.threads': 'first', |
16 | 'app.html.threadCard': 'first', |
17 | 'unread.sync.isUnread': 'first' |
18 | }) |
19 | |
20 | exports.create = (api) => { |
21 | var contentHtmlObs |
22 | |
23 | return nest('app.page.blogIndex', function (location) { |
24 | // location here can expected to be: { page: 'blogIndex'} |
25 | // |
26 | var strings = api.translations.sync.strings() |
27 | |
28 | return h('Page -blogIndex', {title: strings.home}, [ |
29 | h('div.context', 'context (sidebar)'), |
30 | h('div.content', [ |
31 | blogs(), |
32 | h('Button -showMore', { 'ev-click': contentHtmlObs.more }, strings.showMore) |
33 | ]), |
34 | ]) |
35 | }) |
36 | |
37 | function blogs () { |
38 | // TODO - replace with actual blogs |
39 | var morePlease = false |
40 | var threadsObs = api.state.obs.threads() |
41 | |
42 | // DUCT TAPE: debounce the observable so it doesn't |
43 | // update the dom more than 1/second |
44 | threadsObs(function () { |
45 | if(morePlease) threadsObs.more() |
46 | }) |
47 | threadsObsDebounced = Debounce(threadsObs, 1000) |
48 | threadsObsDebounced(function () { |
49 | morePlease = false |
50 | }) |
51 | threadsObsDebounced.more = function () { |
52 | morePlease = true |
53 | requestIdleCallback(threadsObs.more) |
54 | } |
55 | |
56 | var updates = h('div.threads', []) |
57 | contentHtmlObs = More( |
58 | threadsObsDebounced, |
59 | function render (threads) { |
60 | |
61 | function latestUpdate(thread) { |
62 | var m = thread.timestamp || 0 |
63 | if(!thread.replies) return m |
64 | |
65 | for(var i = 0; i < thread.replies.length; i++) |
66 | m = Math.max(thread.replies[i].timestamp||0, m) |
67 | return m |
68 | } |
69 | |
70 | var o = {} |
71 | function roots (r) { |
72 | return Object.keys(r || {}).map(function (name) { |
73 | var id = r[name] |
74 | if(!o[id]) { |
75 | o[id] = true |
76 | return threads.roots[id] |
77 | } |
78 | }).filter(function (e) { |
79 | return e && e.value |
80 | }) |
81 | } |
82 | |
83 | var groupedThreads = roots(threads.private) |
84 | .concat(roots(threads.channels)) |
85 | .concat(roots(threads.groups)) |
86 | .filter(function (thread) { |
87 | return thread.value.content.recps || thread.value.content.channel |
88 | }) |
89 | .map(function (thread) { |
90 | var unread = 0 |
91 | if(api.unread.sync.isUnread(thread)) |
92 | unread ++ |
93 | ;(thread.replies || []).forEach(function (msg) { |
94 | if(api.unread.sync.isUnread(msg)) unread ++ |
95 | }) |
96 | thread.unread = unread |
97 | return thread |
98 | }) |
99 | .sort((a, b) => latestUpdate(b) - latestUpdate(a)) |
100 | |
101 | morphdom( |
102 | updates, |
103 | h('div.threads', |
104 | groupedThreads.map(thread => { |
105 | const { recps, channel } = thread.value.content |
106 | var onClick |
107 | if (channel && !recps) |
108 | onClick = (ev) => api.history.sync.push({ channel }) |
109 | |
110 | return api.app.html.threadCard(thread, { onClick }) |
111 | }) |
112 | ) |
113 | ) |
114 | |
115 | return updates |
116 | } |
117 | ) |
118 | |
119 | return contentHtmlObs |
120 | } |
121 | } |
122 | |
123 |
Built with git-ssb-web