git ssb

2+

mixmix / ticktack



Tree: c98c520dc293d99e6462eda47eb8183248adcf78

Files: c98c520dc293d99e6462eda47eb8183248adcf78 / app / page / home.js

3956 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})
17
18function toRecpGroup(msg) {
19 //cannocialize
20 return Array.isArray(msg.value.content.repcs) &&
21 msg.value.content.recps.map(function (e) {
22 return (isString(e) ? e : e.link)
23 }).sort().map(function (id) {
24 return id.substring(0, 10)
25 }).join(',')
26}
27
28exports.create = (api) => {
29 return nest('app.page.home', function (location) {
30 // location here can expected to be: { page: 'home'}
31 var strings = api.translations.sync.strings()
32
33
34 // function filterForThread (thread) {
35 // if(thread.value.private)
36 // return {private: toRecpGroup(thread)}
37 // else if(thread.value.content.channel)
38 // return {channel: thread.value.content.channel}
39 // }
40
41 // function filter (rule, thread) {
42 // if(!thread.value) return false
43 // if(!rule) return true
44 // if(rule.channel) {
45 // return rule.channel == thread.value.content.channel
46 // }
47 // else if(rule.group)
48 // return rule.group == thread.value.content.group
49 // else if(rule.private)
50 // return rule.private == toRecpGroup(thread)
51 // else return true
52 // }
53
54 var morePlease = false
55 var threadsObs = api.state.obs.threads()
56
57 // DUCT TAPE: debounce the observable so it doesn't
58 // update the dom more than 1/second
59 threadsObs(function () {
60 if(morePlease) threadsObs.more()
61 })
62 threadsObsDebounced = Debounce(threadsObs, 1000)
63 threadsObsDebounced(function () {
64 morePlease = false
65 })
66 threadsObsDebounced.more = function () {
67 morePlease = true
68 requestIdleCallback(threadsObs.more)
69 }
70
71 var container = h('div.container', [])
72 var threadsHtmlObs = More(
73 threadsObsDebounced,
74 function render (threads) {
75
76 var groupedThreads =
77 roots(threads.private)
78 .concat(roots(threads.channels))
79 .concat(roots(threads.groups))
80 .filter(function (thread) {
81 return thread.value.content.recps || thread.value.content.channel
82 })
83 .sort(function (a, b) {
84 return latestUpdate(b) - latestUpdate(a)
85 })
86
87 function latestUpdate(thread) {
88 var m = thread.timestamp
89 if(!thread.replies) return m
90
91 for(var i = 0; i < thread.replies.length; i++)
92 m = Math.max(thread.replies[i].timestamp, m)
93 return m
94 }
95
96 function roots (r) {
97 return Object.keys(r || {}).map(function (k) {
98 return threads.roots[r[k]]
99 }).filter(function (e) {
100 return e && e.value
101 })
102 }
103
104
105 morphdom(container,
106 // LEGACY: some of these containers could be removed
107 // but they are here to be compatible with the old MCSS.
108 h('div.container', [
109 //private section
110 h('section.updates -directMessage', [
111 h('div.threads',
112 groupedThreads.map(thread => {
113 const channel = thread.value.content.channel
114 const onClick = channel
115 ? (ev) => api.history.sync.push({ channel })
116 : null // threadCard will install default onClick
117
118 return api.app.html.threadCard(thread, { onClick })
119 })
120 )
121 ])
122 ])
123 )
124
125 return container
126 }
127 )
128 return h('Page -home', {title: strings.home}, [
129 threadsHtmlObs,
130 h('button', {'ev-click': threadsHtmlObs.more}, [strings.showMore])
131 ])
132 })
133}
134
135
136
137

Built with git-ssb-web