Add "Copy QR Code" button with clipboard support
Implemented a copy-to-clipboard button for QR codes, including Blazor logic for feedback and disabled states. Injected IJSRuntime for JS interop and added supporting JS functions for image copying and fallback download. Reduced QR code image size for better compatibility. Added responsive and accessible CSS for the new button. Cleaned up timers and feedback state on component disposal.
This commit is contained in:
@@ -54,6 +54,154 @@
|
||||
<a href="." class="reload">Reload</a>
|
||||
<span class="dismiss">🗙</span>
|
||||
</div>
|
||||
|
||||
<!-- JavaScript functions for clipboard operations -->
|
||||
<script>
|
||||
// Original function for normal copy (kept for compatibility)
|
||||
window.copyImageToClipboard = async function (imageId) {
|
||||
try {
|
||||
// Check if Clipboard API is supported
|
||||
if (!navigator.clipboard || !navigator.clipboard.write) {
|
||||
console.warn('Clipboard API not supported');
|
||||
return false;
|
||||
}
|
||||
|
||||
const img = document.getElementById(imageId);
|
||||
if (!img) {
|
||||
console.error('Image element not found');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a canvas to convert the image to blob
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// Set canvas dimensions to match image
|
||||
canvas.width = img.naturalWidth || img.width;
|
||||
canvas.height = img.naturalHeight || img.height;
|
||||
|
||||
// Draw the image on canvas
|
||||
ctx.drawImage(img, 0, 0);
|
||||
|
||||
// Convert canvas to blob
|
||||
return new Promise((resolve) => {
|
||||
canvas.toBlob(async (blob) => {
|
||||
if (!blob) {
|
||||
console.error('Failed to create blob from canvas');
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Create ClipboardItem and write to clipboard
|
||||
const clipboardItem = new ClipboardItem({ 'image/png': blob });
|
||||
await navigator.clipboard.write([clipboardItem]);
|
||||
console.log('Image copied to clipboard successfully');
|
||||
resolve(true);
|
||||
} catch (error) {
|
||||
console.error('Failed to copy image to clipboard:', error);
|
||||
resolve(false);
|
||||
}
|
||||
}, 'image/png');
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error copying image to clipboard:', error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// New function for copying smaller images to clipboard
|
||||
window.copyImageToClipboardSmall = async function (imageId) {
|
||||
try {
|
||||
// Check if Clipboard API is supported
|
||||
if (!navigator.clipboard || !navigator.clipboard.write) {
|
||||
console.warn('Clipboard API not supported');
|
||||
return false;
|
||||
}
|
||||
|
||||
const img = document.getElementById(imageId);
|
||||
if (!img) {
|
||||
console.error('Image element not found');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a canvas to convert the image to blob
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// Set smaller canvas dimensions (max 512x512 for better clipboard handling)
|
||||
const maxSize = 512;
|
||||
let { width, height } = img.naturalWidth && img.naturalHeight ?
|
||||
{ width: img.naturalWidth, height: img.naturalHeight } :
|
||||
{ width: img.width, height: img.height };
|
||||
|
||||
// Scale down if image is too large
|
||||
if (width > maxSize || height > maxSize) {
|
||||
const scale = Math.min(maxSize / width, maxSize / height);
|
||||
width = Math.floor(width * scale);
|
||||
height = Math.floor(height * scale);
|
||||
}
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
// Draw the image on canvas with scaling
|
||||
ctx.drawImage(img, 0, 0, width, height);
|
||||
|
||||
// Convert canvas to blob with higher compression
|
||||
return new Promise((resolve) => {
|
||||
canvas.toBlob(async (blob) => {
|
||||
if (!blob) {
|
||||
console.error('Failed to create blob from canvas');
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Create ClipboardItem and write to clipboard
|
||||
const clipboardItem = new ClipboardItem({ 'image/png': blob });
|
||||
await navigator.clipboard.write([clipboardItem]);
|
||||
console.log('Smaller image copied to clipboard successfully');
|
||||
resolve(true);
|
||||
} catch (error) {
|
||||
console.error('Failed to copy image to clipboard:', error);
|
||||
resolve(false);
|
||||
}
|
||||
}, 'image/png', 0.8); // Lower quality for smaller size
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error copying image to clipboard:', error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Fallback function for browsers that don't support Clipboard API
|
||||
window.downloadQRCode = function (imageId, filename = 'qrcode.png') {
|
||||
try {
|
||||
const img = document.getElementById(imageId);
|
||||
if (!img) {
|
||||
console.error('Image element not found');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a temporary link element
|
||||
const link = document.createElement('a');
|
||||
link.href = img.src;
|
||||
link.download = filename;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error downloading image:', error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script>
|
||||
</body>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user