From 9ffca825ffe09f09662ee1e53d44e675f139724d Mon Sep 17 00:00:00 2001 From: John C Fitzpatrick Date: Thu, 18 Sep 2025 10:04:46 -0700 Subject: [PATCH] feat: Universal clipboard utility with improved copy functionality (#663) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Add universal clipboard utility with enhanced copy functionality - Add comprehensive clipboard utility (src/utils/clipboard.ts) with: - Modern Clipboard API with automatic fallback to document.execCommand - Cross-browser compatibility and security context handling - Detailed error reporting and debugging capabilities - Support for secure (HTTPS) and insecure (HTTP/localhost) contexts - Update components to use new clipboard utility: - BugReportModal: Enhanced copy functionality with error handling - CodeViewerModal: Improved copy-to-clipboard for code snippets - IDEGlobalRules: Robust clipboard operations for rule copying - McpConfigSection: Enhanced config and command copying - DocumentCard: Reliable ID copying functionality - KnowledgeInspector: Improved content copying - ButtonPlayground: Enhanced CSS style copying - Benefits: - Consistent copy behavior across all browser environments - Better error handling and user feedback - Improved accessibility and security context support - Enhanced debugging capabilities Fixes #662 * fix: Improve clipboard utility robustness and add missing host configuration Clipboard utility improvements: - Prevent textarea element leak in clipboard fallback with proper cleanup - Add SSR compatibility with typeof guards for navigator/document - Use finally block to ensure cleanup in all error cases Host configuration fixes: - Update MCP API to use ARCHON_HOST environment variable instead of hardcoded localhost - Add ARCHON_HOST to docker-compose environment variables - Ensures MCP configuration shows correct hostname in different deployment environments Addresses CodeRabbit feedback and restores missing host functionality * fix: Use relative URLs for Vite proxy in development - Update getApiUrl() to return empty string when VITE_API_URL is unset - Ensures all API requests use relative paths (/api/...) in development - Prevents bypassing Vite proxy with absolute URLs (host:port) - Maintains existing functionality for explicit VITE_API_URL configuration - Fix TypeScript error by using bracket notation for environment access Addresses CodeRabbit feedback about dev setup relying on Vite proxy * fix: Resolve TypeScript error in API configuration Use proper type assertion to access VITE_API_URL environment variable * Address PR review comments: Move clipboard utility to features architecture - Move clipboard.ts from src/utils/ to src/features/shared/utils/ - Remove copyTextToClipboard backward compatibility function (dead code) - Update all import statements to use new file location - Maintain full clipboard functionality with modern API and fallbacks Addresses: - Review comment r2348420743: Move to new architecture location - Review comment r2348422625: Remove unused backward compatibility function 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * Fix SSR safety issue in clipboard utility - Add typeof navigator !== 'undefined' guard before accessing navigator.clipboard - Add typeof document !== 'undefined' guard before using document.execCommand fallback - Ensure proper error handling when running in server-side environment - Maintain existing functionality while preventing ReferenceError during SSR/prerender Addresses CodeRabbit feedback: Navigator access needs SSR-safe guards 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --------- Co-authored-by: Claude --- .../components/bug-report/BugReportModal.tsx | 31 ++-- .../src/components/code/CodeViewerModal.tsx | 13 +- .../components/settings/ButtonPlayground.tsx | 15 +- .../components/settings/IDEGlobalRules.tsx | 10 +- archon-ui-main/src/config/api.ts | 28 +--- .../components/KnowledgeInspector.tsx | 9 +- .../mcp/components/McpConfigSection.tsx | 25 +++- .../documents/components/DocumentCard.tsx | 11 +- .../src/features/shared/utils/clipboard.ts | 139 ++++++++++++++++++ docker-compose.yml | 1 + python/src/server/api_routes/mcp_api.py | 2 +- 11 files changed, 225 insertions(+), 59 deletions(-) create mode 100644 archon-ui-main/src/features/shared/utils/clipboard.ts diff --git a/archon-ui-main/src/components/bug-report/BugReportModal.tsx b/archon-ui-main/src/components/bug-report/BugReportModal.tsx index 0ef34a66..69b40262 100644 --- a/archon-ui-main/src/components/bug-report/BugReportModal.tsx +++ b/archon-ui-main/src/components/bug-report/BugReportModal.tsx @@ -11,6 +11,7 @@ import { BugContext, BugReportData, } from "../../services/bugReportService"; +import { copyToClipboard } from "../../features/shared/utils/clipboard"; interface BugReportModalProps { isOpen: boolean; @@ -99,13 +100,21 @@ export const BugReportModal: React.FC = ({ // Fallback: copy to clipboard const formattedReport = bugReportService.formatReportForClipboard(bugReportData); - await navigator.clipboard.writeText(formattedReport); + const clipboardResult = await copyToClipboard(formattedReport); - showToast( - "Failed to create GitHub issue, but bug report was copied to clipboard. Please paste it in a new GitHub issue.", - "warning", - 10000, - ); + if (clipboardResult.success) { + showToast( + "Failed to create GitHub issue, but bug report was copied to clipboard. Please paste it in a new GitHub issue.", + "warning", + 10000, + ); + } else { + showToast( + "Failed to create GitHub issue and could not copy to clipboard. Please report manually.", + "error", + 10000, + ); + } } } catch (error) { console.error("Bug report submission failed:", error); @@ -118,15 +127,15 @@ export const BugReportModal: React.FC = ({ } }; - const copyToClipboard = async () => { + const handleCopyToClipboard = async () => { const bugReportData: BugReportData = { ...report, context }; const formattedReport = bugReportService.formatReportForClipboard(bugReportData); - try { - await navigator.clipboard.writeText(formattedReport); + const result = await copyToClipboard(formattedReport); + if (result.success) { showToast("Bug report copied to clipboard", "success"); - } catch { + } else { showToast("Failed to copy to clipboard", "error"); } }; @@ -372,7 +381,7 @@ export const BugReportModal: React.FC = ({