fix(web): add clipboard fallback for CodeBlock copy button in non-secure contexts

The CodeBlock component was refactored in v0.25.3 to use navigator.clipboard.writeText(),
which requires HTTPS or localhost. This caused the copy button to fail silently for users
accessing Memos over HTTP.

This fix adds a fallback to the copy-to-clipboard library (already used by all other
copy operations in the codebase) when the native clipboard API is unavailable or fails,
ensuring the copy button works reliably in all deployment scenarios.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Steven 2025-12-15 22:51:34 +08:00
parent a2ddf05933
commit b1a52f20ed
1 changed files with 25 additions and 4 deletions

View File

@ -1,3 +1,4 @@
import copy from "copy-to-clipboard";
import hljs from "highlight.js"; import hljs from "highlight.js";
import { CheckIcon, CopyIcon } from "lucide-react"; import { CheckIcon, CopyIcon } from "lucide-react";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
@ -82,11 +83,31 @@ export const CodeBlock = observer(({ children, className, ...props }: CodeBlockP
const handleCopy = async () => { const handleCopy = async () => {
try { try {
await navigator.clipboard.writeText(codeContent); // Try native clipboard API first (requires HTTPS or localhost)
setCopied(true); if (navigator.clipboard && window.isSecureContext) {
setTimeout(() => setCopied(false), 2000); await navigator.clipboard.writeText(codeContent);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} else {
// Fallback to copy-to-clipboard library for non-secure contexts
const success = copy(codeContent);
if (success) {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} else {
console.error("Failed to copy code");
}
}
} catch (err) { } catch (err) {
console.error("Failed to copy code:", err); // If native API fails, try fallback
console.warn("Native clipboard failed, using fallback:", err);
const success = copy(codeContent);
if (success) {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} else {
console.error("Failed to copy code:", err);
}
} }
}; };