-
Notifications
You must be signed in to change notification settings - Fork 341
/
Copy pathomnibar.ts
157 lines (135 loc) · 5.06 KB
/
omnibar.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import debounce from 'lodash/fp/debounce'
import escapeHtml from 'lodash/fp/escape'
import urlRegex from 'url-regex'
import qs from 'query-string'
import type { Browser } from 'webextension-polyfill'
import shortUrl from 'src/util/short-url'
import extractTimeFiltersFromQuery from 'src/util/nlp-time-filter'
import { OVERVIEW_URL } from './constants'
import checkBrowser from './util/check-browser'
import { conditionallySkipToTimeFilter } from './overview/onboarding/utils'
import {
diffTimestamp,
formatTimestamp,
} from '@worldbrain/memex-common/lib/utils/date-time'
import type { BackgroundModules } from './background-script/setup'
export interface OmnibarDeps {
browserAPIs: Pick<Browser, 'tabs' | 'omnibox'>
bgModules: Pick<BackgroundModules, 'search'>
}
function formatTime(timestamp, showTime) {
const inLastSevenDays = diffTimestamp(Date.now(), timestamp, 'days') <= 7
if (showTime) {
return inLastSevenDays
? `🕒 ${formatTimestamp(timestamp, 'HH:mm a ddd')}`
: `🕒 ${formatTimestamp(timestamp, 'HH:mm a D/M/YYYY')}`
}
return inLastSevenDays
? formatTimestamp(timestamp, 'ddd')
: formatTimestamp(timestamp, 'D/M/YYYY')
}
const pageToSuggestion = (timeFilterApplied) => (doc) => {
const url = escapeHtml(shortUrl(doc.url))
const title = escapeHtml(doc.title)
const time = formatTime(doc.displayTime, timeFilterApplied)
return {
content: doc.url,
description:
checkBrowser() === 'firefox'
? `${url} ${title} - ${time}`
: `<url>${url}</url> <dim>${title}</dim> - ${time}`,
}
}
export async function setupOmnibar(deps: OmnibarDeps) {
const setOmniboxMessage = (description: string): void =>
deps.browserAPIs.omnibox.setDefaultSuggestion({
description,
})
let currentQuery: string
let latestResolvedQuery: string
async function makeSuggestion(
query: string,
suggest: (entries: any[]) => void,
) {
currentQuery = query
// Show no suggestions if there is no query.
if (query.trim() === '') {
setOmniboxMessage(
'Enter keywords or start with # to filter by tags',
)
suggest([])
latestResolvedQuery = query
return
}
setOmniboxMessage('Searching...(press enter to search in Dashboard)')
const queryForOldSuggestions = latestResolvedQuery
const queryFilters = extractTimeFiltersFromQuery(query)
const limit = 5
const searchResults = await deps.bgModules.search.unifiedSearch({
untilWhen: queryFilters.to,
fromWhen: queryFilters.from,
query: queryFilters.query,
filterByDomains: [],
filterByListIds: [],
limit,
skip: 0,
})
// A subsequent search could have already started and finished while we
// were busy searching, so we ensure we do not overwrite its results.
if (
currentQuery !== query &&
latestResolvedQuery !== queryForOldSuggestions
) {
return
}
if (!searchResults.docs.length) {
setOmniboxMessage('No results found for this query.')
} else if (!searchResults.resultsExhausted) {
setOmniboxMessage('Found more results - press ENTER to view ALL .')
}
const suggestions = searchResults.docs
.slice(0, limit)
.map(pageToSuggestion(queryFilters.from || queryFilters.to))
suggest(suggestions)
latestResolvedQuery = query
}
/**
* @param {string} text The omnibar text input.
* @returns {string} Overview page URL with `text` formatted as query string params.
*/
const formOverviewQuery = (text) => {
const queryFilters = extractTimeFiltersFromQuery(text)
const queryParams = qs.stringify(queryFilters)
return `${OVERVIEW_URL}?${queryParams}`
}
const acceptInput = async (text, disposition) => {
// Either go to URL if input is valid URL, else form query for overview search using input terms
const url = urlRegex().test(text) ? text : formOverviewQuery(text)
// Skips to time filter in Onboarding Power Search workflow if user queries during demo
await conditionallySkipToTimeFilter()
switch (disposition) {
case 'currentTab':
deps.browserAPIs.tabs.update({
url,
})
break
case 'newForegroundTab':
deps.browserAPIs.tabs.create({
url,
})
break
case 'newBackgroundTab':
deps.browserAPIs.tabs.create({
url,
active: false,
})
break
default:
break
}
}
deps.browserAPIs.omnibox.onInputChanged.addListener(
debounce(500)(makeSuggestion),
)
deps.browserAPIs.omnibox.onInputEntered.addListener(acceptInput)
}