Skip to content

Commit ff95c9f

Browse files
committed
feat: copy text
1 parent 7fc2cd1 commit ff95c9f

File tree

1 file changed

+81
-10
lines changed

1 file changed

+81
-10
lines changed

src/components/History.tsx

Lines changed: 81 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ export function History() {
131131
const [loading, setLoading] = useState(true);
132132
const [expandedEntry, setExpandedEntry] = useState<number | null>(null);
133133
const [diffData, setDiffData] = useState<{[key: number]: TextDiff}>({});
134+
const [copiedStates, setCopiedStates] = useState<{[key: string]: boolean}>({});
134135

135136
useEffect(() => {
136137
loadHistoryData();
@@ -167,6 +168,62 @@ export function History() {
167168
}
168169
};
169170

171+
const copyToClipboard = async (text: string, type: 'original' | 'transformed', entryIndex: number) => {
172+
try {
173+
await navigator.clipboard.writeText(text);
174+
const key = `${entryIndex}-${type}`;
175+
setCopiedStates(prev => ({ ...prev, [key]: true }));
176+
177+
// Reset the copied state after 2 seconds
178+
setTimeout(() => {
179+
setCopiedStates(prev => ({ ...prev, [key]: false }));
180+
}, 2000);
181+
} catch (error) {
182+
console.error('Failed to copy text:', error);
183+
await message('Failed to copy text to clipboard', { title: 'Error', kind: 'error' });
184+
}
185+
};
186+
187+
const CopyButton = ({
188+
text,
189+
type,
190+
entryIndex
191+
}: {
192+
text: string;
193+
type: 'original' | 'transformed';
194+
entryIndex: number;
195+
}) => {
196+
const key = `${entryIndex}-${type}`;
197+
const isCopied = copiedStates[key];
198+
199+
return (
200+
<button
201+
onClick={(e) => {
202+
e.stopPropagation();
203+
copyToClipboard(text, type, entryIndex);
204+
}}
205+
className="flex items-center gap-1 text-xs text-text-secondary hover:text-text-primary transition-colors px-2 py-1 rounded hover:bg-background-tertiary"
206+
title={`Copy ${type} text`}
207+
>
208+
{isCopied ? (
209+
<>
210+
<svg className="w-3 h-3 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
211+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
212+
</svg>
213+
<span className="text-green-600">Copied!</span>
214+
</>
215+
) : (
216+
<>
217+
<svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
218+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
219+
</svg>
220+
<span>Copy</span>
221+
</>
222+
)}
223+
</button>
224+
);
225+
};
226+
170227
const toggleDiffView = (index: number) => {
171228
if (expandedEntry === index) {
172229
setExpandedEntry(null);
@@ -300,23 +357,37 @@ export function History() {
300357
{expandedEntry === index && diffData[index] && (
301358
<div className="mt-4 space-y-4 border-t border-border-primary pt-4">
302359
<div>
303-
<div className="flex items-center gap-2 mb-2">
304-
<span className="text-sm text-text-primary">Original</span>
305-
<span className="text-xs text-red-600 bg-red-50 px-2 py-1 rounded">
306-
-{diffData[index].removed_count} words
307-
</span>
360+
<div className="flex items-center justify-between mb-2">
361+
<div className="flex items-center gap-2">
362+
<span className="text-sm text-text-primary">Original</span>
363+
<span className="text-xs text-red-600 bg-red-50 px-2 py-1 rounded">
364+
-{diffData[index].removed_count} words
365+
</span>
366+
</div>
367+
<CopyButton
368+
text={entry.original_text}
369+
type="original"
370+
entryIndex={index}
371+
/>
308372
</div>
309373
<div className="border border-border-primary rounded-lg p-3 bg-background-tertiary">
310374
{renderDiffText(diffData[index].original_diff, false)}
311375
</div>
312376
</div>
313377

314378
<div>
315-
<div className="flex items-center gap-2 mb-2">
316-
<span className="text-sm text-text-primary">Transformed</span>
317-
<span className="text-xs text-green-600 bg-green-50 px-2 py-1 rounded">
318-
+{diffData[index].added_count} words
319-
</span>
379+
<div className="flex items-center justify-between mb-2">
380+
<div className="flex items-center gap-2">
381+
<span className="text-sm text-text-primary">Transformed</span>
382+
<span className="text-xs text-green-600 bg-green-50 px-2 py-1 rounded">
383+
+{diffData[index].added_count} words
384+
</span>
385+
</div>
386+
<CopyButton
387+
text={entry.transformed_text}
388+
type="transformed"
389+
entryIndex={index}
390+
/>
320391
</div>
321392
<div className="border border-border-primary rounded-lg p-3 bg-background-tertiary">
322393
{renderDiffText(diffData[index].transformed_diff, true)}

0 commit comments

Comments
 (0)