git ssb

2+

mixmix / ticktack



Tree: f6a16e3fc5c25cadd2445d141a36a91d964a1813

Files: f6a16e3fc5c25cadd2445d141a36a91d964a1813 / app / page / blogIndex.js

3552 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 h('Button -primary', { 'ev-click': () => api.history.sync.push({ page: 'blogNew' }) }, strings.blogNew.actions.writeBlog),
33 blogs(),
34 h('Button -showMore', { 'ev-click': contentHtmlObs.more }, strings.showMore)
35 ]),
36 ])
37 })
38
39 function blogs () {
40 // TODO - replace with actual blogs
41 var morePlease = false
42 var threadsObs = api.state.obs.threads()
43
44 // DUCT TAPE: debounce the observable so it doesn't
45 // update the dom more than 1/second
46 threadsObs(function () {
47 if(morePlease) threadsObs.more()
48 })
49 threadsObsDebounced = Debounce(threadsObs, 1000)
50 threadsObsDebounced(function () {
51 morePlease = false
52 })
53 threadsObsDebounced.more = function () {
54 morePlease = true
55 requestIdleCallback(threadsObs.more)
56 }
57
58 var updates = h('div.threads', [])
59 contentHtmlObs = More(
60 threadsObsDebounced,
61 function render (threads) {
62
63 function latestUpdate(thread) {
64 var m = thread.timestamp || 0
65 if(!thread.replies) return m
66
67 for(var i = 0; i < thread.replies.length; i++)
68 m = Math.max(thread.replies[i].timestamp||0, m)
69 return m
70 }
71
72 var o = {}
73 function roots (r) {
74 return Object.keys(r || {}).map(function (name) {
75 var id = r[name]
76 if(!o[id]) {
77 o[id] = true
78 return threads.roots[id]
79 }
80 }).filter(function (e) {
81 return e && e.value
82 })
83 }
84
85 var groupedThreads = roots(threads.private)
86 .concat(roots(threads.channels))
87 .concat(roots(threads.groups))
88 .filter(function (thread) {
89 return thread.value.content.recps || thread.value.content.channel
90 })
91 .map(function (thread) {
92 var unread = 0
93 if(api.unread.sync.isUnread(thread))
94 unread ++
95 ;(thread.replies || []).forEach(function (msg) {
96 if(api.unread.sync.isUnread(msg)) unread ++
97 })
98 thread.unread = unread
99 return thread
100 })
101 .sort((a, b) => latestUpdate(b) - latestUpdate(a))
102
103 morphdom(
104 updates,
105 h('div.threads',
106 groupedThreads.map(thread => {
107 const { recps, channel } = thread.value.content
108 var onClick
109 if (channel && !recps)
110 onClick = (ev) => api.history.sync.push({ channel })
111
112 return api.app.html.threadCard(thread, { onClick })
113 })
114 )
115 )
116
117 return updates
118 }
119 )
120
121 return contentHtmlObs
122 }
123}
124
125

Built with git-ssb-web