Fix stale profile data #214

Merged
enes merged 6 commits from issues/208-profile-box-cache into staging 2025-02-03 16:43:49 +00:00
6 changed files with 38 additions and 18 deletions

View File

@ -26,7 +26,7 @@ import {
import { LoadingSpinner } from './LoadingSpinner' import { LoadingSpinner } from './LoadingSpinner'
import { ZapPopUp } from './Zap' import { ZapPopUp } from './Zap'
import placeholder from '../assets/img/DEGMods Placeholder Img.png' import placeholder from '../assets/img/DEGMods Placeholder Img.png'
import { NDKEvent } from '@nostr-dev-kit/ndk' import { NDKEvent, NDKSubscriptionCacheUsage } from '@nostr-dev-kit/ndk'
import { useProfile } from 'hooks/useProfile' import { useProfile } from 'hooks/useProfile'
type Props = { type Props = {
@ -93,7 +93,9 @@ type ProfileProps = {
} }
export const Profile = ({ pubkey }: ProfileProps) => { export const Profile = ({ pubkey }: ProfileProps) => {
const profile = useProfile(pubkey) const profile = useProfile(pubkey, {
cacheUsage: NDKSubscriptionCacheUsage.PARALLEL
})
const displayName = const displayName =
profile?.displayName || profile?.name || '[name not set up]' profile?.displayName || profile?.name || '[name not set up]'

View File

@ -6,6 +6,7 @@ import NDK, {
NDKList, NDKList,
NDKRelaySet, NDKRelaySet,
NDKSubscriptionCacheUsage, NDKSubscriptionCacheUsage,
NDKSubscriptionOptions,
NDKUser, NDKUser,
zapInvoiceFromEvent zapInvoiceFromEvent
} from '@nostr-dev-kit/ndk' } from '@nostr-dev-kit/ndk'
@ -48,7 +49,10 @@ export interface NDKContextType {
hexKey: string, hexKey: string,
userRelaysType: UserRelaysType userRelaysType: UserRelaysType
) => Promise<NDKEvent | null> ) => Promise<NDKEvent | null>
findMetadata: (pubkey: string) => Promise<UserProfile> findMetadata: (
pubkey: string,
opts?: NDKSubscriptionOptions
) => Promise<UserProfile>
getTotalZapAmount: ( getTotalZapAmount: (
user: string, user: string,
eTag: string, eTag: string,
@ -111,7 +115,12 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
} }
const ndk = useMemo(() => { const ndk = useMemo(() => {
if (import.meta.env.MODE === 'development') {
localStorage.setItem('debug', '*')
} else {
localStorage.removeItem('debug') localStorage.removeItem('debug')
}
const dexieAdapter = new NDKCacheAdapterDexie({ dbName: 'degmod-db' }) const dexieAdapter = new NDKCacheAdapterDexie({ dbName: 'degmod-db' })
dexieAdapter.locking = true dexieAdapter.locking = true
const ndk = new NDK({ const ndk = new NDK({
@ -309,13 +318,16 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
* @param hexKey - The pubkey to search for metadata. * @param hexKey - The pubkey to search for metadata.
* @returns A promise that resolves to the metadata event. * @returns A promise that resolves to the metadata event.
*/ */
const findMetadata = async (pubkey: string): Promise<UserProfile> => { const findMetadata = async (
pubkey: string,
opts?: NDKSubscriptionOptions
): Promise<UserProfile> => {
const npub = hexToNpub(pubkey) const npub = hexToNpub(pubkey)
const user = new NDKUser({ npub }) const user = new NDKUser({ npub })
user.ndk = ndk user.ndk = ndk
const userProfile = await user.fetchProfile() const userProfile = await user.fetchProfile(opts)
return userProfile return userProfile
} }

View File

@ -1,18 +1,19 @@
import { NDKSubscriptionOptions } from '@nostr-dev-kit/ndk'
import { useNDKContext } from 'hooks' import { useNDKContext } from 'hooks'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { UserProfile } from 'types' import { UserProfile } from 'types'
export const useProfile = (pubkey?: string) => { export const useProfile = (pubkey?: string, opts?: NDKSubscriptionOptions) => {
const { findMetadata } = useNDKContext() const { findMetadata } = useNDKContext()
const [profile, setProfile] = useState<UserProfile>() const [profile, setProfile] = useState<UserProfile>()
useEffect(() => { useEffect(() => {
if (pubkey) { if (pubkey) {
findMetadata(pubkey).then((res) => { findMetadata(pubkey, opts).then((res) => {
setProfile(res) setProfile(res)
}) })
} }
}, [findMetadata, pubkey]) }, [findMetadata, pubkey, opts])
return profile return profile
} }

View File

@ -22,7 +22,7 @@ import { npubToHex } from '../utils'
import logo from '../assets/img/DEG Mods Logo With Text.svg' import logo from '../assets/img/DEG Mods Logo With Text.svg'
import placeholder from '../assets/img/DEG Mods Default PP.png' import placeholder from '../assets/img/DEG Mods Default PP.png'
import { resetUserWot } from 'store/reducers/wot' import { resetUserWot } from 'store/reducers/wot'
import { NDKNip07Signer } from '@nostr-dev-kit/ndk' import { NDKNip07Signer, NDKSubscriptionCacheUsage } from '@nostr-dev-kit/ndk'
export const Header = () => { export const Header = () => {
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
@ -66,7 +66,9 @@ export const Header = () => {
}) })
) )
ndk.signer = new NDKNip07Signer() ndk.signer = new NDKNip07Signer()
findMetadata(npub).then((userProfile) => { findMetadata(npub, {
cacheUsage: NDKSubscriptionCacheUsage.ONLY_RELAY
}).then((userProfile) => {
if (userProfile) { if (userProfile) {
dispatch( dispatch(
setUser({ setUser({

View File

@ -1,3 +1,4 @@
import { NDKSubscriptionCacheUsage } from '@nostr-dev-kit/ndk'
import { NDKContextType } from 'contexts/NDKContext' import { NDKContextType } from 'contexts/NDKContext'
import { nip19 } from 'nostr-tools' import { nip19 } from 'nostr-tools'
import { LoaderFunctionArgs, redirect } from 'react-router-dom' import { LoaderFunctionArgs, redirect } from 'react-router-dom'
@ -94,7 +95,9 @@ export const profileRouteLoader =
} }
const settled = await Promise.allSettled([ const settled = await Promise.allSettled([
ndkContext.findMetadata(profilePubkey), ndkContext.findMetadata(profilePubkey, {
cacheUsage: NDKSubscriptionCacheUsage.ONLY_RELAY
}),
ndkContext.getMuteLists(loggedInUserPubkey), ndkContext.getMuteLists(loggedInUserPubkey),
getReportingSet(CurationSetIdentifiers.NSFW, ndkContext), getReportingSet(CurationSetIdentifiers.NSFW, ndkContext),
getReportingSet(CurationSetIdentifiers.Repost, ndkContext) getReportingSet(CurationSetIdentifiers.Repost, ndkContext)

View File

@ -123,12 +123,13 @@ export const ProfileSettings = () => {
} }
const handlePublish = async () => { const handlePublish = async () => {
if (!userState.auth && !userState.user?.pubkey) return if (!userState.auth || !userState.user?.pubkey) return
setIsPublishing(true) setIsPublishing(true)
const prevProfile = userState.user as NDKUserProfile const prevProfile = userState.user as NDKUserProfile
const updatedProfile = { const createdAt = now()
const updatedProfile: NDKUserProfile = {
...prevProfile, ...prevProfile,
name: formState.name, name: formState.name,
displayName: formState.displayName, displayName: formState.displayName,
@ -136,16 +137,16 @@ export const ProfileSettings = () => {
picture: formState.picture, picture: formState.picture,
banner: formState.banner, banner: formState.banner,
nip05: formState.nip05, nip05: formState.nip05,
lud16: formState.lud16 lud16: formState.lud16,
created_at: createdAt
} }
const serializedProfile = serializeProfile(updatedProfile) const serializedProfile = serializeProfile(updatedProfile)
const unsignedEvent: UnsignedEvent = { const unsignedEvent: UnsignedEvent = {
kind: kinds.Metadata, kind: kinds.Metadata,
tags: [], tags: [],
content: serializedProfile, content: serializedProfile,
created_at: now(), created_at: createdAt,
pubkey: userState.user?.pubkey as string pubkey: userState.user?.pubkey as string
} }
@ -176,7 +177,6 @@ export const ProfileSettings = () => {
)}` )}`
) )
const ndkEvent = new NDKEvent(undefined, signedEvent)
const userProfile = profileFromEvent(ndkEvent) const userProfile = profileFromEvent(ndkEvent)
dispatch(setUser(userProfile)) dispatch(setUser(userProfile))
} }