From 839a98a6581fd0a1dca29ebb6fe98960fd11e51b Mon Sep 17 00:00:00 2001 From: Grzegorz Kucmierz Date: Fri, 27 Feb 2026 17:00:11 +0000 Subject: [PATCH] feat: add QR Scanner tool with history, export, persistence and fullscreen support --- package-lock.json | 64 ++++ package.json | 1 + src/components/Sidebar.vue | 1 + src/components/tools/QrScanner.vue | 584 +++++++++++++++++++++++++++++ src/router/index.js | 6 + vite.config.js | 6 + 6 files changed, 662 insertions(+) create mode 100644 src/components/tools/QrScanner.vue diff --git a/package-lock.json b/package-lock.json index 127c6eb..d258f5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "lucide-vue-next": "^0.575.0", "vue": "^3.5.25", + "vue-qrcode-reader": "^5.7.3", "vue-router": "^5.0.3" }, "devDependencies": { @@ -2514,6 +2515,18 @@ "sourcemap-codec": "^1.4.8" } }, + "node_modules/@types/dom-webcodecs": { + "version": "0.1.18", + "resolved": "https://registry.npmjs.org/@types/dom-webcodecs/-/dom-webcodecs-0.1.18.tgz", + "integrity": "sha512-vAvE8C9DGWR+tkb19xyjk1TSUlJ7RUzzp4a9Anu7mwBT+fpyePWK1UxmH14tMO5zHmrnrRIMg5NutnnDztLxgg==", + "license": "MIT" + }, + "node_modules/@types/emscripten": { + "version": "1.41.5", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.41.5.tgz", + "integrity": "sha512-cMQm7pxu6BxtHyqJ7mQZ2kXWV5SLmugybFdHCBbJ5eHzOo6VhBckEgAT3//rP5FwPHNPeEiq4SmQ5ucBwsOo4Q==", + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -2907,6 +2920,16 @@ "node": "18 || 20 || >=22" } }, + "node_modules/barcode-detector": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/barcode-detector/-/barcode-detector-2.2.2.tgz", + "integrity": "sha512-JcSekql+EV93evfzF9zBr+Y6aRfkR+QFvgyzbwQ0dbymZXoAI9+WgT7H1E429f+3RKNncHz2CW98VQtaaKpmfQ==", + "license": "MIT", + "dependencies": { + "@types/dom-webcodecs": "^0.1.11", + "zxing-wasm": "1.1.3" + } + }, "node_modules/baseline-browser-mapping": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", @@ -5235,6 +5258,12 @@ "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==", "license": "MIT" }, + "node_modules/sdp": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/sdp/-/sdp-3.2.1.tgz", + "integrity": "sha512-lwsAIzOPlH8/7IIjjz3K0zYBk7aBVVcvjMwt3M4fLxpjMYyy7i3I97SLHebgn4YBjirkzfp3RvRDWSKsh/+WFw==", + "license": "MIT" + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -6094,6 +6123,19 @@ } } }, + "node_modules/vue-qrcode-reader": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/vue-qrcode-reader/-/vue-qrcode-reader-5.7.3.tgz", + "integrity": "sha512-iSGko42FsEvdHyizBMBs/X+HMO9Z5ONDxjW+mQdoraOR5emRNedmjC5SEJdYzGz8ZP5ME3lwB4iHy3S7MOt5Qw==", + "license": "MIT", + "dependencies": { + "barcode-detector": "2.2.2", + "webrtc-adapter": "8.2.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/vue-router": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-5.0.3.tgz", @@ -6152,6 +6194,19 @@ "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", "license": "MIT" }, + "node_modules/webrtc-adapter": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-8.2.3.tgz", + "integrity": "sha512-gnmRz++suzmvxtp3ehQts6s2JtAGPuDPjA1F3a9ckNpG1kYdYuHWYpazoAnL9FS5/B21tKlhkorbdCXat0+4xQ==", + "license": "BSD-3-Clause", + "dependencies": { + "sdp": "^3.2.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">=3.10.0" + } + }, "node_modules/whatwg-url": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", @@ -6619,6 +6674,15 @@ "funding": { "url": "https://github.com/sponsors/eemeli" } + }, + "node_modules/zxing-wasm": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/zxing-wasm/-/zxing-wasm-1.1.3.tgz", + "integrity": "sha512-MYm9k/5YVs4ZOTIFwlRjfFKD0crhefgbnt1+6TEpmKUDFp3E2uwqGSKwQOd2hOIsta/7Usq4hnpNRYTLoljnfA==", + "license": "MIT", + "dependencies": { + "@types/emscripten": "^1.39.10" + } } } } diff --git a/package.json b/package.json index fb6a8d0..6d051a6 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "dependencies": { "lucide-vue-next": "^0.575.0", "vue": "^3.5.25", + "vue-qrcode-reader": "^5.7.3", "vue-router": "^5.0.3" }, "devDependencies": { diff --git a/src/components/Sidebar.vue b/src/components/Sidebar.vue index f61ef26..0b85956 100644 --- a/src/components/Sidebar.vue +++ b/src/components/Sidebar.vue @@ -13,6 +13,7 @@ defineProps({ Passwords Clipboard Sniffer URL Cleaner + QR Scanner diff --git a/src/components/tools/QrScanner.vue b/src/components/tools/QrScanner.vue new file mode 100644 index 0000000..d606f73 --- /dev/null +++ b/src/components/tools/QrScanner.vue @@ -0,0 +1,584 @@ + + + + + diff --git a/src/router/index.js b/src/router/index.js index 1d6383f..62dc0e3 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -3,6 +3,7 @@ import Main from '../components/Main.vue' import Passwords from '../components/tools/Passwords.vue' import ClipboardSniffer from '../components/tools/ClipboardSniffer.vue' import UrlCleaner from '../components/tools/UrlCleaner.vue' +import QrScanner from '../components/tools/QrScanner.vue' import PrivacyPolicy from '../views/PrivacyPolicy.vue' const routes = [ @@ -26,6 +27,11 @@ const routes = [ name: 'UrlCleaner', component: UrlCleaner }, + { + path: '/qr-scanner', + name: 'QrScanner', + component: QrScanner + }, { path: '/extension-privacy-policy', name: 'PrivacyPolicy', diff --git a/vite.config.js b/vite.config.js index da055f8..0fc66c8 100644 --- a/vite.config.js +++ b/vite.config.js @@ -43,5 +43,11 @@ export default defineConfig({ ], define: { '__APP_VERSION__': JSON.stringify(packageJson.version) + }, + server: { + host: true, + allowedHosts: [ + '.trycloudflare.com' + ] } })