fix(frontend): handle clipboard fallback and markdown word export

This commit is contained in:
吉鑫升 committed 2026-07-03 16:54:16 +08:00
1 parent 195ef3ee40
commit db2f21191c
6 files changed
+86 -37

No files matched your search

@@ -1,7 +1,8 @@
"use client";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { copyTextToClipboard } from "@/core/clipboard";
import { cn } from "@/lib/utils";
import { CheckIcon, CopyIcon } from "lucide-react";
import {
type ComponentProps,
@@ -144,18 +145,13 @@ export const CodeBlockCopyButton = ({
...props
}: CodeBlockCopyButtonProps) => {
const [isCopied, setIsCopied] = useState(false);
const { code } = useContext(CodeBlockContext);
const copyToClipboard = async () => {
if (typeof window === "undefined" || !navigator?.clipboard?.writeText) {
onError?.(new Error("Clipboard API not available"));
return;
}
try {
await navigator.clipboard.writeText(code);
setIsCopied(true);
onCopy?.();
const { code } = useContext(CodeBlockContext);
const copyToClipboard = async () => {
try {
await copyTextToClipboard(code);
setIsCopied(true);
onCopy?.();
setTimeout(() => setIsCopied(false), timeout);
} catch (error) {
onError?.(error as Error);
@@ -28,7 +28,7 @@ import {
ArtifactHeader,
ArtifactTitle,
} from "@/components/ai-elements/artifact";
import { Select, SelectItem } from "@/components/ui/select";
import { Select, SelectItem } from "@/components/ui/select";
import {
SelectContent,
SelectGroup,
@@ -39,7 +39,8 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import { CodeEditor } from "@/components/workspace/code-editor";
import { publishArtifactToKnowledge } from "@/core/agents/api";
import { useAgent } from "@/core/agents/hooks";
import { apiFetch } from "@/core/api";
import { apiFetch } from "@/core/api";
import { copyTextToClipboard } from "@/core/clipboard";
import {
downloadArtifactFile,
} from "@/core/artifacts/download";
@@ -682,7 +683,7 @@ export function ArtifactFileDetail({
disabled={!content}
onClick={async () => {
try {
await navigator.clipboard.writeText(displayContent ?? "");
await copyTextToClipboard(displayContent ?? "");
toast.success(t.clipboard.copiedToClipboard);
} catch (error) {
toast.error("Failed to copy to clipboard");
@@ -692,7 +693,7 @@ export function ArtifactFileDetail({
tooltip={t.clipboard.copyToClipboard}
/>
)}
{!useWriteFileStreaming && language === "markdown" && (
{language === "markdown" && (
<ArtifactAction
icon={isExportingWord ? LoaderIcon : FileType2Icon}
label="另存为 Word"
@@ -1,8 +1,10 @@
import { CheckIcon, CopyIcon } from "lucide-react";
import { useCallback, useState, type ComponentProps } from "react";
import { Button } from "@/components/ui/button";
import { useI18n } from "@/core/i18n/hooks";
import { CheckIcon, CopyIcon } from "lucide-react";
import { useCallback, useState, type ComponentProps } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { copyTextToClipboard } from "@/core/clipboard";
import { useI18n } from "@/core/i18n/hooks";
import { Tooltip } from "./tooltip";
@@ -12,14 +14,18 @@ export function CopyButton({
}: ComponentProps<typeof Button> & {
clipboardData: string;
}) {
const { t } = useI18n();
const [copied, setCopied] = useState(false);
const handleCopy = useCallback(() => {
void navigator.clipboard.writeText(clipboardData);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}, [clipboardData]);
return (
const { t } = useI18n();
const [copied, setCopied] = useState(false);
const handleCopy = useCallback(async () => {
try {
await copyTextToClipboard(clipboardData);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch {
toast.error(t.clipboard.failedToCopyToClipboard);
}
}, [clipboardData, t.clipboard.failedToCopyToClipboard]);
return (
<Tooltip content={t.clipboard.copyToClipboard}>
<Button
size="icon-sm"