Skip to content

Commit f0ed2e0

Browse files
feat: add = omnibox handler, wire it up to reopening in container
1 parent 0da7aa0 commit f0ed2e0

File tree

6 files changed

+88
-0
lines changed

6 files changed

+88
-0
lines changed

src/_locales/dict.common.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2780,6 +2780,13 @@ export const commonTranslations: Translations = {
27802780
zh_CN: '扩展没有在隐私窗口中运行的权限',
27812781
zh_TW: '擴充套件沒有於隱私視窗中執行的權限',
27822782
},
2783+
2784+
// ---
2785+
// -- Omnibox
2786+
// -
2787+
'omnibox.container_switch.prompt': {
2788+
en: 'Type the name of the container you want for this tab…',
2789+
},
27832790
}
27842791

27852792
if (!window.translations) window.translations = commonTranslations

src/bg/background.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { Menu } from 'src/services/menu'
1717
import { WebReq } from 'src/services/web-req'
1818
import { Sync } from 'src/services/_services'
1919
import { Styles } from 'src/services/styles'
20+
import * as omnibox from 'src/services/omnibox'
2021

2122
void (async function main() {
2223
Info.setInstanceType(InstanceType.bg)
@@ -119,6 +120,8 @@ void (async function main() {
119120
if (newVersion <= currentVersion) browser.runtime.reload()
120121
})
121122

123+
omnibox.setupListeners()
124+
122125
Logs.info(`Init end: ${performance.now() - ts}ms`)
123126
})()
124127

src/manifest.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,5 +498,8 @@
498498
},
499499
"background": {
500500
"page": "bg/background.html"
501+
},
502+
"omnibox": {
503+
"keyword": "="
501504
}
502505
}

src/services/omnibox.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { Containers } from 'src/services/containers'
2+
import { translate } from 'src/dict'
3+
import * as IPC from 'src/services/ipc'
4+
import * as Logs from 'src/services/logs'
5+
import { Tabs } from 'src/services/tabs.bg'
6+
import { Windows } from 'src/services/windows'
7+
import { Container, InstanceType } from 'src/types'
8+
9+
function setupListeners() {
10+
browser.omnibox.setDefaultSuggestion({
11+
description: translate('omnibox.container_switch.prompt'),
12+
})
13+
14+
function matchContainers(input: string): Container[] {
15+
// TODO: order by score of some sort?
16+
// TODO: At the very least, put an exact match first.
17+
// TODO: Validate we want Sidebery records, not Firefox records.
18+
return Object.values(Containers.reactive.byId).filter(container =>
19+
container.name.toLowerCase().includes(input.toLowerCase())
20+
)
21+
}
22+
23+
browser.omnibox.onInputChanged.addListener(async (input, suggest) => {
24+
const suggestions = matchContainers(input).map(ctx => ({
25+
content: ctx.name,
26+
description: ctx.name,
27+
deletable: false,
28+
}))
29+
suggest(suggestions)
30+
})
31+
32+
browser.omnibox.onInputEntered.addListener(async (input, _disposition) => {
33+
// NOTE: We're semantically _re-opening_ tabs, which conflicts with a disposition. Ignore it.
34+
35+
if (!Windows.lastFocusedWinId) {
36+
Logs.err('omnibox: no last focused window ID found')
37+
return
38+
}
39+
40+
const matchingContainers = matchContainers(input)
41+
if (matchingContainers.length <= 0) {
42+
Logs.warn('omnibox: no matching containers found')
43+
return
44+
}
45+
const firstMatchingContainer = matchingContainers[0]
46+
47+
const sidebarTabs = await Tabs.getSidebarTabs(Windows.lastFocusedWinId)
48+
if (!sidebarTabs) {
49+
Logs.err('omnibox: no sidebar tabs found for last focused window ID')
50+
return
51+
}
52+
53+
const con = IPC.getConnection(InstanceType.sidebar, Windows.lastFocusedWinId)
54+
if ((con?.localPort && con.localPort.error) || (con?.remotePort && con.remotePort.error)) {
55+
Logs.err('need to fall back to creating tabs by hand')
56+
return
57+
}
58+
59+
const activeTabs = sidebarTabs.filter(tab => tab.active)
60+
try {
61+
await IPC.sidebar(
62+
Windows.lastFocusedWinId,
63+
'reopenInContainer',
64+
activeTabs.map(tab => tab.id),
65+
firstMatchingContainer.id
66+
)
67+
} catch {
68+
Logs.warn('failed to re-open tabs', activeTabs, 'in container', firstMatchingContainer)
69+
}
70+
})
71+
}
72+
73+
export { setupListeners }

src/sidebar/sidebar.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ async function main(): Promise<void> {
4343
getTabsTreeData: Tabs.getTabsTreeData,
4444
moveTabsToThisWin: Tabs.moveToThisWin,
4545
openTabs: Tabs.open,
46+
reopenInContainer: Tabs.reopenInContainer,
4647
handleReopening: Tabs.handleReopening,
4748
getActivePanelConfig: Sidebar.getActivePanelConfig,
4849
stopDrag: DnD.onExternalStop,

src/types/ipc.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ export type SidebarActions = {
114114

115115
moveTabsToThisWin: (tabs: Tab[], dst?: DstPlaceInfo) => Promise<boolean>
116116
openTabs: (items: ItemInfo[], dst: DstPlaceInfo) => Promise<boolean>
117+
reopenInContainer: (ids: ID[], containerId: string) => Promise<void>
117118

118119
notify: (config: Notification, timeout?: number) => void
119120
notifyAboutNewSnapshot: () => void

0 commit comments

Comments
 (0)