git ssb

2+

mixmix / ticktack



Tree: 30cc7a8935378d1ee6fddd76239383d8da592a47

Files: 30cc7a8935378d1ee6fddd76239383d8da592a47 / app / page / home.js

4161 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.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
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 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