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.
209 lines
8.2 KiB
HTML
209 lines
8.2 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes" />
|
|
<meta name="theme-color" content="#2d5a27" />
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
<meta name="description" content="QRPay - Generate QR payment codes instantly for secure bank transfers" />
|
|
<title>QRPay</title>
|
|
<base href="/" />
|
|
<link rel="preload" id="webassembly" />
|
|
<link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.min.css" />
|
|
<link rel="stylesheet" href="css/app.css" />
|
|
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
|
|
<link rel="apple-touch-icon" href="logo.svg" />
|
|
<link href="QRPay.styles.css" rel="stylesheet" />
|
|
<script type="importmap"></script>
|
|
</head>
|
|
|
|
<body>
|
|
<div id="app">
|
|
<!-- Modern Loading Screen with Logo -->
|
|
<div class="loading-container">
|
|
<div class="loading-content">
|
|
<!-- Logo -->
|
|
<div class="loading-logo">
|
|
<img src="logo.svg" alt="QRPay Logo" />
|
|
</div>
|
|
|
|
<!-- Brand Name -->
|
|
<h1 class="loading-title">QRPay</h1>
|
|
|
|
<!-- Progress Indicator -->
|
|
<div class="loading-progress-wrapper">
|
|
<svg class="loading-progress">
|
|
<circle class="loading-track" r="40%" cx="50%" cy="50%" />
|
|
<circle class="loading-fill" r="40%" cx="50%" cy="50%" />
|
|
</svg>
|
|
</div>
|
|
|
|
<!-- Loading Text -->
|
|
<div class="loading-progress-text"></div>
|
|
|
|
<!-- Subtitle -->
|
|
<p class="loading-subtitle">Initializing secure payment system</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="blazor-error-ui">
|
|
An unhandled error has occurred.
|
|
<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>
|
|
|
|
</html>
|