feat(qr): sync generator text to url path payload and add generator button to scanner list
All checks were successful
Deploy to Production / deploy (push) Successful in 24s

This commit is contained in:
2026-03-04 03:07:17 +00:00
parent fdd841177b
commit 6be7abfe02
5 changed files with 45 additions and 2 deletions

7
package-lock.json generated
View File

@@ -9,6 +9,7 @@
"version": "0.6.20", "version": "0.6.20",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@gkucmierz/utils": "^1.28.7",
"barcode-detector": "^3.1.0", "barcode-detector": "^3.1.0",
"lucide-vue-next": "^0.575.0", "lucide-vue-next": "^0.575.0",
"marked": "^17.0.3", "marked": "^17.0.3",
@@ -2135,6 +2136,12 @@
"node": "^20.19.0 || ^22.13.0 || >=24" "node": "^20.19.0 || ^22.13.0 || >=24"
} }
}, },
"node_modules/@gkucmierz/utils": {
"version": "1.28.7",
"resolved": "https://registry.npmjs.org/@gkucmierz/utils/-/utils-1.28.7.tgz",
"integrity": "sha512-ekN8W4PL+SEeG0adWlkxxmTv6StLgxqtGRB9eBdWmkT5S4GSfJHYmzLY1ebc4jlL40OEa992ryvsT/TJS7eMmA==",
"license": "MIT"
},
"node_modules/@humanfs/core": { "node_modules/@humanfs/core": {
"version": "0.19.1", "version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",

View File

@@ -13,6 +13,7 @@
"prepare": "husky" "prepare": "husky"
}, },
"dependencies": { "dependencies": {
"@gkucmierz/utils": "^1.28.7",
"barcode-detector": "^3.1.0", "barcode-detector": "^3.1.0",
"lucide-vue-next": "^0.575.0", "lucide-vue-next": "^0.575.0",
"marked": "^17.0.3", "marked": "^17.0.3",

View File

@@ -4,6 +4,11 @@ import { Download } from 'lucide-vue-next'
import QRCode from 'qrcode' import QRCode from 'qrcode'
import { useFillHeight } from '../../composables/useFillHeight' import { useFillHeight } from '../../composables/useFillHeight'
import { useLocalStorage } from '../../composables/useLocalStorage' import { useLocalStorage } from '../../composables/useLocalStorage'
import { useRoute, useRouter } from 'vue-router'
import { fromBase64Url, toBase64Url } from '@gkucmierz/utils'
const route = useRoute()
const router = useRouter()
const text = useLocalStorage('text', '', 'qr-code') const text = useLocalStorage('text', '', 'qr-code')
const ecc = useLocalStorage('ecc', 'M', 'qr-code') const ecc = useLocalStorage('ecc', 'M', 'qr-code')
@@ -55,7 +60,26 @@ watch([text, ecc], () => {
generateQR() generateQR()
}) })
watch(text, (newText) => {
if (newText) {
router.replace({ name: 'QrCode', params: { payload: toBase64Url(newText) } })
} else {
router.replace({ name: 'QrCode', params: {} })
}
})
onMounted(() => { onMounted(() => {
if (route.params.payload) {
try {
const decodedPayload = fromBase64Url(route.params.payload)
text.value = decodedPayload
} catch (e) {
console.error('Failed to parse QR payload from URL', e)
}
} else if (text.value) {
router.replace({ name: 'QrCode', params: { payload: toBase64Url(text.value) } })
}
if (text.value) generateQR() if (text.value) generateQR()
}) })

View File

@@ -1,6 +1,8 @@
<script setup> <script setup>
import { ref, onMounted, onUnmounted, watch, computed } from 'vue' import { ref, onMounted, onUnmounted, watch, computed } from 'vue'
import { SwitchCamera, Trash2, Copy, Download, X } from 'lucide-vue-next' import { SwitchCamera, Trash2, Copy, Download, X, QrCode } from 'lucide-vue-next'
import { useRouter } from 'vue-router'
import { toBase64Url } from '@gkucmierz/utils'
import { useCamera } from '../../composables/useCamera' import { useCamera } from '../../composables/useCamera'
import { useQrDetection } from '../../composables/useQrDetection' import { useQrDetection } from '../../composables/useQrDetection'
@@ -12,6 +14,12 @@ const bgCanvas = ref(null)
let bgRafId = null let bgRafId = null
const videoRef = ref(null) const videoRef = ref(null)
const router = useRouter()
const navigateToGenerateQr = (text) => {
const payload = toBase64Url(text)
router.push({ name: 'QrCode', params: { payload } })
}
const overlayCanvas = ref(null) const overlayCanvas = ref(null)
const { const {
@@ -353,6 +361,9 @@ const isUrl = (string) => {
<button class="icon-btn" @click="copyToClipboard(code.value)" title="Copy" v-ripple> <button class="icon-btn" @click="copyToClipboard(code.value)" title="Copy" v-ripple>
<Copy size="18" /> <Copy size="18" />
</button> </button>
<button class="icon-btn" @click="navigateToGenerateQr(code.value)" title="Generate QR Code" v-ripple>
<QrCode size="18" />
</button>
<button class="icon-btn delete-btn" @click="removeCode(code.id)" title="Remove" v-ripple> <button class="icon-btn delete-btn" @click="removeCode(code.id)" title="Remove" v-ripple>
<Trash2 size="18" /> <Trash2 size="18" />
</button> </button>

View File

@@ -34,7 +34,7 @@ const routes = [
component: QrScanner component: QrScanner
}, },
{ {
path: '/qr-code', path: '/qr-code/:payload?',
name: 'QrCode', name: 'QrCode',
component: QrCode component: QrCode
}, },