Files: 06ded70b47c2b7b6dbd436a59f532f6caff0e67c / lib / depject / app / html / search.js
2900 bytesRaw
1 | const h = require('mutant/h') |
2 | const nest = require('depnest') |
3 | const addSuggest = require('suggest-box') |
4 | const ssbUri = require('ssb-uri') |
5 | const electron = require('electron') |
6 | |
7 | exports.needs = nest({ |
8 | 'profile.async.suggest': 'first', |
9 | 'channel.async.suggest': 'first', |
10 | 'intl.sync.i18n': 'first', |
11 | 'keys.sync.id': 'first' |
12 | }) |
13 | |
14 | exports.gives = nest('app.html.search') |
15 | |
16 | const pages = ['/public', '/private', '/mentions', '/all', '/gatherings', '/participating', '/attending-gatherings', '/profile'] |
17 | |
18 | exports.create = function (api) { |
19 | const i18n = api.intl.sync.i18n |
20 | return nest('app.html.search', function (setView) { |
21 | const getProfileSuggestions = api.profile.async.suggest() |
22 | const getChannelSuggestions = api.channel.async.suggest() |
23 | const searchBox = h('input.search', { |
24 | type: 'search', |
25 | title: i18n('Search for word, @feedId, #channel or %msgId\nYou can also add author:@id or is:private for more filtering'), |
26 | placeholder: i18n('word, @key, #channel'), |
27 | 'ev-suggestselect': (ev) => { |
28 | setView(ev.detail.id) |
29 | searchBox.value = ev.detail.id |
30 | }, |
31 | 'ev-keydown': (ev) => { |
32 | if (ev.key === 'Enter') { |
33 | doSearch() |
34 | ev.preventDefault() |
35 | } |
36 | } |
37 | }) |
38 | electron.ipcRenderer.on('activateSearch', () => { |
39 | searchBox.focus() |
40 | searchBox.select() // should handle selecting everything in the box |
41 | }) |
42 | |
43 | setImmediate(() => { |
44 | addSuggest(searchBox, (inputText, cb) => { |
45 | if (inputText[0] === '@') { |
46 | getProfileSuggestions(inputText.slice(1), cb) |
47 | } else if (inputText[0] === '#') { |
48 | getChannelSuggestions(inputText.slice(1), cb) |
49 | } else if (inputText[0] === '/') { |
50 | cb(null, getPageSuggestions(inputText)) |
51 | } |
52 | }, { cls: 'SuggestBox' }) |
53 | }) |
54 | |
55 | return searchBox |
56 | |
57 | function doSearch () { |
58 | const prefixes = ['/', '?', '@', '#', '%', 'ssb:'] |
59 | const value = searchBox.value.trim() |
60 | |
61 | if (prefixes.some(p => value.startsWith(p))) { |
62 | if (value.startsWith('@') && value.length < 30) { |
63 | // probably not a key |
64 | } else if (value.startsWith('ssb:')) { |
65 | try { |
66 | setView(ssbUri.toSigilLink(value)) |
67 | } catch (e) { |
68 | // not a URI |
69 | } |
70 | } else if (value.length > 2) { |
71 | setView(value) |
72 | } |
73 | } else if (value.trim()) { |
74 | if (value.length > 2) { |
75 | setView(`?${value.trim()}`) |
76 | } |
77 | } |
78 | } |
79 | |
80 | function getPageSuggestions (input) { |
81 | return pages.sort().filter(p => p.startsWith(input.toLowerCase())).map(p => { |
82 | if (p !== '/profile') { |
83 | return { |
84 | id: p, |
85 | value: p, |
86 | title: p |
87 | } |
88 | } |
89 | const id = api.keys.sync.id() |
90 | return { |
91 | id: id, |
92 | value: '/profile', |
93 | title: '/profile' |
94 | } |
95 | }) |
96 | } |
97 | }) |
98 | } |
99 |
Built with git-ssb-web