Commit 51b10fcae8f88e89444a0c702a5a50bcaf49c157
use ssb-about reducer for `about.obs`
Matt McKegg committed on 6/12/2017, 11:54:23 AMParent: 196bfa929c905a10e03900db3ff77a5f05c35300
Files changed
about/obs.js | changed |
about/obs.js | |||
---|---|---|---|
@@ -1,14 +1,13 @@ | |||
1 | -var {Value, Struct, Dict, computed} = require('mutant') | ||
2 | -var pullPause = require('pull-pause') | ||
1 … | +var {Value, computed, onceTrue} = require('mutant') | ||
2 … | +var defer = require('pull-defer') | ||
3 | 3 … | var pull = require('pull-stream') | |
4 | -var msgs = require('ssb-msgs') | ||
5 | 4 … | var nest = require('depnest') | |
6 | 5 … | var ref = require('ssb-ref') | |
7 | 6 … | var colorHash = new (require('color-hash'))() | |
8 | 7 … | ||
9 | 8 … | exports.needs = nest({ | |
10 | - 'sbot.pull.query': 'first', | ||
9 … | + 'sbot.obs.connection': 'first', | ||
11 | 10 … | 'blob.sync.url': 'first', | |
12 | 11 … | 'keys.sync.id': 'first' | |
13 | 12 … | }) | |
14 | 13 … | ||
@@ -30,161 +29,147 @@ | |||
30 | 29 … | var cacheLoading = false | |
31 | 30 … | ||
32 | 31 … | return nest({ | |
33 | 32 … | 'about.obs': { | |
34 | - name: (id) => get(id).displayName, | ||
33 … | + name: (id) => get(id).name, | ||
35 | 34 … | description: (id) => get(id).description, | |
36 | 35 … | image: (id) => get(id).image, | |
37 | 36 … | imageUrl: (id) => get(id).imageUrl, | |
38 | - | ||
39 | 37 … | names: (id) => get(id).names, | |
40 | 38 … | images: (id) => get(id).images, | |
41 | 39 … | color: (id) => computed(id, (id) => colorHash.hex(id)) | |
42 | 40 … | } | |
43 | 41 … | }) | |
44 | 42 … | ||
45 | 43 … | function get (id) { | |
44 … | + if (!ref.isFeed(id)) { | ||
45 … | + console.log(id) //throw new Error('About requires an id!') | ||
46 … | + console.trace() | ||
47 … | + } | ||
46 | 48 … | if (!cacheLoading) { | |
47 | 49 … | cacheLoading = true | |
48 | 50 … | loadCache() | |
51 … | + window.things = cache | ||
49 | 52 … | } | |
50 | 53 … | if (!cache[id]) { | |
51 | - cache[id] = About(api, id, sync) | ||
54 … | + cache[id] = About(api, id) | ||
52 | 55 … | } | |
53 | 56 … | return cache[id] | |
54 | 57 … | } | |
55 | 58 … | ||
56 | 59 … | function loadCache () { | |
57 | 60 … | pull( | |
58 | - api.sbot.pull.query({ | ||
59 | - query: [ | ||
60 | - {$filter: { | ||
61 | - value: { | ||
62 | - content: { | ||
63 | - type: 'about' | ||
64 | - } | ||
65 | - } | ||
66 | - }}, | ||
67 | - {$map: { | ||
68 | - timestamp: 'timestamp', | ||
69 | - author: ['value', 'author'], | ||
70 | - id: ['value', 'content', 'about'], | ||
71 | - name: ['value', 'content', 'name'], | ||
72 | - image: ['value', 'content', 'image'], | ||
73 | - description: ['value', 'content', 'description'] | ||
74 | - }} | ||
75 | - ], | ||
76 | - live: true | ||
77 | - }), | ||
78 | - pull.drain( | ||
79 | - msg => { | ||
80 | - if (msg.sync) { | ||
81 | - sync.set(true) | ||
82 | - } else if (msgs.isLink(msg.id, 'feed')) { | ||
83 | - get(msg.id).push(msg) | ||
61 … | + StreamWhenConnected(api.sbot.obs.connection, sbot => sbot.about.stream({live: true})), | ||
62 … | + pull.drain(item => { | ||
63 … | + for (var target in item) { | ||
64 … | + if (ref.isFeed(target)) { | ||
65 … | + get(target).push(item[target]) | ||
84 | 66 … | } | |
85 | - }, | ||
86 | - () => sync.set(true) | ||
87 | - ) | ||
67 … | + } | ||
68 … | + | ||
69 … | + if (!sync()) { | ||
70 … | + sync.set(true) | ||
71 … | + } | ||
72 … | + }) | ||
88 | 73 … | ) | |
89 | 74 … | } | |
90 | 75 … | } | |
91 | 76 … | ||
92 | -function About (api, id, sync) { | ||
93 | - if (!ref.isLink(id)) throw new Error('About requires an id!') | ||
94 | - | ||
95 | - var pauser = pullPause((paused) => {}) | ||
96 | - | ||
77 … | +function About (api, id) { | ||
97 | 78 … | // transparent image | |
98 | 79 … | var fallbackImageUrl = 'data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==' | |
99 | 80 … | ||
81 … | + var state = Value({}) | ||
100 | 82 … | var yourId = api.keys.sync.id() | |
101 | - var lastestTimestamps = {} | ||
83 … | + var image = computed([state, 'image', id, yourId], socialValue) | ||
84 … | + var name = computed([state, 'name', id, yourId, id.slice(1, 10)], socialValue) | ||
85 … | + var description = computed([state, 'description', id, yourId], socialValue) | ||
102 | 86 … | ||
103 | - var obs = Struct({ | ||
104 | - assignedNames: Dict(), | ||
105 | - assignedImages: Dict(), | ||
106 | - assignedDescriptions: Dict() | ||
107 | - }, { | ||
108 | - onListen: pauser.resume, | ||
109 | - onUnlisten: pauser.pause | ||
110 | - }) | ||
111 | - | ||
112 | - obs.sync = computed([sync, obs], (v) => v) | ||
113 | - obs.displayName = computed([obs.assignedNames, id, yourId, id.slice(1, 10)], socialValue) | ||
114 | - obs.description = computed([obs.assignedDescriptions, id, yourId], socialValue) | ||
115 | - obs.image = computed([obs.assignedImages, id, yourId], socialValue) | ||
116 | - | ||
117 | - obs.names = computed(obs.assignedNames, indexByValue) | ||
118 | - obs.images = computed(obs.assignedImages, indexByValue) | ||
119 | - | ||
120 | - obs.imageUrl = computed(obs.image, (blobId) => { | ||
121 | - if (blobId) { | ||
122 | - return api.blob.sync.url(blobId) | ||
123 | - } else { | ||
124 | - return fallbackImageUrl | ||
125 | - } | ||
126 | - }) | ||
127 | - | ||
128 | - obs.push = push | ||
129 | - | ||
130 | - return obs | ||
131 | - | ||
132 | - // scoped | ||
133 | - | ||
134 | - function push (msg) { | ||
135 | - if (!lastestTimestamps[msg.author]) { | ||
136 | - lastestTimestamps[msg.author] = { | ||
137 | - name: 0, image: 0, description: 0 | ||
87 … | + return { | ||
88 … | + name, | ||
89 … | + image, | ||
90 … | + description, | ||
91 … | + names: computed([state, 'name', id, yourId, id.slice(1, 10)], allValues), | ||
92 … | + images: computed([state, 'image', id, yourId], allValues), | ||
93 … | + descriptions: computed([state, 'description', id, yourId], allValues), | ||
94 … | + imageUrl: computed(image, (blobId) => { | ||
95 … | + if (blobId) { | ||
96 … | + return api.blob.sync.url(blobId) | ||
97 … | + } else { | ||
98 … | + return fallbackImageUrl | ||
138 | 99 … | } | |
139 | - } | ||
140 | - if (msg.name && lastestTimestamps[msg.author].name < msg.timestamp) { | ||
141 | - lastestTimestamps[msg.author].name = msg.timestamp | ||
142 | - obs.assignedNames.put(msg.author, msg.name) | ||
143 | - } | ||
144 | - if (msg.image && lastestTimestamps[msg.author].image < msg.timestamp) { | ||
145 | - lastestTimestamps[msg.author].image = msg.timestamp | ||
146 | - var obj = msgs.link(msg.image, 'blob') | ||
147 | - if (obj && obj.link) { | ||
148 | - obs.assignedImages.put(msg.author, obj.link) | ||
100 … | + }), | ||
101 … | + push: function (values) { | ||
102 … | + var lastState = state() | ||
103 … | + var changed = false | ||
104 … | + for (var key in values) { | ||
105 … | + var valuesForKey = lastState[key] = lastState[key] || {} | ||
106 … | + for (var author in values[key]) { | ||
107 … | + var value = values[key][author] | ||
108 … | + if (!valuesForKey[author] || value.lastSeq > valuesForKey[author].lastSeq) { | ||
109 … | + valuesForKey[author] = value | ||
110 … | + changed = true | ||
111 … | + } | ||
112 … | + } | ||
149 | 113 … | } | |
114 … | + if (changed) { | ||
115 … | + state.set(lastState) | ||
116 … | + } | ||
150 | 117 … | } | |
151 | - if (msg.description && lastestTimestamps[msg.author].description < msg.timestamp) { | ||
152 | - lastestTimestamps[msg.author].description = msg.timestamp | ||
153 | - obs.assignedDescriptions.put(msg.author, msg.description) | ||
154 | - } | ||
155 | 118 … | } | |
156 | 119 … | } | |
157 | 120 … | ||
158 | -function socialValue (lookup, id, yourId, fallback) { | ||
159 | - return lookup[yourId] || lookup[id] || highestRank(lookup) || fallback || null | ||
121 … | +function socialValue (lookup, key, id, yourId, fallback) { | ||
122 … | + var result = lookup[key] ? getValue(lookup[key][yourId]) || getValue(lookup[key][id]) || highestRank(lookup[key]) : null | ||
123 … | + if (result != null) { | ||
124 … | + return result | ||
125 … | + } else { | ||
126 … | + return fallback || null | ||
127 … | + } | ||
160 | 128 … | } | |
161 | 129 … | ||
130 … | +function allValues (lookup, key, id, yourId) { | ||
131 … | + var values = {} | ||
132 … | + for (var author in lookup[key]) { | ||
133 … | + var value = getValue(lookup[key][author]) | ||
134 … | + if (value != null) { | ||
135 … | + values[value] = values[value] || [] | ||
136 … | + values[value].push(author) | ||
137 … | + } | ||
138 … | + } | ||
139 … | + return values | ||
140 … | +} | ||
141 … | + | ||
162 | 142 … | function highestRank (lookup) { | |
163 | - var indexed = indexByValue(lookup) | ||
143 … | + var counts = {} | ||
164 | 144 … | var highestCount = 0 | |
165 | 145 … | var currentHighest = null | |
166 | - Object.keys(indexed).forEach((item) => { | ||
167 | - var count = indexed[item].length | ||
168 | - if (count > highestCount) { | ||
169 | - highestCount = count | ||
170 | - currentHighest = item | ||
146 … | + for (var key in lookup) { | ||
147 … | + var value = getValue(lookup[key]) | ||
148 … | + if (value != null) { | ||
149 … | + counts[value] = (counts[value] || 0) + 1 | ||
150 … | + if (counts[value] > highestCount) { | ||
151 … | + currentHighest = value | ||
152 … | + highestCount = counts[value] | ||
153 … | + } | ||
171 | 154 … | } | |
172 | - }) | ||
155 … | + } | ||
173 | 156 … | return currentHighest | |
174 | 157 … | } | |
175 | 158 … | ||
176 | -function indexByValue (lookup) { | ||
177 | - var result = {} | ||
178 | - Object.keys(lookup).forEach((key) => { | ||
179 | - var value = lookup[key] | ||
180 | - if (!result[value]) { | ||
181 | - result[value] = [] | ||
159 … | +function getValue (item) { | ||
160 … | + if (item && item.value) { | ||
161 … | + if (typeof item.value === 'string') { | ||
162 … | + return item.value | ||
163 … | + } else if (item.value && item.value.link && ref.isLink(item.value.link)) { | ||
164 … | + return item.value.link | ||
182 | 165 … | } | |
183 | - result[value].push(key) | ||
184 | - }) | ||
185 | - return result | ||
166 … | + } | ||
186 | 167 … | } | |
187 | 168 … | ||
188 | -function isAbout (msg) { | ||
189 | - return msg.value && msg.value.content && msg.value.content.type === 'about' | ||
169 … | +function StreamWhenConnected (connection, fn) { | ||
170 … | + var stream = defer.source() | ||
171 … | + onceTrue(connection, function (connection) { | ||
172 … | + stream.resolve(fn(connection)) | ||
173 … | + }) | ||
174 … | + return stream | ||
190 | 175 … | } |
Built with git-ssb-web