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