feat: add copy, download and write NFC to qrcode components (#3335)

This commit is contained in:
dni ⚡
2025-09-02 14:48:29 +02:00
committed by GitHub
parent 5021570f68
commit 2375f7bcf8
11 changed files with 269 additions and 172 deletions

View File

@@ -2,7 +2,7 @@ exclude: '^lnbits/static/bundle.*|^docs/.*|^lnbits/static/vendor/.*|^lnbits/exte
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0 rev: v6.0.0
hooks: hooks:
- id: trailing-whitespace - id: trailing-whitespace
- id: end-of-file-fixer - id: end-of-file-fixer
@@ -14,16 +14,16 @@ repos:
- id: mixed-line-ending - id: mixed-line-ending
- id: check-case-conflict - id: check-case-conflict
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 24.2.0 rev: 25.1.0
hooks: hooks:
- id: black - id: black
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.2 rev: v0.12.10
hooks: hooks:
- id: ruff - id: ruff
args: [ --fix, --exit-non-zero-on-fix ] args: [ --fix, --exit-non-zero-on-fix ]
- repo: https://github.com/pre-commit/mirrors-prettier - repo: https://github.com/rbubley/mirrors-prettier
rev: "v4.0.0-alpha.8" rev: v3.6.2
hooks: hooks:
- id: prettier - id: prettier
types_or: [css, javascript, html, json] types_or: [css, javascript, html, json]

View File

@@ -53,8 +53,7 @@
<div class="q-pa-md"> <div class="q-pa-md">
<lnbits-qrcode <lnbits-qrcode
:value="wallet.adminkey" :value="wallet.adminkey"
:options="{ width: 250 }" :show-buttons="false"
class="rounded-borders"
></lnbits-qrcode> ></lnbits-qrcode>
</div> </div>
</q-popup-proxy> </q-popup-proxy>
@@ -86,8 +85,7 @@
<div class="q-pa-md"> <div class="q-pa-md">
<lnbits-qrcode <lnbits-qrcode
:value="wallet.inkey" :value="wallet.inkey"
:options="{ width: 250 }" :show-buttons="false"
class="rounded-borders"
></lnbits-qrcode> ></lnbits-qrcode>
</div> </div>
</q-popup-proxy> </q-popup-proxy>

View File

@@ -328,13 +328,10 @@
<q-card v-if="selectedRelease" class="q-pa-lg lnbits__dialog-card"> <q-card v-if="selectedRelease" class="q-pa-lg lnbits__dialog-card">
<q-card-section> <q-card-section>
<div v-if="selectedRelease.paymentRequest"> <div v-if="selectedRelease.paymentRequest">
<a :href="'lightning:' + selectedRelease.paymentRequest"> <lnbits-qrcode
<q-responsive :ratio="1" class="q-mx-xl"> :value="'lightning:' + selectedRelease.paymentRequest.toUpperCase()"
<lnbits-qrcode :href="'lightning:' + selectedRelease.paymentRequest"
:value="'lightning:' + selectedRelease.paymentRequest.toUpperCase()" ></lnbits-qrcode>
></lnbits-qrcode>
</q-responsive>
</a>
</div> </div>
<div v-else> <div v-else>
<q-spinner-bars color="primary" size="2.55em"></q-spinner-bars> <q-spinner-bars color="primary" size="2.55em"></q-spinner-bars>
@@ -702,13 +699,10 @@
<q-card-section v-if="selectedExtension.payToEnable.showQRCode"> <q-card-section v-if="selectedExtension.payToEnable.showQRCode">
<div class="row q-mt-lg"> <div class="row q-mt-lg">
<div v-if="selectedExtension.payToEnable.paymentRequest" class="col"> <div v-if="selectedExtension.payToEnable.paymentRequest" class="col">
<a <lnbits-qrcode
:value="'lightning:' + selectedExtension.payToEnable.paymentRequest.toUpperCase()"
:href="'lightning:' + selectedExtension.payToEnable.paymentRequest" :href="'lightning:' + selectedExtension.payToEnable.paymentRequest"
> ></lnbits-qrcode>
<lnbits-qrcode
:value="'lightning:' + selectedExtension.payToEnable.paymentRequest.toUpperCase()"
></lnbits-qrcode>
</a>
</div> </div>
<div v-else class="col"> <div v-else class="col">
<q-spinner-bars color="primary" size="2.55em"></q-spinner-bars> <q-spinner-bars color="primary" size="2.55em"></q-spinner-bars>

View File

@@ -209,16 +209,6 @@
></payment-list> ></payment-list>
</q-card-section> </q-card-section>
</q-card> </q-card>
<div id="hiddenQrCodeContainer" style="display: none">
<lnbits-qrcode
v-if="receive.fiatPaymentReq"
:value="receive.fiatPaymentReq"
></lnbits-qrcode>
<lnbits-qrcode
v-else
:value="'lightning:' + (this.receive.paymentReq || '').toUpperCase()"
></lnbits-qrcode>
</div>
</div> </div>
{% if HIDE_API %} {% if HIDE_API %}
<div class="col-12 col-md-4 q-gutter-y-md"> <div class="col-12 col-md-4 q-gutter-y-md">
@@ -277,13 +267,15 @@
:label="$t('drain_funds')" :label="$t('drain_funds')"
> >
<q-card> <q-card>
<q-card-section class="text-center"> <q-card-section>
<a href="lightning:{{wallet.lnurlwithdraw_full}}"> <lnbits-qrcode
<lnbits-qrcode value="lightning:{{wallet.lnurlwithdraw_full}}"
:value="lightning:{{wallet.lnurlwithdraw_full}}" href="lightning:{{wallet.lnurlwithdraw_full}}"
></lnbits-qrcode> ></lnbits-qrcode>
</a> <p
<p v-text="$t('drain_funds_desc')"></p> class="text-center"
v-text="$t('drain_funds_desc')"
></p>
</q-card-section> </q-card-section>
</q-card> </q-card>
</q-expansion-item> </q-expansion-item>
@@ -411,21 +403,15 @@
:label="$t('export_to_phone')" :label="$t('export_to_phone')"
> >
<q-card> <q-card>
<q-card-section class="text-center"> <q-card-section>
<p v-text="$t('export_to_phone_desc')"></p> <p
class="text-center"
v-text="$t('export_to_phone_desc')"
></p>
<lnbits-qrcode <lnbits-qrcode
:value="`${baseUrl}wallet?usr=${g.user.id}&wal=${g.wallet.id}`" :value="`${baseUrl}wallet?usr=${g.user.id}&wal=${g.wallet.id}`"
></lnbits-qrcode> ></lnbits-qrcode>
</q-card-section> </q-card-section>
<span v-text="exportWalletQR"></span>
<q-card-actions class="flex-center q-pb-md">
<q-btn
outline
color="grey"
:label="$t('copy_wallet_url')"
@click="copyText(`${baseUrl}wallet?usr=${g.user.id}&wal=${g.wallet.id}`)"
></q-btn>
</q-card-actions>
</q-card> </q-card>
</q-expansion-item> </q-expansion-item>
</q-card-section> </q-card-section>
@@ -862,18 +848,19 @@
v-else-if="receive.paymentReq && receive.lnurl == null" v-else-if="receive.paymentReq && receive.lnurl == null"
class="q-pa-lg q-pt-xl lnbits__dialog-card" class="q-pa-lg q-pt-xl lnbits__dialog-card"
> >
<div class="text-center q-mb-lg"> <lnbits-qrcode
<a v-if="receive.fiatPaymentReq"
v-if="receive.fiatPaymentReq" :show-buttons="false"
:href="receive.fiatPaymentReq" :href="receive.fiatPaymentReq"
target="_blank" :value="receive.fiatPaymentReq"
> >
<div v-html="invoiceQrCode"></div> </lnbits-qrcode>
</a> <lnbits-qrcode
<a v-else :href="'lightning:' + receive.paymentReq"> v-else
<div v-html="invoiceQrCode"></div> :href="'lightning:' + receive.paymentReq"
</a> :value="'lightning:' + receive.paymentReq"
</div> >
</lnbits-qrcode>
<div class="text-center"> <div class="text-center">
<h3 class="q-my-md"> <h3 class="q-my-md">
<span v-text="formattedAmount"></span> <span v-text="formattedAmount"></span>
@@ -898,12 +885,6 @@
</div> </div>
</div> </div>
<div class="row q-mt-lg"> <div class="row q-mt-lg">
<q-btn
outline
color="grey"
@click="copyText(receive.fiatPaymentReq || receive.paymentReq)"
:label="$t('copy_invoice')"
></q-btn>
<q-btn <q-btn
v-close-popup v-close-popup
flat flat

File diff suppressed because one or more lines are too long

View File

@@ -9,19 +9,123 @@ window.app.component('lnbits-qrcode', {
type: String, type: String,
required: true required: true
}, },
options: Object nfc: {
type: Boolean,
default: false
},
showButtons: {
type: Boolean,
default: true
},
href: {
type: String,
default: ''
},
margin: {
type: Number,
default: 3
},
maxWidth: {
type: Number,
default: 450
},
logo: {
type: String,
default: LNBITS_QR_LOGO
}
}, },
data() { data() {
return { return {
custom: { nfcTagWriting: false,
margin: 3, nfcSupported: typeof NDEFReader != 'undefined'
width: 350,
size: 350,
logo: LNBITS_QR_LOGO
}
} }
}, },
created() { methods: {
this.custom = {...this.custom, ...this.options} clickQrCode(event) {
if (this.href === '') {
this.copyText(this.value)
event.preventDefault()
event.stopPropagation()
return false
}
},
async writeNfcTag() {
try {
if (!this.nfcSupported) {
throw {
toString: function () {
return 'NFC not supported on this device or browser.'
}
}
}
const ndef = new NDEFReader()
this.nfcTagWriting = true
this.$q.notify({
message: 'Tap your NFC tag to write the LNURL-withdraw link to it.'
})
await ndef.write({
records: [{recordType: 'url', data: this.value, lang: 'en'}]
})
this.nfcTagWriting = false
this.$q.notify({
type: 'positive',
message: 'NFC tag written successfully.'
})
} catch (error) {
this.nfcTagWriting = false
this.$q.notify({
type: 'negative',
message: error
? error.toString()
: 'An unexpected error has occurred.'
})
}
},
downloadSVG() {
const filename = 'qrcode.svg'
const svg = this.$refs.qrCode.$el
if (!svg) {
console.error('SVG element not found')
return
}
// Serialize the SVG content
const serializer = new XMLSerializer()
let source = serializer.serializeToString(svg)
// Add SVG namespace if not present
if (!source.match(/^<svg[^>]+xmlns="http:\/\/www\.w3\.org\/2000\/svg"/)) {
source = source.replace(
/^<svg/,
'<svg xmlns="http://www.w3.org/2000/svg"'
)
}
// Add XML declaration
source = '<?xml version="1.0" standalone="no"?>\n' + source
// Convert to Blob and trigger download
const blob = new Blob([source], {type: 'image/svg+xml;charset=utf-8'})
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = filename
document.body.appendChild(link)
link.click()
// Cleanup
document.body.removeChild(link)
URL.revokeObjectURL(url)
}
},
mounted() {
this.$refs.qrCode.$el.style.maxWidth = this.maxWidth + 'px'
this.$refs.qrCode.$el.setAttribute('width', '100%')
this.$refs.qrCode.$el.setAttribute('height', null)
} }
}) })

View File

@@ -154,7 +154,7 @@ function confettiStars() {
setTimeout(shoot, 200) setTimeout(shoot, 200)
} }
!(function (t, e) { !(function (t, e) {
!(function t(e, n, a, i) { ;(!(function t(e, n, a, i) {
var o = !!( var o = !!(
e.Worker && e.Worker &&
e.Blob && e.Blob &&
@@ -248,12 +248,12 @@ function confettiStars() {
function e(e, n) { function e(e, n) {
t.postMessage({options: e || {}, callback: n}) t.postMessage({options: e || {}, callback: n})
} }
;(t.init = function (e) { ;((t.init = function (e) {
var n = e.transferControlToOffscreen() var n = e.transferControlToOffscreen()
t.postMessage({canvas: n}, [n]) t.postMessage({canvas: n}, [n])
}), }),
(t.fire = function (n, a, i) { (t.fire = function (n, a, i) {
if (g) return e(n, null), g if (g) return (e(n, null), g)
var o = Math.random().toString(36).slice(2) var o = Math.random().toString(36).slice(2)
return (g = l(function (a) { return (g = l(function (a) {
function r(e) { function r(e) {
@@ -264,15 +264,15 @@ function confettiStars() {
i(), i(),
a()) a())
} }
t.addEventListener('message', r), ;(t.addEventListener('message', r),
e(n, o), e(n, o),
(m[o] = r.bind(null, {data: {callback: o}})) (m[o] = r.bind(null, {data: {callback: o}})))
})) }))
}), }),
(t.reset = function () { (t.reset = function () {
for (var e in (t.postMessage({reset: !0}), m)) for (var e in (t.postMessage({reset: !0}), m))
m[e](), delete m[e] (m[e](), delete m[e])
}) }))
})(h) })(h)
} }
return h return h
@@ -328,12 +328,12 @@ function confettiStars() {
) )
} }
function k(t) { function k(t) {
;(t.width = document.documentElement.clientWidth), ;((t.width = document.documentElement.clientWidth),
(t.height = document.documentElement.clientHeight) (t.height = document.documentElement.clientHeight))
} }
function I(t) { function I(t) {
var e = t.getBoundingClientRect() var e = t.getBoundingClientRect()
;(t.width = e.width), (t.height = e.height) ;((t.width = e.width), (t.height = e.height))
} }
function T(t, e, n, o, r) { function T(t, e, n, o, r) {
var c, var c,
@@ -342,10 +342,10 @@ function confettiStars() {
d = t.getContext('2d'), d = t.getContext('2d'),
f = l(function (e) { f = l(function (e) {
function l() { function l() {
;(c = s = null), d.clearRect(0, 0, o.width, o.height), r(), e() ;((c = s = null), d.clearRect(0, 0, o.width, o.height), r(), e())
} }
;(c = b.frame(function e() { ;((c = b.frame(function e() {
!a || ;(!a ||
(o.width === i.width && o.height === i.height) || (o.width === i.width && o.height === i.height) ||
((o.width = t.width = i.width), (o.height = t.height = i.height)), ((o.width = t.width = i.width), (o.height = t.height = i.height)),
o.width || o.width ||
@@ -354,7 +354,7 @@ function confettiStars() {
d.clearRect(0, 0, o.width, o.height), d.clearRect(0, 0, o.width, o.height),
(u = u.filter(function (t) { (u = u.filter(function (t) {
return (function (t, e) { return (function (t, e) {
;(e.x += Math.cos(e.angle2D) * e.velocity + e.drift), ;((e.x += Math.cos(e.angle2D) * e.velocity + e.drift),
(e.y += Math.sin(e.angle2D) * e.velocity + e.gravity), (e.y += Math.sin(e.angle2D) * e.velocity + e.gravity),
(e.wobble += 0.1), (e.wobble += 0.1),
(e.velocity *= e.decay), (e.velocity *= e.decay),
@@ -363,7 +363,7 @@ function confettiStars() {
(e.tiltCos = Math.cos(e.tiltAngle)), (e.tiltCos = Math.cos(e.tiltAngle)),
(e.random = Math.random() + 5), (e.random = Math.random() + 5),
(e.wobbleX = e.x + 10 * e.scalar * Math.cos(e.wobble)), (e.wobbleX = e.x + 10 * e.scalar * Math.cos(e.wobble)),
(e.wobbleY = e.y + 10 * e.scalar * Math.sin(e.wobble)) (e.wobbleY = e.y + 10 * e.scalar * Math.sin(e.wobble)))
var n = e.tick++ / e.totalTicks, var n = e.tick++ / e.totalTicks,
a = e.x + e.random * e.tiltCos, a = e.x + e.random * e.tiltCos,
i = e.y + e.random * e.tiltSin, i = e.y + e.random * e.tiltSin,
@@ -393,12 +393,12 @@ function confettiStars() {
2 * Math.PI 2 * Math.PI
) )
: (function (t, e, n, a, i, o, r, l, c) { : (function (t, e, n, a, i, o, r, l, c) {
t.save(), ;(t.save(),
t.translate(e, n), t.translate(e, n),
t.rotate(o), t.rotate(o),
t.scale(a, i), t.scale(a, i),
t.arc(0, 0, 1, r, l, c), t.arc(0, 0, 1, r, l, c),
t.restore() t.restore())
})( })(
t, t,
e.x, e.x,
@@ -420,18 +420,18 @@ function confettiStars() {
})(d, t) })(d, t)
})).length })).length
? (c = b.frame(e)) ? (c = b.frame(e))
: l() : l())
})), })),
(s = l) (s = l))
}) })
return { return {
addFettis: function (t) { addFettis: function (t) {
return (u = u.concat(t)), f return ((u = u.concat(t)), f)
}, },
canvas: t, canvas: t,
promise: f, promise: f,
reset: function () { reset: function () {
c && b.cancel(c), s && s() ;(c && b.cancel(c), s && s())
} }
} }
} }
@@ -466,7 +466,7 @@ function confettiStars() {
k = p(e, 'scalar'), k = p(e, 'scalar'),
I = (function (t) { I = (function (t) {
var e = p(t, 'origin', Object) var e = p(t, 'origin', Object)
return (e.x = p(e, 'x', Number)), (e.y = p(e, 'y', Number)), e return ((e.x = p(e, 'x', Number)), (e.y = p(e, 'y', Number)), e)
})(e), })(e),
E = d, E = d,
S = [], S = [],
@@ -531,7 +531,7 @@ function confettiStars() {
return l(function (t) { return l(function (t) {
t() t()
}) })
i && a ;(i && a
? (t = a.canvas) ? (t = a.canvas)
: i && : i &&
!t && !t &&
@@ -547,7 +547,7 @@ function confettiStars() {
) )
})(g)), })(g)),
document.body.appendChild(t)), document.body.appendChild(t)),
r && !d && u(t) r && !d && u(t))
var m = {width: t.width, height: t.height} var m = {width: t.width, height: t.height}
function b() { function b() {
if (s) { if (s) {
@@ -564,9 +564,9 @@ function confettiStars() {
m.width = m.height = null m.width = m.height = null
} }
function v() { function v() {
;(a = null), ;((a = null),
r && e.removeEventListener('resize', b), r && e.removeEventListener('resize', b),
i && t && (document.body.removeChild(t), (t = null), (d = !1)) i && t && (document.body.removeChild(t), (t = null), (d = !1)))
} }
return ( return (
s && !d && s.init(t), s && !d && s.init(t),
@@ -578,12 +578,13 @@ function confettiStars() {
} }
return ( return (
(g.reset = function () { (g.reset = function () {
s && s.reset(), a && a.reset() ;(s && s.reset(), a && a.reset())
}), }),
g g
) )
} }
;(n.exports = E(null, {useWorker: !0, resize: !0})), (n.exports.create = E) ;((n.exports = E(null, {useWorker: !0, resize: !0})),
(n.exports.create = E))
})( })(
(function () { (function () {
return void 0 !== t ? t : 'undefined' != typeof self ? self : this || {} return void 0 !== t ? t : 'undefined' != typeof self ? self : this || {}
@@ -591,5 +592,5 @@ function confettiStars() {
e, e,
!1 !1
), ),
(t.confetti = e.exports) (t.confetti = e.exports))
})(window, {}) })(window, {})

View File

@@ -45,7 +45,6 @@ window.WalletPageLogic = {
payment_hash: null payment_hash: null
} }
}, },
invoiceQrCode: '',
disclaimerDialog: { disclaimerDialog: {
show: false, show: false,
location: window.location location: window.location
@@ -313,13 +312,6 @@ window.WalletPageLogic = {
}) })
} }
} }
// Hack as rendering in dialog causes reactivity issues. Does speed up, as only rendering lnbits-qrcode once.
this.$nextTick(() => {
this.invoiceQrCode = document.getElementById(
'hiddenQrCodeContainer'
).innerHTML
})
}) })
.catch(err => { .catch(err => {
LNbits.utils.notifyApiError(err) LNbits.utils.notifyApiError(err)

View File

@@ -617,21 +617,65 @@
</template> </template>
<template id="lnbits-qrcode"> <template id="lnbits-qrcode">
<div class="qrcode__wrapper"> <div
<qrcode-vue class="qrcode__outer"
:value="value" :style="`margin: 13px auto; max-width: ${maxWidth}px`"
level="Q" >
render-as="svg" <div ref="qrWrapper" class="qrcode__wrapper">
:margin="custom.margin" <a
:size="custom.width" :href="href"
class="rounded-borders" :title="href === '' ? value : href"
></qrcode-vue> @click="clickQrCode"
<img class="no-link full-width"
v-if="custom.logo" >
class="qrcode__image" <qrcode-vue
:src="custom.logo" ref="qrCode"
alt="qrcode icon" :value="value"
/> :margin="margin"
:size="size"
level="Q"
render-as="svg"
class="rounded-borders q-mb-sm"
>
<q-tooltip :model-value="href === '' ? value : href"></q-tooltip>
</qrcode-vue>
</a>
<img
:src="logo"
class="qrcode__image"
alt="qrcode icon"
style="pointer-events: none"
/>
</div>
<div
v-if="showButtons"
class="qrcode__buttons row q-gutter-x-sm"
style="justify-content: flex-end"
>
<q-btn
v-if="nfc && nfcSupported"
:disabled="nfcTagWriting"
flat
dense
class="text-grey"
icon="nfc"
@click="writeNfcTag"
>
<q-tooltip>Write NFC Tag</q-tooltip>
</q-btn>
<q-btn flat dense class="text-grey" icon="download" @click="downloadSVG">
<q-tooltip>Download SVG</q-tooltip>
</q-btn>
<q-btn
flat
dense
class="text-grey"
@click="copyText(value)"
icon="content_copy"
>
<q-tooltip>Copy</q-tooltip>
</q-btn>
</div>
</div> </div>
</template> </template>
@@ -640,17 +684,16 @@
<q-tabs <q-tabs
v-model="tab" v-model="tab"
dense dense
class="text-grey q-mb-md" class="text-grey"
active-color="primary" active-color="primary"
indicator-color="primary" indicator-color="primary"
align="justify" align="justify"
narrow-indicator
inline-label inline-label
> >
<q-tab name="bech32" icon="qr_code" label="bech32"></q-tab> <q-tab name="bech32" icon="qr_code" label="bech32"></q-tab>
<q-tab name="lud17" icon="link" label="url (lud17)"></q-tab> <q-tab name="lud17" icon="link" label="url (lud17)"></q-tab>
</q-tabs> </q-tabs>
<lnbits-qrcode :value="lnurl" class="rounded-borders"></lnbits-qrcode> <lnbits-qrcode :value="lnurl" nfc="true"></lnbits-qrcode>
</div> </div>
</template> </template>
@@ -1044,42 +1087,22 @@
<div <div
v-if="props.row.isIn && props.row.isPending && props.row.bolt11" v-if="props.row.isIn && props.row.isPending && props.row.bolt11"
class="text-center q-my-lg"
> >
<div v-if="props.row.extra.fiat_payment_request"> <div v-if="props.row.extra.fiat_payment_request">
<a <lnbits-qrcode
:value="props.row.extra.fiat_payment_request"
:href="props.row.extra.fiat_payment_request" :href="props.row.extra.fiat_payment_request"
target="_blank" :show-buttons="false"
> ></lnbits-qrcode>
<lnbits-qrcode
:value="props.row.extra.fiat_payment_request"
></lnbits-qrcode>
</a>
</div> </div>
<div v-else> <div v-else>
<a :href="'lightning:' + props.row.bolt11"> <lnbits-qrcode
<lnbits-qrcode :value="'lightning:' + props.row.bolt11.toUpperCase()"
:value="'lightning:' + props.row.bolt11.toUpperCase()" :href="'lightning:' + props.row.bolt11"
></lnbits-qrcode> ></lnbits-qrcode>
</a>
</div> </div>
</div> </div>
</q-card-section> <div class="row q-mt-md">
<q-card-section>
<div class="row q-gutter-x-sm">
<q-btn
v-if="
props.row.isIn && props.row.isPending && props.row.bolt11
"
outline
color="grey"
@click="
copyText(
props.row.extra.fiat_payment_request || props.row.bolt11
)
"
:label="$t('copy_invoice')"
></q-btn>
<q-btn <q-btn
outline outline
color="grey" color="grey"
@@ -1196,9 +1219,13 @@
:endpoint="endpoint" :endpoint="endpoint"
> >
<template v-slot:actions> <template v-slot:actions>
<q-btn v-close-popup flat color="grey" class="q-ml-auto" <q-btn
>Close</q-btn v-close-popup
> flat
color="grey"
class="q-ml-auto"
:label="$t('close')"
></q-btn>
</template> </template>
</lnbits-extension-settings-form> </lnbits-extension-settings-form>
</q-card> </q-card>
@@ -1282,10 +1309,10 @@
<q-dialog v-model="showQRDialog"> <q-dialog v-model="showQRDialog">
<q-card class="q-pa-md"> <q-card class="q-pa-md">
<q-card-section> <q-card-section>
<lnbits-qrcode :value="qrValue" :size="200"></lnbits-qrcode> <lnbits-qrcode :value="qrValue"></lnbits-qrcode>
</q-card-section> </q-card-section>
<q-card-actions align="right"> <q-card-actions align="right">
<q-btn flat label="Close" v-close-popup /> <q-btn flat :label="$t('close')" v-close-popup />
</q-card-actions> </q-card-actions>
</q-card> </q-card>
</q-dialog> </q-dialog>

8
package-lock.json generated
View File

@@ -23,7 +23,7 @@
"devDependencies": { "devDependencies": {
"concat": "^1.0.3", "concat": "^1.0.3",
"minify": "^9.2.0", "minify": "^9.2.0",
"prettier": "^3.3.3", "prettier": "^3.6.2",
"pyright": "1.1.289", "pyright": "1.1.289",
"sass": "^1.78.0" "sass": "^1.78.0"
} }
@@ -1222,9 +1222,9 @@
} }
}, },
"node_modules/prettier": { "node_modules/prettier": {
"version": "3.3.3", "version": "3.6.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"bin": { "bin": {

View File

@@ -15,7 +15,7 @@
"devDependencies": { "devDependencies": {
"concat": "^1.0.3", "concat": "^1.0.3",
"minify": "^9.2.0", "minify": "^9.2.0",
"prettier": "^3.3.3", "prettier": "^3.6.2",
"pyright": "1.1.289", "pyright": "1.1.289",
"sass": "^1.78.0" "sass": "^1.78.0"
}, },