git ssb

7+

dinoworm ๐Ÿ› / patchcore



Tree: 77e61a99aecc53624a9d106a5ea374c2b933963b

Files: 77e61a99aecc53624a9d106a5ea374c2b933963b / feed / obs / thread.js

4126 bytesRaw
1var nest = require('depnest')
2var sort = require('ssb-sort')
3var ref = require('ssb-ref')
4var isBlog = require('scuttle-blog/isBlog')
5var Blog = require('scuttle-blog')
6
7var { Array: MutantArray, Value, map, computed, concat } = require('mutant')
8
9exports.needs = nest({
10 'backlinks.obs.for': 'first',
11 'sbot.async.get': 'first',
12 'message.sync.unbox': 'first',
13 'message.sync.root': 'first',
14 'message.sync.isBlocked': 'first',
15 'sbot.obs.connection': 'first'
16})
17
18exports.gives = nest('feed.obs.thread')
19
20exports.create = function (api) {
21 return nest('feed.obs.thread', thread)
22
23 function thread (rootId, { branch } = {}) {
24 if (!ref.isLink(rootId)) throw new Error('an id must be specified')
25 var sync = Value(false)
26 var { isBlocked, root } = api.message.sync
27
28 var prepend = MutantArray()
29 api.sbot.async.get(rootId, (err, value) => {
30 if (!err) {
31 var msg = unboxIfNeeded({key: rootId, value})
32 if (isBlocked(msg)) msg.isBlocked = true
33
34 if (isBlog(msg)) {
35 // resolve the blog body before returning
36 Blog(api.sbot.obs.connection).async.get(msg, (err, result) => {
37 if (!err) {
38 msg.body = result.body
39 prepend.push(Value(msg))
40 sync.set(true)
41 }
42 })
43 } else {
44 sync.set(true)
45 prepend.push(Value(msg))
46 }
47 } else {
48 sync.set(true)
49 }
50 })
51
52 var backlinks = api.backlinks.obs.for(rootId)
53
54 // wrap computed in a map to turn into individual observables
55 var replies = map(computed(backlinks, (msgs) => {
56 return sort(msgs.filter(msg => {
57 const { type, branch } = msg.value.content
58 return type !== 'vote' && !isBlocked(msg) && (root(msg) === rootId || matchAny(branch, rootId))
59 }))
60 }), x => Value(x), {
61 // avoid refresh of entire list when items added
62 comparer: (a, b) => a === b
63 })
64
65 // append the root message to the sorted replies list
66 // -------------------------
67 // concat preserves the individual observable messages so that clients don't need to
68 // rerender the entire list when an item is added (map will only be called for new items)
69 // (we can't use a computed here as it would squash the individual observables into a single one)
70 var messages = concat([prepend, replies])
71
72 var result = {
73 messages,
74 lastId: computed(messages, (messages) => {
75 var branches = sort.heads(messages)
76 if (branches.length <= 1) {
77 branches = branches[0]
78 }
79 return branches
80 }),
81 rootId: computed(messages, (messages) => {
82 if (branch && messages.length) {
83 return messages[0].value.content.root
84 } else {
85 return rootId
86 }
87 }),
88 branchId: computed(messages, (messages) => {
89 if (branch) return rootId
90 }),
91 previousKey: function (msg) {
92 return PreviousKey(result.messages, msg)
93 },
94 isPrivate: computed(messages, msgs => {
95 if (!msgs[0]) return false
96
97 return msgs[0].value.private || false
98 }),
99 channel: computed(messages, msgs => {
100 if (!msgs[0]) return undefined
101
102 return msgs[0].value.content.channel
103 }),
104 recps: computed(messages, msgs => {
105 if (!msgs[0]) return undefined
106
107 return msgs[0].value.content.recps
108 })
109 }
110
111 result.sync = computed([backlinks.sync, sync], (a, b) => a && b, {idle: true})
112 return result
113 }
114
115 function unboxIfNeeded (msg) {
116 if (msg.value && typeof msg.value.content === 'string') {
117 return api.message.sync.unbox(msg) || msg
118 } else {
119 return msg
120 }
121 }
122}
123
124function PreviousKey (collection, item) {
125 return computed(collection, (c) => {
126 var index = collection.indexOf(item)
127 if (~index) {
128 var previous = c[index - 1]
129 if (previous) {
130 return previous.key
131 }
132 }
133 })
134}
135
136function matchAny (valueOrArray, compare) {
137 if (valueOrArray === compare) {
138 return true
139 } else if (Array.isArray(valueOrArray)) {
140 return valueOrArray.includes(compare)
141 }
142}
143

Built with git-ssb-web