git ssb

10+

Matt McKegg / patchwork



Commit 29ec3b383dd48c6e69c75488b52ddf72714de7ad

include posts in feed post-tagged with subscribed tag, you replied, or mentioned

fixes #575 #601
Matt McKegg committed on 10/24/2017, 4:30:33 AM
Parent: 9bd39239444aeffd84194ae531a8fa96d2fcba13

Files changed

modules/feed/html/rollup.jschanged
modules/page/html/render/public.jschanged
sbot/roots.jschanged
modules/feed/html/rollup.jsView
@@ -42,8 +42,9 @@
4242 return nest('feed.html.rollup', function (getStream, {
4343 prepend,
4444 rootFilter = returnTrue,
4545 bumpFilter = returnTrue,
46+ prefiltered = false,
4647 displayFilter = returnTrue,
4748 updateStream, // override the stream used for realtime updates
4849 waitFor = true
4950 }) {
@@ -123,10 +124,10 @@
123124 result.reload = refresh
124125
125126 return result
126127
127- function canRenderMessage(msg) {
128- return api.message.html.canRender(msg);
128+ function canRenderMessage (msg) {
129+ return api.message.html.canRender(msg)
129130 }
130131
131132 function refresh () {
132133 onceTrue(waitFor, () => {
@@ -150,9 +151,9 @@
150151 }))
151152
152153 pull(
153154 stream,
154- pull.filter(bumpFilter),
155+ prefiltered ? pull.through() : pull.filter(bumpFilter),
155156 abortable,
156157 api.feed.pull.rollup(rootFilter),
157158 scroller
158159 )
modules/page/html/render/public.jsView
@@ -71,10 +71,13 @@
7171
7272 var filters = api.settings.obs.get('filters')
7373 var feedView = api.feed.html.rollup(getStream, {
7474 prepend,
75+ prefiltered: true, // we've already filtered out the roots we don't want to include
7576 updateStream: api.sbot.pull.stream(sbot => sbot.patchwork.latest({ids: [id]})),
7677 bumpFilter: function (msg) {
78+ // this needs to match the logic in sbot/roots so that we display the
79+ // correct bump explainations
7780 if (msg.value && msg.value.content && typeof msg.value.content === 'object') {
7881 var type = msg.value.content.type
7982 if (type === 'vote') return false
8083
sbot/roots.jsView
@@ -4,8 +4,9 @@
44 var pullCat = require('pull-cat')
55 var HLRU = require('hashlru')
66 var extend = require('xtend')
77 var normalizeChannel = require('../lib/normalize-channel')
8+var Defer = require('pull-defer')
89
910 // HACK: pull it out of patchcore
1011 var getRoot = require('patchcore/message/sync/root').create().message.sync.root
1112
@@ -24,132 +25,108 @@
2425 var cache = HLRU(100)
2526
2627 return {
2728 latest: function ({ids = [ssb.id]}) {
28- var filter = null
29- return pull(
30- // READ INDEX
31- index.read({old: false}),
29+ var stream = Defer.source()
30+ getFilter((err, filter) => {
31+ if (err) return stream.abort(err)
32+ stream.resolve(pull(
33+ index.read({old: false}),
3234
33- // LOAD FILTERS
34- pull.asyncMap((item, cb) => {
35- if (!filter) {
36- // pause stream until filters have loaded
37- getFilter((err, result) => {
38- if (err) return cb(err)
39- filter = result
40- cb(null, item)
41- })
42- } else {
43- cb(null, item)
44- }
45- }),
35+ // BUMP FILTER
36+ pull.filter(item => {
37+ if (filter && item.value && item.value) {
38+ var filterResult = filter(ids, item.value)
39+ if (filterResult) {
40+ item.value.filterResult = filterResult
41+ return true
42+ }
43+ }
44+ }),
4645
47- // BUMP FILTER
48- pull.filter(item => {
49- if (filter && item.value && item.value) {
50- return filter(ids, item.value)
51- }
52- }),
46+ // LOOKUP AND ADD ROOTS
47+ LookupRoots(),
5348
54- // LOOKUP ROOTS
55- pull.asyncMap((item, cb) => {
56- var msg = item.value
57- var key = item.key[1]
58- if (key === msg.key) {
59- // already a root
60- cb(null, msg)
61- }
62- getThruCache(key, (_, value) => {
63- cb(null, extend(msg, {
64- root: value
65- }))
49+ // FILTER ROOTS
50+ pull.filter(item => {
51+ var root = item.root || item
52+ if (filter && root && root.value) {
53+ return checkReplyForcesDisplay(item) || filter(ids, root)
54+ }
6655 })
67- }),
68-
69- // FILTER
70- pull.filter(item => {
71- var root = item.root || item
72- if (filter && root && root.value) {
73- return filter(ids, root)
74- }
75- })
76- )
56+ ))
57+ })
58+ return stream
7759 },
78- read: function ({ids = [ssb.id], reverse, live, old, limit, lt, gt}) {
79- var opts = {reverse, live, old}
8060
61+ read: function ({ids = [ssb.id], reverse, limit, lt, gt}) {
62+ var opts = {reverse, old: true}
63+
8164 // handle markers passed in to lt / gt
8265 if (lt && typeof lt.timestamp === 'number') lt = lt.timestamp
8366 if (gt && typeof gt.timestamp === 'number') gt = gt.timestamp
8467 if (typeof lt === 'number') opts.lt = [lt]
8568 if (typeof gt === 'number') opts.gt = [gt]
8669
8770 var seen = new Set()
71+ var included = new Set()
8872 var marker = {marker: true, timestamp: null}
89- var filter = null
9073
91- var stream = pull(
74+ var stream = Defer.source()
9275
93- // READ ROOTS
94- index.read(opts),
76+ getFilter((err, filter) => {
77+ if (err) return stream.abort(err)
78+ stream.resolve(pull(
79+ // READ ROOTS INDEX
80+ index.read(opts),
9581
96- // LOAD FILTERS
97- pull.asyncMap((item, cb) => {
98- if (!filter) {
99- // pause stream until filters have loaded
100- getFilter((err, result) => {
101- if (err) return cb(err)
102- filter = result
103- cb(null, item)
104- })
105- } else {
106- cb(null, item)
107- }
108- }),
82+ // BUMP FILTER
83+ pull.filter(item => {
84+ // keep track of latest timestamp
85+ marker.timestamp = item.key[0]
10986
110- // BUMP FILTER
111- pull.filter(item => {
112- if (filter && item.value && item.value.value) {
113- return filter(ids, item.value)
114- }
115- }),
87+ if (filter && item.value && item.value) {
88+ var filterResult = filter(ids, item.value)
89+ if (filterResult) {
90+ item.value.filterResult = filterResult
91+ return true
92+ }
93+ }
94+ }),
11695
117- // MAP ROOTS
118- pull.map(item => {
119- if (item.sync) return item
120- marker.timestamp = item.key[0]
121- return item.key[1]
122- }),
96+ // LOOKUP AND ADD ROOTS
97+ LookupRoots(),
12398
124- // UNIQUE
125- pull.filter(item => {
126- if (old === false) return true // don't filter live stream
127- if (item && item.sync) {
128- return true
129- } else if (typeof item === 'string') {
130- if (!seen.has(item)) {
131- seen.add(item)
132- return true
99+ // FILTER ROOTS
100+ pull.filter(item => {
101+ var root = item.root || item
102+
103+ // skip this item if it has already been included
104+ if (!included.has(root.key) && filter && root && root.value) {
105+ if (checkReplyForcesDisplay(item)) {
106+ // include this item if it has matching tags or the author is you
107+ included.add(root.key)
108+ return true
109+ } else if (!seen.has(root.key)) {
110+ seen.add(root.key)
111+ var result = filter(ids, root)
112+ if (result) {
113+ // include this item if we have not yet seen it and the root filter passes
114+ included.add(root.key)
115+ return true
116+ }
117+ }
133118 }
134- }
135- }),
119+ }),
136120
137- // LOOKUP (with cache)
138- pull.asyncMap((item, cb) => {
139- if (item.sync) return cb(null, item)
140- var key = item
141- getThruCache(key, cb)
142- }),
121+ // MAP ROOT ITEMS
122+ pull.map(item => {
123+ var root = item.root || item
124+ return root
125+ })
126+ ))
127+ })
143128
144- // ROOT FILTER
145- pull.filter(msg => {
146- if (filter && msg.value && !getRoot(msg)) {
147- return filter(ids, msg)
148- }
149- })
150- )
151-
152129 // TRUNCATE
153130 if (typeof limit === 'number') {
154131 var count = 0
155132 return pullCat([
@@ -196,26 +173,69 @@
196173 cb(null, function (ids, msg) {
197174 var type = msg.value.content.type
198175 if (type === 'vote') return false // filter out likes
199176 var matchesChannel = (type !== 'channel' && checkChannel(subscriptions, ids, msg.value.content.channel))
200- var matchesTag = checkTag(subscriptions, ids, msg.value.content.mentions)
201- return ids.includes(msg.value.author) || matchesChannel || matchesTag || checkFollowing(friends, ids, msg.value.author)
177+ var matchingTags = getMatchingTags(subscriptions, ids, msg.value.content.mentions)
178+ var isYours = ids.includes(msg.value.author)
179+ var mentionsYou = getMentionsYou(ids, msg.value.content.mentions)
180+ var following = checkFollowing(friends, ids, msg.value.author)
181+ if (isYours || matchesChannel || matchingTags.length || following || mentionsYou) {
182+ return {
183+ matchingTags, matchesChannel, isYours, following, mentionsYou
184+ }
185+ }
202186 })
203187 })
204188 })
205189 }
190+
191+ function LookupRoots () {
192+ return pull.asyncMap((item, cb) => {
193+ var msg = item.value
194+ var key = item.key[1]
195+ if (key === msg.key) {
196+ // already a root
197+ return cb(null, msg)
198+ }
199+ getThruCache(key, (_, value) => {
200+ cb(null, extend(msg, {
201+ root: value
202+ }))
203+ })
204+ })
205+ }
206206 }
207207
208-function checkTag (lookup, ids, mentions) {
208+function getMatchingTags (lookup, ids, mentions) {
209209 if (Array.isArray(mentions)) {
210- return mentions.some((mention) => {
210+ return mentions.reduce((result, mention) => {
211211 if (mention && typeof mention.link === 'string' && mention.link.startsWith('#')) {
212- return checkChannel(lookup, ids, mention.link.slice(1))
212+ if (checkChannel(lookup, ids, mention.link.slice(1))) {
213+ result.push(normalizeChannel(mention.link.slice(1)))
214+ }
213215 }
216+ return result
217+ }, [])
218+ }
219+ return []
220+}
221+
222+function getMentionsYou (ids, mentions) {
223+ if (Array.isArray(mentions)) {
224+ return mentions.some((mention) => {
225+ if (mention && typeof mention.link === 'string') {
226+ return ids.includes(mention.link)
227+ }
214228 })
215229 }
216230 }
217231
232+function checkReplyForcesDisplay (item) {
233+ var filterResult = item.filterResult || {}
234+ var matchesTags = filterResult.matchingTags && !!filterResult.matchingTags.length
235+ return matchesTags || filterResult.isYours || filterResult.mentionsYou
236+}
237+
218238 function checkFollowing (lookup, ids, target) {
219239 // TODO: rewrite contacts index (for some reason the order is different)
220240 if (!lookup) return false
221241 // HACK: only lookup the first ID until a method is added to ssb-friends to

Built with git-ssb-web