Files: d09572761fb01c4513bc32466066d899f32ff4ab / feed / obs / thread.js
2865 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 last = messages[messages.length - 1] |
51 | if (last) return last.key |
52 | }), |
53 | rootId: computed(messages, (messages) => { |
54 | if (branch && messages.length) { |
55 | return messages[0].value.content.root |
56 | } else { |
57 | return rootId |
58 | } |
59 | }), |
60 | branchId: computed(messages, (messages) => { |
61 | if (branch) return rootId |
62 | }), |
63 | previousKey: function (msg) { |
64 | return PreviousKey(result.messages, msg) |
65 | }, |
66 | isPrivate: computed(messages, msgs => { |
67 | if (!msgs[0]) return false |
68 | |
69 | return msgs[0].value.private || false |
70 | }), |
71 | channel: computed(messages, msgs => { |
72 | if (!msgs[0]) return undefined |
73 | |
74 | return msgs[0].value.content.channel |
75 | }), |
76 | recps: computed(messages, msgs => { |
77 | if (!msgs[0]) return undefined |
78 | |
79 | return msgs[0].value.content.recps |
80 | }) |
81 | } |
82 | |
83 | result.sync = messageLookup.sync |
84 | |
85 | return result |
86 | } |
87 | |
88 | function unboxIfNeeded () { |
89 | return pull.map(function (msg) { |
90 | if (msg.sync || (msg.value && typeof msg.value.content === 'object')) { |
91 | return msg |
92 | } else { |
93 | return api.message.sync.unbox(msg) |
94 | } |
95 | }) |
96 | } |
97 | } |
98 | |
99 | function getKey (msg) { |
100 | return msg.key |
101 | } |
102 | |
103 | function PreviousKey (collection, item) { |
104 | return computed(collection, (c) => { |
105 | var index = collection.indexOf(item) |
106 | if (~index) { |
107 | var previous = c[index - 1] |
108 | if (previous) { |
109 | return previous.key |
110 | } |
111 | } |
112 | }) |
113 | } |
114 |
Built with git-ssb-web