Files: d06c60e3b13b5795e7acad4aff8901f5039efb83 / feed / obs / thread.js
2906 bytesRaw
1 | var nest = require('depnest') |
2 | var pull = require('pull-stream') |
3 | var pullCat = require('pull-cat') |
4 | var sort = require('ssb-sort') |
5 | var ref = require('ssb-ref') |
6 | var { map, computed } = require('mutant') |
7 | |
8 | exports.needs = nest({ |
9 | 'sbot.pull.links': 'first', |
10 | 'sbot.async.get': 'first', |
11 | 'lib.obs.pullLookup': 'first', |
12 | 'message.sync.unbox': 'first' |
13 | }) |
14 | |
15 | exports.gives = nest('feed.obs.thread') |
16 | |
17 | exports.create = function (api) { |
18 | return nest('feed.obs.thread', thread) |
19 | |
20 | function thread (rootId, { branch } = {}) { |
21 | if (!ref.isLink(rootId)) throw new Error('an id must be specified') |
22 | |
23 | var rootMessageStream = pull( |
24 | pull.values([rootId]), |
25 | pull.asyncMap((key, cb) => { |
26 | return api.sbot.async.get(key, (err, value) => cb(err, {key, value})) |
27 | }) |
28 | ) |
29 | |
30 | var messageLookup = api.lib.obs.pullLookup(pull( |
31 | pullCat([ |
32 | rootMessageStream, |
33 | api.sbot.pull.links({ rel: branch ? 'branch' : 'root', dest: rootId, keys: true, values: true, live: true }) |
34 | ]), |
35 | unboxIfNeeded() |
36 | ), 'key') |
37 | |
38 | var orderedIds = computed(messageLookup, (lookup) => { |
39 | var msgs = Object.keys(lookup).map(k => lookup[k]) |
40 | return sort(msgs).map(getKey) |
41 | }) |
42 | |
43 | var messages = map(orderedIds, (id) => { |
44 | return messageLookup.get(id) |
45 | }) |
46 | |
47 | var result = { |
48 | messages, |
49 | lastId: computed(messages, (messages) => { |
50 | var branches = sort.heads(messages) |
51 | if(branches.length <= 1) branches = branches[0] |
52 | return branches |
53 | }), |
54 | rootId: computed(messages, (messages) => { |
55 | if (branch && messages.length) { |
56 | return messages[0].value.content.root |
57 | } else { |
58 | return rootId |
59 | } |
60 | }), |
61 | branchId: computed(messages, (messages) => { |
62 | if (branch) return rootId |
63 | }), |
64 | previousKey: function (msg) { |
65 | return PreviousKey(result.messages, msg) |
66 | }, |
67 | isPrivate: computed(messages, msgs => { |
68 | if (!msgs[0]) return false |
69 | |
70 | return msgs[0].value.private || false |
71 | }), |
72 | channel: computed(messages, msgs => { |
73 | if (!msgs[0]) return undefined |
74 | |
75 | return msgs[0].value.content.channel |
76 | }), |
77 | recps: computed(messages, msgs => { |
78 | if (!msgs[0]) return undefined |
79 | |
80 | return msgs[0].value.content.recps |
81 | }) |
82 | } |
83 | |
84 | result.sync = messageLookup.sync |
85 | |
86 | return result |
87 | } |
88 | |
89 | function unboxIfNeeded () { |
90 | return pull.map(function (msg) { |
91 | if (msg.sync || (msg.value && typeof msg.value.content === 'object')) { |
92 | return msg |
93 | } else { |
94 | return api.message.sync.unbox(msg) |
95 | } |
96 | }) |
97 | } |
98 | } |
99 | |
100 | function getKey (msg) { |
101 | return msg.key |
102 | } |
103 | |
104 | function PreviousKey (collection, item) { |
105 | return computed(collection, (c) => { |
106 | var index = collection.indexOf(item) |
107 | if (~index) { |
108 | var previous = c[index - 1] |
109 | if (previous) { |
110 | return previous.key |
111 | } |
112 | } |
113 | }) |
114 | } |
115 |
Built with git-ssb-web