feat: update ark provider

This commit is contained in:
reya 2024-01-27 09:08:41 +07:00
parent bc48391a1a
commit 353c18bb76
3 changed files with 110 additions and 128 deletions

View File

@ -145,7 +145,6 @@ export class Ark {
cacheUsage: NDKSubscriptionCacheUsage.CACHE_FIRST, cacheUsage: NDKSubscriptionCacheUsage.CACHE_FIRST,
}); });
if (!profile) return null;
return profile; return profile;
} catch { } catch {
throw new Error("user not found"); throw new Error("user not found");
@ -167,8 +166,9 @@ export class Ark {
(user) => user.pubkey, (user) => user.pubkey,
); );
if (!pubkey || pubkey === this.account.pubkey) if (!pubkey || pubkey === this.account.pubkey) {
this.account.contacts = contacts; this.account.contacts = contacts;
}
return contacts; return contacts;
} catch (e) { } catch (e) {

View File

@ -1,8 +1,10 @@
import { useQuery } from "@tanstack/react-query"; import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useArk } from "./useArk"; import { useArk } from "./useArk";
export function useProfile(pubkey: string) { export function useProfile(pubkey: string) {
const ark = useArk(); const ark = useArk();
const queryClient = useQueryClient();
const { const {
isLoading, isLoading,
isError, isError,
@ -17,6 +19,9 @@ export function useProfile(pubkey: string) {
); );
return profile; return profile;
}, },
initialData: () => {
return queryClient.getQueryData(["user", pubkey]);
},
refetchOnMount: false, refetchOnMount: false,
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
refetchOnReconnect: false, refetchOnReconnect: false,

View File

@ -23,6 +23,7 @@ import { useSetAtom } from "jotai";
import Linkify from "linkify-react"; import Linkify from "linkify-react";
import { normalizeRelayUrlSet } from "nostr-fetch"; import { normalizeRelayUrlSet } from "nostr-fetch";
import { PropsWithChildren, useEffect, useState } from "react"; import { PropsWithChildren, useEffect, useState } from "react";
import { toast } from "sonner";
import { Ark } from "./ark"; import { Ark } from "./ark";
import { LumeContext } from "./context"; import { LumeContext } from "./context";
@ -80,55 +81,65 @@ export const LumeProvider = ({ children }: PropsWithChildren<object>) => {
return new NDKPrivateKeySigner(userPrivkey); return new NDKPrivateKeySigner(userPrivkey);
} catch (e) { } catch (e) {
console.error(e); toast.error(String(e));
return null; return null;
} }
} }
async function initNDK() { async function initNDK() {
const explicitRelayUrls = normalizeRelayUrlSet([ try {
"wss://nostr.mutinywallet.com/", const explicitRelayUrls = normalizeRelayUrlSet([
"wss://bostr.nokotaro.com/", "wss://nostr.mutinywallet.com/",
]); "wss://bostr.nokotaro.com/",
]);
const tauriCache = new NDKCacheAdapterTauri(storage); const outboxRelayUrls = normalizeRelayUrlSet(["wss://purplepag.es/"]);
const ndk = new NDK({
cacheAdapter: tauriCache,
explicitRelayUrls,
enableOutboxModel: !storage.settings.lowPower,
autoConnectUserRelays: !storage.settings.lowPower,
autoFetchUserMutelist: !storage.settings.lowPower,
clientName: "Lume",
});
// use tauri fetch const tauriCache = new NDKCacheAdapterTauri(storage);
ndk.httpFetch = fetch; const ndk = new NDK({
cacheAdapter: tauriCache,
explicitRelayUrls,
outboxRelayUrls,
enableOutboxModel: !storage.settings.lowPower,
autoConnectUserRelays: !storage.settings.lowPower,
autoFetchUserMutelist: false, // #TODO: add support mute list
clientName: "Lume",
});
// add signer // use tauri fetch
const signer = await initNostrSigner({ ndk.httpFetch = fetch;
nsecbunker: storage.settings.nsecbunker,
});
if (signer) ndk.signer = signer; // add signer
const signer = await initNostrSigner({
nsecbunker: storage.settings.nsecbunker,
});
// connect if (signer) ndk.signer = signer;
await ndk.connect(3000);
// auth // connect
ndk.relayAuthDefaultPolicy = async (relay: NDKRelay, challenge: string) => { await ndk.connect(3000);
const signIn = NDKRelayAuthPolicies.signIn({ ndk });
const event = await signIn(relay, challenge).catch((e) => // auth
console.log("auth failed", e), ndk.relayAuthDefaultPolicy = async (
); relay: NDKRelay,
if (event) { challenge: string,
await sendNativeNotification( ) => {
`You've sign in sucessfully to relay: ${relay.url}`, const signIn = NDKRelayAuthPolicies.signIn({ ndk });
const event = await signIn(relay, challenge).catch((e) =>
console.log("auth failed", e),
); );
return event; if (event) {
} await sendNativeNotification(
}; `You've sign in sucessfully to relay: ${relay.url}`,
);
return event;
}
};
setNDK(ndk); setNDK(ndk);
} catch (e) {
toast.error(String(e));
}
} }
async function initArk() { async function initArk() {
@ -137,102 +148,68 @@ export const LumeProvider = ({ children }: PropsWithChildren<object>) => {
// ark utils // ark utils
const ark = new Ark({ ndk, account: storage.currentUser }); const ark = new Ark({ ndk, account: storage.currentUser });
if (ndk && storage.currentUser) { try {
const user = new NDKUser({ pubkey: storage.currentUser.pubkey }); if (ndk && storage.currentUser) {
ndk.activeUser = user; const user = new NDKUser({ pubkey: storage.currentUser.pubkey });
ndk.activeUser = user;
// update contacts // update contacts
await ark.getUserContacts(); const contacts = await ark.getUserContacts();
// subscribe for new activity if (contacts?.length) {
const activitySub = ndk.subscribe( console.log("total contacts: ", contacts.length);
{ for (const pubkey of ark.account.contacts) {
kinds: [NDKKind.Text, NDKKind.Repost, NDKKind.Zap], await queryClient.prefetchQuery({
since: Math.floor(Date.now() / 1000), queryKey: ["user", pubkey],
"#p": [ark.account.pubkey], queryFn: async () => {
}, return await ark.getUserProfile(pubkey);
{ closeOnEose: false, groupable: false }, },
); });
}
activitySub.addListener("event", async (event: NDKEvent) => {
if (event.pubkey === storage.currentUser.pubkey) return;
setUnreadActivity((state) => state + 1);
const profile = await ark.getUserProfile(event.pubkey);
switch (event.kind) {
case NDKKind.Text:
return await sendNativeNotification(
`${
profile.displayName || profile.name || "Anon"
} has replied to your note`,
);
case NDKKind.Repost:
return await sendNativeNotification(
`${
profile.displayName || profile.name || "Anon"
} has reposted to your note`,
);
case NDKKind.Zap:
return await sendNativeNotification(
`${
profile.displayName || profile.name || "Anon"
} has zapped to your note`,
);
default:
break;
} }
});
// prefetch activty // subscribe for new activity
await queryClient.prefetchInfiniteQuery({ const activitySub = ndk.subscribe(
queryKey: ["activity"], {
initialPageParam: 0, kinds: [NDKKind.Text, NDKKind.Repost, NDKKind.Zap],
queryFn: async ({ since: Math.floor(Date.now() / 1000),
signal, "#p": [ark.account.pubkey],
pageParam, },
}: { { closeOnEose: false, groupable: false },
signal: AbortSignal; );
pageParam: number;
}) => {
const events = await ark.getInfiniteEvents({
filter: {
kinds: [NDKKind.Text, NDKKind.Repost, NDKKind.Zap],
"#p": [ark.account.pubkey],
},
limit: FETCH_LIMIT,
pageParam,
signal,
});
return events; activitySub.addListener("event", async (event: NDKEvent) => {
}, if (event.pubkey === storage.currentUser.pubkey) return;
});
// prefetch timeline setUnreadActivity((state) => state + 1);
await queryClient.prefetchInfiniteQuery({ const profile = await ark.getUserProfile(event.pubkey);
queryKey: ["timeline-9999"],
initialPageParam: 0,
queryFn: async ({
signal,
pageParam,
}: {
signal: AbortSignal;
pageParam: number;
}) => {
const events = await ark.getInfiniteEvents({
filter: {
kinds: [NDKKind.Text, NDKKind.Repost],
authors: ark.account.contacts,
},
limit: FETCH_LIMIT,
pageParam,
signal,
});
return events; switch (event.kind) {
}, case NDKKind.Text:
}); return await sendNativeNotification(
`${
profile.displayName || profile.name || "Anon"
} has replied to your note`,
);
case NDKKind.Repost:
return await sendNativeNotification(
`${
profile.displayName || profile.name || "Anon"
} has reposted to your note`,
);
case NDKKind.Zap:
return await sendNativeNotification(
`${
profile.displayName || profile.name || "Anon"
} has zapped to your note`,
);
default:
break;
}
});
}
} catch (e) {
toast.error(String(e));
} }
setArk(ark); setArk(ark);