Commit 95e0edd1b9246ddcd3bbfbf732cf9a4007d078de
support for private messages
Dominic Tarr committed on 5/16/2016, 9:34:04 AMParent: 9d629c55b19f5dc728643731fffb36dac23c0eca
Files changed
modules/main.js | changed |
modules/tabs.js | changed |
modules/thread.js | changed |
modules/crypto.js | added |
modules/private.js | added |
package.json | changed |
util.js | changed |
modules/main.js | ||
---|---|---|
@@ -5,9 +5,8 @@ | ||
5 | 5 | var Scroller = require('pull-scroll') |
6 | 6 | |
7 | 7 | exports.screen_view = function (path, sbot) { |
8 | 8 | if(path === '/') { |
9 | - | |
10 | 9 | var content = h('div.column') |
11 | 10 | var div = h('div.column', {style: {'overflow':'auto'}}, |
12 | 11 | u.decorate(exports.message_compose, {}, function (d, e, v) { |
13 | 12 | return d(e, v, sbot) |
@@ -16,9 +15,9 @@ | ||
16 | 15 | ) |
17 | 16 | var render = ui.createRenderers(exports.message_render, sbot) |
18 | 17 | |
19 | 18 | pull( |
20 | - sbot.createLogStream({reverse: true}), | |
19 | + u.next(sbot.createLogStream, {reverse: true, limit: 100}), | |
21 | 20 | Scroller(div, content, render, false, false) |
22 | 21 | ) |
23 | 22 | |
24 | 23 | return div |
@@ -30,4 +29,5 @@ | ||
30 | 29 | |
31 | 30 | |
32 | 31 | |
33 | 32 | |
33 | + |
modules/tabs.js | ||
---|---|---|
@@ -8,10 +8,10 @@ | ||
8 | 8 | if(!el) return |
9 | 9 | if(el.tagName !== 'A') return ancestor(el.parentElement) |
10 | 10 | return el |
11 | 11 | } |
12 | + | |
12 | 13 | exports.app = function (_, sbot) { |
13 | - | |
14 | 14 | function screen (path) { |
15 | 15 | return u.first(exports.screen_view, function (fn) { |
16 | 16 | return fn(path, sbot) |
17 | 17 | }) |
@@ -21,10 +21,15 @@ | ||
21 | 21 | tabs.classList.add('screen') |
22 | 22 | var main = screen('/') |
23 | 23 | if(main) tabs.add('main', main, true) |
24 | 24 | |
25 | + var private = screen('/private') | |
26 | + if(private) tabs.add('private', private, true) | |
27 | + | |
28 | + | |
25 | 29 | tabs.onclick = function (ev) { |
26 | 30 | var link = ancestor(ev.target) |
31 | + if(!link) return | |
27 | 32 | var path = link.hash.substring(1) |
28 | 33 | |
29 | 34 | ev.preventDefault() |
30 | 35 | ev.stopPropagation() |
@@ -41,4 +46,5 @@ | ||
41 | 46 | |
42 | 47 | exports.message_render = [] |
43 | 48 | exports.screen_view = [] |
44 | 49 | |
50 | + |
modules/thread.js | ||
---|---|---|
@@ -1,8 +1,8 @@ | ||
1 | 1 | var ui = require('../ui') |
2 | 2 | var pull = require('pull-stream') |
3 | 3 | var Cat = require('pull-cat') |
4 | -var Sort = require('pull-sort') | |
4 | +var sort = require('ssb-sort') | |
5 | 5 | var ref = require('ssb-ref') |
6 | 6 | var h = require('hyperscript') |
7 | 7 | var u = require('../util') |
8 | 8 | var Scroller = require('pull-scroll') |
@@ -20,59 +20,69 @@ | ||
20 | 20 | }) |
21 | 21 | } |
22 | 22 | } |
23 | 23 | |
24 | -function threadStream (root, sbot ) { | |
24 | +function getThread (root, sbot, cb) { | |
25 | 25 | //in this case, it's inconvienent that panel only takes |
26 | 26 | //a stream. maybe it would be better to accept an array? |
27 | 27 | |
28 | - return pull( | |
29 | - Cat([ | |
30 | - once(function (cb) { | |
31 | - sbot.get(root, function (err, value) { | |
32 | - cb(err, {key: root, value: value}) | |
33 | - }) | |
34 | - }), | |
35 | - sbot.links({rel: 'root', dest: root, values: true, keys: true}) | |
36 | - ]), | |
37 | - Sort(function (a, b) { | |
38 | - //THIS IS WRONG AND HAS KNOWN BUGS!!! | |
39 | - //TODO: sort by cryptographic causal ordering. | |
40 | - return a.value.timestamp - b.value.timestamp | |
41 | - }) | |
42 | - ) | |
28 | + return pull(Cat([ | |
29 | + once(function (cb) { | |
30 | + sbot.get(root, function (err, value) { | |
31 | + cb(err, {key: root, value: value}) | |
32 | + }) | |
33 | + }), | |
34 | + sbot.links({rel: 'root', dest: root, values: true, keys: true}) | |
35 | + ]), pull.collect(cb)) | |
43 | 36 | } |
44 | 37 | |
38 | +function unbox(msg) { | |
39 | + return u.first(exports.message_unbox, function (fn) { | |
40 | + return fn(msg) | |
41 | + }) | |
42 | +} | |
43 | + | |
45 | 44 | exports.screen_view = function (id, sbot) { |
46 | 45 | if(ref.isMsg(id)) { |
47 | - var content = h('div.column') | |
48 | - var div = h('div.column', {style: {'overflow':'auto'}}, | |
49 | - h('div', content), | |
50 | - u.decorate(exports.message_compose, {root: id}, function (d, e, v) { | |
51 | - return d(e, v, sbot) | |
52 | - }) | |
53 | - ) | |
46 | + var div = h('div.column', {style: {'overflow-y': 'auto'}}) | |
54 | 47 | var render = ui.createRenderers(exports.message_render, sbot) |
55 | 48 | |
56 | - pull( | |
57 | - threadStream(id, sbot), | |
58 | - Scroller(div, content, render, false, false) | |
59 | - ) | |
49 | + getThread(id, sbot, function (err, thread) { | |
50 | + thread = thread.map(function (msg) { | |
51 | + return 'string' === typeof msg.value.content ? unbox(msg) : msg | |
52 | + }) | |
60 | 53 | |
54 | + if(err) return div.appendChild(h('pre', err.stack)) | |
55 | + sort(thread).map(render).forEach(function (el) { | |
56 | + div.appendChild(el) | |
57 | + }) | |
58 | + | |
59 | + var branches = sort.heads(thread) | |
60 | + var meta = { | |
61 | + root: id, | |
62 | + branch: branches.length > 1 ? branches : branches[0] | |
63 | + } | |
64 | + var recps = thread[0].value.content.recps | |
65 | + if(recps && thread[0].value.private) | |
66 | + meta.recps = recps | |
67 | + | |
68 | + console.log('recipients', thread[0].value.content.recps) | |
69 | + | |
70 | + div.appendChild( | |
71 | + h('div', | |
72 | + u.decorate(exports.message_compose, meta, function (d, e, v) { | |
73 | + return d(e, v, sbot) | |
74 | + })) | |
75 | + ) | |
76 | + }) | |
77 | + | |
61 | 78 | return div |
62 | 79 | } |
63 | 80 | |
64 | - return ui.createStream( | |
65 | - ui.createRenderers(exports.message_render, sbot) | |
66 | - ) | |
67 | 81 | } |
68 | 82 | |
69 | 83 | exports.message_render = [] |
70 | 84 | exports.message_compose = [] |
85 | +exports.message_unbox = [] | |
71 | 86 | |
72 | 87 | |
73 | 88 | |
74 | - | |
75 | - | |
76 | - | |
77 | - | |
78 | - |
modules/crypto.js | ||
---|---|---|
@@ -1,0 +1,37 @@ | ||
1 | + | |
2 | +var path = require('path') | |
3 | +var ssbKeys = require('ssb-keys') | |
4 | +var config = require('ssb-config/inject')(process.env.ssb_appname) | |
5 | +var keys = ssbKeys | |
6 | + .loadSync(path.join(config.path, 'secret')) | |
7 | + | |
8 | +function unbox_value(msg) { | |
9 | + var plaintext = ssbKeys.unbox(msg.content, keys) | |
10 | + if(!plaintext) return null | |
11 | + return { | |
12 | + previous: msg.previous, | |
13 | + author: msg.author, | |
14 | + sequence: msg.sequence, | |
15 | + timestamp: msg.timestamp, | |
16 | + hash: msg.hash, | |
17 | + content: plaintext, | |
18 | + private: true | |
19 | + } | |
20 | +} | |
21 | + | |
22 | +exports.message_unbox = function (msg) { | |
23 | + if(msg.value) { | |
24 | + var value = unbox_value(msg.value) | |
25 | + if(value) | |
26 | + return { | |
27 | + key: msg.key, value: value, timestamp: msg.timestamp | |
28 | + } | |
29 | + } | |
30 | + else | |
31 | + return unbox_value(msg) | |
32 | +} | |
33 | + | |
34 | +exports.message_meta = function (msg) { | |
35 | + if(msg.value.private) | |
36 | + return "PRIVATE" | |
37 | +} |
modules/private.js | ||
---|---|---|
@@ -1,0 +1,49 @@ | ||
1 | +var h = require('hyperscript') | |
2 | +var ui = require('../ui') | |
3 | +var u = require('../util') | |
4 | +var pull = require('pull-stream') | |
5 | +var Scroller = require('pull-scroll') | |
6 | + | |
7 | +function unbox(msg) { | |
8 | + return u.first(exports.message_unbox, function (fn) { | |
9 | + return fn(msg) | |
10 | + }) | |
11 | +} | |
12 | + | |
13 | +exports.screen_view = function (path, sbot) { | |
14 | + if(path === '/private') { | |
15 | + | |
16 | + var content = h('div.column') | |
17 | + | |
18 | + var div = h('div.column', {style: {'overflow':'auto'}}, content) | |
19 | + var render = ui.createRenderers(exports.message_render, sbot) | |
20 | + | |
21 | + pull( | |
22 | + u.next( | |
23 | + sbot.createLogStream.bind(sbot), | |
24 | + {reverse: true, limit: 1000} | |
25 | +//, | |
26 | +// 'lt', 'timestamp' | |
27 | + ), | |
28 | + pull.through(function (e) { | |
29 | + console.log('msg') | |
30 | + }), | |
31 | + pull.filter(function (msg) { | |
32 | + return 'string' == typeof msg.value.content | |
33 | + }), | |
34 | + pull.map(unbox), | |
35 | + pull.filter(Boolean), | |
36 | + Scroller(div, content, render, false, false, function (err) { | |
37 | + if(err) throw err | |
38 | + }) | |
39 | + ) | |
40 | + | |
41 | + return div | |
42 | + } | |
43 | +} | |
44 | + | |
45 | +exports.message_render = [] | |
46 | +exports.message_compose = [] | |
47 | +exports.message_unbox = [] | |
48 | + | |
49 | + |
package.json | ||
---|---|---|
@@ -7,19 +7,21 @@ | ||
7 | 7 | "type": "git", |
8 | 8 | "url": "git://github.com/dominictarr/ssb-patchboard.git" |
9 | 9 | }, |
10 | 10 | "dependencies": { |
11 | - "depject": "0.0.2", | |
11 | + "depject": "^0.1.0", | |
12 | 12 | "hyperscript": "^1.4.7", |
13 | - "hypertabs": "^0.1.0", | |
14 | 13 | "moment": "^2.13.0", |
15 | 14 | "pull-cat": "^1.1.9", |
15 | + "pull-next": "0.0.0", | |
16 | 16 | "pull-paramap": "^1.1.6", |
17 | 17 | "pull-scroll": "^0.1.0", |
18 | - "pull-sort": "^1.0.0", | |
19 | 18 | "pull-stream": "^3.3.2", |
20 | 19 | "ssb-client": "^3.0.1", |
21 | - "ssb-markdown": "^3.0.0" | |
20 | + "ssb-keys": "^5.0.2", | |
21 | + "ssb-markdown": "^3.0.0", | |
22 | + "ssb-sort": "0.0.0", | |
23 | + "suggest-box": "^2.0.0" | |
22 | 24 | }, |
23 | 25 | "devDependencies": {}, |
24 | 26 | "scripts": { |
25 | 27 | "test": "set -e; for t in test/*.js; do node $t; done" |
util.js | ||
---|---|---|
@@ -1,4 +1,7 @@ | ||
1 | +var pull = require('pull-stream') | |
2 | +var Next = require('pull-next') | |
3 | + | |
1 | 4 | function first (list, test) { |
2 | 5 | for(var i in list) { |
3 | 6 | var value = test(list[i], i, list) |
4 | 7 | if(value) return value |
@@ -15,4 +18,23 @@ | ||
15 | 18 | |
16 | 19 | exports.first = first |
17 | 20 | |
18 | 21 | exports.decorate = decorate |
22 | + | |
23 | +exports.next = function (createStream, opts, range, property) { | |
24 | + | |
25 | + range = range || opts.reverse ? 'lt' : 'gt' | |
26 | + property = property || 'timestamp' | |
27 | + | |
28 | + var last = null | |
29 | + return Next(function () { | |
30 | + if(last) { | |
31 | + opts[range] = last[property] | |
32 | + } | |
33 | + return pull( | |
34 | + createStream(opts), | |
35 | + pull.through(function (msg) { | |
36 | + if(!msg.sync) last = msg | |
37 | + }) | |
38 | + ) | |
39 | + }) | |
40 | +} |
Built with git-ssb-web