Merge pull request #133 from BenGWeeks/feature/nostrclient-status-indicator

feat: add nostrclient status indicator and connection button
This commit is contained in:
Arc 2025-12-24 03:58:48 +00:00 committed by GitHub
commit 5e22796198
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 146 additions and 10 deletions

View file

@ -18,7 +18,26 @@ window.app = Vue.createApp({
privateKey: null privateKey: null
} }
}, },
wsConnection: null wsConnection: null,
nostrStatus: {
connected: false,
error: null,
relays_connected: 0,
relays_total: 0
}
}
},
computed: {
nostrStatusColor: function () {
if (this.nostrStatus.connected) {
return 'green'
} else if (this.nostrStatus.warning) {
return 'orange'
}
return 'red'
},
nostrStatusLabel: function () {
return 'Connect'
} }
}, },
methods: { methods: {
@ -198,18 +217,82 @@ window.app = Vue.createApp({
}) })
} }
}, },
checkNostrStatus: async function (showNotification = false) {
try {
const response = await fetch('/nostrclient/api/v1/relays')
const body = await response.json()
if (response.status === 200) {
const relaysConnected = body.filter(r => r.connected).length
if (body.length === 0) {
this.nostrStatus = {
connected: false,
error: 'No relays configured in Nostr Client',
relays_connected: 0,
relays_total: 0,
warning: true
}
} else {
this.nostrStatus = {
connected: true,
error: null,
relays_connected: relaysConnected,
relays_total: body.length
}
}
} else {
this.nostrStatus = {
connected: false,
error: body.detail,
relays_connected: 0,
relays_total: 0
}
}
if (showNotification) {
this.$q.notify({
timeout: 3000,
type: this.nostrStatus.connected ? 'positive' : 'warning',
message: this.nostrStatus.connected ? 'Connected' : 'Disconnected',
caption: this.nostrStatus.error || undefined
})
}
} catch (error) {
console.error('Failed to check nostr status:', error)
this.nostrStatus = {
connected: false,
error: error.message,
relays_connected: 0,
relays_total: 0
}
if (showNotification) {
this.$q.notify({
timeout: 5000,
type: 'negative',
message: this.nostrStatus.error
})
}
}
},
restartNostrConnection: async function () { restartNostrConnection: async function () {
LNbits.utils LNbits.utils
.confirmDialog( .confirmDialog(
'Are you sure you want to reconnect to the nostrcient extension?' 'Are you sure you want to reconnect to the nostrclient extension?'
) )
.onOk(async () => { .onOk(async () => {
try { try {
this.$q.notify({
timeout: 2000,
type: 'info',
message: 'Reconnecting...'
})
await LNbits.api.request( await LNbits.api.request(
'PUT', 'PUT',
'/nostrmarket/api/v1/restart', '/nostrmarket/api/v1/restart',
this.g.user.wallets[0].adminkey this.g.user.wallets[0].adminkey
) )
// Check status after restart (give time for websocket to reconnect)
setTimeout(() => this.checkNostrStatus(true), 3000)
} catch (error) { } catch (error) {
LNbits.utils.notifyApiError(error) LNbits.utils.notifyApiError(error)
} }
@ -300,6 +383,7 @@ window.app = Vue.createApp({
}, },
created: async function () { created: async function () {
await this.getMerchant() await this.getMerchant()
await this.checkNostrStatus()
setInterval(async () => { setInterval(async () => {
if ( if (
!this.wsConnection || !this.wsConnection ||

View file

@ -278,16 +278,68 @@
<div v-if="g.user.admin" class="col-12 q-mb-lg"> <div v-if="g.user.admin" class="col-12 q-mb-lg">
<q-card> <q-card>
<q-card-section class="q-pa-md"> <q-card-section class="q-pa-md">
<q-btn <q-btn-dropdown
label="Restart Nostr Connection" :color="nostrStatusColor"
color="grey" :label="nostrStatusLabel"
outline icon="sync"
split
@click="restartNostrConnection" @click="restartNostrConnection"
> >
<q-tooltip> <q-list>
Restart the connection to the nostrclient extension <q-item clickable v-close-popup @click="restartNostrConnection">
</q-tooltip> <q-item-section avatar>
</q-btn> <q-icon name="refresh" color="primary"></q-icon>
</q-item-section>
<q-item-section>
<q-item-label>Restart Connection</q-item-label>
<q-item-label caption>
Reconnect to the nostrclient extension
</q-item-label>
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="checkNostrStatus(true)">
<q-item-section avatar>
<q-icon name="wifi_find" color="primary"></q-icon>
</q-item-section>
<q-item-section>
<q-item-label>Check Status</q-item-label>
<q-item-label caption>
Check connection to nostrclient
</q-item-label>
</q-item-section>
</q-item>
<q-separator></q-separator>
<q-item>
<q-item-section>
<q-item-label caption>
<strong>Status:</strong>
<q-badge
:color="nostrStatus.connected ? 'green' : 'red'"
class="q-ml-xs"
v-text="nostrStatus.connected ? 'Connected' : 'Disconnected'"
></q-badge>
</q-item-label>
<q-item-label
v-if="nostrStatus.relays_total > 0"
caption
class="q-mt-xs"
>
<strong>Relays:</strong>&nbsp;
<span v-text="nostrStatus.relays_connected"></span>
of
<span v-text="nostrStatus.relays_total"></span>
connected
</q-item-label>
<q-item-label
v-if="nostrStatus.error"
caption
class="text-negative q-mt-xs"
v-text="nostrStatus.error"
></q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-btn-dropdown>
</q-card-section> </q-card-section>
</q-card> </q-card>
</div> </div>