diff --git a/src/App.tsx b/src/App.tsx index cda7fb8..51b4c04 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -26,11 +26,11 @@ function AppContent() { return; } - // Ctrl/Cmd + 1-0 to switch tools - if ((e.ctrlKey || e.metaKey) && e.key >= '1' && e.key <= '0') { + // Ctrl/Cmd + 1-9 and 0 to switch tools + if ((e.ctrlKey || e.metaKey) && (e.key >= '1' && e.key <= '9' || e.key === '0')) { e.preventDefault(); const tools: ToolType[] = ['config', 'markdown', 'diff', 'image', 'regex', 'decoder', 'timestamp', 'generator', 'case', 'url']; - const toolIndex = parseInt(e.key) === 0 ? 9 : parseInt(e.key) - 1; + const toolIndex = e.key === '0' ? 9 : parseInt(e.key) - 1; setActiveTool(tools[toolIndex]); } }; diff --git a/src/components/ImageBeautifier/ImageBeautifier.tsx b/src/components/ImageBeautifier/ImageBeautifier.tsx index 359555c..1d605b8 100644 --- a/src/components/ImageBeautifier/ImageBeautifier.tsx +++ b/src/components/ImageBeautifier/ImageBeautifier.tsx @@ -1,5 +1,5 @@ import React, { useState, useRef, useEffect, useCallback } from 'react'; -import { Upload, Download, Image as ImageIcon, RefreshCw } from 'lucide-react'; +import { Upload, Download, Image as ImageIcon, RefreshCw, Copy, Check } from 'lucide-react'; import clsx from 'clsx'; const gradientPresets = [ @@ -26,6 +26,7 @@ export const ImageBeautifier: React.FC = () => { const [borderRadius, setBorderRadius] = useState(12); const [padding, setPadding] = useState(64); const [shadow, setShadow] = useState(true); + const [copied, setCopied] = useState(false); const fileInputRef = useRef(null); const canvasRef = useRef(null); const dropZoneRef = useRef(null); @@ -92,6 +93,43 @@ export const ImageBeautifier: React.FC = () => { link.click(); }; + const handleCopy = async () => { + if (!canvasRef.current || !image) return; + + try { + // Check if Clipboard API is supported + if (!navigator.clipboard || !window.ClipboardItem) { + alert('Copy to clipboard is not supported in this browser. Please use the Download button instead.'); + return; + } + + const canvas = canvasRef.current; + + // Convert canvas to blob using Promise-based approach + const blob = await new Promise((resolve) => { + canvas.toBlob((blob) => resolve(blob), 'image/png'); + }); + + if (!blob) { + throw new Error('Failed to create blob from canvas'); + } + + // Use Clipboard API to copy the image + await navigator.clipboard.write([ + new window.ClipboardItem({ + 'image/png': blob + }) + ]); + + // Show success feedback + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch (err) { + console.error('Failed to copy image:', err); + alert('Failed to copy image to clipboard. Please try downloading instead.'); + } + }; + const swapColors = () => { const temp = gradientColor1; setGradientColor1(gradientColor2); @@ -405,13 +443,36 @@ export const ImageBeautifier: React.FC = () => {
Preview {image && ( - +
+ + +
)}
diff --git a/src/components/Sidebar/Sidebar.tsx b/src/components/Sidebar/Sidebar.tsx index 3ba4fb4..02c8bb7 100644 --- a/src/components/Sidebar/Sidebar.tsx +++ b/src/components/Sidebar/Sidebar.tsx @@ -77,9 +77,10 @@ export const Sidebar: React.FC = ({ activeTool, onToolChange }) => {/* Tools */}
- {tools.map((tool) => { + {tools.map((tool, index) => { const Icon = tool.icon; const isActive = activeTool === tool.id; + const shortcutKey = index === 9 ? '0' : (index + 1).toString(); return ( ); })}