git ssb

16+

Dominic / patchbay



Tree: 9bc144cce7f943481bbdf418bd837395b337c712

Files: 9bc144cce7f943481bbdf418bd837395b337c712 / router / html / page / search.js

4333 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 return nest('router.html.page', searchPage)
76
77 function searchPage (path) {
78 if (path.match(/^[@#%\/]/)) return
79
80 var queryStr = path.replace(/^\??/, '').trim()
81 var query = queryStr.split(whitespace)
82 var matchesQuery = searchFilter(query)
83
84 const search = Struct({
85 isLinear: Value(false),
86 linear: Struct({
87 checked: Value(0)
88 }),
89 fulltext: Struct({
90 isDone: Value(false)
91 }),
92 matches: Value(0)
93 })
94 const hasNoFulltextMatches = computed([search.fulltext.isDone, search.matches],
95 (done, matches) => done && matches === 0)
96
97 const searchHeader = h('Search', [
98 h('header', h('h1', query.join(' '))),
99 when(search.isLinear,
100 h('section.details', [
101 h('div.searched', ['Searched: ', search.linear.checked]),
102 h('div.matches', [search.matches, ' matches'])
103 ]),
104 h('section.details', [
105 h('div.searched'),
106 when(hasNoFulltextMatches, h('div.matches', 'No matches'))
107 ])
108 )
109 ])
110 var { container, content } = api.main.html.scroller({ prepend: searchHeader })
111 container.id = path // helps tabs find this tab
112
113 function renderMsg (msg) {
114 var el = api.message.html.render(msg)
115 highlight(el, createOrRegExp(query))
116 return el
117 }
118
119 pull(
120 api.sbot.pull.log({old: false}),
121 pull.filter(matchesQuery),
122 Scroller(container, content, renderMsg, true, false)
123 )
124
125 // <Temp>
126 search.isLinear.set(true)
127 pull(
128 next(api.sbot.pull.log, {reverse: true, limit: 500, live: false}),
129 pull.through(() => search.linear.checked.set(search.linear.checked() + 1)),
130 pull.filter(matchesQuery),
131 // </Temp>
132 // TODO - reinstate fulltext search
133 // pull(
134 // next(api.sbot_fulltext_search, {query: queryStr, reverse: true, limit: 500, live: false}),
135 // fallback((err) => {
136 // if (err === true) {
137 // search.fulltext.isDone.set(true)
138 // } else if (/^no source/.test(err.message)) {
139 // search.isLinear.set(true)
140 // return pull(
141 // next(api.sbot_log, {reverse: true, limit: 500, live: false}),
142 // pull.through(() => search.linear.checked.set(search.linear.checked()+1)),
143 // pull.filter(matchesQuery)
144 // )
145 // }
146 // }),
147 pull.through(() => search.matches.set(search.matches() + 1)),
148 Scroller(container, content, renderMsg, false, false)
149 )
150
151 return container
152 }
153}
154
155

Built with git-ssb-web