diff --git a/apps/web/src/components/DiffFilePathCopyButton.browser.test.tsx b/apps/web/src/components/DiffFilePathCopyButton.browser.test.tsx index 1a0b4238f5f6e..0c5d46395f3ae 100644 --- a/apps/web/src/components/DiffFilePathCopyButton.browser.test.tsx +++ b/apps/web/src/components/DiffFilePathCopyButton.browser.test.tsx @@ -8,7 +8,7 @@ import { AnchoredToastProvider } from "./ui/toast"; it("explains a denied clipboard write and lets the same path be copied again", async () => { await using screen = await render( - + , ); using write = vi @@ -28,3 +28,16 @@ it("explains a denied clipboard write and lets the same path be copied again", a expect(write).toHaveBeenCalledTimes(2); expect(write).toHaveBeenLastCalledWith("apps/web/src/index.ts"); }); + +it("copies a Windows workspace's file path with Windows separators", async () => { + await using screen = await render( + + + , + ); + using write = vi.spyOn(navigator.clipboard, "writeText").mockResolvedValue(undefined); + + await screen.getByRole("button", { name: "Copy file path" }).click(); + + await vi.waitFor(() => expect(write).toHaveBeenCalledWith("apps\\web\\src\\index.ts")); +}); diff --git a/apps/web/src/components/DiffFilePathCopyButton.tsx b/apps/web/src/components/DiffFilePathCopyButton.tsx index 59aa256294d85..c2beef232e8ac 100644 --- a/apps/web/src/components/DiffFilePathCopyButton.tsx +++ b/apps/web/src/components/DiffFilePathCopyButton.tsx @@ -1,3 +1,4 @@ +import { formatFilePathForClipboard } from "@t3tools/client-runtime/media-actions"; import { CheckIcon, CopyIcon } from "lucide-react"; import { useRef } from "react"; import { useCopyToClipboard } from "../hooks/useCopyToClipboard"; @@ -5,7 +6,13 @@ import { ANCHORED_COPY_TOAST_TIMEOUT_MS, showAnchoredCopyErrorToast } from "./ui import { Button } from "./ui/button"; import { Tooltip, TooltipPopup, TooltipTrigger } from "./ui/tooltip"; -export function DiffFilePathCopyButton({ filePath }: { filePath: string }) { +export function DiffFilePathCopyButton({ + filePath, + workspaceRoot, +}: { + filePath: string; + workspaceRoot: string | undefined; +}) { const ref = useRef(null); const { copyToClipboard, isCopied } = useCopyToClipboard({ onError: (error) => showAnchoredCopyErrorToast(ref, error), @@ -21,7 +28,9 @@ export function DiffFilePathCopyButton({ filePath }: { filePath: string }) { size="icon-micro" variant="ghost-muted" aria-label="Copy file path" - onClick={() => copyToClipboard(filePath, undefined)} + onClick={() => + copyToClipboard(formatFilePathForClipboard(filePath, workspaceRoot), undefined) + } /> } > diff --git a/apps/web/src/components/DiffPanel.tsx b/apps/web/src/components/DiffPanel.tsx index 99e0b07c1845e..71c197b6ce363 100644 --- a/apps/web/src/components/DiffPanel.tsx +++ b/apps/web/src/components/DiffPanel.tsx @@ -177,12 +177,14 @@ function DiffFileCollapseToggle({ function DiffFileHeaderSuffix({ filePath, + workspaceRoot, hasStat, error, truncated, onRetry, }: { filePath: string; + workspaceRoot: string | undefined; hasStat: boolean; error: boolean; truncated: boolean; @@ -191,7 +193,7 @@ function DiffFileHeaderSuffix({ return ( <> - + {hasStat ? ( onRetry(filePath)} /> @@ -1436,6 +1438,7 @@ export default function DiffPanel({ return (