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