fix: expose more detailed error messages
This commit is contained in:
parent
d37aa61501
commit
71791c9513
27 changed files with 330 additions and 153 deletions
|
|
@ -1,8 +1,10 @@
|
|||
import { buildATag, buildETag, createBookmarkDraftEvent } from '@/lib/draft-event'
|
||||
import { formatError } from '@/lib/error'
|
||||
import { getReplaceableCoordinateFromEvent, isReplaceableEvent } from '@/lib/event'
|
||||
import client from '@/services/client.service'
|
||||
import { Event } from 'nostr-tools'
|
||||
import { createContext, useContext } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { useNostr } from './NostrProvider'
|
||||
|
||||
type TBookmarksContext = {
|
||||
|
|
@ -45,8 +47,15 @@ export function BookmarksProvider({ children }: { children: React.ReactNode }) {
|
|||
[...currentTags, isReplaceable ? buildATag(event) : buildETag(event.id, event.pubkey)],
|
||||
bookmarkListEvent?.content
|
||||
)
|
||||
const newBookmarkEvent = await publish(newBookmarkDraftEvent)
|
||||
await updateBookmarkListEvent(newBookmarkEvent)
|
||||
try {
|
||||
const newBookmarkEvent = await publish(newBookmarkDraftEvent)
|
||||
await updateBookmarkListEvent(newBookmarkEvent)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to add bookmark: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const removeBookmark = async (event: Event) => {
|
||||
|
|
@ -64,8 +73,15 @@ export function BookmarksProvider({ children }: { children: React.ReactNode }) {
|
|||
if (newTags.length === bookmarkListEvent.tags.length) return
|
||||
|
||||
const newBookmarkDraftEvent = createBookmarkDraftEvent(newTags, bookmarkListEvent.content)
|
||||
const newBookmarkEvent = await publish(newBookmarkDraftEvent)
|
||||
await updateBookmarkListEvent(newBookmarkEvent)
|
||||
try {
|
||||
const newBookmarkEvent = await publish(newBookmarkDraftEvent)
|
||||
await updateBookmarkListEvent(newBookmarkEvent)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to remove bookmark: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { buildATag, createUserEmojiListDraftEvent } from '@/lib/draft-event'
|
||||
import { formatError } from '@/lib/error'
|
||||
import { getReplaceableCoordinateFromEvent } from '@/lib/event'
|
||||
import client from '@/services/client.service'
|
||||
import { Event, kinds } from 'nostr-tools'
|
||||
import { createContext, useContext, useMemo } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { useNostr } from './NostrProvider'
|
||||
|
||||
type TEmojiPackContext = {
|
||||
|
|
@ -54,8 +56,15 @@ export function EmojiPackProvider({ children }: { children: React.ReactNode }) {
|
|||
[...currentTags, buildATag(event)],
|
||||
userEmojiListEvent?.content
|
||||
)
|
||||
const newUserEmojiListEvent = await publish(newUserEmojiListDraftEvent)
|
||||
await updateUserEmojiListEvent(newUserEmojiListEvent)
|
||||
try {
|
||||
const newUserEmojiListEvent = await publish(newUserEmojiListDraftEvent)
|
||||
await updateUserEmojiListEvent(newUserEmojiListEvent)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to add emoji pack: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const removeEmojiPack = async (event: Event) => {
|
||||
|
|
@ -72,8 +81,15 @@ export function EmojiPackProvider({ children }: { children: React.ReactNode }) {
|
|||
newTags,
|
||||
userEmojiListEvent.content
|
||||
)
|
||||
const newUserEmojiListEvent = await publish(newUserEmojiListDraftEvent)
|
||||
await updateUserEmojiListEvent(newUserEmojiListEvent)
|
||||
try {
|
||||
const newUserEmojiListEvent = await publish(newUserEmojiListDraftEvent)
|
||||
await updateUserEmojiListEvent(newUserEmojiListEvent)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to remove emoji pack: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { createFavoriteRelaysDraftEvent, createRelaySetDraftEvent } from '@/lib/draft-event'
|
||||
import { formatError } from '@/lib/error'
|
||||
import { getReplaceableEventIdentifier } from '@/lib/event'
|
||||
import { getRelaySetFromEvent } from '@/lib/event-metadata'
|
||||
import { randomString } from '@/lib/random'
|
||||
|
|
@ -10,6 +11,7 @@ import storage from '@/services/local-storage.service'
|
|||
import { TRelaySet } from '@/types'
|
||||
import { Event, kinds } from 'nostr-tools'
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { useNostr } from './NostrProvider'
|
||||
|
||||
type TFavoriteRelaysContext = {
|
||||
|
|
@ -146,8 +148,15 @@ export function FavoriteRelaysProvider({ children }: { children: React.ReactNode
|
|||
[...favoriteRelays, ...normalizedUrls],
|
||||
relaySetEvents
|
||||
)
|
||||
const newFavoriteRelaysEvent = await publish(draftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
try {
|
||||
const newFavoriteRelaysEvent = await publish(draftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to add favorite relays: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const deleteFavoriteRelays = async (relayUrls: string[]) => {
|
||||
|
|
@ -160,8 +169,15 @@ export function FavoriteRelaysProvider({ children }: { children: React.ReactNode
|
|||
favoriteRelays.filter((url) => !normalizedUrls.includes(url)),
|
||||
relaySetEvents
|
||||
)
|
||||
const newFavoriteRelaysEvent = await publish(draftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
try {
|
||||
const newFavoriteRelaysEvent = await publish(draftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to delete favorite relays: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const createRelaySet = async (relaySetName: string, relayUrls: string[] = []) => {
|
||||
|
|
@ -174,15 +190,22 @@ export function FavoriteRelaysProvider({ children }: { children: React.ReactNode
|
|||
name: relaySetName,
|
||||
relayUrls: normalizedUrls
|
||||
})
|
||||
const newRelaySetEvent = await publish(relaySetDraftEvent)
|
||||
await indexedDb.putReplaceableEvent(newRelaySetEvent)
|
||||
try {
|
||||
const newRelaySetEvent = await publish(relaySetDraftEvent)
|
||||
await indexedDb.putReplaceableEvent(newRelaySetEvent)
|
||||
|
||||
const favoriteRelaysDraftEvent = createFavoriteRelaysDraftEvent(favoriteRelays, [
|
||||
...relaySetEvents,
|
||||
newRelaySetEvent
|
||||
])
|
||||
const newFavoriteRelaysEvent = await publish(favoriteRelaysDraftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
const favoriteRelaysDraftEvent = createFavoriteRelaysDraftEvent(favoriteRelays, [
|
||||
...relaySetEvents,
|
||||
newRelaySetEvent
|
||||
])
|
||||
const newFavoriteRelaysEvent = await publish(favoriteRelaysDraftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to create relay set: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const addRelaySets = async (newRelaySetEvents: Event[]) => {
|
||||
|
|
@ -190,8 +213,15 @@ export function FavoriteRelaysProvider({ children }: { children: React.ReactNode
|
|||
...relaySetEvents,
|
||||
...newRelaySetEvents
|
||||
])
|
||||
const newFavoriteRelaysEvent = await publish(favoriteRelaysDraftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
try {
|
||||
const newFavoriteRelaysEvent = await publish(favoriteRelaysDraftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to add relay sets: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const deleteRelaySet = async (id: string) => {
|
||||
|
|
@ -201,30 +231,52 @@ export function FavoriteRelaysProvider({ children }: { children: React.ReactNode
|
|||
if (newRelaySetEvents.length === relaySetEvents.length) return
|
||||
|
||||
const draftEvent = createFavoriteRelaysDraftEvent(favoriteRelays, newRelaySetEvents)
|
||||
const newFavoriteRelaysEvent = await publish(draftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
try {
|
||||
const newFavoriteRelaysEvent = await publish(draftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to delete relay set: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const updateRelaySet = async (newSet: TRelaySet) => {
|
||||
const draftEvent = createRelaySetDraftEvent(newSet)
|
||||
const newRelaySetEvent = await publish(draftEvent)
|
||||
await indexedDb.putReplaceableEvent(newRelaySetEvent)
|
||||
|
||||
setRelaySetEvents((prev) => {
|
||||
return prev.map((event) => {
|
||||
if (getReplaceableEventIdentifier(event) === newSet.id) {
|
||||
return newRelaySetEvent
|
||||
}
|
||||
return event
|
||||
try {
|
||||
const newRelaySetEvent = await publish(draftEvent)
|
||||
await indexedDb.putReplaceableEvent(newRelaySetEvent)
|
||||
|
||||
setRelaySetEvents((prev) => {
|
||||
return prev.map((event) => {
|
||||
if (getReplaceableEventIdentifier(event) === newSet.id) {
|
||||
return newRelaySetEvent
|
||||
}
|
||||
return event
|
||||
})
|
||||
})
|
||||
})
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to update relay set: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const reorderFavoriteRelays = async (reorderedRelays: string[]) => {
|
||||
setFavoriteRelays(reorderedRelays)
|
||||
const draftEvent = createFavoriteRelaysDraftEvent(reorderedRelays, relaySetEvents)
|
||||
const newFavoriteRelaysEvent = await publish(draftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
try {
|
||||
const newFavoriteRelaysEvent = await publish(draftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to reorder favorite relays: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const reorderRelaySets = async (reorderedSets: TRelaySet[]) => {
|
||||
|
|
@ -233,8 +285,15 @@ export function FavoriteRelaysProvider({ children }: { children: React.ReactNode
|
|||
favoriteRelays,
|
||||
reorderedSets.map((set) => set.aTag)
|
||||
)
|
||||
const newFavoriteRelaysEvent = await publish(draftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
try {
|
||||
const newFavoriteRelaysEvent = await publish(draftEvent)
|
||||
updateFavoriteRelaysEvent(newFavoriteRelaysEvent)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to reorder relay sets: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import client from '@/services/client.service'
|
|||
import { createContext, useContext, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNostr } from './NostrProvider'
|
||||
import { formatError } from '@/lib/error'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
type TFollowListContext = {
|
||||
followingSet: Set<string>
|
||||
|
|
@ -44,8 +46,15 @@ export function FollowListProvider({ children }: { children: React.ReactNode })
|
|||
(followListEvent?.tags ?? []).concat([['p', pubkey]]),
|
||||
followListEvent?.content
|
||||
)
|
||||
const newFollowListEvent = await publish(newFollowListDraftEvent)
|
||||
await updateFollowListEvent(newFollowListEvent)
|
||||
try {
|
||||
const newFollowListEvent = await publish(newFollowListDraftEvent)
|
||||
await updateFollowListEvent(newFollowListEvent)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to follow: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const unfollow = async (pubkey: string) => {
|
||||
|
|
@ -58,8 +67,15 @@ export function FollowListProvider({ children }: { children: React.ReactNode })
|
|||
followListEvent.tags.filter(([tagName, tagValue]) => tagName !== 'p' || tagValue !== pubkey),
|
||||
followListEvent.content
|
||||
)
|
||||
const newFollowListEvent = await publish(newFollowListDraftEvent)
|
||||
await updateFollowListEvent(newFollowListEvent)
|
||||
try {
|
||||
const newFollowListEvent = await publish(newFollowListDraftEvent)
|
||||
await updateFollowListEvent(newFollowListEvent)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to unfollow: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { createMuteListDraftEvent } from '@/lib/draft-event'
|
||||
import { formatError } from '@/lib/error'
|
||||
import { getPubkeysFromPTags } from '@/lib/tag'
|
||||
import client from '@/services/client.service'
|
||||
import indexedDb from '@/services/indexed-db.service'
|
||||
|
|
@ -115,7 +116,6 @@ export function MuteListProvider({ children }: { children: React.ReactNode }) {
|
|||
}
|
||||
const newMuteListDraftEvent = createMuteListDraftEvent(tags, content)
|
||||
const event = await publish(newMuteListDraftEvent)
|
||||
toast.success(t('Successfully updated mute list'))
|
||||
return event
|
||||
}
|
||||
|
||||
|
|
@ -147,7 +147,10 @@ export function MuteListProvider({ children }: { children: React.ReactNode }) {
|
|||
const privateTags = await getPrivateTags(newMuteListEvent)
|
||||
await updateMuteListEvent(newMuteListEvent, privateTags)
|
||||
} catch (error) {
|
||||
toast.error(t('Failed to mute user publicly') + ': ' + (error as Error).message)
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(t('Failed to mute user publicly') + ': ' + err, { duration: 10_000 })
|
||||
})
|
||||
} finally {
|
||||
setChanging(false)
|
||||
}
|
||||
|
|
@ -170,7 +173,10 @@ export function MuteListProvider({ children }: { children: React.ReactNode }) {
|
|||
const newMuteListEvent = await publishNewMuteListEvent(muteListEvent?.tags ?? [], cipherText)
|
||||
await updateMuteListEvent(newMuteListEvent, newPrivateTags)
|
||||
} catch (error) {
|
||||
toast.error(t('Failed to mute user privately') + ': ' + (error as Error).message)
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(t('Failed to mute user privately') + ': ' + err, { duration: 10_000 })
|
||||
})
|
||||
} finally {
|
||||
setChanging(false)
|
||||
}
|
||||
|
|
@ -196,6 +202,11 @@ export function MuteListProvider({ children }: { children: React.ReactNode }) {
|
|||
cipherText
|
||||
)
|
||||
await updateMuteListEvent(newMuteListEvent, newPrivateTags)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(t('Failed to unmute user') + ': ' + err, { duration: 10_000 })
|
||||
})
|
||||
} finally {
|
||||
setChanging(false)
|
||||
}
|
||||
|
|
@ -223,6 +234,11 @@ export function MuteListProvider({ children }: { children: React.ReactNode }) {
|
|||
cipherText
|
||||
)
|
||||
await updateMuteListEvent(newMuteListEvent, newPrivateTags)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(t('Failed to switch to public mute') + ': ' + err, { duration: 10_000 })
|
||||
})
|
||||
} finally {
|
||||
setChanging(false)
|
||||
}
|
||||
|
|
@ -248,6 +264,11 @@ export function MuteListProvider({ children }: { children: React.ReactNode }) {
|
|||
const cipherText = await nip04Encrypt(accountPubkey, JSON.stringify(newPrivateTags))
|
||||
const newMuteListEvent = await publishNewMuteListEvent(newTags, cipherText)
|
||||
await updateMuteListEvent(newMuteListEvent, newPrivateTags)
|
||||
} catch (error) {
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(t('Failed to switch to private mute') + ': ' + err, { duration: 10_000 })
|
||||
})
|
||||
} finally {
|
||||
setChanging(false)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { MAX_PINNED_NOTES } from '@/constants'
|
||||
import { buildETag, createPinListDraftEvent } from '@/lib/draft-event'
|
||||
import { formatError } from '@/lib/error'
|
||||
import { getPinnedEventHexIdSetFromPinListEvent } from '@/lib/event-metadata'
|
||||
import client from '@/services/client.service'
|
||||
import { Event, kinds } from 'nostr-tools'
|
||||
|
|
@ -67,7 +68,7 @@ export function PinListProvider({ children }: { children: React.ReactNode }) {
|
|||
const { unwrap } = toast.promise(_pin, {
|
||||
loading: t('Pinning...'),
|
||||
success: t('Pinned!'),
|
||||
error: (err) => t('Failed to pin: {{error}}', { error: err.message })
|
||||
error: (err) => t('Failed to pin: {{error}}', { error: formatError(err).join('; ') })
|
||||
})
|
||||
await unwrap()
|
||||
}
|
||||
|
|
@ -92,7 +93,7 @@ export function PinListProvider({ children }: { children: React.ReactNode }) {
|
|||
const { unwrap } = toast.promise(_unpin, {
|
||||
loading: t('Unpinning...'),
|
||||
success: t('Unpinned!'),
|
||||
error: (err) => t('Failed to unpin: {{error}}', { error: err.message })
|
||||
error: (err) => t('Failed to unpin: {{error}}', { error: formatError(err).join('; ') })
|
||||
})
|
||||
await unwrap()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { ExtendedKind } from '@/constants'
|
||||
import { formatError } from '@/lib/error'
|
||||
import { getPubkeysFromPTags } from '@/lib/tag'
|
||||
import indexedDb from '@/services/indexed-db.service'
|
||||
import { Event } from 'nostr-tools'
|
||||
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { z } from 'zod'
|
||||
import { useNostr } from './NostrProvider'
|
||||
|
||||
|
|
@ -105,7 +107,10 @@ export function PinnedUsersProvider({ children }: { children: React.ReactNode })
|
|||
const newEvent = await publish(draftEvent)
|
||||
await updatePinnedUsersEvent(newEvent, privateTags)
|
||||
} catch (error) {
|
||||
console.error('Failed to pin user:', error)
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to pin user: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
},
|
||||
[accountPubkey, isPinned, pinnedUsersEvent, publish, updatePinnedUsersEvent, privateTags]
|
||||
|
|
@ -130,7 +135,10 @@ export function PinnedUsersProvider({ children }: { children: React.ReactNode })
|
|||
const newEvent = await publish(draftEvent)
|
||||
await updatePinnedUsersEvent(newEvent, newPrivateTags)
|
||||
} catch (error) {
|
||||
console.error('Failed to unpin user:', error)
|
||||
const errors = formatError(error)
|
||||
errors.forEach((err) => {
|
||||
toast.error(`Failed to unpin user: ${err}`, { duration: 10_000 })
|
||||
})
|
||||
}
|
||||
},
|
||||
[
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue