mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Fix browser keyboard lifecycle regressions
This commit is contained in:
@@ -17,6 +17,7 @@ import { resolveKeyboardFocusScope } from "@/keyboard/focus-scope";
|
||||
import {
|
||||
buildBrowserShortcutPolicy,
|
||||
parseBrowserShortcutInput,
|
||||
shouldPublishBrowserShortcutPolicy,
|
||||
} from "@/keyboard/browser-shortcuts";
|
||||
import type { KeyboardFocusScope, KeyboardShortcutPayload } from "@/keyboard/actions";
|
||||
import {
|
||||
@@ -220,6 +221,7 @@ export function useKeyboardShortcuts({
|
||||
browserFocusRestoreElement?: HTMLElement | null;
|
||||
}) => {
|
||||
const store = useKeyboardShortcutsStore.getState();
|
||||
const previousChordState = chordStateRef.current;
|
||||
const result = resolveKeyboardShortcut({
|
||||
event: input.event,
|
||||
context: {
|
||||
@@ -241,7 +243,13 @@ export function useKeyboardShortcuts({
|
||||
});
|
||||
|
||||
chordStateRef.current = result.nextChordState;
|
||||
if ("browserId" in input.event) {
|
||||
if (
|
||||
shouldPublishBrowserShortcutPolicy({
|
||||
isBrowserInput: "browserId" in input.event,
|
||||
previousChordState,
|
||||
nextChordState: result.nextChordState,
|
||||
})
|
||||
) {
|
||||
publishBrowserShortcutPolicy(result.nextChordState);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildBrowserShortcutPolicy, parseBrowserShortcutInput } from "./browser-shortcuts";
|
||||
import {
|
||||
buildBrowserShortcutPolicy,
|
||||
parseBrowserShortcutInput,
|
||||
shouldPublishBrowserShortcutPolicy,
|
||||
} from "./browser-shortcuts";
|
||||
import { buildEffectiveBindings, resolveKeyboardShortcut } from "./keyboard-shortcuts";
|
||||
|
||||
describe("buildBrowserShortcutPolicy", () => {
|
||||
@@ -171,6 +175,18 @@ describe("buildBrowserShortcutPolicy", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("shouldPublishBrowserShortcutPolicy", () => {
|
||||
it("restores the initial browser policy when a host key resets a pending chord", () => {
|
||||
expect(
|
||||
shouldPublishBrowserShortcutPolicy({
|
||||
isBrowserInput: false,
|
||||
previousChordState: { candidateIndices: [1], step: 1, timeoutId: null },
|
||||
nextChordState: { candidateIndices: [], step: 0, timeoutId: null },
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseBrowserShortcutInput", () => {
|
||||
it("normalizes browser shortcut input without losing its identity", () => {
|
||||
expect(
|
||||
|
||||
@@ -29,6 +29,16 @@ interface BrowserShortcutPolicyInput {
|
||||
isDesktop: boolean;
|
||||
}
|
||||
|
||||
export function shouldPublishBrowserShortcutPolicy(input: {
|
||||
isBrowserInput: boolean;
|
||||
nextChordState: ChordState;
|
||||
previousChordState: ChordState;
|
||||
}): boolean {
|
||||
return (
|
||||
input.isBrowserInput || (input.previousChordState.step > 0 && input.nextChordState.step === 0)
|
||||
);
|
||||
}
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||
}
|
||||
|
||||
@@ -230,6 +230,24 @@ describe("BrowserKeyboard", () => {
|
||||
expect(guest.sent).toHaveLength(3);
|
||||
});
|
||||
|
||||
test("ignores guest lifecycle events after the host is destroyed", () => {
|
||||
const { attach, keyboard } = createBrowserKeyboard();
|
||||
const guest = new FakeBrowserContents(71);
|
||||
const host = new FakeBrowserContents(72);
|
||||
attach({ browserId: "browser-a", contents: guest, hostContents: host });
|
||||
keyboard.publish(host.id, { prefixes: [] });
|
||||
|
||||
host.destroy();
|
||||
guest.domReady();
|
||||
|
||||
expect(guest.sent).toEqual([
|
||||
{
|
||||
channel: "paseo:browser-keyboard-policy",
|
||||
payload: { browserId: "browser-a", prefixes: [] },
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test("owns reserved shortcuts and leaves plain guest input contained", () => {
|
||||
const { attach } = createBrowserKeyboard();
|
||||
const guest = new FakeBrowserContents(81);
|
||||
|
||||
@@ -203,6 +203,9 @@ export class BrowserKeyboard {
|
||||
if (this.attachedGuestsByWebContentsId.get(webContentsId) !== guest) {
|
||||
return null;
|
||||
}
|
||||
if (guest.hostContents.isDestroyed()) {
|
||||
return null;
|
||||
}
|
||||
const registration = this.browserRegistry.getRegistrationForWebContents(webContentsId);
|
||||
return registration?.hostWebContentsId === guest.hostContents.id ? registration : null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user