mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-15 12:41:37 +03:00
fix(app): keep the browser page under a still while a dialog is open (#58958)
Co-authored-by: vimtor <vimtor@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
49a112f18e
commit
66a3ed9b8f
@@ -101,6 +101,35 @@ story("keeps a still of the page under floating content that covers it", async (
|
||||
await expect(root.getByText("Captures: 1", { exact: true })).toBeVisible()
|
||||
})
|
||||
|
||||
story("keeps a still of the page under an open dialog instead of blanking the pane", async ({ page }) => {
|
||||
const root = page.getByTestId("browser-pane-fixture")
|
||||
const still = root.locator("#browser-panel img")
|
||||
const native = root.getByTestId("native-Alpha")
|
||||
const toggle = root.getByRole("button", { name: "Toggle dialog", exact: true })
|
||||
await root.getByRole("button", { name: "Hold capture", exact: true }).click()
|
||||
|
||||
// Read in the same task as the click: the page must not hide before its still exists.
|
||||
const visible = await toggle.evaluate((element) => {
|
||||
element.dispatchEvent(new MouseEvent("click", { bubbles: true }))
|
||||
|
||||
return document.querySelector('[data-testid="native-Alpha"]')?.getAttribute("data-visible")
|
||||
})
|
||||
|
||||
expect(visible).toBe("true")
|
||||
await expect(root.getByText("Captures: 1", { exact: true })).toBeVisible()
|
||||
await expect(native).toHaveAttribute("data-visible", "true")
|
||||
await expect(still).toHaveCount(0)
|
||||
|
||||
await root.getByRole("button", { name: "Release capture", exact: true }).click()
|
||||
await expect(native).toHaveAttribute("data-visible", "false")
|
||||
await expect(still).toBeVisible()
|
||||
|
||||
await toggle.click()
|
||||
await expect(native).toHaveAttribute("data-visible", "true")
|
||||
await expect(still).toHaveCount(0)
|
||||
await expect(root.getByText("Captures: 1", { exact: true })).toBeVisible()
|
||||
})
|
||||
|
||||
story("comments on a picked element over a still of the page", async ({ page }) => {
|
||||
const root = page.getByTestId("browser-pane-fixture")
|
||||
const picker = root.getByRole("button", { name: "Select an element to comment on", exact: true })
|
||||
|
||||
@@ -157,8 +157,10 @@ function EmbedView(props: EmbedProps & { input: Input; bridge: Bridge }) {
|
||||
const top = Math.round(rect.top * zoom)
|
||||
const right = Math.round(rect.right * zoom)
|
||||
const bottom = Math.round(rect.bottom * zoom)
|
||||
const shown = props.visible && store.visible && !props.input.dialog()
|
||||
const cover = !!props.frozen || covered(rect)
|
||||
const shown = props.visible && store.visible
|
||||
// A dialog's scrim covers the box like floating content does, so it dims a still of the page
|
||||
// instead of a blank box, and the page does not blink out and back as the dialog opens and closes.
|
||||
const cover = !!props.frozen || props.input.dialog() || covered(rect)
|
||||
|
||||
if (shown && cover) freeze(id)
|
||||
|
||||
@@ -227,7 +229,7 @@ function EmbedView(props: EmbedProps & { input: Input; bridge: Bridge }) {
|
||||
|
||||
// The native views are not clipped by the retained panel's DOM. Hide before the next
|
||||
// animation frame so closing the panel cannot leave the embed above the app.
|
||||
if (!props.visible || !store.visible || props.input.dialog() || !props.id) return hide()
|
||||
if (!props.visible || !store.visible || !props.id) return hide()
|
||||
schedule(300)
|
||||
},
|
||||
),
|
||||
|
||||
@@ -72,6 +72,8 @@ type PaneFixtureState = {
|
||||
error: string | undefined
|
||||
layouts: Record<string, BridgeLayout | undefined>
|
||||
covered: boolean
|
||||
/** Whether a host dialog is open over the app. */
|
||||
dialog: boolean
|
||||
captures: number
|
||||
holdCapture: boolean
|
||||
picker: Record<string, boolean | undefined>
|
||||
@@ -131,6 +133,7 @@ export function mountBrowserPane(input: PaneHost) {
|
||||
error: undefined,
|
||||
layouts: {},
|
||||
covered: false,
|
||||
dialog: false,
|
||||
captures: 0,
|
||||
holdCapture: false,
|
||||
picker: {},
|
||||
@@ -184,7 +187,7 @@ export function mountBrowserPane(input: PaneHost) {
|
||||
}
|
||||
|
||||
// SAFETY: the host embeds call only `embed` and `capture` on their bridge (`runtime/extension/embeds.tsx`).
|
||||
const embeds = input.createEmbeds({ bridge: bridge as Bridge, zoom: () => 1, dialog: () => false })
|
||||
const embeds = input.createEmbeds({ bridge: bridge as Bridge, zoom: () => 1, dialog: () => store.dialog })
|
||||
|
||||
const t = (key: string, params?: Readonly<Partial<Record<string, string | number>>>) =>
|
||||
(messages.get(key) ?? language.t(key)).replace(/\{\{(\w+)\}\}/g, (_, name: string) =>
|
||||
@@ -468,6 +471,7 @@ export function mountBrowserPane(input: PaneHost) {
|
||||
<button onClick={() => setStore("holdCapture", true)}>Hold capture</button>
|
||||
<button onClick={() => held.splice(0).forEach((resolve) => resolve())}>Release capture</button>
|
||||
<button onClick={() => setStore("covered", (covered) => !covered)}>Toggle popover</button>
|
||||
<button onClick={() => setStore("dialog", (open) => !open)}>Toggle dialog</button>
|
||||
<button onClick={pick}>Pick element</button>
|
||||
<button onClick={() => setStore("history", { visits })}>Seed history</button>
|
||||
<button onClick={() => emit(store.session, { type: "page", tabID: current().id, icon, zoom: store.zoom })}>
|
||||
|
||||
Reference in New Issue
Block a user