Browse Source

bug-fixes for cache relay

imwald
Silberengel 5 months ago
parent
commit
30021a3c68
  1. 36
      src/components/CacheRelaysSetting/index.tsx
  2. 40
      src/providers/NostrProvider/index.tsx

36
src/components/CacheRelaysSetting/index.tsx

@ -2,7 +2,7 @@ import { Button } from '@/components/ui/button'
import { normalizeUrl, isLocalNetworkUrl } from '@/lib/url' import { normalizeUrl, isLocalNetworkUrl } from '@/lib/url'
import { useNostr } from '@/providers/NostrProvider' import { useNostr } from '@/providers/NostrProvider'
import { TMailboxRelay, TMailboxRelayScope } from '@/types' import { TMailboxRelay, TMailboxRelayScope } from '@/types'
import { useEffect, useState, useMemo } from 'react' import { useEffect, useState, useMemo, useRef } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { import {
DndContext, DndContext,
@ -45,6 +45,7 @@ export default function CacheRelaysSetting() {
const [relays, setRelays] = useState<TMailboxRelay[]>([]) const [relays, setRelays] = useState<TMailboxRelay[]>([])
const [hasChange, setHasChange] = useState(false) const [hasChange, setHasChange] = useState(false)
const [pushing, setPushing] = useState(false) const [pushing, setPushing] = useState(false)
const justSavedRef = useRef(false)
const [cacheInfo, setCacheInfo] = useState<Record<string, number>>({}) const [cacheInfo, setCacheInfo] = useState<Record<string, number>>({})
const [browsingCache, setBrowsingCache] = useState(false) const [browsingCache, setBrowsingCache] = useState(false)
const [selectedStore, setSelectedStore] = useState<string | null>(null) const [selectedStore, setSelectedStore] = useState<string | null>(null)
@ -92,8 +93,32 @@ export default function CacheRelaysSetting() {
} }
const cacheRelayList = getRelayListFromEvent(cacheRelayListEvent) const cacheRelayList = getRelayListFromEvent(cacheRelayListEvent)
setRelays(cacheRelayList.originalRelays) const newRelays = cacheRelayList.originalRelays
setHasChange(false)
// Use functional update to compare with current state
setRelays((currentRelays) => {
// Check if relays are actually different (deep comparison)
const areRelaysEqual =
newRelays.length === currentRelays.length &&
newRelays.every((relay, index) =>
relay.url === currentRelays[index]?.url &&
relay.scope === currentRelays[index]?.scope
)
// Only update and reset hasChange if relays actually changed AND we just saved
// This prevents resetting hasChange when user is actively making changes
if (!areRelaysEqual) {
if (justSavedRef.current) {
// We just saved, so this update is expected - reset hasChange
justSavedRef.current = false
setHasChange(false)
}
return newRelays
}
// If relays are equal, don't update state (prevents unnecessary re-render)
return currentRelays
})
}, [cacheRelayListEvent]) }, [cacheRelayListEvent])
if (!pubkey) { if (!pubkey) {
@ -369,8 +394,9 @@ export default function CacheRelaysSetting() {
try { try {
const event = createCacheRelaysDraftEvent(relays) const event = createCacheRelaysDraftEvent(relays)
const result = await publish(event) const result = await publish(event)
// Set flag before updating so useEffect knows to reset hasChange
justSavedRef.current = true
await updateCacheRelayListEvent(result) await updateCacheRelayListEvent(result)
setHasChange(false)
// Show publishing feedback // Show publishing feedback
if ((result as any).relayStatuses) { if ((result as any).relayStatuses) {
@ -387,6 +413,8 @@ export default function CacheRelaysSetting() {
showSimplePublishSuccess(t('Cache relays saved')) showSimplePublishSuccess(t('Cache relays saved'))
} }
} catch (error) { } catch (error) {
// Reset flag on error
justSavedRef.current = false
console.error('Failed to save cache relays:', error) console.error('Failed to save cache relays:', error)
// Show error feedback // Show error feedback
if (error instanceof Error && (error as any).relayStatuses) { if (error instanceof Error && (error as any).relayStatuses) {

40
src/providers/NostrProvider/index.tsx

@ -29,7 +29,8 @@ import {
TDraftEvent, TDraftEvent,
TProfile, TProfile,
TPublishOptions, TPublishOptions,
TRelayList TRelayList,
TMailboxRelay
} from '@/types' } from '@/types'
import { hexToBytes } from '@noble/hashes/utils' import { hexToBytes } from '@noble/hashes/utils'
import dayjs from 'dayjs' import dayjs from 'dayjs'
@ -265,8 +266,41 @@ export function NostrProvider({ children }: { children: React.ReactNode }) {
setBlockedRelaysEvent(storedBlockedRelaysEvent) setBlockedRelaysEvent(storedBlockedRelaysEvent)
} }
if (storedRelayListEvent) { // Set initial relay list from stored events (will be updated with merged list later)
setRelayList(getRelayListFromEvent(storedRelayListEvent, blockedRelays)) // Merge cache relays even at initial load so cache relays are available immediately
if (storedRelayListEvent || storedCacheRelayListEvent) {
const baseRelayList = storedRelayListEvent
? getRelayListFromEvent(storedRelayListEvent, blockedRelays)
: { write: [], read: [], originalRelays: [] }
// Merge cache relays if available
if (storedCacheRelayListEvent) {
const cacheRelayList = getRelayListFromEvent(storedCacheRelayListEvent)
// Merge read relays - cache relays first, then others (for offline priority)
const mergedRead = [...cacheRelayList.read, ...baseRelayList.read]
const mergedWrite = [...cacheRelayList.write, ...baseRelayList.write]
const mergedOriginalRelays = new Map<string, TMailboxRelay>()
// Add cache relay original relays first (prioritized)
cacheRelayList.originalRelays.forEach(relay => {
mergedOriginalRelays.set(relay.url, relay)
})
// Then add regular relay original relays
baseRelayList.originalRelays.forEach(relay => {
if (!mergedOriginalRelays.has(relay.url)) {
mergedOriginalRelays.set(relay.url, relay)
}
})
setRelayList({
write: Array.from(new Set(mergedWrite)),
read: Array.from(new Set(mergedRead)),
originalRelays: Array.from(mergedOriginalRelays.values())
})
} else {
setRelayList(baseRelayList)
}
} }
if (storedProfileEvent) { if (storedProfileEvent) {
setProfileEvent(storedProfileEvent) setProfileEvent(storedProfileEvent)

Loading…
Cancel
Save