Commit 49322eb6bd415983d6524e48fa5447d21795f6f6
fully remove pull-next-step, remove /search fallback to linear search (ssb-search only)
mixmix committed on 8/1/2018, 11:52:24 PMParent: 22980df7086fb15c08c87bb6c2d59fa79296d840
Files changed
app/page/notifications.js | changed |
app/page/private.js | changed |
app/page/search.js | changed |
app/page/notifications.js | ||
---|---|---|
@@ -1,9 +1,9 @@ | ||
1 | 1 … | const nest = require('depnest') |
2 | 2 … | const { h } = require('mutant') |
3 | 3 … | const pull = require('pull-stream') |
4 | 4 … | const Scroller = require('pull-scroll') |
5 | -const next = require('pull-next-step') | |
5 … | +const next = require('pull-next-query') | |
6 | 6 … | |
7 | 7 … | exports.gives = nest({ |
8 | 8 … | 'app.html.menuItem': true, |
9 | 9 … | 'app.page.notifications': true |
@@ -12,12 +12,13 @@ | ||
12 | 12 … | exports.needs = nest({ |
13 | 13 … | 'app.html.filter': 'first', |
14 | 14 … | 'app.html.scroller': 'first', |
15 | 15 … | 'app.sync.goTo': 'first', |
16 | - 'feed.pull.mentions': 'first', | |
17 | 16 … | 'feed.pull.public': 'first', |
18 | 17 … | 'keys.sync.id': 'first', |
19 | - 'message.html.render': 'first' | |
18 … | + 'message.html.render': 'first', | |
19 … | + 'message.sync.isBlocked': 'first', | |
20 … | + 'sbot.pull.stream': 'first' | |
20 | 21 … | }) |
21 | 22 … | |
22 | 23 … | exports.create = function (api) { |
23 | 24 … | return nest({ |
@@ -32,30 +33,22 @@ | ||
32 | 33 … | }, '/notifications') |
33 | 34 … | } |
34 | 35 … | |
35 | 36 … | function notificationsPage (location) { |
36 | - const id = api.keys.sync.id() | |
37 | - | |
38 | 37 … | const { filterMenu, filterDownThrough, filterUpThrough, resetFeed } = api.app.html.filter(draw) |
39 | 38 … | const { container, content } = api.app.html.scroller({ prepend: [ filterMenu ] }) |
40 | - const removeMyMessages = () => pull.filter(msg => msg.value.author !== id) | |
41 | - const removePrivateMessages = () => pull.filter(msg => msg.value.private !== true) | |
42 | 39 … | |
43 | 40 … | function draw () { |
44 | 41 … | resetFeed({ container, content }) |
45 | 42 … | |
46 | 43 … | pull( |
47 | - next(api.feed.pull.mentions(id), {old: false, limit: 100, property: ['timestamp']}), | |
48 | - removeMyMessages(), | |
49 | - removePrivateMessages(), | |
44 … | + pullMentions({old: false, live: true}), | |
50 | 45 … | filterDownThrough(), |
51 | 46 … | Scroller(container, content, api.message.html.render, true, false) |
52 | 47 … | ) |
53 | 48 … | |
54 | 49 … | pull( |
55 | - next(api.feed.pull.mentions(id), {reverse: true, limit: 100, live: false, property: ['timestamp']}), | |
56 | - removeMyMessages(), | |
57 | - removePrivateMessages(), | |
50 … | + pullMentions({reverse: true, live: false}), | |
58 | 51 … | filterUpThrough(), |
59 | 52 … | Scroller(container, content, api.message.html.render, false, false) |
60 | 53 … | ) |
61 | 54 … | } |
@@ -63,5 +56,33 @@ | ||
63 | 56 … | |
64 | 57 … | container.title = '/notifications' |
65 | 58 … | return container |
66 | 59 … | } |
60 … | + | |
61 … | + // NOTE - this currently hits mentions AND the patchwork message replies | |
62 … | + function pullMentions (opts) { | |
63 … | + const query = [{ | |
64 … | + $filter: { | |
65 … | + dest: api.keys.sync.id(), | |
66 … | + timestamp: {$gt: 0}, | |
67 … | + value: { | |
68 … | + author: {$ne: api.keys.sync.id()}, // not my messages! | |
69 … | + private: {$ne: true} // not private mentions | |
70 … | + } | |
71 … | + } | |
72 … | + }] | |
73 … | + | |
74 … | + const _opts = Object.assign({ | |
75 … | + query, | |
76 … | + limit: 100, | |
77 … | + index: 'DTA' | |
78 … | + }, opts) | |
79 … | + console.log(_opts) | |
80 … | + | |
81 … | + return api.sbot.pull.stream(server => { | |
82 … | + return pull( | |
83 … | + next(server.backlinks.read, _opts, ['timestamp']), | |
84 … | + pull.filter(m => !api.message.sync.isBlocked(m)) | |
85 … | + ) | |
86 … | + }) | |
87 … | + } | |
67 | 88 … | } |
app/page/private.js | |||
---|---|---|---|
@@ -2,9 +2,9 @@ | |||
2 | 2 … | const { h } = require('mutant') | |
3 | 3 … | const pull = require('pull-stream') | |
4 | 4 … | const Scroller = require('pull-scroll') | |
5 | 5 … | const ref = require('ssb-ref') | |
6 | -const next = require('pull-next-step') | ||
6 … | +const next = require('pull-next-query') | ||
7 | 7 … | ||
8 | 8 … | exports.gives = nest({ | |
9 | 9 … | 'app.html.menuItem': true, | |
10 | 10 … | 'app.page.private': true | |
@@ -56,15 +56,15 @@ | |||
56 | 56 … | function draw () { | |
57 | 57 … | resetFeed({ container, content }) | |
58 | 58 … | ||
59 | 59 … | pull( | |
60 | - next(api.feed.pull.private, {old: false, limit: 100}, ['value', 'timestamp']), | ||
60 … | + pullPrivate({old: false, live: true}), | ||
61 | 61 … | filterDownThrough(), | |
62 | 62 … | Scroller(container, content, api.message.html.render, true, false) | |
63 | 63 … | ) | |
64 | 64 … | ||
65 | 65 … | pull( | |
66 | - next(api.feed.pull.private, {reverse: true, limit: 100, live: false}, ['value', 'timestamp']), | ||
66 … | + pullPrivate({reverse: true}), | ||
67 | 67 … | filterUpThrough(), | |
68 | 68 … | Scroller(container, content, api.message.html.render, false, false) | |
69 | 69 … | ) | |
70 | 70 … | } | |
@@ -72,5 +72,23 @@ | |||
72 | 72 … | ||
73 | 73 … | container.title = '/private' | |
74 | 74 … | return container | |
75 | 75 … | } | |
76 … | + | ||
77 … | + function pullPrivate (opts) { | ||
78 … | + const query = [{ | ||
79 … | + $filter: { | ||
80 … | + timestamp: {$gt: 0}, | ||
81 … | + value: { | ||
82 … | + content: { | ||
83 … | + recps: {$truthy: true} | ||
84 … | + } | ||
85 … | + } | ||
86 … | + } | ||
87 … | + }] | ||
88 … | + | ||
89 … | + const _opts = Object.assign({ query, limit: 100 }, opts) | ||
90 … | + | ||
91 … | + return next(api.feed.pull.private, _opts, ['timestamp']) | ||
92 … | + } | ||
76 | 93 … | } | |
94 … | + |
app/page/search.js | ||
---|---|---|
@@ -1,8 +1,8 @@ | ||
1 | 1 … | const nest = require('depnest') |
2 | -const { h, Struct, Value, when, computed } = require('mutant') | |
2 … | +const { h, Struct, Value } = require('mutant') | |
3 | 3 … | const pull = require('pull-stream') |
4 | -const next = require('pull-next-step') | |
4 … | +const next = require('pull-next-query') | |
5 | 5 … | const Scroller = require('pull-scroll') |
6 | 6 … | const TextNodeSearcher = require('text-node-searcher') |
7 | 7 … | |
8 | 8 … | exports.gives = nest('app.page.search') |
@@ -16,130 +16,42 @@ | ||
16 | 16 … | }) |
17 | 17 … | |
18 | 18 … | var whitespace = /\s+/ |
19 | 19 … | |
20 | -function andSearch (terms, inputs) { | |
21 | - for (var i = 0; i < terms.length; i++) { | |
22 | - var match = false | |
23 | - for (var j = 0; j < inputs.length; j++) { | |
24 | - if (terms[i].test(inputs[j])) match = true | |
25 | - } | |
26 | - // if a term was not matched by anything, filter this one | |
27 | - if (!match) return false | |
28 | - } | |
29 | - return true | |
30 | -} | |
31 | - | |
32 | -function searchFilter (terms) { | |
33 | - return function (msg) { | |
34 | - var c = msg && msg.value && msg.value.content | |
35 | - return c && ( | |
36 | - msg.key === terms[0] || | |
37 | - andSearch(terms.map(function (term) { | |
38 | - return new RegExp('\\b' + term + '\\b', 'i') | |
39 | - }), [c.text, c.name, c.title]) | |
40 | - ) | |
41 | - } | |
42 | -} | |
43 | - | |
44 | -function createOrRegExp (ary) { | |
45 | - return new RegExp(ary.map(function (e) { | |
46 | - return '\\b' + e + '\\b' | |
47 | - }).join('|'), 'i') | |
48 | -} | |
49 | - | |
50 | -function highlight (el, query) { | |
51 | - var searcher = new TextNodeSearcher({container: el}) | |
52 | - searcher.query = query | |
53 | - searcher.highlight() | |
54 | - return el | |
55 | -} | |
56 | - | |
57 | -function fallback (createReader) { | |
58 | - var fallbackRead | |
59 | - return function (read) { | |
60 | - return function (abort, cb) { | |
61 | - read(abort, function next (end, data) { | |
62 | - if (end && createReader && (fallbackRead = createReader(end))) { | |
63 | - createReader = null | |
64 | - read = fallbackRead | |
65 | - read(abort, next) | |
66 | - } else { | |
67 | - cb(end, data) | |
68 | - } | |
69 | - }) | |
70 | - } | |
71 | - } | |
72 | -} | |
73 | - | |
74 | 20 … | exports.create = function (api) { |
75 | 21 … | return nest('app.page.search', searchPage) |
76 | 22 … | |
77 | 23 … | function searchPage (location) { |
78 | 24 … | const query = location.query.trim() |
79 | 25 … | |
80 | - var queryTerms = query.split(whitespace) | |
81 | - var matchesQuery = searchFilter(queryTerms) | |
82 | - | |
83 | 26 … | const search = Struct({ |
84 | - isLinear: Value(false), | |
85 | - linear: Struct({ | |
86 | - checked: Value(0) | |
87 | - }), | |
88 | 27 … | fulltext: Struct({ |
89 | 28 … | isDone: Value(false) |
90 | 29 … | }), |
91 | 30 … | matches: Value(0) |
92 | 31 … | }) |
93 | - const hasNoFulltextMatches = computed([search.fulltext.isDone, search.matches], | |
94 | - (done, matches) => done && matches === 0) | |
95 | 32 … | |
96 | 33 … | const searchHeader = h('Search', [ |
97 | - h('header', h('h1', query)), | |
98 | - when(search.isLinear, | |
99 | - h('section.details', [ | |
100 | - h('div.searched', ['Searched: ', search.linear.checked]), | |
101 | - h('div.matches', [search.matches, ' matches']) | |
102 | - ]), | |
103 | - h('section.details', [ | |
104 | - h('div.searched'), | |
105 | - when(hasNoFulltextMatches, h('div.matches', 'No matches')) | |
106 | - ]) | |
107 | - ) | |
34 … | + h('header', h('h1', query)) | |
108 | 35 … | ]) |
109 | - const { filterMenu, filterDownThrough, filterUpThrough, resetFeed } = api.app.html.filter(draw) | |
36 … | + const { filterMenu, filterDownThrough, resetFeed } = api.app.html.filter(draw) | |
110 | 37 … | const { container, content } = api.app.html.scroller({ prepend: [searchHeader, filterMenu] }) |
111 | 38 … | |
112 | 39 … | function renderMsg (msg) { |
113 | 40 … | var el = api.message.html.render(msg) |
41 … | + var queryTerms = query.split(whitespace) | |
42 … | + | |
114 | 43 … | highlight(el, createOrRegExp(queryTerms)) |
115 | 44 … | return el |
116 | 45 … | } |
117 | 46 … | |
118 | 47 … | function draw () { |
119 | 48 … | resetFeed({ container, content }) |
120 | 49 … | |
50 … | + // TODO figure out how to step on kinda orderless search results | |
121 | 51 … | pull( |
122 | - api.sbot.pull.log({old: false}), | |
123 | - pull.filter(matchesQuery), | |
124 | - filterUpThrough(), | |
125 | - Scroller(container, content, renderMsg, true, false) | |
126 | - ) | |
127 | - | |
128 | - pull( | |
129 | - api.sbot.pull.stream(sbot => next(sbot.search.query, { query, limit: 500 })), | |
130 | - fallback((err) => { | |
131 | - if (err === true) { | |
132 | - search.fulltext.isDone.set(true) | |
133 | - } else if (/^no source/.test(err.message)) { | |
134 | - search.isLinear.set(true) | |
135 | - return pull( | |
136 | - next(api.sbot.pull.log, {reverse: true, limit: 500, live: false}), | |
137 | - pull.through(() => search.linear.checked.set(search.linear.checked() + 1)), | |
138 | - pull.filter(matchesQuery) | |
139 | - ) | |
140 | - } | |
141 | - }), | |
52 … | + // api.sbot.pull.stream(sbot => next(sbot.search.query, { query, limit: 500 })), | |
53 … | + api.sbot.pull.stream(sbot => sbot.search.query({ query, limit: 500 })), | |
142 | 54 … | filterDownThrough(), |
143 | 55 … | pull.through(() => search.matches.set(search.matches() + 1)), |
144 | 56 … | Scroller(container, content, renderMsg, false, false) |
145 | 57 … | ) |
@@ -150,4 +62,18 @@ | ||
150 | 62 … | container.title = '?' + query |
151 | 63 … | return container |
152 | 64 … | } |
153 | 65 … | } |
66 … | + | |
67 … | +function createOrRegExp (ary) { | |
68 … | + return new RegExp(ary.map(function (e) { | |
69 … | + return '\\b' + e + '\\b' | |
70 … | + }).join('|'), 'i') | |
71 … | +} | |
72 … | + | |
73 … | +function highlight (el, query) { | |
74 … | + var searcher = new TextNodeSearcher({container: el}) | |
75 … | + searcher.query = query | |
76 … | + searcher.highlight() | |
77 … | + return el | |
78 … | +} | |
79 … | + |
Built with git-ssb-web