Skip to content

Implement copy to clipboard functionality #59

Closed
@nullcoder

Description

@nullcoder

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew feature implementationpriority: highShould be done soonreadyReady to be worked onuiUser interface and components

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions