diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index fafb703b..3a431503 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -43,7 +43,7 @@ struct CreateFollowData { #[specta::specta] async fn get_account(db: DbState<'_>) -> Result, ()> { db.account() - .find_many(vec![account::active::equals(true)]) + .find_many(vec![account::active::equals(false)]) .exec() .await .map_err(|_| ()) diff --git a/src/components/user/base.tsx b/src/components/user/base.tsx index d8feabba..9f87cfbd 100644 --- a/src/components/user/base.tsx +++ b/src/components/user/base.tsx @@ -1,33 +1,22 @@ import { ImageWithFallback } from '@components/imageWithFallback'; +import { RelayContext } from '@components/relaysProvider'; import { DEFAULT_AVATAR } from '@stores/constants'; -import { createCacheProfile } from '@utils/storage'; import { truncate } from '@utils/truncate'; -import { fetch } from '@tauri-apps/api/http'; -import destr from 'destr'; -import { memo, useCallback, useEffect, useState } from 'react'; +import { Author } from 'nostr-relaypool'; +import { memo, useContext, useEffect, useMemo, useState } from 'react'; export const UserBase = memo(function UserBase({ pubkey }: { pubkey: string }) { - const [profile, setProfile] = useState(null); + const [pool, relays]: any = useContext(RelayContext); - const fetchProfile = useCallback(async (id: string) => { - const res = await fetch(`https://rbr.bio/${id}/metadata.json`, { - method: 'GET', - timeout: 30, - }); - return res.data; - }, []); + const [profile, setProfile] = useState(null); + const user = useMemo(() => new Author(pool, relays, pubkey), [pubkey, pool, relays]); useEffect(() => { - fetchProfile(pubkey) - .then((res: any) => { - setProfile(destr(res.content)); - createCacheProfile(res.pubkey, res.content); - }) - .catch(console.error); - }, [fetchProfile, pubkey]); + user.metaData((res) => setProfile(JSON.parse(res.content)), 0); + }, [user]); return (
diff --git a/src/components/user/extend.tsx b/src/components/user/extend.tsx index 8672de8c..7039cea1 100644 --- a/src/components/user/extend.tsx +++ b/src/components/user/extend.tsx @@ -1,51 +1,34 @@ import { ImageWithFallback } from '@components/imageWithFallback'; +import { RelayContext } from '@components/relaysProvider'; import { DEFAULT_AVATAR } from '@stores/constants'; -import { createCacheProfile, getCacheProfile } from '@utils/storage'; import { truncate } from '@utils/truncate'; import { DotsHorizontalIcon } from '@radix-ui/react-icons'; -import { fetch } from '@tauri-apps/api/http'; import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; -import destr from 'destr'; import { useRouter } from 'next/router'; -import { memo, useCallback, useEffect, useState } from 'react'; +import { Author } from 'nostr-relaypool'; +import { memo, useContext, useEffect, useMemo, useState } from 'react'; dayjs.extend(relativeTime); export const UserExtend = memo(function UserExtend({ pubkey, time }: { pubkey: string; time: any }) { + const [pool, relays]: any = useContext(RelayContext); const router = useRouter(); + const [profile, setProfile] = useState(null); + const user = useMemo(() => new Author(pool, relays, pubkey), [pubkey, pool, relays]); const openUserPage = (e) => { e.stopPropagation(); router.push(`/users/${pubkey}`); }; - const fetchProfile = useCallback(async (id: string) => { - const res = await fetch(`https://rbr.bio/${id}/metadata.json`, { - method: 'GET', - timeout: 30, - }); - return res.data; - }, []); - useEffect(() => { - getCacheProfile(pubkey).then((res) => { - if (res) { - setProfile(destr(res.metadata)); - } else { - fetchProfile(pubkey) - .then((res: any) => { - setProfile(destr(res.content)); - createCacheProfile(pubkey, res.content); - }) - .catch(console.error); - } - }); - }, [fetchProfile, pubkey]); + user.metaData((res) => setProfile(JSON.parse(res.content)), 0); + }, [user]); return (
diff --git a/src/components/user/large.tsx b/src/components/user/large.tsx index 634ab02e..0a660dd2 100644 --- a/src/components/user/large.tsx +++ b/src/components/user/large.tsx @@ -1,44 +1,27 @@ import { ImageWithFallback } from '@components/imageWithFallback'; +import { RelayContext } from '@components/relaysProvider'; import { DEFAULT_AVATAR } from '@stores/constants'; -import { createCacheProfile, getCacheProfile } from '@utils/storage'; import { truncate } from '@utils/truncate'; import { DotsHorizontalIcon } from '@radix-ui/react-icons'; -import { fetch } from '@tauri-apps/api/http'; import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; -import destr from 'destr'; -import { memo, useCallback, useEffect, useState } from 'react'; +import { Author } from 'nostr-relaypool'; +import { memo, useContext, useEffect, useMemo, useState } from 'react'; dayjs.extend(relativeTime); export const UserLarge = memo(function UserLarge({ pubkey, time }: { pubkey: string; time: any }) { - const [profile, setProfile] = useState(null); + const [pool, relays]: any = useContext(RelayContext); - const fetchProfile = useCallback(async (id: string) => { - const res = await fetch(`https://rbr.bio/${id}/metadata.json`, { - method: 'GET', - timeout: 30, - }); - return res.data; - }, []); + const [profile, setProfile] = useState(null); + const user = useMemo(() => new Author(pool, relays, pubkey), [pubkey, pool, relays]); useEffect(() => { - getCacheProfile(pubkey).then((res) => { - if (res) { - setProfile(destr(res.metadata)); - } else { - fetchProfile(pubkey) - .then((res: any) => { - setProfile(destr(res.content)); - createCacheProfile(pubkey, res.content); - }) - .catch(console.error); - } - }); - }, [fetchProfile, pubkey]); + user.metaData((res) => setProfile(JSON.parse(res.content)), 0); + }, [user]); return (
diff --git a/src/components/user/mention.tsx b/src/components/user/mention.tsx index 06b4b0bf..4cae27fd 100644 --- a/src/components/user/mention.tsx +++ b/src/components/user/mention.tsx @@ -1,35 +1,19 @@ -import { createCacheProfile, getCacheProfile } from '@utils/storage'; +import { RelayContext } from '@components/relaysProvider'; + import { truncate } from '@utils/truncate'; -import { fetch } from '@tauri-apps/api/http'; -import destr from 'destr'; -import { memo, useCallback, useEffect, useState } from 'react'; +import { Author } from 'nostr-relaypool'; +import { memo, useContext, useEffect, useMemo, useState } from 'react'; export const UserMention = memo(function UserMention({ pubkey }: { pubkey: string }) { - const [profile, setProfile] = useState(null); + const [pool, relays]: any = useContext(RelayContext); - const fetchProfile = useCallback(async (id: string) => { - const res = await fetch(`https://rbr.bio/${id}/metadata.json`, { - method: 'GET', - timeout: 30, - }); - return res.data; - }, []); + const [profile, setProfile] = useState(null); + const user = useMemo(() => new Author(pool, relays, pubkey), [pubkey, pool, relays]); useEffect(() => { - getCacheProfile(pubkey).then((res) => { - if (res) { - setProfile(destr(res.metadata)); - } else { - fetchProfile(pubkey) - .then((res: any) => { - setProfile(destr(res.content)); - createCacheProfile(pubkey, res.content); - }) - .catch(console.error); - } - }); - }, [fetchProfile, pubkey]); + user.metaData((res) => setProfile(JSON.parse(res.content)), 0); + }, [user]); return @{profile?.name || truncate(pubkey, 16, ' .... ')}; }); diff --git a/src/components/user/mini.tsx b/src/components/user/mini.tsx index b5fa2bdd..22b74547 100644 --- a/src/components/user/mini.tsx +++ b/src/components/user/mini.tsx @@ -1,24 +1,22 @@ import { ImageWithFallback } from '@components/imageWithFallback'; +import { RelayContext } from '@components/relaysProvider'; import { DEFAULT_AVATAR } from '@stores/constants'; -import { getCacheProfile } from '@utils/storage'; import { truncate } from '@utils/truncate'; -import { useCallback, useEffect, useState } from 'react'; +import { Author } from 'nostr-relaypool'; +import { useContext, useEffect, useMemo, useState } from 'react'; export const UserMini = ({ pubkey }: { pubkey: string }) => { - const [profile, setProfile] = useState(null); + const [pool, relays]: any = useContext(RelayContext); - const fetchCacheProfile = useCallback(async (id: string) => { - const res = await getCacheProfile(id); - const data = JSON.parse(res.metadata); - setProfile(data); - }, []); + const [profile, setProfile] = useState(null); + const user = useMemo(() => new Author(pool, relays, pubkey), [pubkey, pool, relays]); useEffect(() => { - fetchCacheProfile(pubkey).catch(console.error); - }, [fetchCacheProfile, pubkey]); + user.metaData((res) => setProfile(JSON.parse(res.content)), 0); + }, [user]); if (profile) { return ( diff --git a/src/pages/onboarding/create/index.tsx b/src/pages/onboarding/create/index.tsx index 55f86ea4..9e9d7880 100644 --- a/src/pages/onboarding/create/index.tsx +++ b/src/pages/onboarding/create/index.tsx @@ -82,7 +82,7 @@ export default function Page() { pool.publish(event, relays); router.push({ pathname: '/onboarding/create/step-2', - query: { id: res.id, privkey: res.privkey }, + query: { id: res.id, pubkey: res.pubkey, privkey: res.privkey }, }); }) .catch(console.error); diff --git a/src/pages/onboarding/create/step-2.tsx b/src/pages/onboarding/create/step-2.tsx index b31d4f78..4831a6e4 100644 --- a/src/pages/onboarding/create/step-2.tsx +++ b/src/pages/onboarding/create/step-2.tsx @@ -3,6 +3,7 @@ import BaseLayout from '@layouts/base'; import { RelayContext } from '@components/relaysProvider'; import { UserBase } from '@components/user/base'; +import { fetchMetadata } from '@utils/metadata'; import { followsTag } from '@utils/transform'; import { CheckCircledIcon } from '@radix-ui/react-icons'; @@ -65,7 +66,7 @@ export default function Page() { const [pool, relays]: any = useContext(RelayContext); const router = useRouter(); - const { id, privkey }: any = router.query || ''; + const { id, pubkey, privkey }: any = router.query || ''; const [loading, setLoading] = useState(false); const [list, setList]: any = useState(initialList); @@ -82,24 +83,25 @@ export default function Page() { const { createFollow } = await import('@utils/bindings'); setLoading(true); + for (const follow of follows) { + const metadata: any = await fetchMetadata(follow, pool, relays); + createFollow({ pubkey: follow, kind: 0, metadata: metadata.content, account_id: parseInt(id) }); + } + // build event const event: any = { content: '', created_at: Math.floor(Date.now() / 1000), kind: 3, - pubkey: id, + pubkey: pubkey, tags: followsTag(follows), }; event.id = getEventHash(event); event.sig = signEvent(event, privkey); - follows.forEach((item) => { - createFollow({ pubkey: item, kind: 0, metadata: JSON.stringify({}), account_id: id }); - }); - pool.publish(event, relays); router.replace('/'); - }, [follows, id, pool, privkey, relays, router]); + }, [follows, id, pool, pubkey, privkey, relays, router]); useEffect(() => { const fetchData = async () => { diff --git a/src/pages/onboarding/login/step-2.tsx b/src/pages/onboarding/login/step-2.tsx index 9e40f6c0..fee12df2 100644 --- a/src/pages/onboarding/login/step-2.tsx +++ b/src/pages/onboarding/login/step-2.tsx @@ -2,21 +2,21 @@ import BaseLayout from '@layouts/base'; import { RelayContext } from '@components/relaysProvider'; -import { createAccount, createFollows } from '@utils/storage'; -import { tagsToArray } from '@utils/transform'; +import { fetchMetadata } from '@utils/metadata'; import { truncate } from '@utils/truncate'; -import destr from 'destr'; import Image from 'next/image'; import { useRouter } from 'next/router'; -import { getPublicKey, nip19 } from 'nostr-tools'; +import { getPublicKey } from 'nostr-tools'; import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, + useCallback, useContext, useEffect, + useRef, useState, } from 'react'; @@ -30,6 +30,28 @@ export default function Page() { const [profile, setProfile] = useState(null); const [done, setDone] = useState(false); + const accountId = useRef(null); + + const insertAccountToStorage = useCallback(async (pubkey, privkey, metadata) => { + const { createAccount } = await import('@utils/bindings'); + createAccount({ pubkey: pubkey, privkey: privkey, metadata: JSON.stringify(metadata) }).then( + (res) => (accountId.current = res.id) + ); + }, []); + + const insertFollowsToStorage = useCallback( + async (tags) => { + const { createFollow } = await import('@utils/bindings'); + if (accountId.current !== null) { + for (const tag of tags) { + const metadata: any = await fetchMetadata(tag[1], pool, relays); + createFollow({ pubkey: tag[1], kind: 0, metadata: metadata.content, account_id: accountId.current }); + } + } + }, + [pool, relays] + ); + useEffect(() => { const unsubscribe = pool.subscribe( [ @@ -42,18 +64,11 @@ export default function Page() { relays, (event: any) => { if (event.kind === 0) { - const data = { - pubkey: pubkey, - privkey: privkey, - npub: nip19.npubEncode(pubkey), - nsec: nip19.nsecEncode(privkey), - metadata: event.content, - }; - setProfile(destr(event.content)); - createAccount(data); + setProfile(JSON.parse(event.content)); + insertAccountToStorage(pubkey, privkey, event.content); } else { if (event.tags.length > 0) { - createFollows(tagsToArray(event.tags), pubkey, 0); + insertFollowsToStorage(event.tags); } } }, @@ -69,7 +84,7 @@ export default function Page() { return () => { unsubscribe; }; - }, [pool, privkey, pubkey, relays]); + }, [insertAccountToStorage, insertFollowsToStorage, pool, relays, privkey, pubkey]); // submit then redirect to home const submit = () => { diff --git a/src/utils/metadata.tsx b/src/utils/metadata.tsx new file mode 100644 index 00000000..5598ed8a --- /dev/null +++ b/src/utils/metadata.tsx @@ -0,0 +1,6 @@ +import { Author } from 'nostr-relaypool'; + +export const fetchMetadata = (pubkey: string, pool: any, relays: any) => { + const author = new Author(pool, relays, pubkey); + return new Promise((resolve) => author.metaData(resolve, 0)); +}; diff --git a/src/utils/transform.tsx b/src/utils/transform.tsx index ebc01fb9..e9bb58e5 100644 --- a/src/utils/transform.tsx +++ b/src/utils/transform.tsx @@ -13,7 +13,7 @@ export const followsTag = (arr) => { const newarr = []; // push item to tags arr.forEach((item) => { - arr.push(['p', item]); + newarr.push(['p', item]); }); return newarr; };