Browse Source

more bug-fixes

imwald
Silberengel 1 month ago
parent
commit
374601717a
  1. 2
      src/i18n/locales/de.ts
  2. 2
      src/i18n/locales/en.ts
  3. 7
      src/lib/error-suppression.ts
  4. 21
      src/pages/primary/SpellsPage/index.tsx
  5. 27
      src/services/client.service.ts

2
src/i18n/locales/de.ts

@ -621,6 +621,8 @@ export default {
'shortcuts.browserBack': 'Zurück im Browser (Verlauf)', 'shortcuts.browserBack': 'Zurück im Browser (Verlauf)',
spellPickerSectionYours: 'Deine Zaubersprüche', spellPickerSectionYours: 'Deine Zaubersprüche',
'Failed to remove spell from local storage':
'Zauberspruch konnte lokal nicht entfernt werden',
Spells: 'Zaubersprüche', Spells: 'Zaubersprüche',
Tags: 'Tags', Tags: 'Tags',

2
src/i18n/locales/en.ts

@ -784,6 +784,8 @@ export default {
'Add tag filter': 'Add tag filter', 'Add tag filter': 'Add tag filter',
spellPickerSectionYours: 'Your spells', spellPickerSectionYours: 'Your spells',
'Failed to remove spell from local storage':
'Failed to remove spell from local storage',
Spells: 'Spells', Spells: 'Spells',

7
src/lib/error-suppression.ts

@ -272,6 +272,13 @@ function suppressExpectedRejections() {
if (msg.includes('The operation is insecure') || (event.reason?.name === 'SecurityError' && msg.includes('insecure'))) { if (msg.includes('The operation is insecure') || (event.reason?.name === 'SecurityError' && msg.includes('insecure'))) {
event.preventDefault() event.preventDefault()
event.stopPropagation() event.stopPropagation()
return
}
// nostr-tools: relay.send() attaches to connectionPromise without .catch(); if the socket
// closes before the REQ is sent, the rejection was previously uncaught (SendingOnClosedConnection).
if (event.reason?.name === 'SendingOnClosedConnection') {
event.preventDefault()
event.stopPropagation()
} }
}) })
} }

21
src/pages/primary/SpellsPage/index.tsx

@ -25,6 +25,7 @@ import UserAvatar from '@/components/UserAvatar'
import Username from '@/components/Username' import Username from '@/components/Username'
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout' import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
import logger from '@/lib/logger' import logger from '@/lib/logger'
import { showPublishingError } from '@/lib/publishing-feedback'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { useNostr } from '@/providers/NostrProvider' import { useNostr } from '@/providers/NostrProvider'
import client from '@/services/client.service' import client from '@/services/client.service'
@ -147,7 +148,7 @@ function SpellSheetOptionRow({
const SpellsPage = forwardRef<TPageRef>(function SpellsPage(_, ref) { const SpellsPage = forwardRef<TPageRef>(function SpellsPage(_, ref) {
const { t } = useTranslation() const { t } = useTranslation()
const { pubkey, relayList } = useNostr() const { pubkey, relayList, attemptDelete } = useNostr()
const [spells, setSpells] = useState<Event[]>([]) const [spells, setSpells] = useState<Event[]>([])
const [favoriteIds, setFavoriteIds] = useState<Set<string>>(new Set()) const [favoriteIds, setFavoriteIds] = useState<Set<string>>(new Set())
const [selectedSpell, setSelectedSpell] = useState<Event | null>(null) const [selectedSpell, setSelectedSpell] = useState<Event | null>(null)
@ -449,13 +450,27 @@ const SpellsPage = forwardRef<TPageRef>(function SpellsPage(_, ref) {
const handleDeleteSpell = useCallback( const handleDeleteSpell = useCallback(
async (spell: Event) => { async (spell: Event) => {
try {
await attemptDelete(spell)
} catch (e) {
logger.error('Spell deletion publish failed', { error: e, spellId: spell.id })
showPublishingError(e instanceof Error ? e : new Error(String(e)))
return
}
try {
await indexedDb.deleteSpellEvent(spell.id) await indexedDb.deleteSpellEvent(spell.id)
const ids = await indexedDb.getSpellFavoriteIds() const ids = await indexedDb.getSpellFavoriteIds()
await indexedDb.setSpellFavoriteIds(ids.filter((id) => id !== spell.id)) await indexedDb.setSpellFavoriteIds(ids.filter((id) => id !== spell.id))
if (selectedSpell?.id === spell.id) setSelectedSpell(null) if (selectedSpell?.id === spell.id) setSelectedSpell(null)
loadSpells() await loadSpells()
} catch (e) {
logger.error('Spell local cleanup after delete failed', { error: e, spellId: spell.id })
showPublishingError(
e instanceof Error ? e : new Error(t('Failed to remove spell from local storage'))
)
}
}, },
[loadSpells, selectedSpell?.id] [attemptDelete, loadSpells, selectedSpell?.id, t]
) )
const { ownSpells, followSpells, otherSpells, spellsForSelect } = useMemo(() => { const { ownSpells, followSpells, otherSpells, spellsForSelect } = useMemo(() => {

27
src/services/client.service.ts

@ -1066,11 +1066,24 @@ class ClientService extends EventTarget {
onclose: (reason: string) => { onclose: (reason: string) => {
releaseOnce() releaseOnce()
if (reason.startsWith('auth-required: ') && that.canSignerAuthenticateRelay()) { if (reason.startsWith('auth-required: ') && that.canSignerAuthenticateRelay()) {
relay.auth(async (authEvt: EventTemplate) => { relay
.auth(async (authEvt: EventTemplate) => {
const evt = await that.signer!.signEvent(authEvt) const evt = await that.signer!.signEvent(authEvt)
if (!evt) throw new Error('sign event failed') if (!evt) throw new Error('sign event failed')
return evt as VerifiedEvent return evt as VerifiedEvent
}).then(() => that.acquireSubSlot(relayKey)).then(() => { })
.then(async () => {
await that.acquireSubSlot(relayKey)
// After AUTH the socket may be closed or the relay dropped from the pool;
// resubscribe on a fresh connection from ensureRelay (fixes SendingOnClosedConnection).
let liveRelay: AbstractRelay
try {
liveRelay = await that.pool.ensureRelay(url, { connectionTimeout: 5000 })
} catch (err) {
that.releaseSubSlot(relayKey)
handleClose(i, (err as Error)?.message ?? String(err))
return
}
let slotReleased2 = false let slotReleased2 = false
const releaseSlot2 = () => { const releaseSlot2 = () => {
if (!slotReleased2) { if (!slotReleased2) {
@ -1078,7 +1091,8 @@ class ClientService extends EventTarget {
that.releaseSubSlot(relayKey) that.releaseSubSlot(relayKey)
} }
} }
const sub2 = relay.subscribe(relayFilters, { try {
const sub2 = liveRelay.subscribe(relayFilters, {
receivedEvent: (_relay, id) => that.trackEventSeenOn(id, _relay), receivedEvent: (_relay, id) => that.trackEventSeenOn(id, _relay),
onevent: (evt: NEvent) => onevent?.(evt), onevent: (evt: NEvent) => onevent?.(evt),
oneose: () => handleEose(i), oneose: () => handleEose(i),
@ -1096,7 +1110,12 @@ class ClientService extends EventTarget {
sub2.close() sub2.close()
} }
}) })
}).catch((err) => { } catch (err) {
releaseSlot2()
handleClose(i, (err as Error)?.message ?? String(err))
}
})
.catch((err) => {
handleClose(i, `auth failed: ${(err as Error)?.message ?? err}`) handleClose(i, `auth failed: ${(err as Error)?.message ?? err}`)
}) })
return return

Loading…
Cancel
Save