Update src/App.jsx
Browse files- src/App.jsx +15 -121
src/App.jsx
CHANGED
|
@@ -1,4 +1,7 @@
|
|
| 1 |
import React, { useState, useEffect, useRef } from 'react';
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
// Main App component
|
| 4 |
const App = () => {
|
|
@@ -204,8 +207,9 @@ const App = () => {
|
|
| 204 |
|
| 205 |
// Effect to generate QR code on the main canvas
|
| 206 |
useEffect(() => {
|
| 207 |
-
|
| 208 |
-
|
|
|
|
| 209 |
errorCorrectionLevel: errorLevel,
|
| 210 |
color: {
|
| 211 |
dark: qrStyles[selectedStyleIndex].fg,
|
|
@@ -223,11 +227,12 @@ const App = () => {
|
|
| 223 |
|
| 224 |
// Effect to generate QR codes for style previews
|
| 225 |
useEffect(() => {
|
| 226 |
-
|
|
|
|
| 227 |
qrStyles.forEach((style, index) => {
|
| 228 |
const canvas = styleCanvasRefs.current[index];
|
| 229 |
if (canvas) {
|
| 230 |
-
|
| 231 |
errorCorrectionLevel: 'H',
|
| 232 |
width: 80, // Fixed size for preview
|
| 233 |
color: {
|
|
@@ -240,7 +245,7 @@ const App = () => {
|
|
| 240 |
}
|
| 241 |
});
|
| 242 |
}
|
| 243 |
-
}, [
|
| 244 |
|
| 245 |
// Function to download the generated QR code
|
| 246 |
const downloadQrCode = () => {
|
|
@@ -277,8 +282,9 @@ const App = () => {
|
|
| 277 |
|
| 278 |
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
|
| 279 |
|
| 280 |
-
|
| 281 |
-
|
|
|
|
| 282 |
|
| 283 |
if (!code) {
|
| 284 |
// Try inverting colors for decoding
|
|
@@ -287,7 +293,7 @@ const App = () => {
|
|
| 287 |
imageData.data[i + 1] = 255 - imageData.data[i + 1];
|
| 288 |
imageData.data[i + 2] = 255 - imageData.data[i + 2];
|
| 289 |
}
|
| 290 |
-
code =
|
| 291 |
}
|
| 292 |
|
| 293 |
if (code) {
|
|
@@ -392,7 +398,6 @@ const App = () => {
|
|
| 392 |
}
|
| 393 |
};
|
| 394 |
|
| 395 |
-
|
| 396 |
// QR Generator Tab Content
|
| 397 |
const QRGeneratorTab = () => (
|
| 398 |
<div className="flex flex-col lg:flex-row p-4 md:p-6 space-y-6 lg:space-y-0 lg:space-x-6 h-full">
|
|
@@ -577,119 +582,8 @@ const App = () => {
|
|
| 577 |
);
|
| 578 |
|
| 579 |
return (
|
|
|
|
| 580 |
<div className={`min-h-screen font-inter antialiased ${currentThemeClasses.bg} ${currentThemeClasses.text} transition-all duration-500 ease-in-out`}>
|
| 581 |
-
{/* Tailwind CSS CDN */}
|
| 582 |
-
<script src="https://cdn.tailwindcss.com"></script>
|
| 583 |
-
{/* Google Fonts - Inter for general text, Orbitron for headings */}
|
| 584 |
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Orbitron:wght@400;500;600;700;800;900&display=swap" rel="stylesheet" />
|
| 585 |
-
{/* Font Awesome for icons */}
|
| 586 |
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" crossOrigin="anonymous" referrerPolicy="no-referrer" />
|
| 587 |
-
{/* QR Code Generation Library (qrcode.js) */}
|
| 588 |
-
<script src="https://cdn.jsdelivr.net/npm/qrcode@1.4.4/build/qrcode.min.js"></script>
|
| 589 |
-
{/* QR Code Decoding Library (jsQR) */}
|
| 590 |
-
<script src="https://cdn.jsdelivr.net/npm/jsqr@1.1.1/dist/jsQR.min.js"></script>
|
| 591 |
-
|
| 592 |
-
{/* Custom CSS for animations and scrollbar */}
|
| 593 |
-
<style>
|
| 594 |
-
{`
|
| 595 |
-
.font-orbitron { font-family: 'Orbitron', sans-serif; }
|
| 596 |
-
.font-inter { font-family: 'Inter', sans-serif; }
|
| 597 |
-
|
| 598 |
-
/* Neon Glow for the header - Adjusted for readability */
|
| 599 |
-
@keyframes neon-glow {
|
| 600 |
-
0%, 100% {
|
| 601 |
-
/* Base text shadow for sharp inner glow */
|
| 602 |
-
text-shadow:
|
| 603 |
-
0 0 4px rgba(0, 255, 255, 0.8), /* Cyan */
|
| 604 |
-
0 0 8px rgba(255, 0, 255, 0.6), /* Magenta */
|
| 605 |
-
0 0 12px rgba(0, 150, 255, 0.4); /* Electric Blue */
|
| 606 |
-
transform: scale(1);
|
| 607 |
-
}
|
| 608 |
-
50% {
|
| 609 |
-
/* Expanded text shadow for soft outer glow */
|
| 610 |
-
text-shadow:
|
| 611 |
-
0 0 6px rgba(0, 255, 255, 1),
|
| 612 |
-
0 0 12px rgba(0, 255, 255, 0.8),
|
| 613 |
-
0 0 20px rgba(255, 0, 255, 0.7),
|
| 614 |
-
0 0 30px rgba(255, 0, 255, 0.5),
|
| 615 |
-
0 0 40px rgba(0, 150, 255, 0.6),
|
| 616 |
-
0 0 50px rgba(0, 150, 255, 0.4);
|
| 617 |
-
transform: scale(1.01);
|
| 618 |
-
}
|
| 619 |
-
}
|
| 620 |
-
.animate-neon-glow {
|
| 621 |
-
animation: neon-glow 2s infinite alternate; /* Slower pulse for elegance */
|
| 622 |
-
}
|
| 623 |
-
|
| 624 |
-
@keyframes scan-light {
|
| 625 |
-
0% {
|
| 626 |
-
transform: translateX(-100%);
|
| 627 |
-
}
|
| 628 |
-
100% {
|
| 629 |
-
transform: translateX(100%);
|
| 630 |
-
}
|
| 631 |
-
}
|
| 632 |
-
.scan-line {
|
| 633 |
-
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
| 634 |
-
width: 100%;
|
| 635 |
-
height: 2px;
|
| 636 |
-
animation: scan-light 3s infinite linear;
|
| 637 |
-
}
|
| 638 |
-
|
| 639 |
-
.custom-scrollbar::-webkit-scrollbar {
|
| 640 |
-
width: 8px;
|
| 641 |
-
}
|
| 642 |
-
.custom-scrollbar::-webkit-scrollbar-track {
|
| 643 |
-
background: rgba(255, 255, 255, 0.05);
|
| 644 |
-
border-radius: 10px;
|
| 645 |
-
}
|
| 646 |
-
.custom-scrollbar::-webkit-scrollbar-thumb {
|
| 647 |
-
background: rgba(255, 255, 255, 0.2);
|
| 648 |
-
border-radius: 10px;
|
| 649 |
-
}
|
| 650 |
-
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
|
| 651 |
-
background: rgba(255, 255, 255, 0.4);
|
| 652 |
-
}
|
| 653 |
-
|
| 654 |
-
/* Custom style for select dropdown arrow */
|
| 655 |
-
select {
|
| 656 |
-
-webkit-appearance: none;
|
| 657 |
-
-moz-appearance: none;
|
| 658 |
-
appearance: none;
|
| 659 |
-
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z' clip-rule='evenodd'%3E%3C/path%3E%3C/svg%3E");
|
| 660 |
-
background-repeat: no-repeat;
|
| 661 |
-
background-position: right 0.75rem center;
|
| 662 |
-
background-size: 1.5em 1.5em;
|
| 663 |
-
}
|
| 664 |
-
|
| 665 |
-
/* Animated background gradient - Cyberpunk style */
|
| 666 |
-
@keyframes cyberpunk-gradient-shift {
|
| 667 |
-
0% { background-position: 0% 0%; background-color: #1a0033; } /* Deep Purple */
|
| 668 |
-
25% { background-position: 25% 50%; background-color: #001a33; } /* Deep Blue */
|
| 669 |
-
50% { background-position: 50% 100%; background-color: #33001a; } /* Dark Magenta */
|
| 670 |
-
75% { background-position: 75% 50%; background-color: #003333; } /* Dark Teal */
|
| 671 |
-
100% { background-position: 100% 0%; background-color: #1a0033; } /* Back to Deep Purple */
|
| 672 |
-
}
|
| 673 |
-
.animate-gradient-shift {
|
| 674 |
-
background-size: 400% 400%;
|
| 675 |
-
animation: cyberpunk-gradient-shift 20s ease infinite; /* Slower, more immersive shift */
|
| 676 |
-
}
|
| 677 |
-
|
| 678 |
-
/* Light theme animated background gradient (if needed, adjust colors) */
|
| 679 |
-
@keyframes gradient-shift-light {
|
| 680 |
-
0% { background-position: 0% 0%; }
|
| 681 |
-
25% { background-position: 25% 50%; }
|
| 682 |
-
50% { background-position: 50% 100%; }
|
| 683 |
-
75% { background-position: 75% 50%; }
|
| 684 |
-
100% { background-position: 100% 0%; }
|
| 685 |
-
}
|
| 686 |
-
.animate-gradient-shift-light {
|
| 687 |
-
background-size: 400% 400%;
|
| 688 |
-
animation: gradient-shift-light 15s ease infinite;
|
| 689 |
-
}
|
| 690 |
-
`}
|
| 691 |
-
</style>
|
| 692 |
-
|
| 693 |
<div className="container mx-auto p-4 max-w-7xl">
|
| 694 |
<h1 className={`text-4xl lg:text-5xl font-extrabold text-center mb-8 bg-clip-text text-transparent bg-gradient-to-r ${currentThemeClasses.headerGlow} font-orbitron`}>
|
| 695 |
QuantumQR Studio
|
|
|
|
| 1 |
import React, { useState, useEffect, useRef } from 'react';
|
| 2 |
+
// Import QRCode and jsQR directly as they should be installed via npm
|
| 3 |
+
import QRCode from 'qrcode';
|
| 4 |
+
import jsQR from 'jsqr';
|
| 5 |
|
| 6 |
// Main App component
|
| 7 |
const App = () => {
|
|
|
|
| 207 |
|
| 208 |
// Effect to generate QR code on the main canvas
|
| 209 |
useEffect(() => {
|
| 210 |
+
// Use the imported QRCode directly, not window.QRCode
|
| 211 |
+
if (qrCanvasRef.current && QRCode && content.trim() !== '') {
|
| 212 |
+
QRCode.toCanvas(qrCanvasRef.current, content, {
|
| 213 |
errorCorrectionLevel: errorLevel,
|
| 214 |
color: {
|
| 215 |
dark: qrStyles[selectedStyleIndex].fg,
|
|
|
|
| 227 |
|
| 228 |
// Effect to generate QR codes for style previews
|
| 229 |
useEffect(() => {
|
| 230 |
+
// Use the imported QRCode directly, not window.QRCode
|
| 231 |
+
if (QRCode) {
|
| 232 |
qrStyles.forEach((style, index) => {
|
| 233 |
const canvas = styleCanvasRefs.current[index];
|
| 234 |
if (canvas) {
|
| 235 |
+
QRCode.toCanvas(canvas, "Sample", {
|
| 236 |
errorCorrectionLevel: 'H',
|
| 237 |
width: 80, // Fixed size for preview
|
| 238 |
color: {
|
|
|
|
| 245 |
}
|
| 246 |
});
|
| 247 |
}
|
| 248 |
+
}, [QRCode]); // Dependency changed to QRCode
|
| 249 |
|
| 250 |
// Function to download the generated QR code
|
| 251 |
const downloadQrCode = () => {
|
|
|
|
| 282 |
|
| 283 |
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
|
| 284 |
|
| 285 |
+
// Use the imported jsQR directly, not window.jsQR
|
| 286 |
+
if (jsQR) {
|
| 287 |
+
let code = jsQR(imageData.data, imageData.width, imageData.height);
|
| 288 |
|
| 289 |
if (!code) {
|
| 290 |
// Try inverting colors for decoding
|
|
|
|
| 293 |
imageData.data[i + 1] = 255 - imageData.data[i + 1];
|
| 294 |
imageData.data[i + 2] = 255 - imageData.data[i + 2];
|
| 295 |
}
|
| 296 |
+
code = jsQR(imageData.data, imageData.width, imageData.height);
|
| 297 |
}
|
| 298 |
|
| 299 |
if (code) {
|
|
|
|
| 398 |
}
|
| 399 |
};
|
| 400 |
|
|
|
|
| 401 |
// QR Generator Tab Content
|
| 402 |
const QRGeneratorTab = () => (
|
| 403 |
<div className="flex flex-col lg:flex-row p-4 md:p-6 space-y-6 lg:space-y-0 lg:space-x-6 h-full">
|
|
|
|
| 582 |
);
|
| 583 |
|
| 584 |
return (
|
| 585 |
+
// The main div for the application, no script or style tags here
|
| 586 |
<div className={`min-h-screen font-inter antialiased ${currentThemeClasses.bg} ${currentThemeClasses.text} transition-all duration-500 ease-in-out`}>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 587 |
<div className="container mx-auto p-4 max-w-7xl">
|
| 588 |
<h1 className={`text-4xl lg:text-5xl font-extrabold text-center mb-8 bg-clip-text text-transparent bg-gradient-to-r ${currentThemeClasses.headerGlow} font-orbitron`}>
|
| 589 |
QuantumQR Studio
|