added indexdb

This commit is contained in:
zmeyer44 2023-10-22 11:04:24 -04:00
parent b817287525
commit f84cc85148
11 changed files with 124 additions and 13 deletions

View File

@ -11,7 +11,7 @@ type MySubscription = {
export default function MySubscription({ pubkey }: MySubscription) { export default function MySubscription({ pubkey }: MySubscription) {
const { ndk, fetchEvents } = useNDK(); const { ndk, fetchEvents } = useNDK();
const { currentUser, mySubscription, follows } = useCurrentUser(); const { currentUser } = useCurrentUser();
const [subscriptionTiers, setSubscriptionTiers] = useState<NDKEvent[]>([]); const [subscriptionTiers, setSubscriptionTiers] = useState<NDKEvent[]>([]);
useEffect(() => { useEffect(() => {
@ -22,13 +22,14 @@ export default function MySubscription({ pubkey }: MySubscription) {
async function handleFetchSubscriptionTiers() { async function handleFetchSubscriptionTiers() {
try { try {
console.log("FETCHING", pubkey); if (!ndk) {
return "NDK MISING";
}
const events = await fetchEvents({ const events = await fetchEvents({
kinds: [30044 as NDKKind], kinds: [30044 as NDKKind],
authors: [pubkey], authors: [pubkey],
}); });
console.log("events", events); console.log("events", events);
setSubscriptionTiers(events); setSubscriptionTiers(events);
} catch (err) { } catch (err) {
console.log("error", err); console.log("error", err);

View File

@ -1,5 +1,5 @@
"use client"; "use client";
import { useState } from "react"; import { useEffect, useState } from "react";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import Image from "next/image"; import Image from "next/image";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@ -40,15 +40,27 @@ export default function ProfilePage({
}; };
}) { }) {
const modal = useModal(); const modal = useModal();
const { currentUser, mySubscription, follows } = useCurrentUser(); const { currentUser, mySubscription, initSubscriptions } = useCurrentUser();
const [activeTab, setActiveTab] = useState("feed"); const [activeTab, setActiveTab] = useState("feed");
const [delegate, setDelegate] = useState<string>();
const { type, data } = nip19.decode(npub); const { type, data } = nip19.decode(npub);
const delegate = getTagValues("delegate", mySubscription?.tags ?? []); const pubkey = data.toString();
useEffect(() => {
console.log("In affectr");
if (mySubscription) {
const _delegate = getTagValues("delegate", mySubscription.tags);
console.log("Setting");
setDelegate(_delegate);
}
}, [mySubscription]);
useEffect(() => {
initSubscriptions(pubkey);
}, []);
console.log("Delegate", delegate);
if (type !== "npub") { if (type !== "npub") {
throw new Error("Invalid list"); throw new Error("Invalid list");
} }
const pubkey = data.toString();
const { profile } = useProfile(pubkey); const { profile } = useProfile(pubkey);
return ( return (

View File

@ -30,6 +30,10 @@ import {
TooltipTrigger, TooltipTrigger,
} from "@/components/ui/tooltip"; } from "@/components/ui/tooltip";
import { useKeyboardShortcut } from "@/lib/hooks/useKeyboardShortcut"; import { useKeyboardShortcut } from "@/lib/hooks/useKeyboardShortcut";
import { db } from "@nostr-dev-kit/ndk-cache-dexie";
import { useLiveQuery } from "dexie-react-hooks";
const LoginModal = dynamic(() => import("@/components/Modals/Login"), { const LoginModal = dynamic(() => import("@/components/Modals/Login"), {
ssr: false, ssr: false,
}); });
@ -40,6 +44,16 @@ export default function AuthActions() {
const { currentUser, logout, attemptLogin, initSubscriptions } = const { currentUser, logout, attemptLogin, initSubscriptions } =
useCurrentUser(); useCurrentUser();
const { ndk } = useNDK(); const { ndk } = useNDK();
const friends = useLiveQuery(
async () => {
console.log("Calling", db);
if (!db) return;
const friends = await db.users.count();
return friends;
},
// specify vars that affect query:
[],
);
useKeyboardShortcut(["shift", "ctrl", "u"], () => { useKeyboardShortcut(["shift", "ctrl", "u"], () => {
if (currentUser) { if (currentUser) {
@ -64,6 +78,7 @@ export default function AuthActions() {
<Notifications user={currentUser} /> <Notifications user={currentUser} />
<Relays /> <Relays />
<UserMenu user={currentUser} logout={logout} /> <UserMenu user={currentUser} logout={logout} />
{friends}
</> </>
); );
} }

View File

@ -22,6 +22,7 @@ import { btcToSats, formatNumber } from "@/lib/utils";
import { formatDate } from "@/lib/utils/dates"; import { formatDate } from "@/lib/utils/dates";
import { follow } from "@/lib/actions/create"; import { follow } from "@/lib/actions/create";
import { log } from "@/lib/utils"; import { log } from "@/lib/utils";
const CreateEventModal = dynamic(() => import("@/components/Modals/NewEvent"), { const CreateEventModal = dynamic(() => import("@/components/Modals/NewEvent"), {
ssr: false, ssr: false,
}); });

View File

@ -6,7 +6,10 @@ import NDK, {
NDKNip07Signer, NDKNip07Signer,
NDKNip46Signer, NDKNip46Signer,
NDKPrivateKeySigner, NDKPrivateKeySigner,
type NDKCacheAdapter,
} from "@nostr-dev-kit/ndk"; } from "@nostr-dev-kit/ndk";
import NDKCacheAdapterDexie from "@nostr-dev-kit/ndk-cache-dexie";
import { db } from "@/lib/ndk/db";
export default function NDKInstance(explicitRelayUrls: string[]) { export default function NDKInstance(explicitRelayUrls: string[]) {
const loaded = useRef(false); const loaded = useRef(false);
@ -16,21 +19,62 @@ export default function NDKInstance(explicitRelayUrls: string[]) {
NDKPrivateKeySigner | NDKNip46Signer | NDKNip07Signer | undefined NDKPrivateKeySigner | NDKNip46Signer | NDKNip07Signer | undefined
>(undefined); >(undefined);
// TODO: fully support NIP-11
async function getExplicitRelays() {
try {
// get relays
const relays = explicitRelayUrls;
const onlineRelays = new Set(relays);
for (const relay of relays) {
try {
const url = new URL(relay);
const res = await fetch(`https://${url.hostname}`, {
method: "GET",
headers: {
Accept: "application/nostr+json",
},
});
if (!res.ok) {
console.info(`${relay} is not working, skipping...`);
onlineRelays.delete(relay);
}
} catch {
console.warn(`${relay} is not working, skipping...`);
onlineRelays.delete(relay);
}
}
// return all online relays
return [...onlineRelays];
} catch (e) {
console.error(e);
}
}
useEffect(() => { useEffect(() => {
async function load() { async function load() {
if (ndk === undefined && loaded.current === false) { if (ndk === undefined && loaded.current === false) {
loaded.current = true; loaded.current = true;
await loadNdk(explicitRelayUrls); await loadNdk();
} }
} }
load(); load();
}, []); }, []);
async function loadNdk( async function loadNdk(
explicitRelayUrls: string[],
signer?: NDKPrivateKeySigner | NDKNip46Signer | NDKNip07Signer, signer?: NDKPrivateKeySigner | NDKNip46Signer | NDKNip07Signer,
) { ) {
const ndkInstance = new NDK({ explicitRelayUrls, signer }); const explicitRelayUrls = await getExplicitRelays();
const dexieAdapter = new NDKCacheAdapterDexie({
dbName: "ndkcache",
});
const ndkInstance = new NDK({
explicitRelayUrls,
signer,
cacheAdapter: dexieAdapter as unknown as NDKCacheAdapter,
});
if (process.env.NODE_ENV === "development") { if (process.env.NODE_ENV === "development") {
ndkInstance.pool.on("connect", () => console.log("✅ connected")); ndkInstance.pool.on("connect", () => console.log("✅ connected"));
ndkInstance.pool.on("disconnect", () => console.log("❌ disconnected")); ndkInstance.pool.on("disconnect", () => console.log("❌ disconnected"));
@ -42,6 +86,7 @@ export default function NDKInstance(explicitRelayUrls: string[]) {
try { try {
await ndkInstance.connect(); await ndkInstance.connect();
ndkInstance.signer = signer;
_setNDK(ndkInstance); _setNDK(ndkInstance);
} catch (error) { } catch (error) {
console.error("ERROR loading NDK NDKInstance", error); console.error("ERROR loading NDK NDKInstance", error);
@ -51,7 +96,7 @@ export default function NDKInstance(explicitRelayUrls: string[]) {
async function setSigner( async function setSigner(
signer: NDKPrivateKeySigner | NDKNip46Signer | NDKNip07Signer, signer: NDKPrivateKeySigner | NDKNip46Signer | NDKNip07Signer,
) { ) {
loadNdk(explicitRelayUrls, signer); loadNdk(signer);
} }
async function fetchEvents(filter: NDKFilter): Promise<NDKEvent[]> { async function fetchEvents(filter: NDKFilter): Promise<NDKEvent[]> {

BIN
bun.lockb

Binary file not shown.

View File

@ -7,6 +7,8 @@ import { useNDK } from "@/app/_providers/ndk";
import { nip19 } from "nostr-tools"; import { nip19 } from "nostr-tools";
import useLists from "./useLists"; import useLists from "./useLists";
import useSubscriptions from "./useSubscriptions"; import useSubscriptions from "./useSubscriptions";
import { db } from "@nostr-dev-kit/ndk-cache-dexie";
import { unixTimeNowInSeconds } from "../nostr/dates";
export default function useCurrentUser() { export default function useCurrentUser() {
const { const {
@ -20,6 +22,7 @@ export default function useCurrentUser() {
const { loginWithNip07, getProfile, ndk, fetchEvents } = useNDK(); const { loginWithNip07, getProfile, ndk, fetchEvents } = useNDK();
const { init } = useLists(); const { init } = useLists();
const { init: initSubscriptions, mySubscription } = useSubscriptions(); const { init: initSubscriptions, mySubscription } = useSubscriptions();
async function attemptLogin() { async function attemptLogin() {
try { try {
const shouldReconnect = localStorage.getItem("shouldReconnect"); const shouldReconnect = localStorage.getItem("shouldReconnect");
@ -67,6 +70,12 @@ export default function useCurrentUser() {
const user = ndk.getUser({ hexpubkey: pubkey }); const user = ndk.getUser({ hexpubkey: pubkey });
console.log("user", user); console.log("user", user);
await user.fetchProfile(); await user.fetchProfile();
// await db.users.add({
// profile: user.profile!,
// pubkey: pubkey,
// createdAt: unixTimeNowInSeconds(),
// });
setCurrentUser(user); setCurrentUser(user);
void init(user.pubkey); void init(user.pubkey);
} }
@ -76,6 +85,7 @@ export default function useCurrentUser() {
console.log("fetching follows"); console.log("fetching follows");
(async () => { (async () => {
const following = await currentUser.follows(); const following = await currentUser.follows();
console.log("Follows", following);
setFollows(following); setFollows(following);
})(); })();
}, [currentUser]); }, [currentUser]);

View File

@ -10,17 +10,21 @@ export default function useSubscriptions() {
const { mySubscription, setMySubscription } = subscriptionsStore(); const { mySubscription, setMySubscription } = subscriptionsStore();
const { fetchEvents, ndk } = useNDK(); const { fetchEvents, ndk } = useNDK();
async function init(pubkey: string) { async function init(pubkey: string) {
if (!ndk) {
return "NDK MISING";
}
setIsLoading(true); setIsLoading(true);
try { try {
const subscriptionLists = await fetchEvents({ const subscriptionLists = await fetchEvents({
kinds: [30044 as NDKKind], kinds: [30044 as NDKKind],
authors: [pubkey], authors: [pubkey],
}); });
console.log("Found subscriptionLists", subscriptionLists);
if (subscriptionLists[0]) { if (subscriptionLists[0]) {
setMySubscription(new NDKList(ndk, subscriptionLists[0].rawEvent())); setMySubscription(new NDKList(ndk, subscriptionLists[0].rawEvent()));
} }
} catch (err) { } catch (err) {
console.log("error in init", err); console.log("error in subscriptionLists", err);
} finally { } finally {
setIsLoading(false); setIsLoading(false);
} }

10
lib/ndk/db.ts Normal file
View File

@ -0,0 +1,10 @@
import Dexie from "dexie";
export class MySubClassedDexie extends Dexie {
constructor() {
super("myDatabase");
this.version(1).stores({});
}
}
export const db = new MySubClassedDexie();

View File

@ -14,6 +14,7 @@
"@hookform/resolvers": "^3.3.2", "@hookform/resolvers": "^3.3.2",
"@noble/hashes": "^1.3.2", "@noble/hashes": "^1.3.2",
"@nostr-dev-kit/ndk": "^2.0.0", "@nostr-dev-kit/ndk": "^2.0.0",
"@nostr-dev-kit/ndk-cache-dexie": "^2.0.3",
"@nostr-dev-kit/ndk-react": "^0.1.1", "@nostr-dev-kit/ndk-react": "^0.1.1",
"@radix-ui/react-aspect-ratio": "^1.0.3", "@radix-ui/react-aspect-ratio": "^1.0.3",
"@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-avatar": "^1.0.4",
@ -37,6 +38,8 @@
"crypto": "^1.0.1", "crypto": "^1.0.1",
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"dayjs": "^1.11.10", "dayjs": "^1.11.10",
"dexie": "^3.2.4",
"dexie-react-hooks": "^1.1.6",
"focus-trap-react": "^10.2.3", "focus-trap-react": "^10.2.3",
"framer-motion": "^10.16.4", "framer-motion": "^10.16.4",
"jotai": "^2.4.3", "jotai": "^2.4.3",

View File

@ -1,4 +1,5 @@
import { z } from "zod"; import { z } from "zod";
import { type NDKUserProfile } from "@nostr-dev-kit/ndk";
type User = { type User = {
npub: string; npub: string;
@ -37,6 +38,15 @@ const EventSchema = z.object({
sig: z.string(), sig: z.string(),
}); });
type Account = NDKUserProfile & {
id: string;
pubkey: string;
follows: null | string[];
circles: null | string[];
is_active: number;
last_login_at: number;
};
export { UserSchema, EventSchema }; export { UserSchema, EventSchema };
export type { User }; export type { User, Account };