git ssb

2+

mixmix / ticktack



Tree: 7a422bfc032eaea6d5b1148c7b46aa5646ac80d2

Files: 7a422bfc032eaea6d5b1148c7b46aa5646ac80d2 / app / page / blogIndex.js

3421 bytesRaw
1const nest = require('depnest')
2const { h } = require('mutant')
3
4const isString = require('lodash/isString')
5const More = require('hypermore')
6const morphdom = require('morphdom')
7const Debounce = require('obv-debounce')
8
9exports.gives = nest('app.page.blogIndex')
10
11exports.needs = nest({
12 'app.html.context': 'first',
13 'app.html.threadCard': 'first',
14 'history.sync.push': 'first',
15 'keys.sync.id': 'first',
16 'translations.sync.strings': 'first',
17 'state.obs.threads': 'first',
18 'unread.sync.isUnread': 'first'
19})
20
21exports.create = (api) => {
22 var contentHtmlObs
23
24 return nest('app.page.blogIndex', function (location) {
25 // location here can expected to be: { page: 'blogIndex'}
26 //
27 var strings = api.translations.sync.strings()
28
29 return h('Page -blogIndex', {title: strings.home}, [
30 api.app.html.context(location),
31 h('div.content', [
32 blogs(),
33 h('Button -showMore', { 'ev-click': contentHtmlObs.more }, strings.showMore)
34 ]),
35 ])
36 })
37
38 function blogs () {
39 // TODO - replace with actual blogs
40 var morePlease = false
41 var threadsObs = api.state.obs.threads()
42
43 // DUCT TAPE: debounce the observable so it doesn't
44 // update the dom more than 1/second
45 threadsObs(function () {
46 if(morePlease) threadsObs.more()
47 })
48 threadsObsDebounced = Debounce(threadsObs, 1000)
49 threadsObsDebounced(function () {
50 morePlease = false
51 })
52 threadsObsDebounced.more = function () {
53 morePlease = true
54 requestIdleCallback(threadsObs.more)
55 }
56
57 var updates = h('div.threads', [])
58 contentHtmlObs = More(
59 threadsObsDebounced,
60 function render (threads) {
61
62 function latestUpdate(thread) {
63 var m = thread.timestamp || 0
64 if(!thread.replies) return m
65
66 for(var i = 0; i < thread.replies.length; i++)
67 m = Math.max(thread.replies[i].timestamp||0, m)
68 return m
69 }
70
71 var o = {}
72 function roots (r) {
73 return Object.keys(r || {}).map(function (name) {
74 var id = r[name]
75 if(!o[id]) {
76 o[id] = true
77 return threads.roots[id]
78 }
79 }).filter(function (e) {
80 return e && e.value
81 })
82 }
83
84 var groupedThreads = roots(threads.private)
85 .concat(roots(threads.channels))
86 .concat(roots(threads.groups))
87 .filter(function (thread) {
88 return thread.value.content.recps || thread.value.content.channel
89 })
90 .map(function (thread) {
91 var unread = 0
92 if(api.unread.sync.isUnread(thread))
93 unread ++
94 ;(thread.replies || []).forEach(function (msg) {
95 if(api.unread.sync.isUnread(msg)) unread ++
96 })
97 thread.unread = unread
98 return thread
99 })
100 .sort((a, b) => latestUpdate(b) - latestUpdate(a))
101
102 morphdom(
103 updates,
104 h('div.threads',
105 groupedThreads.map(thread => {
106 const { recps, channel } = thread.value.content
107 var onClick
108 if (channel && !recps)
109 onClick = (ev) => api.history.sync.push({ channel })
110
111 return api.app.html.threadCard(thread, { onClick })
112 })
113 )
114 )
115
116 return updates
117 }
118 )
119
120 return contentHtmlObs
121 }
122}
123
124

Built with git-ssb-web