git ssb

2+

mixmix / ticktack



Tree: f9050962cfada152aec920f983c68b8527347e71

Files: f9050962cfada152aec920f983c68b8527347e71 / app / page / home.js

4040 bytesRaw
1const nest = require('depnest')
2const { h } = require('mutant')
3const isString = require('lodash/isString')
4const More = require('hypermore')
5const morphdom = require('morphdom')
6const Debounce = require('obv-debounce')
7
8exports.gives = nest('app.page.home')
9
10exports.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.threadCard': '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
29exports.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 function roots (r) {
87 return Object.keys(r || {}).map(function (k) {
88 return threads.roots[r[k]]
89 }).filter(function (e) {
90 return e && e.value
91 })
92 }
93
94
95 var groupedThreads = roots(threads.private)
96 .concat(roots(threads.channels))
97 .concat(roots(threads.groups))
98 .filter(function (thread) {
99 return thread.value.content.recps || thread.value.content.channel
100 })
101 .map(function (thread) {
102 var unread = 0
103 if(api.unread.sync.isUnread(thread))
104 unread ++
105 ;(thread.replies || []).forEach(function (msg) {
106 if(api.unread.sync.isUnread(msg)) unread ++
107 })
108 thread.unread = unread
109 return thread
110 })
111 .sort((a, b) => latestUpdate(b) - latestUpdate(a))
112
113 morphdom(
114 updates,
115 h('div.threads',
116 groupedThreads.map(thread => {
117 const { recps, channel } = thread.value.content
118 var onClick
119 if (channel && !recps)
120 onClick = (ev) => api.history.sync.push({ channel })
121
122 return api.app.html.threadCard(thread, { onClick })
123 })
124 )
125 )
126
127 return updates
128 }
129 )
130 return h('Page -home', {title: strings.home}, [
131 h('div.container', [ threadsHtmlObs ]),
132 h('Button -showMore', { 'ev-click': threadsHtmlObs.more }, strings.showMore)
133 ])
134 })
135}
136
137

Built with git-ssb-web