-
Notifications
You must be signed in to change notification settings - Fork 0
Closed
Labels
featureNew feature implementationNew feature implementationpriority: highShould be done soonShould be done soonreadyReady to be worked onReady to be worked onuiUser interface and componentsUser interface and components
Description
Description
Implement secure copy to clipboard functionality for code blocks and share links, ensuring sensitive data is never logged.
Security Requirements
- NEVER log or console.log copied content (could contain decrypted data)
- Copy full URLs including hash fragments (e.g.,
https://ghostpaste.dev/g/abc123#key=...) - Ensure clipboard API doesn't leak data to browser extensions
- Clear clipboard data from memory after copy
Core Features
1. Share Link Copying
- Copy button next to share URL after gist creation
- Must include full URL with fragment (contains encryption key)
- Visual feedback: "Copied!" tooltip or button text change
- Button text: "Copy Link" → "Copied!" → "Copy Link" (after 2s)
2. Individual File Copying
- Copy button for each file in multi-file gists
- Appears on hover or always visible on mobile
- Copies only the content of that specific file
- Include filename in toast notification: "Copied file.js"
3. Full Gist Copying
- Optional: Copy all files as concatenated text
- Format:
// filename.js\n[content]\n\n// nextfile.js\n[content] - Use case: Quick paste into single file
Visual Feedback
- Success: Green check icon + "Copied!" message
- Error: Red X icon + "Failed to copy" message
- Use toast notifications or inline feedback
- Animation: Subtle scale or fade effect
Implementation Details
// Secure copy function
async function secureCopy(text: string, label?: string) {
try {
await navigator.clipboard.writeText(text);
// Show success feedback
showToast({
title: "Copied\!",
description: label ? `Copied ${label}` : undefined,
variant: "success"
});
} catch (err) {
// Fallback for older browsers
const textArea = document.createElement("textarea");
textArea.value = text;
textArea.style.position = "fixed";
textArea.style.left = "-999999px";
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand("copy");
showToast({ title: "Copied\!", variant: "success" });
} catch {
showToast({ title: "Failed to copy", variant: "error" });
} finally {
document.body.removeChild(textArea);
}
}
// Clear from memory
text = "";
}Acceptance Criteria
- Copy share link includes full URL with hash fragment
- Individual file copy buttons work for each file
- NO console.log or logging of copied content
- Visual feedback shows success/failure
- Fallback works for browsers without clipboard API
- Mobile touch targets are appropriately sized (44x44px min)
- Keyboard shortcut (Cmd/Ctrl+C) works when content selected
- Toast notifications don't block user interaction
- Memory is cleared after copy operation
UI/UX Guidelines
- Copy buttons use consistent icon (e.g., clipboard icon from Lucide)
- Hover state shows tooltip "Copy to clipboard"
- Success state changes icon to checkmark temporarily
- Error state explains why copy failed
- Mobile: Consider long-press to copy as alternative
Technical Notes
- Use navigator.clipboard API as primary method
- Implement textarea fallback for older browsers
- Test Safari iOS clipboard permissions
- Consider rate limiting to prevent spam (max 10 copies per minute)
- Use React hooks for copy state management
- Integrate with existing toast system from feat: add toast notification system #68
Related
- Part of Phase 4 UI Components
- Enhances user experience in viewer (feat: create loading state components #67)
- Works with CodeEditor component (feat: implement PIN authentication with PBKDF2-SHA256 #46)
- Uses toast notifications (feat: add toast notification system #68)
Metadata
Metadata
Assignees
Labels
featureNew feature implementationNew feature implementationpriority: highShould be done soonShould be done soonreadyReady to be worked onReady to be worked onuiUser interface and componentsUser interface and components