git ssb

7+

dinoworm ๐Ÿ› / patchcore



Tree: bbf9cdfc7f84c6262811e691c5feb5c33dc69c0a

Files: bbf9cdfc7f84c6262811e691c5feb5c33dc69c0a / feed / obs / thread.js

3251 bytesRaw
1var nest = require('depnest')
2var sort = require('ssb-sort')
3var ref = require('ssb-ref')
4var { Array: MutantArray, Value, map, computed } = require('mutant')
5
6exports.needs = nest({
7 'backlinks.obs.for': 'first',
8 'sbot.async.get': 'first',
9 'message.sync.unbox': 'first',
10 'message.sync.root': 'first',
11 'message.sync.isBlocked': 'first'
12})
13
14exports.gives = nest('feed.obs.thread')
15
16exports.create = function (api) {
17 return nest('feed.obs.thread', thread)
18
19 function thread (rootId, { branch } = {}) {
20 if (!ref.isLink(rootId)) throw new Error('an id must be specified')
21 var sync = Value(false)
22 var { isBlocked, root } = api.message.sync
23
24 var prepend = MutantArray()
25 api.sbot.async.get(rootId, (err, value) => {
26 sync.set(true)
27 if (!err) {
28 var msg = unboxIfNeeded({key: rootId, value})
29 if (isBlocked(msg)) msg.isBlocked = true
30 prepend.push(Value(msg))
31 }
32 })
33
34 var backlinks = api.backlinks.obs.for(rootId)
35 var replies = map(computed(backlinks, (msgs) => {
36 return msgs.filter(msg => {
37 const { type, branch } = msg.value.content
38 return type !== 'vote' && !isBlocked(msg) && (root(msg) === rootId || matchAny(branch, rootId))
39 })
40 }), x => Value(x), {
41 // avoid refresh of entire list when items added
42 comparer: (a, b) => a === b
43 })
44
45 var messages = computed([prepend, replies], (prepend, replies) => {
46 return sort([...prepend, ...replies])
47 })
48
49 var result = {
50 messages,
51 lastId: computed(messages, (messages) => {
52 var branches = sort.heads(messages)
53 if (branches.length <= 1) {
54 branches = branches[0]
55 }
56 return branches
57 }),
58 rootId: computed(messages, (messages) => {
59 if (branch && messages.length) {
60 return messages[0].value.content.root
61 } else {
62 return rootId
63 }
64 }),
65 branchId: computed(messages, (messages) => {
66 if (branch) return rootId
67 }),
68 previousKey: function (msg) {
69 return PreviousKey(result.messages, msg)
70 },
71 isPrivate: computed(messages, msgs => {
72 if (!msgs[0]) return false
73
74 return msgs[0].value.private || false
75 }),
76 channel: computed(messages, msgs => {
77 if (!msgs[0]) return undefined
78
79 return msgs[0].value.content.channel
80 }),
81 recps: computed(messages, msgs => {
82 if (!msgs[0]) return undefined
83
84 return msgs[0].value.content.recps
85 })
86 }
87
88 result.sync = computed([backlinks.sync, sync], (a, b) => a && b, {idle: true})
89 return result
90 }
91
92 function unboxIfNeeded (msg) {
93 if (msg.value && typeof msg.value.content === 'string') {
94 return api.message.sync.unbox(msg) || msg
95 } else {
96 return msg
97 }
98 }
99}
100
101function PreviousKey (collection, item) {
102 return computed(collection, (c) => {
103 var index = collection.indexOf(item)
104 if (~index) {
105 var previous = c[index - 1]
106 if (previous) {
107 return previous.key
108 }
109 }
110 })
111}
112
113function matchAny (valueOrArray, compare) {
114 if (valueOrArray === compare) {
115 return true
116 } else if (Array.isArray(valueOrArray)) {
117 return valueOrArray.includes(compare)
118 }
119}
120

Built with git-ssb-web