Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3535e3965 | ||
|
|
f405d6834a | ||
|
|
93bcd25ab7 | ||
|
|
9d288e6a98 | ||
|
|
b71382aa1e | ||
|
|
241f1f81a8 |
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -674,5 +674,7 @@ window.localisation.en = {
|
|||||||
paid: 'Paid',
|
paid: 'Paid',
|
||||||
funding_source_retries: 'Max Retries',
|
funding_source_retries: 'Max Retries',
|
||||||
funding_source_retries_desc:
|
funding_source_retries_desc:
|
||||||
'Maximum number of retries for funding sources, before it falls back to VoidWallet.'
|
'Maximum number of retries for funding sources, before it falls back to VoidWallet.',
|
||||||
|
ws_connection_warning:
|
||||||
|
'Lost connection to the websocket. Wait while page tries to reconnect.'
|
||||||
}
|
}
|
||||||
|
|||||||
+127
-8
@@ -179,14 +179,79 @@ window.LNbits = {
|
|||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
onInvoicePaid(wallet, cb) {
|
onInvoicePaid(wallet, cb) {
|
||||||
ws = new WebSocket(`${websocketUrl}/${wallet.inkey}`)
|
const reconnectInterval = 5000 // 5 seconds
|
||||||
ws.onmessage = ev => {
|
const maxRetries = 12 // ~60 seconds
|
||||||
const data = JSON.parse(ev.data)
|
const websocketUrlFull = `${websocketUrl}/${wallet.inkey}`
|
||||||
if (data.payment) {
|
|
||||||
cb(data)
|
if (!g.activeWebsockets) g.activeWebsockets = {}
|
||||||
|
if (!g.disconnectedWallets) g.disconnectedWallets = new Set()
|
||||||
|
|
||||||
|
const updateConnectionWarning = () => {
|
||||||
|
g.connectionWarning = g.disconnectedWallets.size > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
const connect = (retryCount = 0) => {
|
||||||
|
try {
|
||||||
|
const ws = new WebSocket(websocketUrlFull)
|
||||||
|
g.activeWebsockets[wallet.id] = ws
|
||||||
|
console.debug(
|
||||||
|
`Connecting WebSocket for wallet ${wallet.name}... (attempt ${retryCount + 1})`
|
||||||
|
)
|
||||||
|
|
||||||
|
ws.onopen = () => {
|
||||||
|
console.debug(`WebSocket connected for wallet ${wallet.name}`)
|
||||||
|
g.disconnectedWallets.delete(wallet.id)
|
||||||
|
updateConnectionWarning()
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.onmessage = ev => {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(ev.data)
|
||||||
|
if (data.payment) cb(data)
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error parsing WebSocket message:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.onerror = err => {
|
||||||
|
console.error(`WebSocket error for wallet ${wallet.name}:`, err)
|
||||||
|
ws.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.onclose = () => {
|
||||||
|
g.disconnectedWallets.add(wallet.id)
|
||||||
|
updateConnectionWarning()
|
||||||
|
|
||||||
|
if (retryCount < maxRetries) {
|
||||||
|
console.warn(
|
||||||
|
`WebSocket closed for wallet ${wallet.name}. Reconnecting in ${reconnectInterval / 1000}s...`
|
||||||
|
)
|
||||||
|
setTimeout(() => connect(retryCount + 1), reconnectInterval)
|
||||||
|
} else {
|
||||||
|
console.error(
|
||||||
|
`WebSocket for wallet ${wallet.name} failed after ${maxRetries} attempts. Stopping retries.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
`WebSocket connection failed for wallet ${wallet.name}:`,
|
||||||
|
err
|
||||||
|
)
|
||||||
|
g.disconnectedWallets.add(wallet.id)
|
||||||
|
updateConnectionWarning()
|
||||||
|
|
||||||
|
if (retryCount < maxRetries) {
|
||||||
|
setTimeout(() => connect(retryCount + 1), reconnectInterval)
|
||||||
|
} else {
|
||||||
|
console.error(
|
||||||
|
`[LNbits] Stopped retrying wallet ${wallet.name} after ${maxRetries} attempts.`
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ws.onclose
|
|
||||||
|
connect()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
map: {
|
map: {
|
||||||
@@ -459,7 +524,9 @@ if (!window.g) {
|
|||||||
langs: [],
|
langs: [],
|
||||||
walletEventListeners: [],
|
walletEventListeners: [],
|
||||||
updatePayments: false,
|
updatePayments: false,
|
||||||
updatePaymentsHash: ''
|
updatePaymentsHash: '',
|
||||||
|
wsDisconnectionNotification: false,
|
||||||
|
wsReconnectedNotification: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,7 +561,8 @@ window.windowMixin = {
|
|||||||
bgimageChoice: this.$q.localStorage.has('lnbits.backgroundImage')
|
bgimageChoice: this.$q.localStorage.has('lnbits.backgroundImage')
|
||||||
? this.$q.localStorage.getItem('lnbits.backgroundImage')
|
? this.$q.localStorage.getItem('lnbits.backgroundImage')
|
||||||
: USE_DEFAULT_BGIMAGE,
|
: USE_DEFAULT_BGIMAGE,
|
||||||
...WINDOW_SETTINGS
|
...WINDOW_SETTINGS,
|
||||||
|
silentConnectionCleanup: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -802,6 +870,57 @@ window.windowMixin = {
|
|||||||
mounted() {
|
mounted() {
|
||||||
if (this.g.user) {
|
if (this.g.user) {
|
||||||
this.paymentEvents()
|
this.paymentEvents()
|
||||||
|
|
||||||
|
// Retry timer reference (for cleanup)
|
||||||
|
this.connectionRetryTimer = setInterval(() => {
|
||||||
|
if (this.g.disconnectedWallets && this.g.disconnectedWallets.size > 0) {
|
||||||
|
console.warn('Some wallets are still disconnected. Retrying...')
|
||||||
|
this.paymentEvents()
|
||||||
|
}
|
||||||
|
}, 60000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeUnmount() {
|
||||||
|
this.silentConnectionCleanup = true
|
||||||
|
// Prevent background timers when component is destroyed
|
||||||
|
if (this.connectionRetryTimer) {
|
||||||
|
clearInterval(this.connectionRetryTimer)
|
||||||
|
this.connectionRetryTimer = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'g.connectionWarning': {
|
||||||
|
handler(newVal, oldVal) {
|
||||||
|
if (this.silentConnectionCleanup) return
|
||||||
|
|
||||||
|
if (newVal && !g.wsDisconnectionNotification) {
|
||||||
|
this.$q.notify({
|
||||||
|
message: 'Some wallet connections are lost. Retrying...',
|
||||||
|
color: 'negative',
|
||||||
|
icon: null,
|
||||||
|
position: 'top',
|
||||||
|
timeout: 5000
|
||||||
|
})
|
||||||
|
g.wsDisconnectionNotification = true
|
||||||
|
g.wsReconnectedNotification = false
|
||||||
|
} else if (
|
||||||
|
oldVal === true &&
|
||||||
|
newVal === false &&
|
||||||
|
!g.wsReconnectedNotification
|
||||||
|
) {
|
||||||
|
this.$q.notify({
|
||||||
|
message: 'All wallet connections restored.',
|
||||||
|
color: 'positive',
|
||||||
|
icon: null,
|
||||||
|
position: 'top',
|
||||||
|
timeout: 3000
|
||||||
|
})
|
||||||
|
g.wsReconnectedNotification = true
|
||||||
|
g.wsDisconnectionNotification = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,6 +129,20 @@
|
|||||||
>{% endblock %} {% block toolbar_subtitle %}
|
>{% endblock %} {% block toolbar_subtitle %}
|
||||||
<q-badge v-if="g.user && g.user.super_user">Super User</q-badge>
|
<q-badge v-if="g.user && g.user.super_user">Super User</q-badge>
|
||||||
<q-badge v-else-if="g.user && g.user.admin">Admin User</q-badge>
|
<q-badge v-else-if="g.user && g.user.admin">Admin User</q-badge>
|
||||||
|
<q-badge
|
||||||
|
v-if="g.connectionWarning"
|
||||||
|
color="red"
|
||||||
|
class="inline-block q-ml-sm"
|
||||||
|
>
|
||||||
|
<q-icon
|
||||||
|
name="wifi_tethering_off"
|
||||||
|
color="white"
|
||||||
|
size="12px"
|
||||||
|
></q-icon>
|
||||||
|
<q-tooltip
|
||||||
|
><span v-text="$t('ws_connection_warning')"></span
|
||||||
|
></q-tooltip>
|
||||||
|
</q-badge>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</q-toolbar-title>
|
</q-toolbar-title>
|
||||||
{% block beta %} {% if LNBITS_CUSTOM_BADGE is not none and
|
{% block beta %} {% if LNBITS_CUSTOM_BADGE is not none and
|
||||||
|
|||||||
Reference in New Issue
Block a user