From 0cbe24a19fb3a5b6730fc4e3db45e5bfbe354f4f Mon Sep 17 00:00:00 2001 From: ddCat <2695092045@qq.com> Date: Tue, 25 Aug 2026 14:33:34 +0800 Subject: [PATCH] =?UTF-8?q?fix(canvas):=20=E6=8F=90=E7=A4=BA=E8=AF=8D?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=99=A8=20-=20=E9=9A=94=E7=A6=BB=E5=A4=9A?= =?UTF-8?q?=E5=AE=9E=E4=BE=8B=E6=B5=AE=E5=B1=82=E5=AE=9A=E4=BD=8D=E5=B9=B6?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=B7=AF=E7=94=B1=E9=A2=84=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/package.json | 2 +- .../canvas/canvas-prompt-optimizer-drawer.tsx | 7 ++++--- web/test/prompt-optimizer-drawer.test.ts | 14 ++++++++++++++ web/test/workspace-route-loading.test.ts | 7 ++++--- 4 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 web/test/prompt-optimizer-drawer.test.ts diff --git a/web/package.json b/web/package.json index bb748fc03..97ed46f24 100644 --- a/web/package.json +++ b/web/package.json @@ -7,7 +7,7 @@ "dev": "vite --host 0.0.0.0 --port 3000", "build": "tsc --noEmit && vite build", "typecheck": "tsc --noEmit", - "test": "bun test test/api-request.test.ts test/video-api-contracts.test.ts test/image-api-contracts.test.ts test/channel-model-catalog.test.ts test/model-protocols.test.ts test/agent-prompt-cache.test.ts test/canvas-agent-context.test.ts test/canvas-batch-connection.test.ts test/canvas-character-reference.test.ts test/canvas-document.test.ts test/canvas-drawing-engine.test.ts test/canvas-emotion-edit-plan.test.ts test/canvas-extension-nodes.test.ts test/canvas-folder.test.ts test/canvas-generation-layout.test.ts test/canvas-image-batch-retry.test.ts test/canvas-leafer-viewport.test.ts test/canvas-local-runtime.test.ts test/canvas-model-policy.test.ts test/canvas-resource-mention-editor.test.ts test/canvas-resource-references.test.ts test/canvas-storyboard-assets.test.ts test/canvas-storyboard-references.test.ts test/canvas-node-config-reset.test.ts test/canvas-node-registry.test.ts test/canvas-video-regeneration.test.ts test/canvas-video-timeline-segments.test.ts test/create-canvas-handoff.test.ts test/create-library-button.test.ts test/creation-references.test.ts test/generation-asset-repository.node.test.ts test/generation-storage-consistency.test.ts test/generation-task-durability.node.test.ts test/generation-task-local.test.ts test/generation-task-materializer.test.ts test/task-media-fallback.test.ts test/user-scoped-generation-persistence.test.ts test/local-channel-permission.test.ts test/local-channel-runtime-projection.node.test.mjs test/local-channel-task-center.node.test.mjs test/local-channel-ui.node.test.mjs test/local-cli-settings.test.ts test/local-dreamina-cli.test.ts test/local-dreamina-generation.test.ts test/local-dreamina-model-catalog.test.ts test/local-runtime-bootstrap.test.ts test/local-runtime-connection.test.ts test/local-runtime.test.ts test/client-id.test.ts test/grok-image-prompt-limit.test.ts test/image-resolution-tiers.test.ts test/gemini-image.test.ts test/libtv-import.test.ts test/timeline-to-ffmpeg.test.ts test/canvas-video-segment-args.test.ts test/tapnow-import.test.ts && bun test test/local-dreamina-cross-runtime.test.ts", + "test": "bun test test/api-request.test.ts test/video-api-contracts.test.ts test/image-api-contracts.test.ts test/channel-model-catalog.test.ts test/model-protocols.test.ts test/agent-prompt-cache.test.ts test/canvas-agent-context.test.ts test/canvas-batch-connection.test.ts test/canvas-character-reference.test.ts test/canvas-document.test.ts test/canvas-drawing-engine.test.ts test/canvas-emotion-edit-plan.test.ts test/canvas-extension-nodes.test.ts test/canvas-folder.test.ts test/canvas-generation-layout.test.ts test/canvas-image-batch-retry.test.ts test/canvas-leafer-viewport.test.ts test/canvas-local-runtime.test.ts test/canvas-model-policy.test.ts test/canvas-resource-mention-editor.test.ts test/canvas-resource-references.test.ts test/canvas-storyboard-assets.test.ts test/canvas-storyboard-references.test.ts test/canvas-node-config-reset.test.ts test/canvas-node-registry.test.ts test/canvas-video-regeneration.test.ts test/canvas-video-timeline-segments.test.ts test/create-canvas-handoff.test.ts test/create-library-button.test.ts test/creation-references.test.ts test/generation-asset-repository.node.test.ts test/generation-storage-consistency.test.ts test/generation-task-durability.node.test.ts test/generation-task-local.test.ts test/generation-task-materializer.test.ts test/task-media-fallback.test.ts test/user-scoped-generation-persistence.test.ts test/local-channel-permission.test.ts test/local-channel-runtime-projection.node.test.mjs test/local-channel-task-center.node.test.mjs test/local-channel-ui.node.test.mjs test/local-cli-settings.test.ts test/local-dreamina-cli.test.ts test/local-dreamina-generation.test.ts test/local-dreamina-model-catalog.test.ts test/local-runtime-bootstrap.test.ts test/local-runtime-connection.test.ts test/local-runtime.test.ts test/client-id.test.ts test/grok-image-prompt-limit.test.ts test/image-resolution-tiers.test.ts test/gemini-image.test.ts test/libtv-import.test.ts test/timeline-to-ffmpeg.test.ts test/canvas-video-segment-args.test.ts test/tapnow-import.test.ts test/prompt-optimizer-drawer.test.ts && bun test test/local-dreamina-cross-runtime.test.ts", "start": "vite preview --host 0.0.0.0 --port 3000", "format": "prettier --write .", "format:check": "prettier --check ." diff --git a/web/src/components/canvas/canvas-prompt-optimizer-drawer.tsx b/web/src/components/canvas/canvas-prompt-optimizer-drawer.tsx index 42fddba5a..a94678618 100644 --- a/web/src/components/canvas/canvas-prompt-optimizer-drawer.tsx +++ b/web/src/components/canvas/canvas-prompt-optimizer-drawer.tsx @@ -101,6 +101,7 @@ export function CanvasPromptOptimizerDrawer({ open, children, prompt, generation const { message } = App.useApp(); const abortRef = useRef(null); const chatRef = useRef(null); + const contentRef = useRef(null); const [mode, setMode] = useState("expand"); const [activeOptimizerModel, setActiveOptimizerModel] = useState(""); const [draftPrompt, setDraftPrompt] = useState(prompt); @@ -176,7 +177,7 @@ export function CanvasPromptOptimizerDrawer({ open, children, prompt, generation }, [open]); const syncPanelPositionToViewport = useCallback(() => { - const popoverRoot = document.querySelector(".canvas-prompt-optimizer-popover"); + const popoverRoot = contentRef.current?.closest(".canvas-prompt-optimizer-popover"); if (!popoverRoot) return; const rect = popoverRoot.getBoundingClientRect(); @@ -381,7 +382,7 @@ export function CanvasPromptOptimizerDrawer({ open, children, prompt, generation }; const nudgePanel = (deltaX: number, deltaY: number) => { - const popoverRoot = document.querySelector(".canvas-prompt-optimizer-popover"); + const popoverRoot = contentRef.current?.closest(".canvas-prompt-optimizer-popover"); if (!popoverRoot) { setPanelOffset((current) => ({ x: current.x + deltaX, y: current.y + deltaY })); return; @@ -622,7 +623,7 @@ export function CanvasPromptOptimizerDrawer({ open, children, prompt, generation } as CSSProperties; const content = ( -
+
{ diff --git a/web/test/prompt-optimizer-drawer.test.ts b/web/test/prompt-optimizer-drawer.test.ts new file mode 100644 index 000000000..5e500b490 --- /dev/null +++ b/web/test/prompt-optimizer-drawer.test.ts @@ -0,0 +1,14 @@ +import { describe, expect, test } from "bun:test"; +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; + +const source = readFileSync(resolve(import.meta.dir, "../src/components/canvas/canvas-prompt-optimizer-drawer.tsx"), "utf8"); + +describe("prompt optimizer drawer instance isolation", () => { + test("resolves the popover from the current drawer content instead of the first global match", () => { + expect(source).toContain("const contentRef = useRef(null);"); + expect(source).toContain('contentRef.current?.closest(".canvas-prompt-optimizer-popover")'); + expect(source).toContain('
(".canvas-prompt-optimizer-popover")'); + }); +}); diff --git a/web/test/workspace-route-loading.test.ts b/web/test/workspace-route-loading.test.ts index 126bf345f..08526f545 100644 --- a/web/test/workspace-route-loading.test.ts +++ b/web/test/workspace-route-loading.test.ts @@ -19,13 +19,14 @@ describe("workspace route loading", () => { test("preloads the reported workspace routes before navigation", () => { const modules = source("../src/lib/workspace-route-modules.ts"); - const navigation = source("../src/components/layout/app-top-nav.tsx"); + const navigation = source("../src/components/layout/workspace-sidebar-nav.tsx"); for (const route of ["projects", "canvas", "assets", "wallet", "create"]) { expect(modules).toContain(`${route}: () => import`); } - expect(navigation).toContain("onPointerEnter={() => preloadWorkspaceRoute(tool.slug)}"); - expect(navigation).toContain("onFocus={() => preloadWorkspaceRoute(tool.slug)}"); + expect(navigation).toContain("onPointerEnter={() => preloadWorkspaceRoute(linkTo)}"); + expect(navigation).toContain("onPointerDown={() => preloadWorkspaceRoute(linkTo)}"); + expect(navigation).toContain("onFocus={() => preloadWorkspaceRoute(linkTo)}"); }); test("uses a quiet workspace skeleton for initial hydration", () => {