git ssb

2+

mixmix / ticktack



Tree: ed729a600b4f3da6e0abaf26bee51aa7d7d5f86a

Files: ed729a600b4f3da6e0abaf26bee51aa7d7d5f86a / app / page / home.js

4166 bytesRaw
1const nest = require('depnest')
2const { h, computed } = require('mutant')
3const {threadReduce} = require('ssb-reduce-stream')
4const pull = require('pull-stream')
5const isObject = require('lodash/isObject')
6const isString = require('lodash/isString')
7const last = require('lodash/last')
8const get = require('lodash/get')
9const More = require('hypermore')
10const morphdom = require('morphdom')
11const Debounce = require('obv-debounce')
12
13exports.gives = nest('app.page.home')
14
15exports.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
24function 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
34exports.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 groupedThreads
116 .map(function (thread) {
117 var el = api.app.html
118 .threadCard(thread, opts)
119
120 if(thread.value.content.channel) {
121 el.onclick = function (ev) {
122 api.history.sync.push({channel: thread.value.content.channel})
123 ev.preventDefault()
124 }
125 }
126
127 return el
128 })
129 )
130 ]),
131 ])
132 )
133
134 return container
135 }
136 )
137
138 return h('Page -home', [
139 h('h1', 'Home'),
140 api.app.html.nav(),
141 threadsHtmlObs,
142 h('button', {'ev-click': threadsHtmlObs.more}, [strings.showMore])
143 ])
144 })
145}
146
147

Built with git-ssb-web