Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions packages/app/component-tests/browser-pane-restore.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,45 @@ story("⌘T and ⌘W follow focus: side tabs inside the side panel, session tabs
await expect(sessions).toHaveText("1")
})

story("⌘L selects the browser address from the page and the pane, and nowhere else", async ({ page }) => {
const root = page.getByTestId("browser-region-fixture")
const mod = (await page.evaluate(() => /Mac|iPhone|iPad|iPod/.test(navigator.platform))) ? "Meta" : "Control"
const outside = root.getByRole("button", { name: "Beta", exact: true })
const address = root.getByRole("combobox", { name: "Browser address", exact: true })
const editor = page.frameLocator('iframe[title="Browser page"]').getByRole("textbox", { name: "Editor page input" })

const selected = () =>
address.evaluate(
(input: HTMLInputElement) =>
document.activeElement === input &&
input.value.length > 0 &&
input.selectionStart === 0 &&
input.selectionEnd === input.value.length,
)

await expect(root.getByText("Registrations: 1", { exact: true })).toBeVisible()
await outside.click()
await root.getByRole("button", { name: "First inventory", exact: true }).click()
await expect(root.getByTestId("selected")).toHaveText(/^browser:/)

// In the main column ⌘L does not reach into the side panel.
await outside.focus()
await outside.press(`${mod}+l`)
await expect(address).not.toBeFocused()

// A focused page hands ⌘L to the pane, as it does ⌘T and ⌘W, without typing it.
await editor.click()
await editor.press(`${mod}+l`)
await expect.poll(selected).toBe(true)
await expect(editor).not.toHaveValue(/l$/)

// On the pane's own surface too.
await page.locator('#browser-panel [data-component="browser-bar"]').click({ position: { x: 2, y: 2 } })
await expect(address).not.toBeFocused()
await page.keyboard.press(`${mod}+l`)
await expect.poll(selected).toBe(true)
})

story("keeps ⌘T in the browser pane after a click on its loading surface", async ({ page }) => {
const root = page.getByTestId("browser-region-fixture")
const mod = (await page.evaluate(() => /Mac|iPhone|iPad|iPod/.test(navigator.platform))) ? "Meta" : "Control"
Expand Down
8 changes: 0 additions & 8 deletions packages/app/component-tests/browser-pane.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -535,14 +535,6 @@ story("adds the whole page to the session and keeps the draft when the button is
await expect(root.getByTestId("fixture-comments").getByRole("listitem")).toHaveText([/: Check the header layout$/])
})

story("focuses the address field when the page uses the address shortcut", async ({ page }) => {
const root = page.getByTestId("browser-pane-fixture")
await root.getByRole("button", { name: "Address shortcut", exact: true }).click()
const address = root.getByRole("combobox", { name: "Browser address", exact: true })
await expect(address).toBeFocused()
await expect(address).toHaveJSProperty("selectionEnd", "https://alpha.example/".length)
})

story("shows the page's cookies in the site information and clears them", async ({ page }) => {
const root = page.getByTestId("browser-pane-fixture")
await root.getByRole("button", { name: "Site information", exact: true }).click()
Expand Down
10 changes: 0 additions & 10 deletions packages/gui-extensions/src/browser/chromium.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,6 @@ export function createBrowserPage(
detail?: (detail: PageDetail) => void
/** The page's zoom changed, which Chromium applies to every page of the same origin in the partition. */
zoomed?: () => void
/** The user pressed the address shortcut while the page had focus. */
address?: () => void
/** Hands a browser or shell shortcut to the app window. */
shortcut?: (shortcut: PageShortcut) => void
/** The page took keyboard focus. */
Expand Down Expand Up @@ -214,14 +212,6 @@ export function createBrowserPage(
return
}

// The system browser's address shortcut. The app's own focus moves to the address field.
if (!input.shift && pageLetter(input) === "l") {
event.preventDefault()
options.address?.()

return
}

const direction = zoomKey(input)

if (!direction) return
Expand Down
1 change: 0 additions & 1 deletion packages/gui-extensions/src/browser/connection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ function fixture(strip: string[] = []) {
preview: (path) => routed.preview.push(path),
inspect: (event) => routed.inspect.push(event),
page: () => undefined,
address: () => undefined,
shortcut: () => undefined,
focused: () => undefined,
})
Expand Down
4 changes: 0 additions & 4 deletions packages/gui-extensions/src/browser/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ export function createConnection(input: {
inspect: (event: InspectEvent) => void
/** A page's icon or zoom changed. */
page: (event: PageEvent) => void
/** The user pressed the address shortcut while the page had focus. */
address: (tabID: Browser.TabID) => void
/** A focused page handed a browser or shell shortcut to the window. */
shortcut: (event: ShortcutEvent) => void
/** The user put keyboard focus in a page. */
Expand Down Expand Up @@ -162,8 +160,6 @@ export function createConnection(input: {

if (event.type === "page") return input.page(event)

if (event.type === "address") return input.address(event.tabID)

if (event.type === "shortcut") return input.shortcut(event)

if (event.type === "focused") return input.focused()
Expand Down
2 changes: 0 additions & 2 deletions packages/gui-extensions/src/browser/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ export const PaneEvent = Schema.Union([
icon: Schema.optionalKey(detail(MAX_ICON_URL).check(Schema.isStartingWith("data:image/"))),
zoom: Schema.Finite.check(Schema.isBetween({ minimum: 0.25, maximum: 5 })),
}),
// The page asked for the address field, with the platform's address shortcut.
Schema.Struct({ type: Schema.Literal("address"), tabID: Browser.TabID }),
// The user put keyboard focus in the page, outside the window's own document.
Schema.Struct({ type: Schema.Literal("focused"), tabID: Browser.TabID }),
// The page handed a browser or shell shortcut to the window, which runs it as its own key press.
Expand Down
7 changes: 5 additions & 2 deletions packages/gui-extensions/src/browser/keys.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ test("forwards browser and shell shortcuts while leaving page editing, find, rel
["mod", "w", true, "w"],
["mod", "w", false, "w"],
["mod", "\u0432", true, "w", "KeyW"],
// The address field, as in a browser.
["mod", "l", true, "l"],
["mod", "l", false, "l"],
["mod", "l", true, "l", "KeyP"],
["mod", "n", true, "n"],
["mod", "n", false, "n"],
["mod", "1", true, "1"],
Expand Down Expand Up @@ -98,15 +102,14 @@ test("forwards browser and shell shortcuts while leaving page editing, find, rel
["mod", "a", false, undefined],
["mod", "z", false, undefined],
["mod", "y", false, undefined],
// Find, reload, history, and the pane's own address, picker and zoom chords.
// Find, reload, history, and the pane's own picker and zoom chords.
["mod", "f", true, undefined],
["mod", "g", true, undefined],
["mod+shift", "G", true, undefined],
["mod", "r", true, undefined],
["mod", "r", false, undefined],
["mod", "[", true, undefined],
["mod", "]", true, undefined],
["mod", "l", true, undefined],
["mod+shift", "C", true, undefined],
["mod", "=", true, undefined],
["mod", "-", true, undefined],
Expand Down
4 changes: 2 additions & 2 deletions packages/gui-extensions/src/browser/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export type PageShortcut = {
}

// Unshifted chords with the platform's modifier that belong to the app shell or browser pane rather than the page:
// opening, closing or switching tabs, opening settings, and toggling the file tree.
const shellKeys = ["t", "w", "n", "1", "2", "3", "4", "5", "6", "7", "8", "9", ",", "\\"]
// opening, closing or switching tabs, focusing the address field, opening settings, and toggling the file tree.
const shellKeys = ["t", "w", "l", "n", "1", "2", "3", "4", "5", "6", "7", "8", "9", ",", "\\"]

// Shifted chords with the platform's modifier that belong to the app shell rather than the page: reopening a tab,
// switching side-panel tabs, toggling the side panel, opening the command palette, or running session commands. New Window and Close Window
Expand Down
14 changes: 0 additions & 14 deletions packages/gui-extensions/src/browser/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ export function createModel(ctx: SetupContext<typeof definition>) {
const live = new Map<string, Live>()
const listeners = new Map<string, (event: PaneEvent) => void>()
const inspectors = new Map<string, Set<(event: InspectEvent) => void>>()
const addressed = new Map<string, Set<(tabID: Browser.TabID) => void>>()
// Sessions where the user just opened a tab; its pane focuses the address field once the blank page shows.
const opening = new Set<string>()
// Each tab's last recorded page, so a state that repeats it does not write the history again.
Expand Down Expand Up @@ -218,7 +217,6 @@ export function createModel(ctx: SetupContext<typeof definition>) {

if (visits) history.set({ visits })
},
address: (tabID) => addressed.get(id)?.forEach((listener) => listener(tabID)),
// Only the pane on screen holds the page that had focus.
shortcut: (event) => {
if (sessions.current()?.key === id) panes()[0]?.press(event)
Expand Down Expand Up @@ -498,18 +496,6 @@ export function createModel(ctx: SetupContext<typeof definition>) {
recorded.clear()
history.set({ visits: [] })
},
/** The page asking for the address field with its shortcut. */
onAddress(session: Session, listener: (tabID: Browser.TabID) => void) {
const set = addressed.get(session.key) ?? new Set()
set.add(listener)
addressed.set(session.key, set)

return () => {
set.delete(listener)

if (!set.size) addressed.delete(session.key)
}
},
pending,
/**
* Tab IDs to list in the side panel: the desktop's inventory, limited to tabs stored in the strip. Until the first
Expand Down
8 changes: 1 addition & 7 deletions packages/gui-extensions/src/browser/pane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,16 +504,10 @@ export function createBrowserPane(input: {
if (entry.pages.has(id)) report(entry, { type: "page", tabID: id, ...value })
},
zoomed: () => entry.pages.forEach((page) => page.detail()),
address: () => {
if (!entry.pages.has(id) || entry.win.isDestroyed()) return
// The page held keyboard focus; the app's address field needs it back.
entry.win.webContents.focus()
publish(entry, { type: "address", tabID: id })
},
shortcut: (shortcut) => {
if (!entry.pages.has(id) || entry.focusedTabID !== id || entry.win.isDestroyed()) return

// As for the address shortcut: the command runs in the app, which may move focus there.
// The page held keyboard focus; the command runs in the app, which may move focus there, as ⌘L does.
if (entry.win.isFocused()) entry.win.webContents.focus()
publish(entry, { type: "shortcut", ...shortcut })
},
Expand Down
3 changes: 0 additions & 3 deletions packages/gui-extensions/src/browser/panel.fixture.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -495,9 +495,6 @@ export function mountBrowserPane(input: PaneHost) {
<button onClick={() => emit(store.session, { type: "page", tabID: current().id, icon, zoom: store.zoom })}>
Page icon
</button>
<button onClick={() => emit(store.session, { type: "address", tabID: current().id })}>
Address shortcut
</button>
</nav>
<p>Captures: {store.captures}</p>
<p>Zoom: {Math.round(store.zoom * 100)}</p>
Expand Down
11 changes: 0 additions & 11 deletions packages/gui-extensions/src/browser/panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -451,17 +451,6 @@ export default function SessionBrowserPane(props: {
),
)

// The page's address shortcut moves focus to this field when the page is the one on screen.
createKeyed(
() => props.session.key,
(sessionKey) =>
onCleanup(
props.model.onAddress({ key: sessionKey }, (tabID) => {
if (tabID === state()?.id && visible()) focusAddress()
}),
),
)

// A tab the user just opened starts in its address field, once its blank page is on screen. Syncs DOM focus.
createKeyed(
() => (visible() && empty() ? state()?.id : undefined),
Expand Down
4 changes: 2 additions & 2 deletions packages/gui-extensions/src/browser/renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ const setup: Setup<typeof definition> = (ctx) => {
}
})

// The system browser's address shortcut. While the page has focus, the page claims it and main forwards it; here it
// covers focus elsewhere in the pane. Ctrl+L focuses the composer outside the pane on Windows and Linux.
// The system browser's address shortcut, in the pane and, forwarded like mod+t and mod+w, from a page with focus.
// Ctrl+L focuses the composer outside the pane on Windows and Linux.
ctx.add(Command, (): Command | undefined => {
const pane = model()?.pane()

Expand Down
Loading