feat(nostr): Add connecting state to Nostr connection management
- Introduce `isConnecting` state in useNostr composable - Update ConnectionStatus component to handle connecting state - Add warning variant to Badge for connecting status - Implement dynamic status text, color, and animation for connection states - Modify App.vue to pass new isConnecting prop to ConnectionStatus
This commit is contained in:
parent
0923731ee9
commit
18ece1e3e7
5 changed files with 52 additions and 12 deletions
3
.env
3
.env
|
|
@ -1,5 +1,4 @@
|
||||||
# Support agent's public key in npub format
|
# Support agent's public key in npub format
|
||||||
VITE_SUPPORT_NPUB=npub1tm42jkmdn54zncjcylp34e85jagmgndr0skw4v0rsg8rucmu7r5swayth3
|
VITE_SUPPORT_NPUB=npub1tm42jkmdn54zncjcylp34e85jagmgndr0skw4v0rsg8rucmu7r5swayth3
|
||||||
|
|
||||||
VITE_NOSTR_RELAYS=["wss://relay.damus.io","wss://relay.nostr.info"]
|
VITE_NOSTR_RELAYS=["wss://nostr.atitlan.io"]
|
||||||
|
|
||||||
|
|
|
||||||
10
src/App.vue
10
src/App.vue
|
|
@ -1,12 +1,12 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, onUnmounted } from 'vue'
|
import { onMounted, onUnmounted, ref } from 'vue'
|
||||||
import Navbar from '@/components/layout/Navbar.vue'
|
import Navbar from '@/components/layout/Navbar.vue'
|
||||||
import Footer from '@/components/layout/Footer.vue'
|
import Footer from '@/components/layout/Footer.vue'
|
||||||
import ConnectionStatus from '@/components/nostr/ConnectionStatus.vue'
|
import ConnectionStatus from '@/components/nostr/ConnectionStatus.vue'
|
||||||
import { useNostr } from '@/composables/useNostr'
|
import { useNostr } from '@/composables/useNostr'
|
||||||
|
|
||||||
const relays = JSON.parse(import.meta.env.VITE_NOSTR_RELAYS as string)
|
const relays = JSON.parse(import.meta.env.VITE_NOSTR_RELAYS as string)
|
||||||
const { isConnected, error, connect, disconnect } = useNostr({ relays })
|
const { isConnected, isConnecting, error, connect, disconnect } = useNostr({ relays })
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await connect()
|
await connect()
|
||||||
|
|
@ -25,7 +25,11 @@ onUnmounted(() => {
|
||||||
class="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
class="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
||||||
<nav class="container flex h-14 items-center justify-between">
|
<nav class="container flex h-14 items-center justify-between">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<ConnectionStatus :is-connected="isConnected" :error="error" />
|
<ConnectionStatus
|
||||||
|
:is-connected="isConnected"
|
||||||
|
:is-connecting="isConnecting"
|
||||||
|
:error="error"
|
||||||
|
/>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,51 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Badge } from '@/components/ui/badge'
|
import { Badge } from '@/components/ui/badge'
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
isConnected: boolean
|
isConnected: boolean
|
||||||
|
isConnecting: boolean
|
||||||
error?: Error | null
|
error?: Error | null
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
function getStatusVariant() {
|
||||||
|
if (props.isConnecting) return 'warning'
|
||||||
|
return props.isConnected ? 'success' : 'destructive'
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatusText() {
|
||||||
|
if (props.isConnecting) return 'Connecting'
|
||||||
|
return props.isConnected ? 'Online' : 'Offline'
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatusColor() {
|
||||||
|
if (props.isConnecting) return 'bg-yellow-400'
|
||||||
|
return props.isConnected ? 'bg-green-400' : 'bg-red-400'
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatusColorSolid() {
|
||||||
|
if (props.isConnecting) return 'bg-yellow-500'
|
||||||
|
return props.isConnected ? 'bg-green-500' : 'bg-red-500'
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<Badge :variant="isConnected ? 'success' : 'destructive'" class="flex items-center gap-1">
|
<Badge :variant="getStatusVariant()" class="flex items-center gap-1">
|
||||||
<span class="relative flex h-2 w-2">
|
<span class="relative flex h-2 w-2">
|
||||||
<span class="absolute inline-flex h-full w-full animate-ping rounded-full opacity-75"
|
<span
|
||||||
:class="isConnected ? 'bg-green-400' : 'bg-red-400'" />
|
class="absolute inline-flex h-full w-full rounded-full opacity-75"
|
||||||
<span class="relative inline-flex h-2 w-2 rounded-full"
|
:class="[
|
||||||
:class="isConnected ? 'bg-green-500' : 'bg-red-500'" />
|
getStatusColor(),
|
||||||
|
{ 'animate-ping': !props.isConnecting },
|
||||||
|
{ 'animate-pulse': props.isConnecting }
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="relative inline-flex h-2 w-2 rounded-full"
|
||||||
|
:class="getStatusColorSolid()"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span class="text-[10px]">{{ isConnected ? 'Online' : 'Offline' }}</span>
|
<span class="text-[10px]">{{ getStatusText() }}</span>
|
||||||
</Badge>
|
</Badge>
|
||||||
<p v-if="error" class="text-xs text-destructive">
|
<p v-if="error" class="text-xs text-destructive">
|
||||||
{{ error.message }}
|
{{ error.message }}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ export const badgeVariants = cva(
|
||||||
'border-transparent bg-destructive/10 text-destructive hover:bg-destructive/20',
|
'border-transparent bg-destructive/10 text-destructive hover:bg-destructive/20',
|
||||||
success:
|
success:
|
||||||
'border-transparent bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400',
|
'border-transparent bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400',
|
||||||
|
warning:
|
||||||
|
'border-transparent bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400',
|
||||||
outline: 'border-border text-foreground hover:bg-accent hover:text-accent-foreground',
|
outline: 'border-border text-foreground hover:bg-accent hover:text-accent-foreground',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -4,27 +4,33 @@ import { NostrClient, type NostrClientConfig } from '@/lib/nostr/client'
|
||||||
export function useNostr(config: NostrClientConfig) {
|
export function useNostr(config: NostrClientConfig) {
|
||||||
const client = new NostrClient(config)
|
const client = new NostrClient(config)
|
||||||
const isConnected = ref(false)
|
const isConnected = ref(false)
|
||||||
|
const isConnecting = ref(false)
|
||||||
const error = ref<Error | null>(null)
|
const error = ref<Error | null>(null)
|
||||||
|
|
||||||
async function connect() {
|
async function connect() {
|
||||||
try {
|
try {
|
||||||
error.value = null
|
error.value = null
|
||||||
|
isConnecting.value = true
|
||||||
await client.connect()
|
await client.connect()
|
||||||
isConnected.value = client.isConnected
|
isConnected.value = client.isConnected
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error.value = err instanceof Error ? err : new Error('Failed to connect')
|
error.value = err instanceof Error ? err : new Error('Failed to connect')
|
||||||
isConnected.value = false
|
isConnected.value = false
|
||||||
|
} finally {
|
||||||
|
isConnecting.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function disconnect() {
|
function disconnect() {
|
||||||
client.disconnect()
|
client.disconnect()
|
||||||
isConnected.value = false
|
isConnected.value = false
|
||||||
|
isConnecting.value = false
|
||||||
error.value = null
|
error.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isConnected,
|
isConnected,
|
||||||
|
isConnecting,
|
||||||
error,
|
error,
|
||||||
connect,
|
connect,
|
||||||
disconnect
|
disconnect
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue