git ssb

16+

Dominic / patchbay



Tree: 6f4a164dcf3ceba120878c266e2f477496eb7b3e

Files: 6f4a164dcf3ceba120878c266e2f477496eb7b3e / router / html / page / search.js

4311 bytesRaw
1const nest = require('depnest')
2const { h, Struct, Value, when, computed } = require('mutant')
3const pull = require('pull-stream')
4const Scroller = require('pull-scroll')
5const TextNodeSearcher = require('text-node-searcher')
6
7const next = require('../../../junk/next-stepper')
8
9exports.gives = nest('router.html.page')
10
11exports.needs = nest({
12 'main.html.scroller': 'first',
13 'message.html.render': 'first',
14 'sbot.pull.log': 'first',
15 // sbot_fulltext_search: 'first' // TODO add to core?
16})
17
18var whitespace = /\s+/
19
20function 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
32function 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
44function createOrRegExp(ary) {
45 return new RegExp(ary.map(function (e) {
46 return '\\b'+e+'\\b'
47 }).join('|'), 'i')
48}
49
50function highlight(el, query) {
51 var searcher = new TextNodeSearcher({container: el})
52 searcher.query = query
53 searcher.highlight()
54 return el
55}
56
57function fallback(reader) {
58 var fallbackRead
59 return function (read) {
60 return function (abort, cb) {
61 read(abort, function next(end, data) {
62 if (end && reader && (fallbackRead = reader(end))) {
63 reader = null
64 read = fallbackRead
65 read(abort, next)
66 } else {
67 cb(end, data)
68 }
69 })
70 }
71 }
72}
73
74exports.create = function (api) {
75
76 return nest('router.html.page', searchPage)
77
78 function searchPage (path) {
79 if (path.match(/^[@#%\/]/)) return
80
81 var queryStr = path.replace(/^\??/, '').trim()
82 var query = queryStr.split(whitespace)
83 var matchesQuery = searchFilter(query)
84
85 const search = Struct({
86 isLinear: Value(false),
87 linear: Struct({
88 checked: Value(0)
89 }),
90 fulltext: Struct({
91 isDone: Value(false)
92 }),
93 matches: Value(0)
94 })
95 const hasNoFulltextMatches = computed([search.fulltext.isDone, search.matches],
96 (done, matches) => done && matches === 0)
97
98
99 const searchHeader = h('Search', [
100 h('header', h('h1', query.join(' '))),
101 when(search.isLinear,
102 h('section.details', [
103 h('div.searched', ['Searched: ', search.linear.checked]),
104 h('div.matches', [search.matches, ' matches'])
105 ]),
106 h('section.details', [
107 h('div.searched'),
108 when(hasNoFulltextMatches, h('div.matches', 'No matches'))
109 ])
110 )
111 ])
112 var { container, content } = api.main.html.scroller({ prepend: searchHeader })
113 container.id = path // helps tabs find this tab
114
115 function renderMsg(msg) {
116 var el = api.message.html.render(msg)
117 highlight(el, createOrRegExp(query))
118 return el
119 }
120
121 pull(
122 api.sbot.pull.log({old: false}),
123 pull.filter(matchesQuery),
124 Scroller(container, content, renderMsg, true, false)
125 )
126
127 // <Temp>
128 search.isLinear.set(true)
129 pull(
130 next(api.sbot.pull.log, {reverse: true, limit: 500, live: false}),
131 pull.through(() => search.linear.checked.set(search.linear.checked()+1)),
132 pull.filter(matchesQuery),
133 // </Temp>
134 // TODO - reinstate fulltext search
135 // pull(
136 // next(api.sbot_fulltext_search, {query: queryStr, reverse: true, limit: 500, live: false}),
137 // fallback((err) => {
138 // if (err === true) {
139 // search.fulltext.isDone.set(true)
140 // } else if (/^no source/.test(err.message)) {
141 // search.isLinear.set(true)
142 // return pull(
143 // next(api.sbot_log, {reverse: true, limit: 500, live: false}),
144 // pull.through(() => search.linear.checked.set(search.linear.checked()+1)),
145 // pull.filter(matchesQuery)
146 // )
147 // }
148 // }),
149 pull.through(() => search.matches.set(search.matches()+1)),
150 Scroller(container, content, renderMsg, false, false)
151 )
152
153 return container
154 }
155}
156
157

Built with git-ssb-web