Commit bece765b487127c47d7cd4da71eb2574d7218dde
get channel pages working!
Dominic Tarr committed on 8/14/2017, 5:19:15 AMParent: 1edfe7452d88b203db8a281861c9a4c05a70610e
Files changed
app/index.js | changed |
app/page/home.js | changed |
app/page/channel.js | added |
router/sync/routes.js | changed |
state/obs.js | changed |
app/index.js | ||
---|---|---|
@@ -9,8 +9,10 @@ | ||
9 | 9 | threadCard: require('./html/thread-card') |
10 | 10 | }, |
11 | 11 | page: { |
12 | 12 | group: require('./page/group'), |
13 | + channel: require('./page/channel'), | |
13 | 14 | home: require('./page/home'), |
14 | 15 | private: require('./page/private') |
15 | 16 | } |
16 | 17 | } |
18 | + |
app/page/home.js | ||
---|---|---|
@@ -111,27 +111,19 @@ | ||
111 | 111 | h('div.container', [ |
112 | 112 | //private section |
113 | 113 | h('section.updates -directMessage', [ |
114 | 114 | h('div.threads', |
115 | -// Object.keys(threads.roots) | |
116 | -// .map(function (id) { | |
117 | -// return threads.roots[id] | |
118 | -// }) | |
119 | -// .filter(function (thread) { | |
120 | -// return filter(location.filter, thread) | |
121 | -// }) | |
122 | 115 | groupedThreads |
123 | 116 | .map(function (thread) { |
124 | 117 | var el = api.app.html |
125 | 118 | .threadCard(thread, opts) |
126 | -//DISABLE: rethinking pages | |
127 | -// if(!location.filter && el) | |
128 | -// el.onclick = function () { | |
129 | -// if(!filterForThread(thread)) | |
130 | -// api.history.sync.push({key: thread.key}) | |
131 | -// else | |
132 | -// api.history.sync.push({page: 'home', filter: filterForThread(thread)}) | |
133 | -// } | |
119 | + if(thread.value.content.channel) { | |
120 | + el.onclick = function (ev) { | |
121 | + console.log('THTREAD CHANNEL', thread.value.content.channel) | |
122 | + api.history.sync.push({channel: thread.value.content.channel}) | |
123 | + ev.preventDefault() | |
124 | + } | |
125 | + } | |
134 | 126 | return el |
135 | 127 | }) |
136 | 128 | ) |
137 | 129 | ]), |
@@ -149,14 +141,4 @@ | ||
149 | 141 | ]) |
150 | 142 | }) |
151 | 143 | } |
152 | 144 | |
153 | - | |
154 | - | |
155 | - | |
156 | - | |
157 | - | |
158 | - | |
159 | - | |
160 | - | |
161 | - | |
162 | - |
app/page/channel.js | ||
---|---|---|
@@ -1,0 +1,140 @@ | ||
1 | +const nest = require('depnest') | |
2 | +const { h, computed } = require('mutant') | |
3 | +const {threadReduce} = require('ssb-reduce-stream') | |
4 | +const pull = require('pull-stream') | |
5 | +const isObject = require('lodash/isObject') | |
6 | +const isString = require('lodash/isString') | |
7 | +const last = require('lodash/last') | |
8 | +const get = require('lodash/get') | |
9 | +const More = require('hypermore') | |
10 | +const morphdom = require('morphdom') | |
11 | +const Debounce = require('obv-debounce') | |
12 | +const PullObv = require('pull-obv') | |
13 | + | |
14 | +exports.gives = nest('app.page.channel') | |
15 | + | |
16 | +exports.needs = nest({ | |
17 | + 'app.html.nav': 'first', | |
18 | + 'history.sync.push': 'first', | |
19 | + 'keys.sync.id': 'first', | |
20 | + 'translations.sync.strings': 'first', | |
21 | + 'state.obs.threads': 'first', | |
22 | + 'app.html.threadCard': 'first', | |
23 | + 'feed.pull.channel': 'first' | |
24 | +}) | |
25 | + | |
26 | +function toRecpGroup(msg) { | |
27 | + //cannocialize | |
28 | + return Array.isArray(msg.value.content.repcs) && | |
29 | + msg.value.content.recps.map(function (e) { | |
30 | + return (isString(e) ? e : e.link) | |
31 | + }).sort().map(function (id) { | |
32 | + return id.substring(0, 10) | |
33 | + }).join(',') | |
34 | +} | |
35 | + | |
36 | +exports.create = (api) => { | |
37 | + return nest('app.page.channel', function (location) { | |
38 | + // location here can expected to be: { page: 'home' } | |
39 | + var strings = api.translations.sync.strings() | |
40 | + | |
41 | + var container = h('div.container', []) | |
42 | + | |
43 | + function filterForThread (thread) { | |
44 | + if(thread.value.private) | |
45 | + return {private: toRecpGroup(thread)} | |
46 | + else if(thread.value.content.channel) | |
47 | + return {channel: thread.value.content.channel} | |
48 | + } | |
49 | + | |
50 | + function filter (rule, thread) { | |
51 | + if(!thread.value) return false | |
52 | + if(!rule) return true | |
53 | + if(rule.channel) { | |
54 | + return rule.channel == thread.value.content.channel | |
55 | + } | |
56 | + else if(rule.group) | |
57 | + return rule.group == thread.value.content.group | |
58 | + else if(rule.private) | |
59 | + return rule.private == toRecpGroup(thread) | |
60 | + else return true | |
61 | + } | |
62 | + | |
63 | + var morePlease = false | |
64 | + var threadsObs = api.state.obs.threads() | |
65 | + | |
66 | + var createChannelStream = api.feed.pull.channel(location.channel) | |
67 | + | |
68 | + var channelObs = PullObv( | |
69 | + threadReduce, | |
70 | + createChannelStream({reverse: true, limit: 1000}) | |
71 | + ) | |
72 | + | |
73 | +// // DUCT TAPE: debounce the observable so it doesn't | |
74 | +// // update the dom more than 1/second | |
75 | +// threadsObs(function () { | |
76 | +// if(morePlease) threadsObs.more() | |
77 | +// }) | |
78 | +// threadsObsDebounced = Debounce(threadsObs, 1000) | |
79 | +// threadsObsDebounced(function () { | |
80 | +// morePlease = false | |
81 | +// }) | |
82 | +// threadsObsDebounced.more = function () { | |
83 | +// morePlease = true | |
84 | +// requestIdleCallback(threadsObs.more) | |
85 | +// } | |
86 | + | |
87 | + var threadsHtmlObs = More( | |
88 | +// threadsObsDebounced, | |
89 | + channelObs, | |
90 | + function render (threads) { | |
91 | + | |
92 | + var sorted = Object.keys(threads.roots) | |
93 | + .map(function (id) { | |
94 | + return threads.roots[id] | |
95 | + }) | |
96 | + .sort(function (a, b) { | |
97 | + return latestUpdate(b) - latestUpdate(a) | |
98 | + }) | |
99 | + | |
100 | + | |
101 | + function latestUpdate(thread) { | |
102 | + var m = thread.timestamp | |
103 | + if(!thread.replies) return m | |
104 | + | |
105 | + for(var i = 0; i < thread.replies.length; i++) | |
106 | + m = Math.max(thread.replies[i].timestamp, m) | |
107 | + return m | |
108 | + } | |
109 | + | |
110 | + morphdom(container, | |
111 | + // LEGACY: some of these containers could be removed | |
112 | + // but they are here to be compatible with the old MCSS. | |
113 | + h('div.container', [ | |
114 | + //private section | |
115 | + h('section.updates -directMessage', [ | |
116 | + h('div.threads', | |
117 | + sorted | |
118 | + .map(function (thread) { | |
119 | + var el = api.app.html | |
120 | + .threadCard(thread, opts) | |
121 | + return el | |
122 | + }) | |
123 | + ) | |
124 | + ]), | |
125 | + ]) | |
126 | + ) | |
127 | + return container | |
128 | + } | |
129 | + ) | |
130 | + | |
131 | + return h('Page -home', [ | |
132 | + h('h1', location.channel), | |
133 | + api.app.html.nav(), | |
134 | + threadsHtmlObs, | |
135 | + h('button', {'ev-click': threadsHtmlObs.more}, [strings.showMore]) | |
136 | + ]) | |
137 | + }) | |
138 | +} | |
139 | + | |
140 | + |
router/sync/routes.js | ||
---|---|---|
@@ -4,8 +4,9 @@ | ||
4 | 4 | |
5 | 5 | exports.needs = nest({ |
6 | 6 | 'app.page.home': 'first', |
7 | 7 | 'app.page.group': 'first', |
8 | + 'app.page.channel': 'first', | |
8 | 9 | 'app.page.private': 'first' |
9 | 10 | }) |
10 | 11 | |
11 | 12 | exports.create = (api) => { |
@@ -15,9 +16,9 @@ | ||
15 | 16 | |
16 | 17 | const routes = [ |
17 | 18 | [ location => location.page === 'home', pages.home ], |
18 | 19 | [ location => location.type === 'group', pages.group ], |
19 | - [ location => location.page === 'channel', pages.channel ], | |
20 | + [ location => location.channel , pages.channel ], | |
20 | 21 | [ location => ref.isMsg(location.key), pages.private ] |
21 | 22 | ] |
22 | 23 | |
23 | 24 | return [...routes, ...sofar] |
@@ -32,4 +33,5 @@ | ||
32 | 33 | |
33 | 34 | |
34 | 35 | |
35 | 36 | |
37 | + |
state/obs.js | ||
---|---|---|
@@ -1,8 +1,8 @@ | ||
1 | 1 | var PullObv = require('pull-obv') |
2 | 2 | var threadReduce = require('ssb-reduce-stream') |
3 | 3 | var pull = require('pull-stream') |
4 | -const Next = require('pull-next') | |
4 | +var Next = require('pull-next') | |
5 | 5 | |
6 | 6 | var nest = require('depnest') |
7 | 7 | |
8 | 8 | function isObject (o) { |
@@ -10,12 +10,8 @@ | ||
10 | 10 | } |
11 | 11 | |
12 | 12 | exports.gives = nest('state.obs.threads', true) |
13 | 13 | |
14 | -//{ | |
15 | -// state: {obs: {threads: true}} | |
16 | -//} | |
17 | - | |
18 | 14 | exports.needs = nest({ |
19 | 15 | 'message.sync.unbox': 'first', |
20 | 16 | 'sbot.pull.log': 'first' |
21 | 17 | }) |
@@ -67,29 +63,33 @@ | ||
67 | 63 | var timer |
68 | 64 | //keep localStorage up to date |
69 | 65 | threadsObs(function (threadsState) { |
70 | 66 | if(timer) return |
71 | - clearTimeout(timer) | |
72 | 67 | timer = setTimeout(function () { |
73 | 68 | timer = null |
74 | 69 | threadsState.last = lastTimestamp |
70 | + console.log('save state') | |
75 | 71 | localStorage.threadsState = JSON.stringify(threadsState) |
76 | 72 | }, 1000) |
77 | 73 | }) |
78 | 74 | |
79 | 75 | //stream live messages. this *should* work. |
80 | 76 | //there is no back pressure on new events |
81 | 77 | //only a show more on the top (currently) |
82 | 78 | |
83 | - pull( | |
84 | - Next(function () { | |
85 | - return api.sbot.pull.log({reverse: true, limit: 500, gte: firstTimestamp}) | |
86 | - }), | |
87 | - pull.drain(function (data) { | |
88 | - firstTimestamp = data.timestamp | |
89 | - threadsObs.set(threadReduce(threadsObs.value, data)) | |
90 | - }) | |
91 | - ) | |
79 | +// pull( | |
80 | +// Next(function () { | |
81 | +// return api.sbot.pull.log({limit: 500, gte: firstTimestamp, live: true}) | |
82 | +// }), | |
83 | +// pull.drain(function (data) { | |
84 | +// if(data.sync) return | |
85 | +// firstTimestamp = data.timestamp | |
86 | +// console.log("SET", data.timestamp, firstTimestamp) | |
87 | +// threadsObs.set(threadReduce(threadsObs.value, data)) | |
88 | +// }) | |
89 | +// ) | |
90 | + | |
92 | 91 | return threadsObs |
93 | 92 | }) |
94 | 93 | } |
95 | 94 | |
95 | + |
Built with git-ssb-web