Commit 5a28f5df1543b0e5813e5fe7dbc74f2ec907ff5a
Merge pull request #65 from ssbc/exclude-replies-from-people-blocked-by-root-author
don't include replies in threads or rollups from people blocked by root message authorMatt McKegg authored on 7/8/2018, 3:08:23 AM
GitHub committed on 7/8/2018, 3:08:23 AM
Parent: 9e85f1068f54ff3bc4458e10ee35cd4f89c31434
Parent: f84a9667fa03b5fc5f43b038c6e7616276a5907a
Files changed
contact/obs.js | changed |
feed/obs/thread.js | changed |
feed/pull/with-replies.js | changed |
message/sync/is-blocked.js | changed |
contact/obs.js | ||
---|---|---|
@@ -9,9 +9,9 @@ | ||
9 | 9 … | 'sbot.pull.stream': 'first' |
10 | 10 … | }) |
11 | 11 … | |
12 | 12 … | exports.gives = nest({ |
13 | - 'contact.obs': ['following', 'followers', 'blocking', 'blockers'], | |
13 … | + 'contact.obs': ['following', 'followers', 'blocking', 'blockers', 'raw'], | |
14 | 14 … | 'sbot.hook.publish': true |
15 | 15 … | }) |
16 | 16 … | |
17 | 17 … | exports.create = function (api) { |
@@ -31,9 +31,10 @@ | ||
31 | 31 … | |
32 | 32 … | following: (key) => matchingValueKeys(get(key, cache), true), |
33 | 33 … | followers: (key) => matchingValueKeys(get(key, reverseCache), true), |
34 | 34 … | blocking: (key) => matchingValueKeys(get(key, cache), false), |
35 | - blockers: (key) => matchingValueKeys(get(key, reverseCache), false) | |
35 … | + blockers: (key) => matchingValueKeys(get(key, reverseCache), false), | |
36 … | + raw: (key) => get(key, cache) | |
36 | 37 … | }, |
37 | 38 … | 'sbot.hook.publish': function (msg) { |
38 | 39 … | if (!isContact(msg)) return |
39 | 40 … |
feed/obs/thread.js | |||
---|---|---|---|
@@ -3,9 +3,9 @@ | |||
3 | 3 … | var ref = require('ssb-ref') | |
4 | 4 … | var isBlog = require('scuttle-blog/isBlog') | |
5 | 5 … | var Blog = require('scuttle-blog') | |
6 | 6 … | ||
7 | -var { Array: MutantArray, Value, map, computed, concat } = require('mutant') | ||
7 … | +var { Array: MutantArray, Value, map, computed, concat, ProxyCollection } = require('mutant') | ||
8 | 8 … | ||
9 | 9 … | exports.needs = nest({ | |
10 | 10 … | 'backlinks.obs.for': 'first', | |
11 | 11 … | 'sbot.async.get': 'first', | |
@@ -23,46 +23,49 @@ | |||
23 | 23 … | function thread (rootId, { branch } = {}) { | |
24 | 24 … | if (!ref.isLink(rootId)) throw new Error('an id must be specified') | |
25 | 25 … | var sync = Value(false) | |
26 | 26 … | var { isBlocked, root } = api.message.sync | |
27 … | + var replies = ProxyCollection() | ||
27 | 28 … | ||
28 | 29 … | var prepend = MutantArray() | |
29 | 30 … | api.sbot.async.get(rootId, (err, value) => { | |
31 … | + var rootMessage = null | ||
30 | 32 … | if (!err) { | |
31 | - var msg = unboxIfNeeded({key: rootId, value}) | ||
32 | - if (isBlocked(msg)) msg.isBlocked = true | ||
33 … | + rootMessage = unboxIfNeeded({key: rootId, value}) | ||
34 … | + if (isBlocked(rootMessage)) rootMessage.isBlocked = true | ||
33 | 35 … | ||
34 | - if (isBlog(msg)) { | ||
36 … | + if (isBlog(rootMessage)) { | ||
35 | 37 … | // resolve the blog body before returning | |
36 | - Blog(api.sbot.obs.connection).async.get(msg, (err, result) => { | ||
38 … | + Blog(api.sbot.obs.connection).async.get(rootMessage, (err, result) => { | ||
37 | 39 … | if (!err) { | |
38 | - msg.body = result.body | ||
39 | - prepend.push(Value(msg)) | ||
40 … | + rootMessage.body = result.body | ||
41 … | + prepend.push(Value(rootMessage)) | ||
40 | 42 … | sync.set(true) | |
41 | 43 … | } | |
42 | 44 … | }) | |
43 | 45 … | } else { | |
44 | 46 … | sync.set(true) | |
45 | - prepend.push(Value(msg)) | ||
47 … | + prepend.push(Value(rootMessage)) | ||
46 | 48 … | } | |
47 | 49 … | } else { | |
48 | 50 … | sync.set(true) | |
49 | 51 … | } | |
52 … | + | ||
53 … | + // calcaulate after message has been resolved so that we can check if thread author blocks the reply | ||
54 … | + // wrap computed in a map to turn into individual observables | ||
55 … | + replies.set(map(computed(backlinks, (msgs) => { | ||
56 … | + return sort(msgs.filter(msg => { | ||
57 … | + const { type, branch } = msg.value.content | ||
58 … | + return type !== 'vote' && !isBlocked(msg, rootMessage) && (root(msg) === rootId || matchAny(branch, rootId)) | ||
59 … | + })) | ||
60 … | + }), x => Value(x), { | ||
61 … | + // avoid refresh of entire list when items added | ||
62 … | + comparer: (a, b) => a === b | ||
63 … | + })) | ||
50 | 64 … | }) | |
51 | 65 … | ||
52 | 66 … | var backlinks = api.backlinks.obs.for(rootId) | |
53 | 67 … | ||
54 | - // wrap computed in a map to turn into individual observables | ||
55 | - var replies = map(computed(backlinks, (msgs) => { | ||
56 | - return sort(msgs.filter(msg => { | ||
57 | - const { type, branch } = msg.value.content | ||
58 | - return type !== 'vote' && !isBlocked(msg) && (root(msg) === rootId || matchAny(branch, rootId)) | ||
59 | - })) | ||
60 | - }), x => Value(x), { | ||
61 | - // avoid refresh of entire list when items added | ||
62 | - comparer: (a, b) => a === b | ||
63 | - }) | ||
64 | - | ||
65 | 68 … | // append the root message to the sorted replies list | |
66 | 69 … | // ------------------------- | |
67 | 70 … | // concat preserves the individual observable messages so that clients don't need to | |
68 | 71 … | // rerender the entire list when an item is added (map will only be called for new items) |
feed/pull/with-replies.js | ||
---|---|---|
@@ -18,9 +18,9 @@ | ||
18 | 18 … | // use global backlinks cache |
19 | 19 … | var backlinks = api.backlinks.obs.for(rootMessage.key) |
20 | 20 … | onceTrue(backlinks.sync, () => { |
21 | 21 … | var replies = resolve(backlinks).filter(msg => { |
22 | - return api.message.sync.root(msg) === rootMessage.key && !api.message.sync.isBlocked(msg) | |
22 … | + return api.message.sync.root(msg) === rootMessage.key && !api.message.sync.isBlocked(msg, rootMessage) | |
23 | 23 … | }) |
24 | 24 … | cb(null, extend(rootMessage, { replies })) |
25 | 25 … | }) |
26 | 26 … | }) |
message/sync/is-blocked.js | ||
---|---|---|
@@ -3,18 +3,27 @@ | ||
3 | 3 … | exports.gives = nest('message.sync.isBlocked') |
4 | 4 … | |
5 | 5 … | exports.needs = nest({ |
6 | 6 … | 'contact.obs.blocking': 'first', |
7 … | + 'contact.obs.raw': 'first', | |
7 | 8 … | 'keys.sync.id': 'first' |
8 | 9 … | }) |
9 | 10 … | |
10 | 11 … | exports.create = function (api) { |
11 | 12 … | var cache = null |
12 | 13 … | |
13 | - return nest('message.sync.isBlocked', function isBlockedMessage (msg) { | |
14 … | + return nest('message.sync.isBlocked', function isBlockedMessage (msg, rootMessage) { | |
14 | 15 … | if (!cache) { |
15 | 16 … | cache = api.contact.obs.blocking(api.keys.sync.id()) |
16 | 17 … | } |
17 | 18 … | |
19 … | + if (rootMessage) { | |
20 … | + // check if the author of the root message blocks the author of the message | |
21 … | + var rawContact = api.contact.obs.raw(rootMessage.value.author) | |
22 … | + if (rawContact()[msg.value.author] === false) { | |
23 … | + return true | |
24 … | + } | |
25 … | + } | |
26 … | + | |
18 | 27 … | return cache().includes(msg.value.author) |
19 | 28 … | }) |
20 | 29 … | } |
Built with git-ssb-web