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. 29
      src/pages/primary/SpellsPage/index.tsx
  5. 75
      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()
} }
}) })
} }

29
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) => {
await indexedDb.deleteSpellEvent(spell.id) try {
const ids = await indexedDb.getSpellFavoriteIds() await attemptDelete(spell)
await indexedDb.setSpellFavoriteIds(ids.filter((id) => id !== spell.id)) } catch (e) {
if (selectedSpell?.id === spell.id) setSelectedSpell(null) logger.error('Spell deletion publish failed', { error: e, spellId: spell.id })
loadSpells() showPublishingError(e instanceof Error ? e : new Error(String(e)))
return
}
try {
await indexedDb.deleteSpellEvent(spell.id)
const ids = await indexedDb.getSpellFavoriteIds()
await indexedDb.setSpellFavoriteIds(ids.filter((id) => id !== spell.id))
if (selectedSpell?.id === spell.id) setSelectedSpell(null)
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(() => {

75
src/services/client.service.ts

@ -1066,39 +1066,58 @@ 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
const evt = await that.signer!.signEvent(authEvt) .auth(async (authEvt: EventTemplate) => {
if (!evt) throw new Error('sign event failed') const evt = await that.signer!.signEvent(authEvt)
return evt as VerifiedEvent if (!evt) throw new Error('sign event failed')
}).then(() => that.acquireSubSlot(relayKey)).then(() => { return evt as VerifiedEvent
let slotReleased2 = false })
const releaseSlot2 = () => { .then(async () => {
if (!slotReleased2) { await that.acquireSubSlot(relayKey)
slotReleased2 = true // 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) that.releaseSubSlot(relayKey)
handleClose(i, (err as Error)?.message ?? String(err))
return
} }
} let slotReleased2 = false
const sub2 = relay.subscribe(relayFilters, { const releaseSlot2 = () => {
receivedEvent: (_relay, id) => that.trackEventSeenOn(id, _relay), if (!slotReleased2) {
onevent: (evt: NEvent) => onevent?.(evt), slotReleased2 = true
oneose: () => handleEose(i), that.releaseSubSlot(relayKey)
onclose: (reason2: string) => { }
releaseSlot2() }
handleClose(i, reason2) try {
}, const sub2 = liveRelay.subscribe(relayFilters, {
alreadyHaveEvent: localAlreadyHaveEvent, receivedEvent: (_relay, id) => that.trackEventSeenOn(id, _relay),
eoseTimeout: 10_000 onevent: (evt: NEvent) => onevent?.(evt),
}) oneose: () => handleEose(i),
subs.push({ onclose: (reason2: string) => {
relayKey, releaseSlot2()
close: () => { handleClose(i, reason2)
},
alreadyHaveEvent: localAlreadyHaveEvent,
eoseTimeout: 10_000
})
subs.push({
relayKey,
close: () => {
releaseSlot2()
sub2.close()
}
})
} catch (err) {
releaseSlot2() releaseSlot2()
sub2.close() handleClose(i, (err as Error)?.message ?? String(err))
} }
}) })
}).catch((err) => { .catch((err) => {
handleClose(i, `auth failed: ${(err as Error)?.message ?? err}`) handleClose(i, `auth failed: ${(err as Error)?.message ?? err}`)
}) })
return return
} }
if (reason.startsWith('auth-required: ')) { if (reason.startsWith('auth-required: ')) {

Loading…
Cancel
Save