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