feat: favorite relays (#250)

This commit is contained in:
Cody Tseng
2025-04-05 15:31:34 +08:00
committed by GitHub
parent fab9ff88b5
commit c739d9d28c
63 changed files with 1081 additions and 982 deletions

View File

@@ -1,5 +1,5 @@
import LoginDialog from '@/components/LoginDialog'
import { BIG_RELAY_URLS, COMMENT_EVENT_KIND, PICTURE_EVENT_KIND } from '@/constants'
import { BIG_RELAY_URLS, ExtendedKind } from '@/constants'
import { useToast } from '@/hooks'
import {
getLatestEvent,
@@ -30,6 +30,7 @@ type TNostrContext = {
relayList: TRelayList | null
followListEvent?: Event
muteListEvent?: Event
favoriteRelaysEvent?: Event
account: TAccountPointer | null
accounts: TAccountPointer[]
nsec: string | null
@@ -55,6 +56,7 @@ type TNostrContext = {
updateProfileEvent: (profileEvent: Event) => Promise<void>
updateFollowListEvent: (followListEvent: Event) => Promise<void>
updateMuteListEvent: (muteListEvent: Event, tags: string[][]) => Promise<void>
updateFavoriteRelaysEvent: (favoriteRelaysEvent: Event) => Promise<void>
}
const NostrContext = createContext<TNostrContext | undefined>(undefined)
@@ -80,6 +82,7 @@ export function NostrProvider({ children }: { children: React.ReactNode }) {
const [relayList, setRelayList] = useState<TRelayList | null>(null)
const [followListEvent, setFollowListEvent] = useState<Event | undefined>(undefined)
const [muteListEvent, setMuteListEvent] = useState<Event | undefined>(undefined)
const [favoriteRelaysEvent, setFavoriteRelaysEvent] = useState<Event | undefined>(undefined)
useEffect(() => {
const init = async () => {
@@ -131,13 +134,19 @@ export function NostrProvider({ children }: { children: React.ReactNode }) {
} else {
setNcryptsec(null)
}
const [storedRelayListEvent, storedProfileEvent, storedFollowListEvent, storedMuteListEvent] =
await Promise.all([
indexedDb.getReplaceableEvent(account.pubkey, kinds.RelayList),
indexedDb.getReplaceableEvent(account.pubkey, kinds.Metadata),
indexedDb.getReplaceableEvent(account.pubkey, kinds.Contacts),
indexedDb.getReplaceableEvent(account.pubkey, kinds.Mutelist)
])
const [
storedRelayListEvent,
storedProfileEvent,
storedFollowListEvent,
storedMuteListEvent,
storedFavoriteRelaysEvent
] = await Promise.all([
indexedDb.getReplaceableEvent(account.pubkey, kinds.RelayList),
indexedDb.getReplaceableEvent(account.pubkey, kinds.Metadata),
indexedDb.getReplaceableEvent(account.pubkey, kinds.Contacts),
indexedDb.getReplaceableEvent(account.pubkey, kinds.Mutelist),
indexedDb.getReplaceableEvent(account.pubkey, ExtendedKind.FAVORITE_RELAYS)
])
if (storedRelayListEvent) {
setRelayList(
storedRelayListEvent ? getRelayListFromRelayListEvent(storedRelayListEvent) : null
@@ -153,6 +162,9 @@ export function NostrProvider({ children }: { children: React.ReactNode }) {
if (storedMuteListEvent) {
setMuteListEvent(storedMuteListEvent)
}
if (storedFavoriteRelaysEvent) {
setFavoriteRelaysEvent(storedFavoriteRelaysEvent)
}
const relayListEvents = await client.fetchEvents(BIG_RELAY_URLS, {
kinds: [kinds.RelayList],
@@ -167,13 +179,14 @@ export function NostrProvider({ children }: { children: React.ReactNode }) {
setRelayList(relayList)
const events = await client.fetchEvents(relayList.write.concat(BIG_RELAY_URLS).slice(0, 4), {
kinds: [kinds.Metadata, kinds.Contacts, kinds.Mutelist],
kinds: [kinds.Metadata, kinds.Contacts, kinds.Mutelist, ExtendedKind.FAVORITE_RELAYS],
authors: [account.pubkey]
})
const sortedEvents = events.sort((a, b) => b.created_at - a.created_at)
const profileEvent = sortedEvents.find((e) => e.kind === kinds.Metadata)
const followListEvent = sortedEvents.find((e) => e.kind === kinds.Contacts)
const muteListEvent = sortedEvents.find((e) => e.kind === kinds.Mutelist)
const favoriteRelaysEvent = sortedEvents.find((e) => e.kind === ExtendedKind.FAVORITE_RELAYS)
if (profileEvent) {
setProfileEvent(profileEvent)
setProfile(getProfileFromProfileEvent(profileEvent))
@@ -192,6 +205,10 @@ export function NostrProvider({ children }: { children: React.ReactNode }) {
setMuteListEvent(muteListEvent)
await indexedDb.putReplaceableEvent(muteListEvent)
}
if (favoriteRelaysEvent) {
setFavoriteRelaysEvent(favoriteRelaysEvent)
await indexedDb.putReplaceableEvent(favoriteRelaysEvent)
}
client.initUserIndexFromFollowings(account.pubkey, controller.signal)
return controller
@@ -414,8 +431,8 @@ export function NostrProvider({ children }: { children: React.ReactNode }) {
kinds.ShortTextNote,
kinds.Reaction,
kinds.Repost,
COMMENT_EVENT_KIND,
PICTURE_EVENT_KIND
ExtendedKind.COMMENT,
ExtendedKind.PICTURE
].includes(draftEvent.kind)
) {
const mentions: string[] = []
@@ -509,6 +526,13 @@ export function NostrProvider({ children }: { children: React.ReactNode }) {
setMuteListEvent(muteListEvent)
}
const updateFavoriteRelaysEvent = async (favoriteRelaysEvent: Event) => {
const newFavoriteRelaysEvent = await indexedDb.putReplaceableEvent(favoriteRelaysEvent)
if (newFavoriteRelaysEvent.id !== favoriteRelaysEvent.id) return
setFavoriteRelaysEvent(newFavoriteRelaysEvent)
}
return (
<NostrContext.Provider
value={{
@@ -518,6 +542,7 @@ export function NostrProvider({ children }: { children: React.ReactNode }) {
relayList,
followListEvent,
muteListEvent,
favoriteRelaysEvent,
account,
accounts: storage
.getAccounts()
@@ -541,7 +566,8 @@ export function NostrProvider({ children }: { children: React.ReactNode }) {
updateRelayListEvent,
updateProfileEvent,
updateFollowListEvent,
updateMuteListEvent
updateMuteListEvent,
updateFavoriteRelaysEvent
}}
>
{children}