feat: move qrcode scanner into reuseable component (#3567)
Co-authored-by: Tiago Vasconcelos <talvasconcelos@gmail.com>
This commit is contained in:
parent
4da651b74a
commit
6449276003
12 changed files with 111 additions and 65 deletions
2
lnbits/static/bundle-components.min.js
vendored
2
lnbits/static/bundle-components.min.js
vendored
File diff suppressed because one or more lines are too long
2
lnbits/static/bundle.min.js
vendored
2
lnbits/static/bundle.min.js
vendored
File diff suppressed because one or more lines are too long
55
lnbits/static/js/components/lnbits-qrcode-scanner.js
Normal file
55
lnbits/static/js/components/lnbits-qrcode-scanner.js
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
window.app.component('lnbits-qrcode-scanner', {
|
||||
template: '#lnbits-qrcode-scanner',
|
||||
mixins: [window.windowMixin],
|
||||
watch: {
|
||||
'g.showScanner'(newVal) {
|
||||
if (newVal === true) {
|
||||
if (this.g.hasCamera === false) {
|
||||
Quasar.Notify.create({
|
||||
message: 'No camera found on this device.',
|
||||
type: 'negative'
|
||||
})
|
||||
this.g.showScanner = false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
detect(val) {
|
||||
const rawValue = val[0].rawValue
|
||||
console.log('Detected QR code value:', rawValue)
|
||||
this.$emit('detect', rawValue)
|
||||
this.g.showScanner = false
|
||||
},
|
||||
async onInitQR(promise) {
|
||||
try {
|
||||
await promise
|
||||
} catch (error) {
|
||||
const mapping = {
|
||||
NotAllowedError: 'ERROR: you need to grant camera access permission',
|
||||
NotFoundError: 'ERROR: no camera on this device',
|
||||
NotSupportedError:
|
||||
'ERROR: secure context required (HTTPS, localhost)',
|
||||
NotReadableError: 'ERROR: is the camera already in use?',
|
||||
OverconstrainedError: 'ERROR: installed cameras are not suitable',
|
||||
StreamApiNotSupportedError:
|
||||
'ERROR: Stream API is not supported in this browser',
|
||||
InsecureContextError:
|
||||
'ERROR: Camera access is only permitted in secure context. Use HTTPS or localhost rather than HTTP.'
|
||||
}
|
||||
const valid_error = Object.keys(mapping).filter(key => {
|
||||
return error.name === key
|
||||
})
|
||||
const camera_error = valid_error
|
||||
? mapping[valid_error]
|
||||
: `ERROR: Camera error (${error.name})`
|
||||
Quasar.Notify.create({
|
||||
message: camera_error,
|
||||
type: 'negative'
|
||||
})
|
||||
this.g.hasCamera = false
|
||||
this.showScanner = false
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -11,6 +11,7 @@ const localStore = (key, defaultValue) => {
|
|||
window.g = Vue.reactive({
|
||||
isUserAuthorized: !!Quasar.Cookies.get('is_lnbits_user_authorized'),
|
||||
offline: !navigator.onLine,
|
||||
hasCamera: false,
|
||||
visibleDrawer: false,
|
||||
extensions: WINDOW_SETTINGS.EXTENSIONS,
|
||||
user: null,
|
||||
|
|
@ -18,6 +19,7 @@ window.g = Vue.reactive({
|
|||
fiatBalance: 0,
|
||||
exchangeRate: 0,
|
||||
fiatTracking: false,
|
||||
showScanner: false,
|
||||
payments: [],
|
||||
walletEventListeners: [],
|
||||
showNewWalletDialog: false,
|
||||
|
|
@ -52,7 +54,8 @@ window.g = Vue.reactive({
|
|||
),
|
||||
ads: WINDOW_SETTINGS.AD_SPACE.split(',').map(ad => ad.split(';')),
|
||||
denomination: WINDOW_SETTINGS.LNBITS_DENOMINATION,
|
||||
isSatsDenomination: WINDOW_SETTINGS.LNBITS_DENOMINATION == 'sats'
|
||||
isSatsDenomination: WINDOW_SETTINGS.LNBITS_DENOMINATION == 'sats',
|
||||
scanDetectCallback: null
|
||||
})
|
||||
|
||||
window.dateFormat = 'YYYY-MM-DD HH:mm'
|
||||
|
|
@ -78,3 +81,9 @@ if (navigator.serviceWorker != null) {
|
|||
console.log('Registered events at scope: ', registration.scope)
|
||||
})
|
||||
}
|
||||
|
||||
if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {
|
||||
navigator.mediaDevices.enumerateDevices().then(devices => {
|
||||
window.g.hasCamera = devices.some(device => device.kind === 'videoinput')
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,12 +97,6 @@ window.PageWallet = {
|
|||
msatoshiFormat(value) {
|
||||
return LNbits.utils.formatSat(value / 1000)
|
||||
},
|
||||
closeCamera() {
|
||||
this.parse.camera.show = false
|
||||
},
|
||||
showCamera() {
|
||||
this.parse.camera.show = true
|
||||
},
|
||||
showReceiveDialog() {
|
||||
this.receive.show = true
|
||||
this.receive.status = 'pending'
|
||||
|
|
@ -205,35 +199,6 @@ window.PageWallet = {
|
|||
this.receive.status = 'pending'
|
||||
})
|
||||
},
|
||||
async onInitQR(promise) {
|
||||
try {
|
||||
await promise
|
||||
} catch (error) {
|
||||
const mapping = {
|
||||
NotAllowedError: 'ERROR: you need to grant camera access permission',
|
||||
NotFoundError: 'ERROR: no camera on this device',
|
||||
NotSupportedError:
|
||||
'ERROR: secure context required (HTTPS, localhost)',
|
||||
NotReadableError: 'ERROR: is the camera already in use?',
|
||||
OverconstrainedError: 'ERROR: installed cameras are not suitable',
|
||||
StreamApiNotSupportedError:
|
||||
'ERROR: Stream API is not supported in this browser',
|
||||
InsecureContextError:
|
||||
'ERROR: Camera access is only permitted in secure context. Use HTTPS or localhost rather than HTTP.'
|
||||
}
|
||||
const valid_error = Object.keys(mapping).filter(key => {
|
||||
return error.name === key
|
||||
})
|
||||
const camera_error = valid_error
|
||||
? mapping[valid_error]
|
||||
: `ERROR: Camera error (${error.name})`
|
||||
this.parse.camera.show = false
|
||||
Quasar.Notify.create({
|
||||
message: camera_error,
|
||||
type: 'negative'
|
||||
})
|
||||
}
|
||||
},
|
||||
lnurlScan() {
|
||||
LNbits.api
|
||||
.request('POST', '/api/v1/lnurlscan', this.g.wallet.adminkey, {
|
||||
|
|
@ -281,8 +246,8 @@ window.PageWallet = {
|
|||
LNbits.utils.notifyApiError(err)
|
||||
})
|
||||
},
|
||||
decodeQR(res) {
|
||||
this.parse.data.request = res[0].rawValue
|
||||
decodeQR(val) {
|
||||
this.parse.data.request = val
|
||||
this.decodeRequest()
|
||||
this.parse.camera.show = false
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,15 @@
|
|||
window.windowMixin = {
|
||||
methods: {
|
||||
handleScan(val) {
|
||||
if (this.g.scanDetectCallback) {
|
||||
this.g.scanDetectCallback(val)
|
||||
this.g.scanDetectCallback = null
|
||||
}
|
||||
},
|
||||
openScanDialog(scanDetectCallback) {
|
||||
this.g.showScanner = true
|
||||
this.g.scanDetectCallback = scanDetectCallback
|
||||
},
|
||||
openNewWalletDialog(walletType = 'lightning') {
|
||||
this.g.newWalletType = walletType
|
||||
this.g.showNewWalletDialog = true
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@
|
|||
"js/components/lnbits-header-wallets.js",
|
||||
"js/components/lnbits-drawer.js",
|
||||
"js/components/lnbits-theme.js",
|
||||
"js/components/lnbits-qrcode-scanner.js",
|
||||
"js/components/lnbits-manage-extension-list.js",
|
||||
"js/components/lnbits-manage-wallet-list.js",
|
||||
"js/components/lnbits-language-dropdown.js",
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
<div id="vue">
|
||||
<q-layout view="hHh lpR lfr" v-cloak>
|
||||
<lnbits-disclaimer></lnbits-disclaimer>
|
||||
<lnbits-qrcode-scanner @detect="handleScan"></lnbits-qrcode-scanner>
|
||||
<lnbits-theme></lnbits-theme>
|
||||
<lnbits-header></lnbits-header>
|
||||
{% block drawer %}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ include('components/admin/extensions.vue') %} {%
|
|||
include('components/admin/assets-config.vue') %} {%
|
||||
include('components/admin/notifications.vue') %} {%
|
||||
include('components/admin/server.vue') %} {%
|
||||
include('components/lnbits-qrcode-scanner.vue') %} {%
|
||||
include('components/lnbits-disclaimer.vue') %} {%
|
||||
include('components/lnbits-footer.vue') %} {%
|
||||
include('components/lnbits-header.vue') %} {%
|
||||
|
|
|
|||
22
lnbits/templates/components/lnbits-qrcode-scanner.vue
Normal file
22
lnbits/templates/components/lnbits-qrcode-scanner.vue
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<template id="lnbits-qrcode-scanner">
|
||||
<q-dialog v-model="g.showScanner" position="top">
|
||||
<q-card class="q-pa-lg q-pt-xl">
|
||||
<div class="text-center q-mb-lg">
|
||||
<qrcode-stream
|
||||
@detect="detect"
|
||||
@camera-on="onInitQR"
|
||||
class="rounded-borders"
|
||||
></qrcode-stream>
|
||||
</div>
|
||||
<div class="row q-mt-lg">
|
||||
<q-btn
|
||||
@click="g.showScanner = false"
|
||||
flat
|
||||
color="grey"
|
||||
class="q-ml-auto"
|
||||
:label="$t('cancel')"
|
||||
></q-btn>
|
||||
</div>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
|
@ -156,14 +156,15 @@
|
|||
icon="file_upload"
|
||||
></q-btn>
|
||||
<q-btn
|
||||
v-if="g.hasCamera"
|
||||
unelevated
|
||||
color="secondary"
|
||||
icon="qr_code_scanner"
|
||||
color="secondary"
|
||||
@click="openScanDialog(decodeQR)"
|
||||
:disable="
|
||||
!this.g.wallet.canReceivePayments &&
|
||||
!this.g.wallet.canSendPayments
|
||||
"
|
||||
@click="showCamera"
|
||||
>
|
||||
<q-tooltip
|
||||
><span v-text="$t('camera_tooltip')"></span
|
||||
|
|
@ -842,27 +843,6 @@
|
|||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<q-dialog v-model="parse.camera.show" position="top">
|
||||
<q-card class="q-pa-lg q-pt-xl">
|
||||
<div class="text-center q-mb-lg">
|
||||
<qrcode-stream
|
||||
@detect="decodeQR"
|
||||
@camera-on="onInitQR"
|
||||
class="rounded-borders"
|
||||
></qrcode-stream>
|
||||
</div>
|
||||
<div class="row q-mt-lg">
|
||||
<q-btn
|
||||
@click="closeCamera"
|
||||
flat
|
||||
color="grey"
|
||||
class="q-ml-auto"
|
||||
:label="$t('cancel')"
|
||||
></q-btn>
|
||||
</div>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<div
|
||||
class="lt-md fixed-bottom left-0 right-0 bg-primary text-white shadow-2 z-top"
|
||||
>
|
||||
|
|
@ -877,12 +857,13 @@
|
|||
<q-tab @click="showParseDialog" icon="file_upload" :label="$t('send')">
|
||||
</q-tab>
|
||||
</q-tabs>
|
||||
|
||||
<q-btn
|
||||
@click="openScanDialog(decodeQR)"
|
||||
round
|
||||
size="35px"
|
||||
unelevated
|
||||
size="35px"
|
||||
icon="qr_code_scanner"
|
||||
@click="showCamera"
|
||||
class="text-white bg-primary z-top vertical-bottom absolute-center absolute"
|
||||
>
|
||||
</q-btn>
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@
|
|||
"js/components/lnbits-header-wallets.js",
|
||||
"js/components/lnbits-drawer.js",
|
||||
"js/components/lnbits-theme.js",
|
||||
"js/components/lnbits-qrcode-scanner.js",
|
||||
"js/components/lnbits-manage-extension-list.js",
|
||||
"js/components/lnbits-manage-wallet-list.js",
|
||||
"js/components/lnbits-language-dropdown.js",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue