fix(webui): restore code block copy fallback
This commit is contained in:
@@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next";
|
||||
|
||||
import { useThemeValue } from "@/hooks/useTheme";
|
||||
import { hasAnsi, parseAnsiSegments, stripAnsi } from "@/lib/ansi";
|
||||
import { copyTextToClipboard } from "@/lib/clipboard";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface CodeBlockProps {
|
||||
@@ -192,8 +193,8 @@ export function CodeBlock({
|
||||
const renderAnsi = shouldRenderAnsi(language, code);
|
||||
|
||||
const onCopy = useCallback(() => {
|
||||
if (!navigator.clipboard) return;
|
||||
navigator.clipboard.writeText(renderAnsi ? stripAnsi(code) : code).then(() => {
|
||||
void copyTextToClipboard(renderAnsi ? stripAnsi(code) : code).then((ok) => {
|
||||
if (!ok) return;
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 1_500);
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { act, render, screen } from "@testing-library/react";
|
||||
import { act, render, screen, waitFor } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
@@ -146,6 +146,35 @@ describe("CodeBlock", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("copies with the textarea fallback when Clipboard API is unavailable", async () => {
|
||||
const user = userEvent.setup();
|
||||
Object.defineProperty(navigator, "clipboard", {
|
||||
configurable: true,
|
||||
value: undefined,
|
||||
});
|
||||
const execCommand = vi.fn().mockReturnValue(true);
|
||||
Object.defineProperty(document, "execCommand", {
|
||||
configurable: true,
|
||||
value: execCommand,
|
||||
});
|
||||
|
||||
try {
|
||||
render(
|
||||
<ThemeProvider theme="dark">
|
||||
<CodeBlock language="ts" code="const value = 1;" highlight={false} />
|
||||
</ThemeProvider>,
|
||||
);
|
||||
|
||||
await user.click(screen.getByRole("button", { name: /copy/i }));
|
||||
|
||||
await waitFor(() => expect(execCommand).toHaveBeenCalledWith("copy"));
|
||||
expect(screen.getByText("Copied")).toBeInTheDocument();
|
||||
} finally {
|
||||
Reflect.deleteProperty(navigator, "clipboard");
|
||||
Reflect.deleteProperty(document, "execCommand");
|
||||
}
|
||||
});
|
||||
|
||||
it("reads theme from context without creating per-block observers", async () => {
|
||||
const originalMutationObserver = globalThis.MutationObserver;
|
||||
const observer = vi.fn();
|
||||
|
||||
Reference in New Issue
Block a user