Dark Mode

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 534d2b9

Browse files
authored andcommitted
Fix clipboard copy for JPEG and other image formats
The Clipboard API only supports writing image/png. Added a helper function that converts any image format (JPEG, GIF, WebP, etc.) to PNG via canvas before writing to clipboard.
1 parent 096511a commit 534d2b9

File tree

1 file changed

+48
-5
lines changed
  • clipboard-backup.html

1 file changed

+48
-5
lines changed

clipboard-backup.html

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -488,16 +488,41 @@

Saved Backups

488488
return item;
489489
}
490490

491+
// Convert any image data URL to PNG blob (required for clipboard API)
492+
async function convertImageToPngBlob(dataUrl) {
493+
return new Promise((resolve, reject) => {
494+
const img = new Image();
495+
img.onload = () => {
496+
const canvas = document.createElement('canvas');
497+
canvas.width = img.naturalWidth;
498+
canvas.height = img.naturalHeight;
499+
const ctx = canvas.getContext('2d');
500+
ctx.drawImage(img, 0, 0);
501+
canvas.toBlob((blob) => {
502+
if (blob) {
503+
resolve(blob);
504+
} else {
505+
reject(new Error('Failed to convert image to PNG'));
506+
}
507+
}, 'image/png');
508+
};
509+
img.onerror = () => reject(new Error('Failed to load image'));
510+
img.src = dataUrl;
511+
});
512+
}
513+
491514
async function copyBackup(backup, button) {
492515
try {
493-
const clipboardItems = [];
494516
const blobParts = {};
517+
let hasImage = false;
495518

496519
for (const [mimeType, data] of Object.entries(backup.formats)) {
497520
if (mimeType.startsWith('image/')) {
498-
// Convert data URL to blob
499-
const response = await fetch(data);
500-
blobParts[mimeType] = await response.blob();
521+
// Convert all images to PNG (only format supported by clipboard API)
522+
if (!hasImage) {
523+
blobParts['image/png'] = await convertImageToPngBlob(data);
524+
hasImage = true;
525+
}
501526
} else {
502527
blobParts[mimeType] = new Blob([data], { type: mimeType });
503528
}
@@ -530,7 +555,25 @@

Saved Backups

530555
alert('Failed to copy to clipboard. Please try again.');
531556
}
532557
} else {
533-
alert('Failed to copy to clipboard. Please try again.');
558+
// Fallback for images: try copying just the image as PNG
559+
const imageFormats = Object.entries(backup.formats).filter(([k]) => k.startsWith('image/'));
560+
if (imageFormats.length > 0) {
561+
try {
562+
const pngBlob = await convertImageToPngBlob(imageFormats[0][1]);
563+
const clipboardItem = new ClipboardItem({ 'image/png': pngBlob });
564+
await navigator.clipboard.write([clipboardItem]);
565+
button.innerHTML = ' Copied!';
566+
button.classList.add('copied');
567+
setTimeout(() => {
568+
button.innerHTML = ' Copy';
569+
button.classList.remove('copied');
570+
}, 2000);
571+
} catch (e) {
572+
alert('Failed to copy to clipboard. Please try again.');
573+
}
574+
} else {
575+
alert('Failed to copy to clipboard. Please try again.');
576+
}
534577
}
535578
}
536579
}

0 commit comments

Comments
(0)