update useNostr hook
This commit is contained in:
@@ -18,11 +18,11 @@ const ITEM_PER_PAGE = 10;
|
||||
|
||||
export function NetworkBlock() {
|
||||
// subscribe for live update
|
||||
useNewsfeed();
|
||||
// useNewsfeed();
|
||||
|
||||
const { status, data, fetchNextPage, hasNextPage, isFetchingNextPage } =
|
||||
useInfiniteQuery({
|
||||
queryKey: ['newsfeed-circle'],
|
||||
queryKey: ['network-widget'],
|
||||
queryFn: async ({ pageParam = 0 }) => {
|
||||
return await getNotes(ITEM_PER_PAGE, pageParam);
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useNostr } from '@utils/hooks/useNostr';
|
||||
export function SplashScreen() {
|
||||
const { ndk, relayUrls } = useNDK();
|
||||
const { status, account } = useAccount();
|
||||
const { fetchChats, fetchNotes } = useNostr();
|
||||
const { fetchUserData } = useNostr();
|
||||
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [errorMessage, setErrorMessage] = useState<null | string>(null);
|
||||
@@ -27,18 +27,15 @@ export function SplashScreen() {
|
||||
if (step) await invoke('close_splashscreen');
|
||||
|
||||
try {
|
||||
const notes = await fetchNotes();
|
||||
const chats = await fetchChats();
|
||||
|
||||
if (notes.status === 'ok' && chats.status === 'ok') {
|
||||
const user = await fetchUserData();
|
||||
if (user.status === 'ok') {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
await updateLastLogin(now);
|
||||
invoke('close_splashscreen');
|
||||
} else {
|
||||
setIsLoading(false);
|
||||
setErrorMessage(notes.message || chats.message);
|
||||
console.log('fetch notes failed, error: ', notes.message);
|
||||
console.log('fetch chats failed, error: ', chats.message);
|
||||
setErrorMessage(user.message);
|
||||
console.log('fetch failed, error: ', user.message);
|
||||
}
|
||||
} catch (e) {
|
||||
setIsLoading(false);
|
||||
|
||||
@@ -1,51 +1,24 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { useNDK } from '@libs/ndk/provider';
|
||||
import { createNote, getNoteByID } from '@libs/storage';
|
||||
|
||||
import { parser } from '@utils/parser';
|
||||
import { LumeEvent } from '@utils/types';
|
||||
|
||||
export function useEvent(id: string, fallback?: string) {
|
||||
export function useEvent(id: string, embed?: string) {
|
||||
const { ndk } = useNDK();
|
||||
const { status, data, error, isFetching } = useQuery(
|
||||
['note', id],
|
||||
async () => {
|
||||
const result = await getNoteByID(id);
|
||||
if (result) {
|
||||
return result as LumeEvent;
|
||||
if (embed) {
|
||||
const event: LumeEvent = JSON.parse(embed);
|
||||
if (event.kind === 1) embed['content'] = parser(event);
|
||||
return embed;
|
||||
} else {
|
||||
if (fallback) {
|
||||
const embed: LumeEvent = JSON.parse(fallback);
|
||||
if (embed.kind === 1) embed['content'] = parser(embed);
|
||||
embed['event_id'] = embed.id;
|
||||
await createNote(
|
||||
embed.id,
|
||||
embed.pubkey,
|
||||
embed.kind,
|
||||
embed.tags,
|
||||
embed.content as unknown as string,
|
||||
embed.created_at
|
||||
);
|
||||
return embed;
|
||||
} else {
|
||||
const event = (await ndk.fetchEvent(id)) as unknown as LumeEvent;
|
||||
if (event) {
|
||||
await createNote(
|
||||
event.id,
|
||||
event.pubkey,
|
||||
event.kind,
|
||||
event.tags,
|
||||
event.content as unknown as string,
|
||||
event.created_at
|
||||
);
|
||||
event['event_id'] = event.id;
|
||||
if (event.kind === 1) event['content'] = parser(event);
|
||||
return event as unknown as LumeEvent;
|
||||
} else {
|
||||
throw new Error('Event not found');
|
||||
}
|
||||
}
|
||||
const event = (await ndk.fetchEvent(id)) as unknown as LumeEvent;
|
||||
if (!event) throw new Error('Event not found');
|
||||
if (event.kind === 1) event['content'] = parser(event);
|
||||
return event as unknown as LumeEvent;
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
import { NDKEvent, NDKKind, NDKPrivateKeySigner, NDKUser } from '@nostr-dev-kit/ndk';
|
||||
import {
|
||||
NDKEvent,
|
||||
NDKFilter,
|
||||
NDKKind,
|
||||
NDKPrivateKeySigner,
|
||||
NDKSubscription,
|
||||
NDKUser,
|
||||
} from '@nostr-dev-kit/ndk';
|
||||
import { ndkAdapter } from '@nostr-fetch/adapter-ndk';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import destr from 'destr';
|
||||
import { LRUCache } from 'lru-cache';
|
||||
import { NostrFetcher } from 'nostr-fetch';
|
||||
@@ -7,152 +15,95 @@ import { nip19 } from 'nostr-tools';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { useNDK } from '@libs/ndk/provider';
|
||||
import {
|
||||
countTotalNotes,
|
||||
createChat,
|
||||
createNote,
|
||||
getLastLogin,
|
||||
updateAccount,
|
||||
} from '@libs/storage';
|
||||
import { updateAccount } from '@libs/storage';
|
||||
|
||||
import { useStronghold } from '@stores/stronghold';
|
||||
|
||||
import { nHoursAgo } from '@utils/date';
|
||||
import { useAccount } from '@utils/hooks/useAccount';
|
||||
|
||||
export function useNostr() {
|
||||
const { ndk, relayUrls } = useNDK();
|
||||
const { account } = useAccount();
|
||||
|
||||
const fetcher = useMemo(() => NostrFetcher.withCustomPool(ndkAdapter(ndk)), [ndk]);
|
||||
const queryClient = useQueryClient();
|
||||
const privkey = useStronghold((state) => state.privkey);
|
||||
const fetcher = useMemo(() => NostrFetcher.withCustomPool(ndkAdapter(ndk)), [ndk]);
|
||||
const subManager = useMemo(
|
||||
() =>
|
||||
new LRUCache<string, NDKSubscription, void>({
|
||||
max: 4,
|
||||
dispose: (sub) => sub.stop(),
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
async function fetchNetwork(prevFollow?: string[]) {
|
||||
const follows = new Set<string>(prevFollow || []);
|
||||
const lruNetwork = new LRUCache<string, string, void>({ max: 300 });
|
||||
const sub = async (
|
||||
filter: NDKFilter,
|
||||
callback: (event: NDKEvent) => void,
|
||||
closeOnEose?: boolean
|
||||
) => {
|
||||
const subEvent = ndk.subscribe(filter, { closeOnEose: closeOnEose ?? true });
|
||||
subManager.set(JSON.stringify(filter), subEvent);
|
||||
|
||||
let network: string[];
|
||||
subEvent.addListener('event', (event: NDKEvent) => {
|
||||
callback(event);
|
||||
});
|
||||
};
|
||||
|
||||
// fetch user's follows
|
||||
if (!prevFollow) {
|
||||
console.log("fetching user's follow...");
|
||||
const user = ndk.getUser({ hexpubkey: account.pubkey });
|
||||
const list = await user.follows();
|
||||
list.forEach((item: NDKUser) => {
|
||||
follows.add(nip19.decode(item.npub).data as string);
|
||||
});
|
||||
}
|
||||
const fetchUserData = async (preFollows?: string[]) => {
|
||||
try {
|
||||
const follows = new Set<string>(preFollows || []);
|
||||
const lruNetwork = new LRUCache<string, string, void>({ max: 300 });
|
||||
|
||||
// fetch network
|
||||
if (!account.network) {
|
||||
console.log("fetching user's network...");
|
||||
// fetch user's follows
|
||||
if (!preFollows) {
|
||||
const user = ndk.getUser({ hexpubkey: account.pubkey });
|
||||
const list = await user.follows();
|
||||
list.forEach((item: NDKUser) => {
|
||||
follows.add(nip19.decode(item.npub).data as string);
|
||||
});
|
||||
}
|
||||
|
||||
// build user's network
|
||||
const events = await ndk.fetchEvents({ kinds: [3], authors: [...follows] });
|
||||
|
||||
events.forEach((event: NDKEvent) => {
|
||||
event.tags.forEach((tag) => {
|
||||
if (tag[0] === 'p') lruNetwork.set(tag[1], tag[1]);
|
||||
});
|
||||
});
|
||||
|
||||
network = [...lruNetwork.values()] as string[];
|
||||
} else {
|
||||
network = account.network;
|
||||
}
|
||||
const network = [...lruNetwork.values()] as string[];
|
||||
|
||||
// update user in db
|
||||
await updateAccount('follows', [...follows]);
|
||||
await updateAccount('network', network);
|
||||
await updateAccount('follows', [...follows]);
|
||||
await updateAccount('network', [...new Set([...follows, ...network])]);
|
||||
|
||||
return [...new Set([...follows, ...network])];
|
||||
}
|
||||
|
||||
async function fetchNotes(prevFollow?: string[]) {
|
||||
try {
|
||||
if (!ndk) return { status: 'failed', message: 'NDK instance not found' };
|
||||
|
||||
const network = await fetchNetwork(prevFollow);
|
||||
const totalNotes = await countTotalNotes();
|
||||
const lastLogin = await getLastLogin();
|
||||
|
||||
if (network.length > 0) {
|
||||
console.log('fetching notes...');
|
||||
|
||||
let since: number;
|
||||
if (totalNotes === 0 || lastLogin === 0) {
|
||||
since = nHoursAgo(24);
|
||||
} else {
|
||||
since = lastLogin;
|
||||
}
|
||||
|
||||
const events = await fetcher.fetchAllEvents(
|
||||
relayUrls,
|
||||
{
|
||||
kinds: [1],
|
||||
authors: network,
|
||||
},
|
||||
{ since: since }
|
||||
);
|
||||
|
||||
for (const event of events) {
|
||||
await createNote(
|
||||
event.id,
|
||||
event.pubkey,
|
||||
event.kind,
|
||||
event.tags,
|
||||
event.content,
|
||||
event.created_at
|
||||
);
|
||||
}
|
||||
}
|
||||
queryClient.invalidateQueries(['currentAccount']);
|
||||
|
||||
return { status: 'ok' };
|
||||
} catch (e) {
|
||||
console.error('failed fetch notes, error: ', e);
|
||||
return { status: 'failed', message: e };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
async function fetchChats() {
|
||||
const fetchNotes = async (since: number) => {
|
||||
try {
|
||||
if (!ndk) return { status: 'failed', message: 'NDK instance not found' };
|
||||
|
||||
const lastLogin = await getLastLogin();
|
||||
|
||||
const outgoingMessages = await fetcher.fetchAllEvents(
|
||||
const events = await fetcher.fetchAllEvents(
|
||||
relayUrls,
|
||||
{
|
||||
kinds: [4],
|
||||
authors: [account.pubkey],
|
||||
kinds: [1],
|
||||
authors: account.network ?? account.follows,
|
||||
},
|
||||
{ since: lastLogin }
|
||||
{ since: since }
|
||||
);
|
||||
|
||||
const incomingMessages = await fetcher.fetchAllEvents(
|
||||
relayUrls,
|
||||
{ kinds: [4], '#p': [account.pubkey] },
|
||||
{ since: lastLogin }
|
||||
);
|
||||
|
||||
const messages = [...outgoingMessages, ...incomingMessages];
|
||||
|
||||
for (const event of messages) {
|
||||
const receiverPubkey = event.tags.find((t) => t[0] === 'p')[1] || account.pubkey;
|
||||
await createChat(
|
||||
event.id,
|
||||
receiverPubkey,
|
||||
event.pubkey,
|
||||
event.content,
|
||||
event.tags,
|
||||
event.created_at
|
||||
);
|
||||
}
|
||||
|
||||
return { status: 'ok' };
|
||||
return { status: 'ok', notes: events };
|
||||
} catch (e) {
|
||||
console.error('failed fetch messages, error: ', e);
|
||||
console.error('failed get notes, error: ', e);
|
||||
return { status: 'failed', message: e };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const publish = async ({
|
||||
content,
|
||||
@@ -203,5 +154,5 @@ export function useNostr() {
|
||||
return res;
|
||||
};
|
||||
|
||||
return { fetchNotes, fetchChats, publish, createZap };
|
||||
return { sub, fetchUserData, fetchNotes, publish, createZap };
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ export function useProfile(pubkey: string, fallback?: string) {
|
||||
['user', pubkey],
|
||||
async () => {
|
||||
if (!fallback) {
|
||||
const user = await ndk.getUser({ hexpubkey: pubkey });
|
||||
const user = ndk.getUser({ hexpubkey: pubkey });
|
||||
await user.fetchProfile();
|
||||
if (user.profile) {
|
||||
user.profile.display_name = user.profile.displayName;
|
||||
|
||||
Reference in New Issue
Block a user