Commit fd15190d894f51e76a7c0fd5f53b0db037f171b8
use mutual friends / followers to determine distance instead of buggy hops
also more detail about two way directional message flow. ssbc/ssb-friends#3Matt McKegg committed on 10/18/2017, 1:59:48 AM
Parent: 461fd4459a46469a272bb9fe6c369b1dd1c9323c
Files changed
locales/en.json | changed |
modules/page/html/render/profile.js | changed |
modules/profile/html/preview.js | changed |
modules/profile/obs/hops.js | deleted |
modules/profile/obs/contact.js | added |
sbot/index.js | changed |
sbot/hops.js | deleted |
locales/en.json | ||
---|---|---|
@@ -165,6 +165,10 @@ | ||
165 | 165 | "This person is blocked by %s of your friends.": { |
166 | 166 | "one": "This person is blocked by %s of your friends.", |
167 | 167 | "other": "This person is blocked by %s of your friends." |
168 | 168 | }, |
169 | - "Blocked by": "Blocked by" | |
169 | + "Blocked by": "Blocked by", | |
170 | + "However, this person should be able to see your posts.": "However, this person should be able to see your posts.", | |
171 | + "However, since they follow someone that follows you, they should be able to see your posts.": "However, since they follow someone that follows you, they should be able to see your posts.", | |
172 | + "They might not be able to see your posts either.": "They might not be able to see your posts either.", | |
173 | + "However, since you follow someone that follows them, you should be able to see their latest posts.": "However, since you follow someone that follows them, you should be able to see their latest posts." | |
170 | 174 | } |
modules/page/html/render/profile.js | ||
---|---|---|
@@ -1,8 +1,7 @@ | ||
1 | 1 | var nest = require('depnest') |
2 | 2 | var ref = require('ssb-ref') |
3 | 3 | var {h, when, computed, map, send, dictToCollection, resolve} = require('mutant') |
4 | -var extend = require('xtend') | |
5 | 4 | |
6 | 5 | exports.needs = nest({ |
7 | 6 | 'about.obs': { |
8 | 7 | name: 'first', |
@@ -23,17 +22,12 @@ | ||
23 | 22 | 'sheet.display': 'first', |
24 | 23 | 'profile.obs.rank': 'first', |
25 | 24 | 'profile.sheet.edit': 'first', |
26 | 25 | 'app.navigate': 'first', |
27 | - 'contact.obs': { | |
28 | - followers: 'first', | |
29 | - following: 'first', | |
30 | - blockers: 'first' | |
31 | - }, | |
26 | + 'profile.obs.contact': 'first', | |
32 | 27 | 'contact.html.followToggle': 'first', |
33 | 28 | 'intl.sync.i18n': 'first', |
34 | 29 | 'intl.sync.i18n_n': 'first', |
35 | - 'profile.obs.hops': 'first', | |
36 | 30 | 'sheet.profiles': 'first' |
37 | 31 | }) |
38 | 32 | exports.gives = nest('page.html.render') |
39 | 33 | |
@@ -41,44 +35,28 @@ | ||
41 | 35 | const i18n = api.intl.sync.i18n |
42 | 36 | const plural = api.intl.sync.i18n_n |
43 | 37 | return nest('page.html.render', function profile (id) { |
44 | 38 | if (!ref.isFeed(id)) return |
45 | - | |
39 | + var yourId = api.keys.sync.id() | |
46 | 40 | var name = api.about.obs.name(id) |
47 | 41 | var description = api.about.obs.description(id) |
48 | - var yourId = api.keys.sync.id() | |
49 | - var yourFollows = api.contact.obs.following(yourId) | |
50 | - var yourFollowers = api.contact.obs.followers(yourId) | |
42 | + var contact = api.profile.obs.contact(id) | |
51 | 43 | |
52 | - var rawFollowers = api.contact.obs.followers(id) | |
53 | - var rawFollowing = api.contact.obs.following(id) | |
54 | - var friendsLoaded = computed([rawFollowers.sync, rawFollowing.sync], (...x) => x.every(Boolean)) | |
55 | - | |
56 | - var hops = api.profile.obs.hops(yourId, id) | |
57 | - | |
58 | - var friends = computed([rawFollowing, rawFollowers], (following, followers) => { | |
44 | + var friends = computed([contact.following, contact.followers], (following, followers) => { | |
59 | 45 | return Array.from(following).filter(follow => followers.includes(follow)) |
60 | 46 | }) |
61 | 47 | |
62 | - var following = computed([rawFollowing, friends], (following, friends) => { | |
63 | - return Array.from(following).filter(follow => !friends.includes(follow)) | |
48 | + var following = computed([contact.following, friends], (following, friends) => { | |
49 | + return following.filter(follow => !friends.includes(follow)) | |
64 | 50 | }) |
65 | 51 | |
66 | - var followers = computed([rawFollowers, friends], (followers, friends) => { | |
67 | - return Array.from(followers).filter(follower => !friends.includes(follower)) | |
52 | + var followers = computed([contact.followers, friends], (followers, friends) => { | |
53 | + return followers.filter(follower => !friends.includes(follower)) | |
68 | 54 | }) |
69 | 55 | |
70 | - var blockers = api.contact.obs.blockers(id) | |
71 | - var youBlock = computed(blockers, function (blockers) { | |
72 | - return blockers.includes(yourId) | |
73 | - }) | |
56 | + var names = computed([api.about.obs.names(id), contact.yourFollowing, contact.following, yourId, id], filterByValues) | |
57 | + var images = computed([api.about.obs.images(id), contact.yourFollowing, contact.following, yourId, id], filterByValues) | |
74 | 58 | |
75 | - var yourBlockingFriends = computed([yourFollowers, yourFollows, blockers], inAllSets) | |
76 | - var mutualFriends = computed([yourFollowers, yourFollows, rawFollowers, rawFollowing], inAllSets) | |
77 | - | |
78 | - var names = computed([api.about.obs.names(id), yourFollows, rawFollowing, yourId, id], filterByValues) | |
79 | - var images = computed([api.about.obs.images(id), yourFollows, rawFollowing, yourId, id], filterByValues) | |
80 | - | |
81 | 59 | var namePicker = h('div', {className: 'Picker'}, [ |
82 | 60 | map(dictToCollection(names), (item) => { |
83 | 61 | var isSelf = computed(item.value, (ids) => ids.includes(id)) |
84 | 62 | var isAssigned = computed(item.value, (ids) => ids.includes(yourId)) |
@@ -156,44 +134,46 @@ | ||
156 | 134 | h('section -publicKey', [ |
157 | 135 | h('pre', {title: i18n('Public key for this profile')}, id) |
158 | 136 | ]), |
159 | 137 | |
160 | - computed([hops, yourBlockingFriends, youBlock], (value, yourBlockingFriends, youBlock) => { | |
161 | - if (value) { | |
162 | - if ((value[0] > 1 || youBlock) && yourBlockingFriends.length > 0) { | |
163 | - return h('section -blockWarning', [ | |
164 | - h('a', { | |
165 | - href: '#', | |
166 | - 'ev-click': send(displayBlockingFriends, yourBlockingFriends) | |
167 | - }, [ | |
168 | - '⚠️ ', plural('This person is blocked by %s of your friends.', yourBlockingFriends.length) | |
169 | - ]) | |
170 | - ]) | |
171 | - } else if (value[0] > 2 || value[0] === undefined) { | |
172 | - return h('section -distanceWarning', [ | |
173 | - h('h1', i18n(`You don't follow anyone who follows this person`)), | |
174 | - h('p', i18n('You might not be seeing their latest messages. You could try joining a pub that they are a member of.')) | |
175 | - ]) | |
176 | - } else if (value[1] > 2 || value[1] === undefined) { | |
177 | - return h('section -distanceWarning', [ | |
138 | + when(contact.notFollowing, [ | |
139 | + when(contact.blockingFriendsCount, h('section -blockWarning', [ | |
140 | + h('a', { | |
141 | + href: '#', | |
142 | + 'ev-click': send(displayBlockingFriends, contact.blockingFriends) | |
143 | + }, [ | |
144 | + '⚠️ ', computed(['This person is blocked by %s of your friends.', contact.blockingFriendsCount], plural) | |
145 | + ]) | |
146 | + ])), | |
147 | + | |
148 | + when(contact.noOutgoing, | |
149 | + h('section -distanceWarning', [ | |
150 | + h('h1', i18n(`You don't follow anyone who follows this person`)), | |
151 | + h('p', i18n('You might not be seeing their latest messages. You could try joining a pub that they are a member of.')), | |
152 | + when(contact.hasIncoming, | |
153 | + h('p', i18n('However, since they follow someone that follows you, they should be able to see your posts.')), | |
154 | + h('p', i18n(`They might not be able to see your posts either.`)) | |
155 | + ) | |
156 | + ]), | |
157 | + when(contact.noIncoming, | |
158 | + h('section -distanceWarning', [ | |
178 | 159 | h('h1', i18n('This person does not follow anyone that follows you')), |
179 | - h('p', i18n('They might not receive your private messages or replies. You could try joining a pub that they are a member of.')) | |
180 | - ]) | |
181 | - } else if (value[0] === 2) { | |
182 | - return h('section -mutualFriends', [ | |
183 | - h('a', { | |
184 | - href: '#', | |
185 | - 'ev-click': send(displayMutualFriends, mutualFriends) | |
186 | - }, [ | |
187 | - '👥 ', | |
188 | - computed(mutualFriends, (items) => { | |
189 | - return plural('You share %s mutual friends with this person.', items.length) | |
190 | - }) | |
160 | + h('p', i18n('They might not receive your private messages or replies. You could try joining a pub that they are a member of.')), | |
161 | + h('p', i18n('However, since you follow someone that follows them, you should be able to see their latest posts.')) | |
162 | + ]), | |
163 | + when(contact.mutualFriendsCount, | |
164 | + h('section -mutualFriends', [ | |
165 | + h('a', { | |
166 | + href: '#', | |
167 | + 'ev-click': send(displayMutualFriends, contact.mutualFriends) | |
168 | + }, [ | |
169 | + '👥 ', computed(['You share %s mutual friends with this person.', contact.mutualFriendsCount], plural) | |
170 | + ]) | |
191 | 171 | ]) |
192 | - ]) | |
193 | - } | |
194 | - } | |
195 | - }), | |
172 | + ) | |
173 | + ) | |
174 | + ) | |
175 | + ]), | |
196 | 176 | |
197 | 177 | h('section -description', [ |
198 | 178 | computed(description, (text) => { |
199 | 179 | if (typeof text === 'string') { |
@@ -207,9 +187,9 @@ | ||
207 | 187 | |
208 | 188 | var feedView = api.feed.html.rollup(api.feed.pull.profile(id), { |
209 | 189 | prepend, |
210 | 190 | displayFilter: (msg) => msg.value.author === id, |
211 | - rootFilter: (msg) => !youBlock(), | |
191 | + rootFilter: (msg) => !contact.youBlock(), | |
212 | 192 | bumpFilter: (msg) => msg.value.author === id |
213 | 193 | }) |
214 | 194 | |
215 | 195 | var container = h('div', {className: 'SplitView'}, [ |
@@ -217,22 +197,22 @@ | ||
217 | 197 | feedView |
218 | 198 | ]), |
219 | 199 | h('div.side.-right', [ |
220 | 200 | h('button PrivateMessageButton', {'ev-click': () => api.app.navigate('/private', {compose: {to: id}})}, i18n('Send Private Message')), |
221 | - when(friendsLoaded, | |
201 | + when(contact.sync, | |
222 | 202 | h('div', [ |
223 | - renderContactBlock(i18n('Friends'), friends, yourFollows), | |
224 | - renderContactBlock(i18n('Followers'), followers, yourFollows), | |
225 | - renderContactBlock(i18n('Following'), following, yourFollows), | |
226 | - renderContactBlock(i18n('Blocked by'), yourBlockingFriends, yourFollows) | |
203 | + renderContactBlock(i18n('Friends'), friends, contact.yourFollowing), | |
204 | + renderContactBlock(i18n('Followers'), followers, contact.yourFollowing), | |
205 | + renderContactBlock(i18n('Following'), following, contact.yourFollowing), | |
206 | + renderContactBlock(i18n('Blocked by'), contact.blockingFriends, contact.yourFollowing) | |
227 | 207 | ]), |
228 | 208 | h('div', {className: 'Loading'}) |
229 | 209 | ) |
230 | 210 | ]) |
231 | 211 | ]) |
232 | 212 | |
233 | 213 | // refresh feed (to hide all posts) when blocked |
234 | - youBlock(feedView.reload) | |
214 | + contact.youBlock(feedView.reload) | |
235 | 215 | |
236 | 216 | container.pendingUpdates = feedView.pendingUpdates |
237 | 217 | container.reload = feedView.reload |
238 | 218 | return container |
@@ -245,17 +225,17 @@ | ||
245 | 225 | function displayBlockingFriends (profiles) { |
246 | 226 | api.sheet.profiles(profiles, i18n('Blocked by')) |
247 | 227 | } |
248 | 228 | |
249 | - function renderContactBlock (title, profiles, yourFollows) { | |
229 | + function renderContactBlock (title, profiles, yourFollowing) { | |
250 | 230 | profiles = api.profile.obs.rank(profiles) |
251 | 231 | return [ |
252 | 232 | when(computed(profiles, x => x.length), h('h2', title)), |
253 | 233 | h('div', { |
254 | 234 | classList: 'ProfileList' |
255 | 235 | }, [ |
256 | 236 | map(profiles, (id) => { |
257 | - var following = computed(yourFollows, f => f.includes(id)) | |
237 | + var following = computed(yourFollowing, f => f.includes(id)) | |
258 | 238 | return h('a.profile', { |
259 | 239 | href: id, |
260 | 240 | classList: [ |
261 | 241 | when(following, '-following') |
@@ -361,8 +341,4 @@ | ||
361 | 341 | } |
362 | 342 | return result |
363 | 343 | }, {}) |
364 | 344 | } |
365 | - | |
366 | -function inAllSets (first, ...rest) { | |
367 | - return first.filter(value => rest.every((collection) => collection.includes(value))) | |
368 | -} |
modules/profile/html/preview.js | ||
---|---|---|
@@ -1,6 +1,7 @@ | ||
1 | 1 | var nest = require('depnest') |
2 | 2 | var h = require('mutant/h') |
3 | +var when = require('mutant/when') | |
3 | 4 | var computed = require('mutant/computed') |
4 | 5 | var send = require('mutant/send') |
5 | 6 | |
6 | 7 | exports.needs = nest({ |
@@ -8,20 +9,13 @@ | ||
8 | 9 | 'about.html.image': 'first', |
9 | 10 | 'keys.sync.id': 'first', |
10 | 11 | 'sheet.display': 'first', |
11 | 12 | 'app.navigate': 'first', |
12 | - 'contact.obs': { | |
13 | - followers: 'first', | |
14 | - following: 'first', | |
15 | - blockers: 'first' | |
16 | - }, | |
17 | - 'contact.async.block': 'first', | |
18 | - 'contact.async.unblock': 'first', | |
19 | 13 | 'intl.sync.i18n': 'first', |
20 | 14 | 'intl.sync.i18n_n': 'first', |
21 | - 'profile.obs.hops': 'first', | |
22 | 15 | 'sheet.profiles': 'first', |
23 | - 'contact.html.followToggle': 'first' | |
16 | + 'contact.html.followToggle': 'first', | |
17 | + 'profile.obs.contact': 'first' | |
24 | 18 | }) |
25 | 19 | |
26 | 20 | exports.gives = nest('profile.html.preview') |
27 | 21 | |
@@ -30,23 +24,10 @@ | ||
30 | 24 | const plural = api.intl.sync.i18n_n |
31 | 25 | |
32 | 26 | return nest('profile.html.preview', function (id) { |
33 | 27 | var name = api.about.obs.name(id) |
34 | - var yourId = api.keys.sync.id() | |
35 | - var yourFollows = api.contact.obs.following(yourId) | |
36 | - var yourFollowers = api.contact.obs.followers(yourId) | |
28 | + var contact = api.profile.obs.contact(id) | |
37 | 29 | |
38 | - var rawFollowers = api.contact.obs.followers(id) | |
39 | - var rawFollowing = api.contact.obs.following(id) | |
40 | - var hops = api.profile.obs.hops(yourId, id) | |
41 | - | |
42 | - var blockers = api.contact.obs.blockers(id) | |
43 | - var youBlock = computed(blockers, function (blockers) { | |
44 | - return blockers.includes(yourId) | |
45 | - }) | |
46 | - var yourBlockingFriends = computed([yourFollowers, yourFollows, blockers], inAllSets) | |
47 | - var mutualFriends = computed([yourFollowers, yourFollows, rawFollowers, rawFollowing], inAllSets) | |
48 | - | |
49 | 30 | return h('ProfilePreview', [ |
50 | 31 | h('header', [ |
51 | 32 | h('div.image', api.about.html.image(id)), |
52 | 33 | h('div.main', [ |
@@ -62,45 +43,45 @@ | ||
62 | 43 | h('pre', {title: i18n('Public key for this profile')}, id) |
63 | 44 | ]) |
64 | 45 | ]) |
65 | 46 | ]), |
66 | - computed([hops, yourBlockingFriends, youBlock], (value, yourBlockingFriends, youBlock) => { | |
67 | - if (value) { | |
68 | - if ((value[0] > 1 || youBlock) && yourBlockingFriends.length > 0) { | |
69 | - return h('section -blockWarning', [ | |
70 | - h('a', { | |
71 | - href: '#', | |
72 | - 'ev-click': send(displayBlockingFriends, yourBlockingFriends) | |
73 | - }, [ | |
74 | - '⚠️ ', plural('This person is blocked by %s of your friends.', yourBlockingFriends.length) | |
75 | - ]) | |
47 | + | |
48 | + when(contact.isYou, h('section -you', [ | |
49 | + i18n('This is you.') | |
50 | + ])), | |
51 | + | |
52 | + when(contact.notFollowing, [ | |
53 | + when(contact.blockingFriendsCount, | |
54 | + h('section -blockWarning', [ | |
55 | + h('a', { | |
56 | + href: '#', | |
57 | + 'ev-click': send(displayBlockingFriends, contact.blockingFriends) | |
58 | + }, [ | |
59 | + '⚠️ ', computed(['This person is blocked by %s of your friends.', contact.blockingFriendsCount], plural) | |
76 | 60 | ]) |
77 | - } else if (value[0] > 2 || value[0] === undefined) { | |
78 | - return h('section -distanceWarning', [ | |
61 | + ]), | |
62 | + when(contact.noOutgoing, | |
63 | + h('section -distanceWarning', [ | |
79 | 64 | '⚠️ ', i18n(`You don't follow anyone who follows this person`) |
80 | - ]) | |
81 | - } else if (value[1] > 2 || value[1] === undefined) { | |
82 | - return h('section -distanceWarning', [ | |
83 | - '⚠️ ', i18n('This person does not follow anyone that follows you') | |
84 | - ]) | |
85 | - } else if (value[0] === 2) { | |
86 | - return h('section -mutualFriends', [ | |
87 | - h('a', { | |
88 | - href: '#', | |
89 | - 'ev-click': send(displayMutualFriends, mutualFriends) | |
90 | - }, [ | |
91 | - computed(mutualFriends, (items) => { | |
92 | - return plural('You share %s mutual friends with this person.', items.length) | |
93 | - }) | |
94 | - ]) | |
95 | - ]) | |
96 | - } else if (value[0] === 0) { | |
97 | - return h('section -you', [ | |
98 | - i18n('This is you.') | |
99 | - ]) | |
100 | - } | |
101 | - } | |
102 | - }) | |
65 | + ]), | |
66 | + when(contact.noIncoming, | |
67 | + h('section -distanceWarning', [ | |
68 | + '⚠️ ', i18n('This person does not follow anyone that follows you') | |
69 | + ]), | |
70 | + when(contact.mutualFriendsCount, | |
71 | + h('section -mutualFriends', [ | |
72 | + h('a', { | |
73 | + href: '#', | |
74 | + 'ev-click': send(displayMutualFriends, contact.mutualFriends) | |
75 | + }, [ | |
76 | + '👥 ', computed(['You share %s mutual friends with this person.', contact.mutualFriendsCount], plural) | |
77 | + ]) | |
78 | + ]) | |
79 | + ) | |
80 | + ) | |
81 | + ) | |
82 | + ) | |
83 | + ]) | |
103 | 84 | ]) |
104 | 85 | }) |
105 | 86 | |
106 | 87 | function displayMutualFriends (profiles) { |
@@ -110,8 +91,4 @@ | ||
110 | 91 | function displayBlockingFriends (profiles) { |
111 | 92 | api.sheet.profiles(profiles, i18n('Blocked by')) |
112 | 93 | } |
113 | 94 | } |
114 | - | |
115 | -function inAllSets (first, ...rest) { | |
116 | - return first.filter(value => rest.every((collection) => collection.includes(value))) | |
117 | -} |
modules/profile/obs/hops.js | ||
---|---|---|
@@ -1,60 +1,0 @@ | ||
1 | -var Value = require('mutant/value') | |
2 | -var computed = require('mutant/computed') | |
3 | -var Sustained = require('../../../lib/sustained') | |
4 | -var nest = require('depnest') | |
5 | - | |
6 | -exports.needs = nest({ | |
7 | - 'profile.obs.recentlyUpdated': 'first', | |
8 | - 'contact.obs.following': 'first', | |
9 | - 'sbot.obs.connection': 'first' | |
10 | -}) | |
11 | - | |
12 | -exports.gives = nest('profile.obs.hops') | |
13 | - | |
14 | -exports.create = function (api) { | |
15 | - return nest('profile.obs.hops', function (from, to) { | |
16 | - // create observable value that refreshes hops whenever friend graph changes | |
17 | - // and has stabilized for more than 500 ms | |
18 | - // also only watches if observable is currently being observed | |
19 | - | |
20 | - var value = Value() | |
21 | - var updates = IncrementableValue() | |
22 | - var releases = [] | |
23 | - | |
24 | - var fromFollowing = api.contact.obs.following(from) | |
25 | - var toFollowing = api.contact.obs.following(to) | |
26 | - | |
27 | - return computed([value], (value) => value, { | |
28 | - onListen: function () { | |
29 | - releases.push(fromFollowing(updates.increment)) | |
30 | - releases.push(toFollowing(updates.increment)) | |
31 | - releases.push(api.sbot.obs.connection(updates.increment)) | |
32 | - releases.push(Sustained(updates, 500)(refresh)) | |
33 | - refresh() | |
34 | - }, | |
35 | - onUnlisten: function () { | |
36 | - while (releases.length) { | |
37 | - releases.pop()() | |
38 | - } | |
39 | - } | |
40 | - }) | |
41 | - | |
42 | - // scoped | |
43 | - function refresh () { | |
44 | - if (api.sbot.obs.connection()) { | |
45 | - api.sbot.obs.connection().patchwork.getHops({from, to}, (err, result) => { | |
46 | - if (err) return console.log(err) | |
47 | - value.set(result) | |
48 | - }) | |
49 | - } | |
50 | - } | |
51 | - }) | |
52 | -} | |
53 | - | |
54 | -function IncrementableValue () { | |
55 | - var value = Value(0) | |
56 | - value.increment = function () { | |
57 | - value.set((value() || 0) + 1) | |
58 | - } | |
59 | - return value | |
60 | -} |
modules/profile/obs/contact.js | ||
---|---|---|
@@ -1,0 +1,79 @@ | ||
1 | +var computed = require('mutant/computed') | |
2 | +var nest = require('depnest') | |
3 | + | |
4 | +exports.needs = nest({ | |
5 | + 'keys.sync.id': 'first', | |
6 | + 'contact.obs': { | |
7 | + followers: 'first', | |
8 | + following: 'first', | |
9 | + blockers: 'first' | |
10 | + } | |
11 | +}) | |
12 | + | |
13 | +exports.gives = nest('profile.obs.contact') | |
14 | + | |
15 | +exports.create = function (api) { | |
16 | + return nest('profile.obs.contact', function (id) { | |
17 | + var yourId = api.keys.sync.id() | |
18 | + var yourFollowing = api.contact.obs.following(yourId) | |
19 | + var yourFollowers = api.contact.obs.followers(yourId) | |
20 | + | |
21 | + var followers = api.contact.obs.followers(id) | |
22 | + var following = api.contact.obs.following(id) | |
23 | + var sync = computed([followers.sync, following.sync], (...x) => x.every(Boolean)) | |
24 | + | |
25 | + var blockers = api.contact.obs.blockers(id) | |
26 | + var youBlock = computed(blockers, function (blockers) { | |
27 | + return blockers.includes(yourId) | |
28 | + }) | |
29 | + | |
30 | + var youFollow = computed([yourFollowing], function (yourFollowing) { | |
31 | + return yourFollowing.includes(id) | |
32 | + }) | |
33 | + | |
34 | + var blockingFriends = computed([yourFollowers, yourFollowing, blockers], inAllSets) | |
35 | + var mutualFriends = computed([yourFollowers, yourFollowing, followers, following], inAllSets) | |
36 | + var hasOutgoing = computed([yourFollowers, following], (a, b) => { | |
37 | + return a.some((id) => b.includes(id)) | |
38 | + }) | |
39 | + var hasIncoming = computed([followers, yourFollowing], (a, b) => { | |
40 | + return a.some((id) => b.includes(id)) | |
41 | + }) | |
42 | + | |
43 | + var isYou = computed([yourId, id], (a, b) => a === b) | |
44 | + | |
45 | + return { | |
46 | + followers, | |
47 | + following, | |
48 | + blockers, | |
49 | + blockingFriends, | |
50 | + blockingFriendsCount: count(blockingFriends), | |
51 | + mutualFriends, | |
52 | + mutualFriendsCount: count(mutualFriends), | |
53 | + hasOutgoing, | |
54 | + noOutgoing: not(hasOutgoing, isYou), | |
55 | + hasIncoming, | |
56 | + noIncoming: not(hasIncoming, isYou), | |
57 | + yourId, | |
58 | + yourFollowing, | |
59 | + yourFollowers, | |
60 | + youFollow, | |
61 | + youBlock, | |
62 | + isYou, | |
63 | + notFollowing: not(youFollow, isYou), | |
64 | + sync | |
65 | + } | |
66 | + }) | |
67 | +} | |
68 | + | |
69 | +function inAllSets (first, ...rest) { | |
70 | + return first.filter(value => rest.every((collection) => collection.includes(value))) | |
71 | +} | |
72 | + | |
73 | +function not (obs, isFalse) { | |
74 | + return computed([obs, isFalse], (x, isFalse) => isFalse ? false : !x) | |
75 | +} | |
76 | + | |
77 | +function count (obs) { | |
78 | + return computed(obs, (x) => x.length) | |
79 | +} |
sbot/index.js | ||
---|---|---|
@@ -5,9 +5,8 @@ | ||
5 | 5 | var Progress = require('./progress') |
6 | 6 | var Search = require('./search') |
7 | 7 | var RecentFeeds = require('./recent-feeds') |
8 | 8 | var LiveBacklinks = require('./live-backlinks') |
9 | -var Hops = require('./hops') | |
10 | 9 | |
11 | 10 | exports.name = 'patchwork' |
12 | 11 | exports.version = require('../package.json').version |
13 | 12 | exports.manifest = { |
@@ -21,9 +20,8 @@ | ||
21 | 20 | heartbeat: 'source', |
22 | 21 | |
23 | 22 | getSubscriptions: 'async', |
24 | 23 | getChannels: 'async', |
25 | - getHops: 'async', | |
26 | 24 | |
27 | 25 | liveBacklinks: { |
28 | 26 | subscribe: 'sync', |
29 | 27 | unsubscribe: 'sync', |
@@ -49,8 +47,7 @@ | ||
49 | 47 | recentFeeds: recentFeeds.stream, |
50 | 48 | linearSearch: search.linear, |
51 | 49 | getSubscriptions: subscriptions.get, |
52 | 50 | getChannels: channels.get, |
53 | - liveBacklinks: LiveBacklinks(ssb, config), | |
54 | - getHops: Hops(ssb, config) | |
51 | + liveBacklinks: LiveBacklinks(ssb, config) | |
55 | 52 | } |
56 | 53 | } |
sbot/hops.js | ||
---|---|---|
@@ -1,11 +1,0 @@ | ||
1 | -module.exports = function (ssb, config) { | |
2 | - return function getHops ({from, to}, cb) { | |
3 | - ssb.friends.hops(from, (err, result) => { | |
4 | - if (err) return cb(err) | |
5 | - ssb.friends.hops(to, (err, reverseResult) => { | |
6 | - if (err) return cb(err) | |
7 | - cb(null, [result[to], reverseResult[from]]) | |
8 | - }) | |
9 | - }) | |
10 | - } | |
11 | -} |
Built with git-ssb-web