Compare commits

...
10 changed files with 117 additions and 155 deletions
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
+6 -67
View File
@@ -2,18 +2,6 @@ window.LNbits = {
g: window.g, g: window.g,
utils: window._lnbitsUtils, utils: window._lnbitsUtils,
api: window._lnbitsApi, api: window._lnbitsApi,
events: {
onInvoicePaid(wallet, cb) {
ws = new WebSocket(`${websocketUrl}/${wallet.inkey}`)
ws.onmessage = ev => {
const data = JSON.parse(ev.data)
if (data.payment) {
cb(data)
}
}
return ws.onclose
}
},
map: { map: {
user(data) { user(data) {
const obj = { const obj = {
@@ -27,16 +15,12 @@ window.LNbits = {
extra: data.extra ?? {} extra: data.extra ?? {}
} }
const mapWallet = this.wallet const mapWallet = this.wallet
obj.wallets = obj.wallets obj.wallets = obj.wallets.map(mapWallet).sort((a, b) => {
.map(obj => { if (a.extra.pinned !== b.extra.pinned) {
return mapWallet(obj) return a.extra.pinned ? -1 : 1
}) }
.sort((a, b) => { return a.name.localeCompare(b.name)
if (a.extra.pinned !== b.extra.pinned) { })
return a.extra.pinned ? -1 : 1
}
return a.name.localeCompare(b.name)
})
obj.walletOptions = obj.wallets.map(obj => { obj.walletOptions = obj.wallets.map(obj => {
return { return {
label: [obj.name, ' - ', obj.id.substring(0, 5), '...'].join(''), label: [obj.name, ' - ', obj.id.substring(0, 5), '...'].join(''),
@@ -77,51 +61,6 @@ window.LNbits = {
newWallet.url = `/wallet?&wal=${data.id}` newWallet.url = `/wallet?&wal=${data.id}`
newWallet.storedPaylinks = data.stored_paylinks.links newWallet.storedPaylinks = data.stored_paylinks.links
return newWallet return newWallet
},
payment(data) {
obj = {
checking_id: data.checking_id,
status: data.status,
amount: data.amount,
fee: data.fee,
memo: data.memo,
time: data.time,
bolt11: data.bolt11,
preimage: data.preimage,
payment_hash: data.payment_hash,
expiry: data.expiry,
extra: data.extra ?? {},
wallet_id: data.wallet_id,
webhook: data.webhook,
webhook_status: data.webhook_status,
fiat_amount: data.fiat_amount,
fiat_currency: data.fiat_currency,
labels: data.labels
}
obj.date = moment.utc(data.created_at).local().format(window.dateFormat)
obj.dateFrom = moment.utc(data.created_at).local().fromNow()
obj.expirydate = moment.utc(obj.expiry).local().format(window.dateFormat)
obj.expirydateFrom = moment.utc(obj.expiry).local().fromNow()
obj.msat = obj.amount
obj.sat = obj.msat / 1000
obj.tag = obj.extra?.tag
obj.fsat = new Intl.NumberFormat(window.i18n.global.locale).format(
obj.sat
)
obj.isIn = obj.amount > 0
obj.isOut = obj.amount < 0
obj.isPending = obj.status === 'pending'
obj.isPaid = obj.status === 'success'
obj.isFailed = obj.status === 'failed'
obj._q = [obj.memo, obj.sat].join(' ').toLowerCase()
try {
obj.details = JSON.parse(data.extra?.details || '{}')
} catch {
obj.details = {extraDetails: data.extra?.details}
}
return obj
} }
} }
} }
@@ -147,6 +147,49 @@ window.app.component('lnbits-payment-list', {
} }
}, },
methods: { methods: {
mapPayment(data) {
const obj = {
checking_id: data.checking_id,
status: data.status,
amount: data.amount,
fee: data.fee,
memo: data.memo,
time: data.time,
bolt11: data.bolt11,
preimage: data.preimage,
payment_hash: data.payment_hash,
expiry: data.expiry,
extra: data.extra ?? {},
wallet_id: data.wallet_id,
webhook: data.webhook,
webhook_status: data.webhook_status,
fiat_amount: data.fiat_amount,
fiat_currency: data.fiat_currency,
labels: data.labels
}
obj.date = moment.utc(data.created_at).local().format(window.dateFormat)
obj.dateFrom = moment.utc(data.created_at).local().fromNow()
obj.expirydate = moment.utc(obj.expiry).local().format(window.dateFormat)
obj.expirydateFrom = moment.utc(obj.expiry).local().fromNow()
obj.msat = obj.amount
obj.sat = obj.msat / 1000
obj.tag = obj.extra?.tag
obj.fsat = new Intl.NumberFormat(window.i18n.global.locale).format(
obj.sat
)
obj.isIn = obj.amount > 0
obj.isOut = obj.amount < 0
obj.isPending = obj.status === 'pending'
obj.isPaid = obj.status === 'success'
obj.isFailed = obj.status === 'failed'
obj._q = [obj.memo, obj.sat].join(' ').toLowerCase()
try {
obj.details = JSON.parse(data.extra?.details || '{}')
} catch {
obj.details = {extraDetails: data.extra?.details}
}
return obj
},
searchByDate() { searchByDate() {
if (typeof this.searchDate === 'string') { if (typeof this.searchDate === 'string') {
this.searchDate = { this.searchDate = {
@@ -195,9 +238,7 @@ window.app.component('lnbits-payment-list', {
.then(response => { .then(response => {
this.paymentsTable.loading = false this.paymentsTable.loading = false
this.paymentsTable.pagination.rowsNumber = response.data.total this.paymentsTable.pagination.rowsNumber = response.data.total
this.payments = response.data.data.map(obj => { this.payments = response.data.data.map(this.mapPayment)
return LNbits.map.payment(obj)
})
this.recheckPendingPayments() this.recheckPendingPayments()
}) })
.catch(err => { .catch(err => {
@@ -216,9 +257,7 @@ window.app.component('lnbits-payment-list', {
.then(response => { .then(response => {
this.paymentsTable.loading = false this.paymentsTable.loading = false
this.paymentsTable.pagination.rowsNumber = response.data.total this.paymentsTable.pagination.rowsNumber = response.data.total
this.payments = response.data.data.map(obj => { this.payments = response.data.data.map(this.mapPayment)
return LNbits.map.payment(obj)
})
}) })
.catch(err => { .catch(err => {
this.paymentsTable.loading = false this.paymentsTable.loading = false
@@ -264,11 +303,7 @@ window.app.component('lnbits-payment-list', {
p => p.checking_id === updatedPayment.checking_id p => p.checking_id === updatedPayment.checking_id
) )
if (index !== -1) { if (index !== -1) {
this.payments.splice( this.payments.splice(index, 1, this.mapPayment(updatedPayment))
index,
1,
LNbits.map.payment(updatedPayment)
)
updatedPayments += 1 updatedPayments += 1
} }
} }
@@ -327,7 +362,7 @@ window.app.component('lnbits-payment-list', {
} }
const params = new URLSearchParams(query) const params = new URLSearchParams(query)
LNbits.api.getPayments(this.g.wallet, params).then(response => { LNbits.api.getPayments(this.g.wallet, params).then(response => {
let payments = response.data.data.map(LNbits.map.payment) let payments = response.data.data.map(this.mapPayment)
let columns = this.paymentsCSV.columns let columns = this.paymentsCSV.columns
if (detailed) { if (detailed) {
-2
View File
@@ -18,13 +18,11 @@ window.g = Vue.reactive({
fiatBalance: 0, fiatBalance: 0,
exchangeRate: 0, exchangeRate: 0,
fiatTracking: false, fiatTracking: false,
wallets: [],
payments: [], payments: [],
walletEventListeners: [], walletEventListeners: [],
showNewWalletDialog: false, showNewWalletDialog: false,
newWalletType: 'lightning', newWalletType: 'lightning',
updatePayments: false, updatePayments: false,
updatePaymentsHash: '',
currencies: WINDOW_SETTINGS.LNBITS_CURRENCIES ?? [], currencies: WINDOW_SETTINGS.LNBITS_CURRENCIES ?? [],
allowedCurrencies: WINDOW_SETTINGS.LNBITS_ALLOWED_CURRENCIES ?? [], allowedCurrencies: WINDOW_SETTINGS.LNBITS_ALLOWED_CURRENCIES ?? [],
locale: localStore('lnbits.lang', navigator.languages[1] ?? 'en'), locale: localStore('lnbits.lang', navigator.languages[1] ?? 'en'),
+6
View File
@@ -86,6 +86,12 @@ window.i18n = new VueI18n.createI18n({
}) })
window.app.mixin({ window.app.mixin({
data() {
return {
g: window.g,
...WINDOW_SETTINGS
}
},
computed: { computed: {
isVueRoute() { isVueRoute() {
const currentPath = window.location.pathname const currentPath = window.location.pathname
-4
View File
@@ -661,10 +661,6 @@ window.PageWallet = {
}, },
'g.updatePayments'() { 'g.updatePayments'() {
this.parse.show = false this.parse.show = false
if (this.receive.paymentHash === this.g.updatePaymentsHash) {
this.receive.show = false
this.receive.paymentHash = null
}
if ( if (
this.g.wallet.currency && this.g.wallet.currency &&
this.$q.localStorage.getItem( this.$q.localStorage.getItem(
+51 -53
View File
@@ -1,54 +1,61 @@
window.windowMixin = { window.windowMixin = {
i18n: window.i18n,
data() {
return {
g: window.g,
utils: window._lnbitsUtils,
...WINDOW_SETTINGS
}
},
methods: { methods: {
openNewWalletDialog(walletType = 'lightning') { openNewWalletDialog(walletType = 'lightning') {
this.g.newWalletType = walletType this.g.newWalletType = walletType
this.g.showNewWalletDialog = true this.g.showNewWalletDialog = true
}, },
onWebsocketMessage(ev) {
const data = JSON.parse(ev.data)
if (!data.payment) {
console.error('ws message no payment', data)
return
}
// update sidebar wallet balances
this.g.user.wallets.forEach(w => {
if (w.id === data.payment.wallet_id) {
w.sat = data.wallet_balance
}
})
// if current wallet, update balance and payments
if (this.g.wallet.id === data.payment.wallet_id) {
this.g.wallet.sat = data.wallet_balance
// lnbits-payment-list is watching
this.g.updatePayments = !this.g.updatePayments
}
// NOTE: react only on incoming payments for now
if (data.payment.amount > 0) {
eventReaction(data.wallet_balance * 1000)
}
},
paymentEvents() { paymentEvents() {
this.g.walletEventListeners = this.g.walletEventListeners || [] let timeout
this.g.user.wallets.forEach(wallet => { this.g.user.wallets.forEach(wallet => {
if (!this.g.walletEventListeners.includes(wallet.id)) { if (!this.g.walletEventListeners.includes(wallet.id)) {
this.g.walletEventListeners.push(wallet.id) this.g.walletEventListeners.push(wallet.id)
LNbits.events.onInvoicePaid(wallet, data => { const ws = new WebSocket(`${websocketUrl}/${wallet.inkey}`)
const walletIndex = this.g.user.wallets.findIndex( ws.onmessage = this.onWebsocketMessage
w => w.id === wallet.id ws.onopen = () => console.log('ws connected for wallet', wallet.id)
// onclose and onerror can both happen on their own or together,
// so we add a clearTimeout to avoid multiple reconnections
ws.onclose = () => {
console.log('ws closed, reconnecting...', wallet.id)
this.g.walletEventListeners = this.g.walletEventListeners.filter(
id => id !== wallet.id
) )
if (walletIndex !== -1) { clearTimeout(timeout)
//needed for balance being deducted timeout = setTimeout(this.paymentEvents, 5000)
let satBalance = data.wallet_balance }
if (data.payment.amount < 0) { ws.onerror = () => {
satBalance = data.wallet_balance += data.payment.amount / 1000 console.warn('ws error, reconnecting...', wallet.id)
} this.g.walletEventListeners = this.g.walletEventListeners.filter(
//update the wallet id => id !== wallet.id
Object.assign(this.g.user.wallets[walletIndex], { )
sat: satBalance, clearTimeout(timeout)
msat: data.wallet_balance * 1000, timeout = setTimeout(this.paymentEvents, 5000)
fsat: data.wallet_balance.toLocaleString() }
})
//update the current wallet
if (this.g.wallet.id === data.payment.wallet_id) {
Object.assign(this.g.wallet, this.g.user.wallets[walletIndex])
//if on the wallet page and payment is incoming trigger the eventReaction
if (
data.payment.amount > 0 &&
window.location.pathname === '/wallet'
) {
eventReaction(data.wallet_balance * 1000)
}
}
}
this.g.updatePaymentsHash = data.payment.payment_hash
this.g.updatePayments = !this.g.updatePayments
})
} }
}) })
}, },
@@ -100,19 +107,10 @@ window.windowMixin = {
}) })
} }
}, },
async created() { created() {
if (window.user) { // map jinja variable once on pageload
this.g.user = Vue.reactive(window.LNbits.map.user(window.user)) if (window.user && !this.g.user) {
} this.g.user = window.LNbits.map.user(window.user)
if (window.wallet) {
this.g.wallet = Vue.reactive(window.LNbits.map.wallet(window.wallet))
}
if (window.extensions) {
this.g.extensions = Vue.reactive(window.extensions)
}
},
mounted() {
if (this.g.user) {
this.paymentEvents() this.paymentEvents()
} }
} }
+1 -11
View File
@@ -1,18 +1,8 @@
{% macro window_vars(user, wallet, extensions, extension_data) -%} {% macro window_vars(user) -%}
<script id="window-vars-script"> <script id="window-vars-script">
window.extensions = JSON.parse('{{ EXTENSIONS | tojson | safe }}');
{% if extension_data %}
window.extension_data = {{ extension_data | tojson | safe }};
{% endif %}
{% if currencies %}
window.currencies = {{ currencies | tojson | safe }};
{% endif %}
{% if user %} {% if user %}
window.user = JSON.parse({{ user | tojson | safe }}); window.user = JSON.parse({{ user | tojson | safe }});
{% endif %} {% endif %}
{% if wallet %}
window.wallet = JSON.parse({{ wallet | tojson | safe }});
{% endif %}
</script> </script>
<script> <script>
//Needed for Vue to create the app on first load (although called on every page, its only loaded once) //Needed for Vue to create the app on first load (although called on every page, its only loaded once)
+4 -4
View File
@@ -133,8 +133,8 @@
unelevated unelevated
color="primary" color="primary"
class="q-mr-md" class="q-mr-md"
@click="showParseDialog" @click="showReceiveDialog"
:disable="!this.g.wallet.canSendPayments" :disable="!this.g.wallet.canReceivePayments"
:label="$t('receive')" :label="$t('receive')"
icon="file_download" icon="file_download"
></q-btn> ></q-btn>
@@ -142,8 +142,8 @@
unelevated unelevated
color="primary" color="primary"
class="q-mr-md" class="q-mr-md"
@click="showReceiveDialog" @click="showParseDialog"
:disable="!this.g.wallet.canReceivePayments" :disable="!this.g.wallet.canSendPayments"
:label="$t('send')" :label="$t('send')"
icon="file_upload" icon="file_upload"
></q-btn> ></q-btn>