feat: refactor create lnbits-theme vue component (#3515)

This commit is contained in:
dni ⚡
2025-11-13 11:50:33 +01:00
committed by GitHub
parent 9d0ec97d39
commit b7d178c08e
16 changed files with 221 additions and 278 deletions
+5 -5
View File
@@ -97,11 +97,11 @@ def template_renderer(additional_folders: list | None = None) -> Jinja2Templates
"LNBITS_THEME_OPTIONS": settings.lnbits_theme_options, "LNBITS_THEME_OPTIONS": settings.lnbits_theme_options,
"LNBITS_VERSION": settings.version, "LNBITS_VERSION": settings.version,
"USE_CUSTOM_LOGO": settings.lnbits_custom_logo, "USE_CUSTOM_LOGO": settings.lnbits_custom_logo,
"USE_DEFAULT_REACTION": settings.lnbits_default_reaction, "LNBITS_DEFAULT_REACTION": settings.lnbits_default_reaction,
"USE_DEFAULT_THEME": settings.lnbits_default_theme, "LNBITS_DEFAULT_THEME": settings.lnbits_default_theme,
"USE_DEFAULT_BORDER": settings.lnbits_default_border, "LNBITS_DEFAULT_BORDER": settings.lnbits_default_border,
"USE_DEFAULT_GRADIENT": settings.lnbits_default_gradient, "LNBITS_DEFAULT_GRADIENT": settings.lnbits_default_gradient,
"USE_DEFAULT_BGIMAGE": settings.lnbits_default_bgimage, "LNBITS_DEFAULT_BGIMAGE": settings.lnbits_default_bgimage,
"VOIDWALLET": settings.lnbits_backend_wallet_class == "VoidWallet", "VOIDWALLET": settings.lnbits_backend_wallet_class == "VoidWallet",
"WEBPUSH_PUBKEY": settings.lnbits_webpush_pubkey, "WEBPUSH_PUBKEY": settings.lnbits_webpush_pubkey,
"LNBITS_DENOMINATION": settings.lnbits_denomination, "LNBITS_DENOMINATION": settings.lnbits_denomination,
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+10 -10
View File
File diff suppressed because one or more lines are too long
+5
View File
@@ -185,6 +185,11 @@ body[data-theme=salvador] [data-theme=salvador] .q-stepper--dark {
} }
body.gradient-bg { body.gradient-bg {
background-image: linear-gradient(to bottom right, #fff, var(--q-primary));
background-attachment: fixed;
}
body.gradient-bg.body--dark {
background-image: linear-gradient(to bottom right, var(--q-dark-page), #0a0a0a); background-image: linear-gradient(to bottom right, var(--q-dark-page), #0a0a0a);
background-attachment: fixed; background-attachment: fixed;
} }
+107
View File
@@ -0,0 +1,107 @@
window.app.component('lnbits-theme', {
mixins: [window.windowMixin],
watch: {
'g.reactionChoice'(val) {
this.$q.localStorage.set('lnbits.reactions', val)
},
'g.themeChoice'(val) {
document.body.setAttribute('data-theme', val)
this.$q.localStorage.set('lnbits.theme', val)
},
'g.darkChoice'(val) {
this.$q.dark.set(val)
this.$q.localStorage.set('lnbits.darkMode', val)
},
'g.borderChoice'(val) {
document.body.classList.forEach(cls => {
if (cls.endsWith('-border')) {
document.body.classList.remove(cls)
}
})
this.$q.localStorage.setItem('lnbits.border', val)
document.body.classList.add(val)
},
'g.gradientChoice'(val) {
this.$q.localStorage.set('lnbits.gradientBg', val)
if (val === true) {
document.body.classList.add('gradient-bg')
} else {
document.body.classList.remove('gradient-bg')
}
},
'g.bgimageChoice'(val) {
this.$q.localStorage.set('lnbits.backgroundImage', val)
if (val === '') {
document.body.classList.remove('bg-image')
} else {
document.body.classList.add('bg-image')
document.body.style.setProperty('--background', `url(${val})`)
}
}
},
methods: {
async checkUrlParams() {
const params = new URLSearchParams(window.location.search)
if (params.length === 0) {
return
}
if (params.has('theme')) {
const theme = params.get('theme').trim().toLowerCase()
this.g.themeChoice = theme
params.delete('theme')
}
if (params.has('border')) {
const border = params.get('border').trim().toLowerCase()
this.g.borderChoice = border
params.delete('border')
}
if (params.has('gradient')) {
const gradient = params.get('gradient').toLowerCase()
this.g.gradientChoice = gradient === '1' || gradient === 'true'
params.delete('gradient')
}
if (params.has('dark')) {
const dark = params.get('dark').trim().toLowerCase()
this.g.darkChoice = dark === '1' || dark === 'true'
params.delete('dark')
}
if (params.has('usr')) {
try {
await LNbits.api.loginUsr(params.get('usr'))
window.location.href = '/wallet'
} catch (e) {
LNbits.utils.notifyApiError(e)
}
params.delete('usr')
}
// cleanup url
const cleanParams = params.size ? `?${params.toString()}` : ''
const url = window.location.pathname + cleanParams
// TODO state gets overridden somewhere else
window.history.replaceState(null, null, url)
}
},
created() {
// TODO: fix Chart global import each chart has to take care of its own config
// else there is no reactivity on theme change
Chart.defaults.color = this.$q.dark.isActive ? '#fff' : '#000'
this.$q.dark.set(this.g.darkChoice)
document.body.setAttribute('data-theme', this.g.themeChoice)
document.body.classList.add(this.g.borderChoice)
if (this.g.gradientChoice === true) {
document.body.classList.add('gradient-bg')
}
if (this.g.bgimageChoice !== '') {
document.body.classList.add('bg-image')
document.body.style.setProperty(
'--background',
`url(${this.g.bgimageChoice})`
)
}
this.checkUrlParams()
}
})
+30 -3
View File
@@ -1,4 +1,12 @@
const localStore = (key, defaultValue) => {
const value = Quasar.LocalStorage.getItem(key)
return value !== null && value !== undefined && value !== 'undefined'
? value
: defaultValue
}
window.g = Vue.reactive({ window.g = Vue.reactive({
isUserAuthorized: !!Quasar.Cookies.get('is_lnbits_user_authorized'),
offline: !navigator.onLine, offline: !navigator.onLine,
visibleDrawer: false, visibleDrawer: false,
extensions: [], extensions: [],
@@ -12,9 +20,26 @@ window.g = Vue.reactive({
walletEventListeners: [], walletEventListeners: [],
updatePayments: false, updatePayments: false,
updatePaymentsHash: '', updatePaymentsHash: '',
walletFlip: Quasar.LocalStorage.getItem('lnbits.walletFlip') ?? false, walletFlip: localStore('lnbits.walletFlip', false),
locale: locale: localStore('lnbits.lang', navigator.languages[1] ?? 'en'),
Quasar.LocalStorage.getItem('lnbits.lang') ?? navigator.languages[1] ?? 'en' darkChoice: localStore('lnbits.darkMode', true),
themeChoice: localStore('lnbits.theme', WINDOW_SETTINGS.LNBITS_DEFAULT_THEME),
borderChoice: localStore(
'lnbits.border',
WINDOW_SETTINGS.LNBITS_DEFAULT_REACTION
),
gradientChoice: localStore(
'lnbits.gradientBg',
WINDOW_SETTINGS.LNBITS_DEFAULT_GRADIENT
),
reactionChoice: localStore(
'lnbits.reactions',
WINDOW_SETTINGS.LNBITS_DEFAULT_REACTION
),
bgimageChoice: localStore(
'lnbits.backgroundImage',
WINDOW_SETTINGS.LNBITS_DEFAULT_BGIMAGE
)
}) })
window.dateFormat = 'YYYY-MM-DD HH:mm' window.dateFormat = 'YYYY-MM-DD HH:mm'
@@ -22,3 +47,5 @@ window.dateFormat = 'YYYY-MM-DD HH:mm'
const websocketPrefix = const websocketPrefix =
window.location.protocol === 'http:' ? 'ws://' : 'wss://' window.location.protocol === 'http:' ? 'ws://' : 'wss://'
const websocketUrl = `${websocketPrefix}${window.location.host}/api/v1/ws` const websocketUrl = `${websocketPrefix}${window.location.host}/api/v1/ws`
const _access_cookies_for_safari_refresh_do_not_delete = document.cookie
+39
View File
@@ -6,6 +6,40 @@ window.PageAccount = {
user: null, user: null,
hasUsername: false, hasUsername: false,
showUserId: false, showUserId: false,
themeOptions: [
{
name: 'bitcoin',
color: 'deep-orange'
},
{
name: 'mint',
color: 'green'
},
{
name: 'autumn',
color: 'brown'
},
{
name: 'monochrome',
color: 'grey'
},
{
name: 'salvador',
color: 'blue-10'
},
{
name: 'freedom',
color: 'pink-13'
},
{
name: 'cyber',
color: 'light-green-9'
},
{
name: 'flamingo',
color: 'pink-3'
}
],
reactionOptions: [ reactionOptions: [
'None', 'None',
'confettiBothSides', 'confettiBothSides',
@@ -542,5 +576,10 @@ window.PageAccount = {
} }
await this.getApiACLs() await this.getApiACLs()
await this.getUserAssets() await this.getUserAssets()
// filter out themes that are not allowed
this.themeOptions = this.themeOptions.filter(theme =>
this.allowedThemes.includes(theme.name)
)
} }
} }
+1 -9
View File
@@ -4,7 +4,6 @@ window.PageHome = {
data() { data() {
return { return {
lnurl: '', lnurl: '',
isUserAuthorized: false,
authAction: 'login', authAction: 'login',
authMethod: 'username-password', authMethod: 'username-password',
usr: '', usr: '',
@@ -136,21 +135,14 @@ window.PageHome = {
} }
}, },
created() { created() {
this.isUserAuthorized = !!this.$q.cookies.get('is_lnbits_user_authorized') if (this.g.isUserAuthorized) {
const _access_cookies_for_safari_refresh_do_not_delete = document.cookie
if (this.isUserAuthorized) {
window.location.href = '/wallet' window.location.href = '/wallet'
} }
const urlParams = new URLSearchParams(window.location.search) const urlParams = new URLSearchParams(window.location.search)
this.reset_key = urlParams.get('reset_key') this.reset_key = urlParams.get('reset_key')
if (this.reset_key) { if (this.reset_key) {
this.authAction = 'reset' this.authAction = 'reset'
} }
// check if lightning parameters are present in the URL // check if lightning parameters are present in the URL
if (urlParams.has('lightning')) { if (urlParams.has('lightning')) {
this.lnurl = urlParams.get('lightning') this.lnurl = urlParams.get('lightning')
+1 -155
View File
@@ -9,28 +9,9 @@ window.windowMixin = {
mobileSimple: true, mobileSimple: true,
addWalletDialog: {show: false, walletType: 'lightning'}, addWalletDialog: {show: false, walletType: 'lightning'},
walletTypes: [{label: 'Lightning Wallet', value: 'lightning'}], walletTypes: [{label: 'Lightning Wallet', value: 'lightning'}],
isUserAuthorized: false,
isSatsDenomination: WINDOW_SETTINGS['LNBITS_DENOMINATION'] == 'sats', isSatsDenomination: WINDOW_SETTINGS['LNBITS_DENOMINATION'] == 'sats',
allowedThemes: WINDOW_SETTINGS['LNBITS_THEME_OPTIONS'], allowedThemes: WINDOW_SETTINGS['LNBITS_THEME_OPTIONS'],
walletEventListeners: [], walletEventListeners: [],
darkChoice: this.$q.localStorage.has('lnbits.darkMode')
? this.$q.localStorage.getItem('lnbits.darkMode')
: true,
borderChoice: this.$q.localStorage.has('lnbits.border')
? this.$q.localStorage.getItem('lnbits.border')
: USE_DEFAULT_BORDER,
gradientChoice: this.$q.localStorage.has('lnbits.gradientBg')
? this.$q.localStorage.getItem('lnbits.gradientBg')
: USE_DEFAULT_GRADIENT,
themeChoice: this.$q.localStorage.has('lnbits.theme')
? this.$q.localStorage.getItem('lnbits.theme')
: USE_DEFAULT_THEME,
reactionChoice: this.$q.localStorage.has('lnbits.reactions')
? this.$q.localStorage.getItem('lnbits.reactions')
: USE_DEFAULT_REACTION,
bgimageChoice: this.$q.localStorage.has('lnbits.backgroundImage')
? this.$q.localStorage.getItem('lnbits.backgroundImage')
: USE_DEFAULT_BGIMAGE,
...WINDOW_SETTINGS ...WINDOW_SETTINGS
} }
}, },
@@ -131,56 +112,6 @@ window.windowMixin = {
return LNbits.utils.formatSat(amount) + ' sats' return LNbits.utils.formatSat(amount) + ' sats'
} }
}, },
changeTheme(newValue) {
document.body.setAttribute('data-theme', newValue)
this.$q.localStorage.set('lnbits.theme', newValue)
this.themeChoice = newValue
},
applyGradient() {
if (this.gradientChoice) {
document.body.classList.add('gradient-bg')
this.$q.localStorage.set('lnbits.gradientBg', true)
// Ensure dark mode is enabled when gradient background is applied
if (!this.$q.dark.isActive) {
this.toggleDarkMode()
}
} else {
document.body.classList.remove('gradient-bg')
this.$q.localStorage.set('lnbits.gradientBg', false)
}
},
applyBackgroundImage() {
if (this.bgimageChoice == 'null') this.bgimageChoice = ''
if (this.bgimageChoice == '') {
document.body.classList.remove('bg-image')
} else {
document.body.classList.add('bg-image')
document.body.style.setProperty(
'--background',
`url(${this.bgimageChoice})`
)
}
this.$q.localStorage.set('lnbits.backgroundImage', this.bgimageChoice)
},
applyBorder() {
// Remove any existing border classes
document.body.classList.forEach(cls => {
if (cls.endsWith('-border')) {
document.body.classList.remove(cls)
}
})
this.$q.localStorage.setItem('lnbits.border', this.borderChoice)
document.body.classList.add(this.borderChoice)
},
toggleDarkMode() {
this.$q.dark.toggle()
this.darkChoice = this.$q.dark.isActive
this.$q.localStorage.set('lnbits.darkMode', this.$q.dark.isActive)
if (!this.$q.dark.isActive) {
this.gradientChoice = false
this.applyGradient()
}
},
copyText(text, message, position) { copyText(text, message, position) {
Quasar.copyToClipboard(text).then(() => { Quasar.copyToClipboard(text).then(() => {
Quasar.Notify.create({ Quasar.Notify.create({
@@ -189,77 +120,6 @@ window.windowMixin = {
}) })
}) })
}, },
async checkUsrInUrl() {
try {
const params = new URLSearchParams(window.location.search)
const usr = params.get('usr')
if (!usr) {
return
}
if (!this.isUserAuthorized) {
await LNbits.api.loginUsr(usr)
}
params.delete('usr')
const cleanQueryPrams = params.size ? `?${params.toString()}` : ''
window.history.replaceState(
{},
document.title,
window.location.pathname + cleanQueryPrams
)
} finally {
this.isUserAuthorized = !!this.$q.cookies.get(
'is_lnbits_user_authorized'
)
}
},
themeParams() {
const url = new URL(window.location.href)
const params = new URLSearchParams(window.location.search)
const fields = ['theme', 'dark', 'gradient']
const toBoolean = value =>
value.trim().toLowerCase() === 'true' || value === '1'
// Check if any of the relevant parameters ('theme', 'dark', 'gradient') are present in the URL.
if (fields.some(param => params.has(param))) {
const theme = params.get('theme')
const darkMode = params.get('dark')
const gradient = params.get('gradient')
const border = params.get('border')
if (theme && this.allowedThemes.includes(theme.trim().toLowerCase())) {
const normalizedTheme = theme.trim().toLowerCase()
document.body.setAttribute('data-theme', normalizedTheme)
this.$q.localStorage.set('lnbits.theme', normalizedTheme)
}
if (darkMode) {
const isDark = toBoolean(darkMode)
this.$q.localStorage.set('lnbits.darkMode', isDark)
if (!isDark) {
this.$q.localStorage.set('lnbits.gradientBg', false)
}
}
if (gradient) {
const isGradient = toBoolean(gradient)
this.$q.localStorage.set('lnbits.gradientBg', isGradient)
if (isGradient) {
this.$q.localStorage.set('lnbits.darkMode', true)
}
}
if (border) {
this.$q.localStorage.set('lnbits.border', border)
}
// Remove processed parameters
fields.forEach(param => params.delete(param))
window.history.replaceState(null, null, url.pathname)
}
},
refreshRoute() { refreshRoute() {
const path = window.location.pathname const path = window.location.pathname
console.log(path) console.log(path)
@@ -270,19 +130,6 @@ window.windowMixin = {
} }
}, },
async created() { async created() {
this.$q.dark.set(
this.$q.localStorage.has('lnbits.darkMode')
? this.$q.localStorage.getItem('lnbits.darkMode')
: true
)
Chart.defaults.color = this.$q.dark.isActive ? '#fff' : '#000'
this.changeTheme(this.themeChoice)
this.applyBorder()
if (this.$q.dark.isActive) {
this.applyGradient()
}
this.applyBackgroundImage()
addEventListener('offline', event => { addEventListener('offline', event => {
console.log('offline', event) console.log('offline', event)
this.g.offline = true this.g.offline = true
@@ -296,6 +143,7 @@ window.windowMixin = {
if (window.user) { if (window.user) {
this.g.user = Vue.reactive(window.LNbits.map.user(window.user)) this.g.user = Vue.reactive(window.LNbits.map.user(window.user))
} }
if (this.g.user?.extra?.wallet_invite_requests?.length) { if (this.g.user?.extra?.wallet_invite_requests?.length) {
this.walletTypes.push({ this.walletTypes.push({
label: `Lightning Wallet (Share Invite: ${this.g.user.extra.wallet_invite_requests.length})`, label: `Lightning Wallet (Share Invite: ${this.g.user.extra.wallet_invite_requests.length})`,
@@ -308,8 +156,6 @@ window.windowMixin = {
if (window.extensions) { if (window.extensions) {
this.g.extensions = Vue.reactive(window.extensions) this.g.extensions = Vue.reactive(window.extensions)
} }
await this.checkUsrInUrl()
this.themeParams()
if ( if (
this.$q.screen.gt.sm || this.$q.screen.gt.sm ||
this.$q.localStorage.getItem('lnbits.mobileSimple') == false this.$q.localStorage.getItem('lnbits.mobileSimple') == false
+5
View File
@@ -23,6 +23,11 @@
} }
body.gradient-bg { body.gradient-bg {
background-image: linear-gradient(to bottom right, #fff, var(--q-primary));
background-attachment: fixed;
}
body.gradient-bg.body--dark {
background-image: linear-gradient( background-image: linear-gradient(
to bottom right, to bottom right,
var(--q-dark-page), var(--q-dark-page),
+1
View File
@@ -75,6 +75,7 @@
"js/components/lnbits-header.js", "js/components/lnbits-header.js",
"js/components/lnbits-header-wallets.js", "js/components/lnbits-header-wallets.js",
"js/components/lnbits-drawer.js", "js/components/lnbits-drawer.js",
"js/components/lnbits-theme.js",
"js/components/lnbits-manage-extension-list.js", "js/components/lnbits-manage-extension-list.js",
"js/components/lnbits-language-dropdown.js", "js/components/lnbits-language-dropdown.js",
"js/components/extension-settings.js", "js/components/extension-settings.js",
+1
View File
@@ -33,6 +33,7 @@
<body data-theme="bitcoin"> <body data-theme="bitcoin">
<div id="vue"> <div id="vue">
<q-layout view="hHh lpR lfr" v-cloak> <q-layout view="hHh lpR lfr" v-cloak>
<lnbits-theme></lnbits-theme>
<lnbits-header></lnbits-header> <lnbits-header></lnbits-header>
{% block drawer %} {% block drawer %}
<lnbits-drawer></lnbits-drawer> <lnbits-drawer></lnbits-drawer>
@@ -73,7 +73,7 @@
<lnbits-language-dropdown></lnbits-language-dropdown> <lnbits-language-dropdown></lnbits-language-dropdown>
<q-btn-dropdown <q-btn-dropdown
v-if="g.user || isUserAuthorized" v-if="g.user || g.isUserAuthorized"
flat flat
rounded rounded
size="sm" size="sm"
+12 -93
View File
@@ -391,93 +391,17 @@
</div> </div>
<div class="col-8"> <div class="col-8">
<q-btn <q-btn
v-if="allowedThemes.includes('classic')" v-for="theme in themeOptions"
:key="theme.name"
@click="g.themeChoice = theme.name"
:color="theme.color"
dense dense
flat flat
@click="changeTheme('classic')"
icon="circle" icon="circle"
color="deep-purple"
size="md" size="md"
><q-tooltip>classic</q-tooltip> ><q-tooltip
</q-btn> ><span v-text="theme.name"></span
<q-btn ></q-tooltip>
v-if="allowedThemes.includes('bitcoin')"
dense
flat
@click="changeTheme('bitcoin')"
icon="circle"
color="deep-orange"
size="md"
><q-tooltip>bitcoin</q-tooltip>
</q-btn>
<q-btn
v-if="allowedThemes.includes('mint')"
dense
flat
@click="changeTheme('mint')"
icon="circle"
color="green"
size="md"
><q-tooltip>mint</q-tooltip> </q-btn
><q-btn
v-if="allowedThemes.includes('autumn')"
dense
flat
@click="changeTheme('autumn')"
icon="circle"
color="brown"
size="md"
><q-tooltip>autumn</q-tooltip>
</q-btn>
<q-btn
v-if="allowedThemes.includes('monochrome')"
dense
flat
@click="changeTheme('monochrome')"
icon="circle"
color="grey"
size="md"
><q-tooltip>monochrome</q-tooltip>
</q-btn>
<q-btn
v-if="allowedThemes.includes('salvador')"
dense
flat
@click="changeTheme('salvador')"
icon="circle"
color="blue-10"
size="md"
><q-tooltip>elSalvador</q-tooltip>
</q-btn>
<q-btn
v-if="allowedThemes.includes('freedom')"
dense
flat
@click="changeTheme('freedom')"
icon="circle"
color="pink-13"
size="md"
><q-tooltip>freedom</q-tooltip>
</q-btn>
<q-btn
v-if="allowedThemes.includes('cyber')"
dense
flat
@click="changeTheme('cyber')"
icon="circle"
color="light-green-9"
size="md"
><q-tooltip>cyber</q-tooltip>
</q-btn>
<q-btn
v-if="allowedThemes.includes('flamingo')"
dense
flat
@click="changeTheme('flamingo')"
icon="circle"
color="pink-3"
size="md"
><q-tooltip>flamingo</q-tooltip>
</q-btn> </q-btn>
</div> </div>
</div> </div>
@@ -487,9 +411,8 @@
</div> </div>
<div class="col-8"> <div class="col-8">
<q-input <q-input
v-model="bgimageChoice" v-model="g.bgimageChoice"
:label="$t('background_image')" :label="$t('background_image')"
@update:model-value="applyBackgroundImage"
> >
<q-tooltip <q-tooltip
><span v-text="$t('background_image')"></span ><span v-text="$t('background_image')"></span
@@ -507,8 +430,7 @@
flat flat
round round
icon="gradient" icon="gradient"
v-model="gradientChoice" v-model="g.gradientChoice"
@update:model-value="applyGradient"
> >
<q-tooltip <q-tooltip
><span v-text="$t('toggle_gradient')"></span ><span v-text="$t('toggle_gradient')"></span
@@ -526,8 +448,7 @@
dense dense
flat flat
round round
v-model="darkChoice" v-model="g.darkChoice"
@click="toggleDarkMode"
:icon="$q.dark.isActive ? 'brightness_3' : 'wb_sunny'" :icon="$q.dark.isActive ? 'brightness_3' : 'wb_sunny'"
size="sm" size="sm"
> >
@@ -543,10 +464,9 @@
</div> </div>
<div class="col-8"> <div class="col-8">
<q-select <q-select
v-model="borderChoice" v-model="g.borderChoice"
:options="borderOptions" :options="borderOptions"
label="Borders" label="Borders"
@update:model-value="applyBorder"
> >
<q-tooltip <q-tooltip
><span v-text="$t('border_choices')"></span ><span v-text="$t('border_choices')"></span
@@ -571,10 +491,9 @@
</div> </div>
<div class="col-8"> <div class="col-8">
<q-select <q-select
v-model="reactionChoice" v-model="g.reactionChoice"
:options="reactionOptions" :options="reactionOptions"
label="Reactions" label="Reactions"
@update:model-value="reactionChoiceFunc"
> >
<q-tooltip <q-tooltip
><span v-text="$t('payment_reactions')"></span ><span v-text="$t('payment_reactions')"></span
+1
View File
@@ -127,6 +127,7 @@
"js/components/lnbits-header.js", "js/components/lnbits-header.js",
"js/components/lnbits-header-wallets.js", "js/components/lnbits-header-wallets.js",
"js/components/lnbits-drawer.js", "js/components/lnbits-drawer.js",
"js/components/lnbits-theme.js",
"js/components/lnbits-manage-extension-list.js", "js/components/lnbits-manage-extension-list.js",
"js/components/lnbits-language-dropdown.js", "js/components/lnbits-language-dropdown.js",
"js/components/extension-settings.js", "js/components/extension-settings.js",