git ssb

7+

dinoworm ๐Ÿ› / patchcore



Tree: c2865b1db3cc50c32ef351f6f877be6cafcf0381

Files: c2865b1db3cc50c32ef351f6f877be6cafcf0381 / about / obs.js

4293 bytesRaw
1var {Value, computed, onceTrue} = require('mutant')
2var defer = require('pull-defer')
3var pull = require('pull-stream')
4var nest = require('depnest')
5var ref = require('ssb-ref')
6var colorHash = new (require('color-hash'))()
7
8exports.needs = nest({
9 'sbot.obs.connection': 'first',
10 'blob.sync.url': 'first',
11 'keys.sync.id': 'first'
12})
13
14exports.gives = nest({
15 'about.obs': [
16 'name',
17 'description',
18 'image',
19 'imageUrl',
20 'names',
21 'images',
22 'color'
23 ]
24})
25
26exports.create = function (api) {
27 var sync = Value(false)
28 var cache = {}
29 var cacheLoading = false
30
31 return nest({
32 'about.obs': {
33 name: (id) => get(id).name,
34 description: (id) => get(id).description,
35 image: (id) => get(id).image,
36 imageUrl: (id) => get(id).imageUrl,
37 names: (id) => get(id).names,
38 images: (id) => get(id).images,
39 color: (id) => computed(id, (id) => colorHash.hex(id))
40 }
41 })
42
43 function get (id) {
44 if (!ref.isFeed(id)) throw new Error('About requires an id!')
45 if (!cacheLoading) {
46 cacheLoading = true
47 loadCache()
48 }
49 if (!cache[id]) {
50 cache[id] = About(api, id)
51 }
52 return cache[id]
53 }
54
55 function loadCache () {
56 pull(
57 StreamWhenConnected(api.sbot.obs.connection, sbot => sbot.about.stream({live: true})),
58 pull.drain(item => {
59 for (var target in item) {
60 if (ref.isFeed(target)) {
61 get(target).push(item[target])
62 }
63 }
64
65 if (!sync()) {
66 sync.set(true)
67 }
68 })
69 )
70 }
71}
72
73function About (api, id) {
74 // transparent image
75 var fallbackImageUrl = 'data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='
76
77 var state = Value({})
78 var yourId = api.keys.sync.id()
79 var image = computed([state, 'image', id, yourId], socialValue)
80 var name = computed([state, 'name', id, yourId, id.slice(1, 10)], socialValue)
81 var description = computed([state, 'description', id, yourId], socialValue)
82
83 return {
84 name,
85 image,
86 description,
87 names: computed([state, 'name', id, yourId, id.slice(1, 10)], allValues),
88 images: computed([state, 'image', id, yourId], allValues),
89 descriptions: computed([state, 'description', id, yourId], allValues),
90 imageUrl: computed(image, (blobId) => {
91 if (blobId) {
92 return api.blob.sync.url(blobId)
93 } else {
94 return fallbackImageUrl
95 }
96 }),
97 push: function (values) {
98 var lastState = state()
99 var changed = false
100 for (var key in values) {
101 var valuesForKey = lastState[key] = lastState[key] || {}
102 for (var author in values[key]) {
103 var value = values[key][author]
104 if (!valuesForKey[author] || value[1] > valuesForKey[author][1]) {
105 valuesForKey[author] = value
106 changed = true
107 }
108 }
109 }
110 if (changed) {
111 state.set(lastState)
112 }
113 }
114 }
115}
116
117function socialValue (lookup, key, id, yourId, fallback) {
118 var result = lookup[key] ? getValue(lookup[key][yourId]) || getValue(lookup[key][id]) || highestRank(lookup[key]) : null
119 if (result != null) {
120 return result
121 } else {
122 return fallback || null
123 }
124}
125
126function allValues (lookup, key, id, yourId) {
127 var values = {}
128 for (var author in lookup[key]) {
129 var value = getValue(lookup[key][author])
130 if (value != null) {
131 values[value] = values[value] || []
132 values[value].push(author)
133 }
134 }
135 return values
136}
137
138function highestRank (lookup) {
139 var counts = {}
140 var highestCount = 0
141 var currentHighest = null
142 for (var key in lookup) {
143 var value = getValue(lookup[key])
144 if (value != null) {
145 counts[value] = (counts[value] || 0) + 1
146 if (counts[value] > highestCount) {
147 currentHighest = value
148 highestCount = counts[value]
149 }
150 }
151 }
152 return currentHighest
153}
154
155function getValue (item) {
156 if (item && item[0]) {
157 if (typeof item[0] === 'string') {
158 return item[0]
159 } else if (item[0] && item[0].link && ref.isLink(item[0].link)) {
160 return item[0].link
161 }
162 }
163}
164
165function StreamWhenConnected (connection, fn) {
166 var stream = defer.source()
167 onceTrue(connection, function (connection) {
168 stream.resolve(fn(connection))
169 })
170 return stream
171}
172

Built with git-ssb-web