git ssb

7+

dinoworm ๐Ÿ› / patchcore



Tree: 375a86a96a5e996629eeda68996cbb4b8293ece0

Files: 375a86a96a5e996629eeda68996cbb4b8293ece0 / contact / obs.js

2699 bytesRaw
1var nest = require('depnest')
2var {Value, computed} = require('mutant')
3var pull = require('pull-stream')
4var ref = require('ssb-ref')
5
6exports.needs = nest({
7 'sbot.pull.stream': 'first'
8})
9
10exports.gives = nest({
11 'contact.obs': ['following', 'followers'],
12 'sbot.hook.publish': true
13})
14
15exports.create = function (api) {
16 var cacheLoading = false
17 var cache = {}
18 var sync = Value(false)
19
20 return nest({
21 'contact.obs': {
22 following: (id) => values(get(id), 'following', true),
23 followers: (id) => values(get(id), 'followers', true)
24 },
25 'sbot.hook.publish': function (msg) {
26 if (isContact(msg)) {
27 // HACK: make interface more responsive when sbot is busy
28 var source = msg.value.author
29 var dest = msg.value.content.contact
30 if (typeof msg.value.content.following === 'boolean') {
31 update(source, {
32 following: {
33 [dest]: [msg.value.content]
34 }
35 })
36 update(dest, {
37 followers: {
38 [source]: [msg.value.content]
39 }
40 })
41 }
42 }
43 }
44 })
45
46 function values (state, key, compare) {
47 var obs = computed([state, key, compare], getIds)
48 obs.sync = sync
49 return obs
50 }
51
52 function loadCache () {
53 pull(
54 api.sbot.pull.stream(sbot => sbot.contacts.stream({live: true})),
55 pull.drain(item => {
56 for (var target in item) {
57 if (ref.isFeed(target)) update(target, item[target])
58 }
59
60 if (!sync()) {
61 sync.set(true)
62 }
63 })
64 )
65 }
66
67 function update (id, values) {
68 var state = get(id)
69 var lastState = state()
70 var changed = false
71 for (var key in values) {
72 var valuesForKey = lastState[key] = lastState[key] || {}
73 for (var dest in values[key]) {
74 var value = values[key][dest]
75 if (!valuesForKey[dest] || value[1] > valuesForKey[dest][1] || !values[1] || !valuesForKey[dest[1]]) {
76 valuesForKey[dest] = value
77 changed = true
78 }
79 }
80 }
81 if (changed) {
82 state.set(lastState)
83 }
84 }
85
86 function get (id) {
87 if (!ref.isFeed(id)) throw new Error('Contact state requires an id!')
88 if (!cacheLoading) {
89 cacheLoading = true
90 loadCache()
91 }
92 if (!cache[id]) {
93 cache[id] = Value({})
94 }
95 return cache[id]
96 }
97}
98
99function getIds (state, key, compare) {
100 var result = new Set()
101 if (state[key]) {
102 for (var dest in state[key]) {
103 if (state[key][dest][0] === compare) {
104 result.add(dest)
105 }
106 }
107 }
108 return result
109}
110
111function isContact (msg) {
112 return msg.value && msg.value.content && msg.value.content.type === 'contact'
113}
114

Built with git-ssb-web