Commit f7dff5dea73ce76928756982a627d93d49cb1968
Merge pull request #3 from ticktackim/homescreen
WIP: Homescreenmix irving authored on 8/11/2017, 12:34:10 AM
GitHub committed on 8/11/2017, 12:34:10 AM
Parent: b87644d4179bd0b35e02a999a6ddb4208fe4615b
Parent: 695b85ae4b52e80b590f126de17de110bc7b7aae
Files changed
app/page/home.js | changed |
app/page/home.mcss | added |
package-lock.json | changed |
package.json | changed |
router/sync/routes.js | changed |
app/page/home.js | ||
---|---|---|
@@ -1,21 +1,112 @@ | ||
1 | 1 | const nest = require('depnest') |
2 | 2 | const { h } = 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') | |
3 | 9 | |
4 | 10 | exports.gives = nest('app.page.home') |
5 | 11 | |
6 | 12 | exports.needs = nest({ |
7 | - 'app.html.nav': 'first' | |
13 | + 'about.html.image': 'first', | |
14 | + 'app.html.nav': 'first', | |
15 | + 'feed.pull.public': 'first', | |
16 | + 'history.sync.push': 'first', | |
17 | + 'message.sync.unbox': 'first', | |
8 | 18 | }) |
9 | 19 | |
20 | +function firstLine (text) { | |
21 | + if(text.length < 80 && !~text.indexOf('\n')) return text | |
22 | + | |
23 | + return text.split('\n')[0].substring(0, 80) | |
24 | +} | |
25 | + | |
10 | 26 | exports.create = (api) => { |
11 | 27 | return nest('app.page.home', home) |
12 | 28 | |
13 | 29 | function home (location) { |
14 | 30 | // location here can expected to be: { page: 'home' } |
15 | 31 | |
32 | + var container = h('div.container', []) | |
33 | + | |
34 | + function subject (msg) { | |
35 | + const { subject, text } = msg.value.content | |
36 | + return firstLine(subject|| text) | |
37 | + } | |
38 | + | |
39 | + function link(location) { | |
40 | + return {'ev-click': () => api.history.sync.push(location)} | |
41 | + } | |
42 | + | |
43 | + function item (name, thread) { | |
44 | + if(!thread.value) return | |
45 | + const lastReply = thread.replies && last(thread.replies) | |
46 | + | |
47 | + return h('div.threadLink', link(thread), [ | |
48 | + name, | |
49 | + h('div.subject', [subject(thread)]), | |
50 | + lastReply ? h('div.reply', [subject(lastReply)]) : null | |
51 | + ]) | |
52 | + } | |
53 | + | |
54 | + function threadGroup (threads, obj, toName) { | |
55 | + // threads = a state object for all the types of threads | |
56 | + // obj = a map of keys to root ids, where key ∈ (channel | group | concatenated list of pubkeys) | |
57 | + // toName = fn that derives a name from a particular thread | |
58 | + | |
59 | + var groupEl = h('div.group') | |
60 | + for(var k in obj) { | |
61 | + var id = obj[k] | |
62 | + var thread = get(threads, ['roots', id]) | |
63 | + if(thread && thread.value) { | |
64 | + var el = item(toName(k, thread), thread) | |
65 | + if(el) groupEl.appendChild(el) | |
66 | + } | |
67 | + } | |
68 | + return groupEl | |
69 | + } | |
70 | + | |
71 | + pull( | |
72 | + api.feed.pull.public({reverse: true, limit: 1000}), | |
73 | + pull.collect(function (err, messages) { | |
74 | + | |
75 | + var threads = messages | |
76 | + .map(function (data) { | |
77 | + if(isObject(data.value.content)) return data | |
78 | + return api.message.sync.unbox(data) | |
79 | + }) | |
80 | + .filter(Boolean) | |
81 | + .reduce(threadReduce, null) | |
82 | + | |
83 | + container.appendChild(threadGroup( | |
84 | + threads, | |
85 | + threads.private, | |
86 | + function (_, msg) { | |
87 | + // NB: msg passed in is actually a 'thread', but only care about root msg | |
88 | + | |
89 | + return h('div.recps', [ | |
90 | + msg.value.content.recps.map(function (link) { | |
91 | + return api.about.html.image(isString(link) ? link : link.link) | |
92 | + }) | |
93 | + ]) | |
94 | + } | |
95 | + )) | |
96 | + | |
97 | + container.appendChild(threadGroup( | |
98 | + threads, | |
99 | + threads.channels, | |
100 | + ch => h('h2.title', '#'+ch) | |
101 | + )) | |
102 | + }) | |
103 | + ) | |
104 | + | |
16 | 105 | return h('Page -home', [ |
17 | 106 | h('h1', 'Home'), |
18 | - api.app.html.nav() | |
107 | + api.app.html.nav(), | |
108 | + container | |
19 | 109 | ]) |
20 | 110 | } |
21 | 111 | } |
112 | + |
app/page/home.mcss | ||
---|---|---|
@@ -1,0 +1,17 @@ | ||
1 | +Page -home { | |
2 | + h1 {} | |
3 | + | |
4 | + div.container { | |
5 | + div.group { | |
6 | + div.threadLink { | |
7 | + div.recps { | |
8 | + img { | |
9 | + $smallAvatar | |
10 | + } | |
11 | + } | |
12 | + } | |
13 | + } | |
14 | + } | |
15 | +} | |
16 | + | |
17 | + |
package-lock.json | ||
---|---|---|
@@ -1535,8 +1535,13 @@ | ||
1535 | 1535 | "requires": { |
1536 | 1536 | "ssb-ref": "2.7.1" |
1537 | 1537 | } |
1538 | 1538 | }, |
1539 | + "ssb-reduce-stream": { | |
1540 | + "version": "0.0.0", | |
1541 | + "resolved": "https://registry.npmjs.org/ssb-reduce-stream/-/ssb-reduce-stream-0.0.0.tgz", | |
1542 | + "integrity": "sha512-YwmRL14bqicMQGQvCuMNa21OwxTmedX1mHDG1O9Ml+O3kXgw9PMx4LNBD2gKH2iw281YPu1yWsfxNsAxcPb1fg==" | |
1543 | + }, | |
1539 | 1544 | "ssb-ref": { |
1540 | 1545 | "version": "2.7.1", |
1541 | 1546 | "resolved": "https://registry.npmjs.org/ssb-ref/-/ssb-ref-2.7.1.tgz", |
1542 | 1547 | "integrity": "sha1-XU7/xUXsD/1/wVuieCmmQLiir7o=", |
package.json | ||
---|---|---|
@@ -28,7 +28,9 @@ | ||
28 | 28 | "patchcore": "^1.9.1", |
29 | 29 | "pull-stream": "^3.6.0", |
30 | 30 | "read-directory": "^2.1.0", |
31 | 31 | "setimmediate": "^1.0.5", |
32 | + "ssb-reduce-stream": "0.0.0", | |
33 | + "ssb-ref": "^2.7.1", | |
32 | 34 | "url": "^0.11.0" |
33 | 35 | } |
34 | 36 | } |
router/sync/routes.js | ||
---|---|---|
@@ -1,7 +1,6 @@ | ||
1 | 1 | const nest = require('depnest') |
2 | -const isEmpty = require('lodash/isEmpty') | |
3 | - | |
2 | +const ref = require('ssb-ref') | |
4 | 3 | exports.gives = nest('router.sync.routes') |
5 | 4 | |
6 | 5 | exports.needs = nest({ |
7 | 6 | 'app.page.home': 'first', |
@@ -10,16 +9,27 @@ | ||
10 | 9 | }) |
11 | 10 | |
12 | 11 | exports.create = (api) => { |
13 | 12 | return nest('router.sync.routes', (sofar = []) => { |
14 | - const { home, group, private: privatePage } = api.app.page | |
15 | - | |
13 | + const pages = api.app.page | |
16 | 14 | // route format: [ routeValidator, routeFunction ] |
15 | + | |
17 | 16 | const routes = [ |
18 | - [ location => location.page === 'home', home ], | |
19 | - [ location => location.type === 'group', group ], | |
20 | - [ location => !isEmpty(location.key), privatePage ] | |
17 | + [ location => location.page === 'home', pages.home ], | |
18 | + [ location => location.type === 'group', pages.group ], | |
19 | + [ location => location.page === 'channel', pages.channel ], | |
20 | + [ location => ref.isMsg(location.key), pages.private ] | |
21 | 21 | ] |
22 | 22 | |
23 | 23 | return [...routes, ...sofar] |
24 | 24 | }) |
25 | 25 | } |
26 | + | |
27 | + | |
28 | + | |
29 | + | |
30 | + | |
31 | + | |
32 | + | |
33 | + | |
34 | + | |
35 | + |
Built with git-ssb-web