diff --git a/src-tauri/migrations/20230921085234_add_metadata_table.sql b/src-tauri/migrations/20230921085234_add_metadata_table.sql new file mode 100644 index 00000000..93c9ece9 --- /dev/null +++ b/src-tauri/migrations/20230921085234_add_metadata_table.sql @@ -0,0 +1,9 @@ +-- Add migration script here +CREATE TABLE + metadata ( + id TEXT NOT NULL PRIMARY KEY, + event TEXT NOT NULL, + author TEXT NOT NULL, + kind NUMBER NOT NULL DEFAULt 0, + created_at INTEGER NOT NULL + ); \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 901ab4b7..08dca932 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -217,6 +217,12 @@ fn main() { sql: include_str!("../migrations/20230918235335_add_uniq_to_relay.sql"), kind: MigrationKind::Up, }, + Migration { + version: 20230921085234, + description: "add metadata", + sql: include_str!("../migrations/20230921085234_add_metadata_table.sql"), + kind: MigrationKind::Up, + }, ], ) .build(), diff --git a/src/libs/ndk/instance.ts b/src/libs/ndk/instance.ts index c99f9929..1998ad81 100644 --- a/src/libs/ndk/instance.ts +++ b/src/libs/ndk/instance.ts @@ -1,4 +1,3 @@ -// inspire by: https://github.com/nostr-dev-kit/ndk-react/ import NDK from '@nostr-dev-kit/ndk'; import { ndkAdapter } from '@nostr-fetch/adapter-ndk'; import { message } from '@tauri-apps/api/dialog'; @@ -6,7 +5,6 @@ import { fetch } from '@tauri-apps/api/http'; import { NostrFetcher } from 'nostr-fetch'; import { useEffect, useMemo, useState } from 'react'; -import TauriAdapter from '@libs/ndk/cache'; import { useStorage } from '@libs/storage/provider'; export const NDKInstance = () => { @@ -15,7 +13,6 @@ export const NDKInstance = () => { const [ndk, setNDK] = useState(undefined); const [relayUrls, setRelayUrls] = useState([]); - const cacheAdapter = useMemo(() => new TauriAdapter(), [ndk]); const fetcher = useMemo( () => (ndk ? NostrFetcher.withCustomPool(ndkAdapter(ndk)) : null), [ndk] @@ -61,7 +58,6 @@ export const NDKInstance = () => { const explicitRelayUrls = await getExplicitRelays(); const instance = new NDK({ explicitRelayUrls, - cacheAdapter, }); try { @@ -79,10 +75,6 @@ export const NDKInstance = () => { useEffect(() => { if (!ndk) initNDK(); - - return () => { - cacheAdapter.saveCache(); - }; }, []); return { diff --git a/src/libs/storage/instance.ts b/src/libs/storage/instance.ts index 6fa39fab..2b05fd9c 100644 --- a/src/libs/storage/instance.ts +++ b/src/libs/storage/instance.ts @@ -6,6 +6,7 @@ import { Stronghold } from 'tauri-plugin-stronghold-api'; import { FULL_RELAYS } from '@stores/constants'; +import { toRawEvent } from '@utils/rawEvent'; import { Account, DBEvent, Relays, Widget } from '@utils/types'; export class LumeStorage { @@ -282,6 +283,31 @@ export class LumeStorage { return results.length < 1; } + public async createMetadata(event: NDKEvent) { + const rawEvent = toRawEvent(event); + + return await this.db.execute( + 'INSERT OR IGNORE INTO metadata (id, event, author, kind, created_at) VALUES ($1, $2, $3, $4, $5);', + [ + rawEvent.id, + JSON.stringify(rawEvent), + rawEvent.pubkey, + rawEvent.kind, + rawEvent.created_at, + ] + ); + } + + public async getMetadataByPubkey(pubkey: string) { + const results: DBEvent[] = await this.db.select( + 'SELECT * FROM metadata WHERE author = $1 AND kind = "0" LIMIT 1;', + [pubkey] + ); + + if (results.length < 1) return null; + return JSON.parse(results[0].event as string) as NDKEvent; + } + public async getExplicitRelayUrls() { if (!this.account) return FULL_RELAYS; diff --git a/src/utils/hooks/useProfile.ts b/src/utils/hooks/useProfile.ts index 62f511c7..690d6052 100644 --- a/src/utils/hooks/useProfile.ts +++ b/src/utils/hooks/useProfile.ts @@ -1,9 +1,11 @@ -import { NDKUserProfile } from '@nostr-dev-kit/ndk'; +import { NDKKind, NDKUserProfile } from '@nostr-dev-kit/ndk'; import { useQuery } from '@tanstack/react-query'; import { useNDK } from '@libs/ndk/provider'; +import { useStorage } from '@libs/storage/provider'; export function useProfile(pubkey: string, embed?: string) { + const { db } = useStorage(); const { ndk } = useNDK(); const { status, @@ -14,14 +16,24 @@ export function useProfile(pubkey: string, embed?: string) { async () => { if (!embed) { const cleanPubkey = pubkey.replace('-', ''); - const user = ndk.getUser({ hexpubkey: cleanPubkey }); - await user.fetchProfile(); - if (user.profile) { - user.profile.display_name = user.profile.displayName; - return user.profile; - } else { - throw new Error(`User not found: ${pubkey}`); + const dbEvent = await db.getMetadataByPubkey(cleanPubkey); + if (dbEvent) { + return JSON.parse(dbEvent.content) as NDKUserProfile; } + + const events = await ndk.fetchEvents( + { + kinds: [NDKKind.Metadata], + authors: [cleanPubkey], + limit: 1, + }, + { closeOnEose: true } + ); + if (!events) throw new Error(`User not found: ${pubkey}`); + const latestEvent = [...events].sort((a, b) => b.created_at - a.created_at)[0]; + await db.createMetadata(latestEvent); + + return JSON.parse(latestEvent.content) as NDKUserProfile; } else { const profile: NDKUserProfile = JSON.parse(embed); return profile;