updated onboarding process use new storage util
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
import { DatabaseContext } from '@components/contexts/database';
|
|
||||||
import { ImageWithFallback } from '@components/imageWithFallback';
|
import { ImageWithFallback } from '@components/imageWithFallback';
|
||||||
|
|
||||||
|
import { createCacheProfile } from '@utils/storage';
|
||||||
import { truncate } from '@utils/truncate';
|
import { truncate } from '@utils/truncate';
|
||||||
|
|
||||||
import { fetch } from '@tauri-apps/api/http';
|
import { fetch } from '@tauri-apps/api/http';
|
||||||
import { memo, useCallback, useContext, useEffect, useState } from 'react';
|
import destr from 'destr';
|
||||||
|
import { memo, useCallback, useEffect, useState } from 'react';
|
||||||
|
|
||||||
export const UserBase = memo(function UserBase({ pubkey }: { pubkey: string }) {
|
export const UserBase = memo(function UserBase({ pubkey }: { pubkey: string }) {
|
||||||
const { db }: any = useContext(DatabaseContext);
|
|
||||||
const [profile, setProfile] = useState(null);
|
const [profile, setProfile] = useState(null);
|
||||||
|
|
||||||
const fetchProfile = useCallback(async (id: string) => {
|
const fetchProfile = useCallback(async (id: string) => {
|
||||||
@@ -15,24 +15,17 @@ export const UserBase = memo(function UserBase({ pubkey }: { pubkey: string }) {
|
|||||||
method: 'GET',
|
method: 'GET',
|
||||||
timeout: 30,
|
timeout: 30,
|
||||||
});
|
});
|
||||||
return res;
|
return res.data;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const cacheProfile = useCallback(
|
|
||||||
async (event) => {
|
|
||||||
// insert to database
|
|
||||||
await db.execute('INSERT OR IGNORE INTO cache_profiles (id, metadata) VALUES (?, ?);', [pubkey, event.content]);
|
|
||||||
// update state
|
|
||||||
setProfile(JSON.parse(event.content));
|
|
||||||
},
|
|
||||||
[db, pubkey]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchProfile(pubkey)
|
fetchProfile(pubkey)
|
||||||
.then((res) => cacheProfile(res))
|
.then((res: any) => {
|
||||||
|
setProfile(destr(res.content));
|
||||||
|
createCacheProfile(res.pubkey, res.content);
|
||||||
|
})
|
||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
}, [fetchProfile, cacheProfile, pubkey]);
|
}, [fetchProfile, pubkey]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -41,7 +34,7 @@ export const UserBase = memo(function UserBase({ pubkey }: { pubkey: string }) {
|
|||||||
<ImageWithFallback src={profile.picture} alt={pubkey} fill={true} className="rounded-full object-cover" />
|
<ImageWithFallback src={profile.picture} alt={pubkey} fill={true} className="rounded-full object-cover" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex w-full flex-1 flex-col items-start">
|
<div className="flex w-full flex-1 flex-col items-start text-start">
|
||||||
<span className="font-medium leading-tight text-zinc-200">{profile?.display_name || profile?.name}</span>
|
<span className="font-medium leading-tight text-zinc-200">{profile?.display_name || profile?.name}</span>
|
||||||
<span className="text-sm leading-tight text-zinc-400">{truncate(pubkey, 16, ' .... ')}</span>
|
<span className="text-sm leading-tight text-zinc-400">{truncate(pubkey, 16, ' .... ')}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
import BaseLayout from '@layouts/base';
|
import BaseLayout from '@layouts/base';
|
||||||
|
|
||||||
import { DatabaseContext } from '@components/contexts/database';
|
import { pool } from '@utils/pool';
|
||||||
import { RelayContext } from '@components/contexts/relay';
|
import { createAccount, getAllRelays } from '@utils/storage';
|
||||||
|
|
||||||
import { EyeClosedIcon, EyeOpenIcon } from '@radix-ui/react-icons';
|
import { EyeClosedIcon, EyeOpenIcon } from '@radix-ui/react-icons';
|
||||||
import { useLocalStorage, writeStorage } from '@rehooks/local-storage';
|
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { generatePrivateKey, getEventHash, getPublicKey, nip19, signEvent } from 'nostr-tools';
|
import { generatePrivateKey, getEventHash, getPublicKey, nip19, signEvent } from 'nostr-tools';
|
||||||
import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useMemo, useState } from 'react';
|
import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useMemo, useState } from 'react';
|
||||||
import { Config, names, uniqueNamesGenerator } from 'unique-names-generator';
|
import { Config, names, uniqueNamesGenerator } from 'unique-names-generator';
|
||||||
|
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
@@ -18,11 +17,6 @@ const config: Config = {
|
|||||||
export default function Page() {
|
export default function Page() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { db }: any = useContext(DatabaseContext);
|
|
||||||
const relayPool: any = useContext(RelayContext);
|
|
||||||
|
|
||||||
const [relays] = useLocalStorage('relays');
|
|
||||||
|
|
||||||
const [type, setType] = useState('password');
|
const [type, setType] = useState('password');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
@@ -33,16 +27,8 @@ export default function Page() {
|
|||||||
const npub = nip19.npubEncode(pubKey);
|
const npub = nip19.npubEncode(pubKey);
|
||||||
const nsec = nip19.nsecEncode(privKey);
|
const nsec = nip19.nsecEncode(privKey);
|
||||||
|
|
||||||
// toggle privatek key
|
// auto-generated profile metadata
|
||||||
const showPrivateKey = () => {
|
const metadata = useMemo(
|
||||||
if (type === 'password') {
|
|
||||||
setType('text');
|
|
||||||
} else {
|
|
||||||
setType('password');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// auto-generated profile
|
|
||||||
const data = useMemo(
|
|
||||||
() => ({
|
() => ({
|
||||||
display_name: name,
|
display_name: name,
|
||||||
name: name,
|
name: name,
|
||||||
@@ -52,23 +38,35 @@ export default function Page() {
|
|||||||
}),
|
}),
|
||||||
[name]
|
[name]
|
||||||
);
|
);
|
||||||
// insert to database
|
|
||||||
const insertDB = async () => {
|
// build profile
|
||||||
await db.execute('INSERT OR IGNORE INTO accounts (id, privkey, npub, nsec, metadata) VALUES (?, ?, ?, ?, ?)', [
|
const data = useMemo(
|
||||||
pubKey,
|
() => ({
|
||||||
privKey,
|
pubkey: pubKey,
|
||||||
npub,
|
privkey: privKey,
|
||||||
nsec,
|
npub: npub,
|
||||||
data,
|
nsec: nsec,
|
||||||
]);
|
metadata: metadata,
|
||||||
|
}),
|
||||||
|
[metadata, npub, nsec, privKey, pubKey]
|
||||||
|
);
|
||||||
|
|
||||||
|
// toggle privatek key
|
||||||
|
const showPrivateKey = () => {
|
||||||
|
if (type === 'password') {
|
||||||
|
setType('text');
|
||||||
|
} else {
|
||||||
|
setType('password');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// build event and broadcast to all relays
|
|
||||||
const createAccount = () => {
|
// create account and broadcast to all relays
|
||||||
|
const submit = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
// build event
|
// build event
|
||||||
const event: any = {
|
const event: any = {
|
||||||
content: JSON.stringify(data),
|
content: JSON.stringify(metadata),
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
kind: 0,
|
kind: 0,
|
||||||
pubkey: pubKey,
|
pubkey: pubKey,
|
||||||
@@ -76,23 +74,20 @@ export default function Page() {
|
|||||||
};
|
};
|
||||||
event.id = getEventHash(event);
|
event.id = getEventHash(event);
|
||||||
event.sig = signEvent(event, privKey);
|
event.sig = signEvent(event, privKey);
|
||||||
|
|
||||||
// insert to database then broadcast
|
// insert to database then broadcast
|
||||||
insertDB()
|
createAccount(data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
getAllRelays()
|
||||||
|
.then((res) => {
|
||||||
// publish to relays
|
// publish to relays
|
||||||
relayPool.publish(event, relays);
|
pool(res).publish(event, res);
|
||||||
// set currentUser in global state
|
router.push({
|
||||||
writeStorage('current-user', {
|
pathname: '/onboarding/create/step-2',
|
||||||
metadata: JSON.stringify(data),
|
query: { id: pubKey, privkey: privKey },
|
||||||
npub: npub,
|
|
||||||
privkey: privKey,
|
|
||||||
id: pubKey,
|
|
||||||
});
|
});
|
||||||
// redirect to pre-follow
|
})
|
||||||
setTimeout(() => {
|
.catch(console.error);
|
||||||
setLoading(false);
|
|
||||||
router.push('/onboarding/create/step-2');
|
|
||||||
}, 1500);
|
|
||||||
})
|
})
|
||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
};
|
};
|
||||||
@@ -146,12 +141,12 @@ export default function Page() {
|
|||||||
<div className="relative w-full rounded-lg border border-black/5 px-3.5 py-4 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-600">
|
<div className="relative w-full rounded-lg border border-black/5 px-3.5 py-4 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-600">
|
||||||
<div className="flex space-x-4">
|
<div className="flex space-x-4">
|
||||||
<div className="relative h-10 w-10 rounded-full">
|
<div className="relative h-10 w-10 rounded-full">
|
||||||
<Image className="inline-block rounded-full" src={data.picture} alt="" fill={true} />
|
<Image className="inline-block rounded-full" src={metadata.picture} alt="" fill={true} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 space-y-4 py-1">
|
<div className="flex-1 space-y-4 py-1">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<p className="font-semibold">{data.display_name}</p>
|
<p className="font-semibold">{metadata.display_name}</p>
|
||||||
<p className="text-zinc-400">@{data.username}</p>
|
<p className="text-zinc-400">@{metadata.username}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="grid grid-cols-3 gap-4">
|
||||||
@@ -183,7 +178,7 @@ export default function Page() {
|
|||||||
</svg>
|
</svg>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
onClick={() => createAccount()}
|
onClick={() => submit()}
|
||||||
className="w-full transform rounded-lg bg-gradient-to-r from-fuchsia-300 via-orange-100 to-amber-300 px-3.5 py-2.5 font-medium text-zinc-800 active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-30"
|
className="w-full transform rounded-lg bg-gradient-to-r from-fuchsia-300 via-orange-100 to-amber-300 px-3.5 py-2.5 font-medium text-zinc-800 active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-30"
|
||||||
>
|
>
|
||||||
<span className="drop-shadow-lg">Continue →</span>
|
<span className="drop-shadow-lg">Continue →</span>
|
||||||
|
|||||||
@@ -1,24 +1,15 @@
|
|||||||
import BaseLayout from '@layouts/base';
|
import BaseLayout from '@layouts/base';
|
||||||
|
|
||||||
import { DatabaseContext } from '@components/contexts/database';
|
|
||||||
import { RelayContext } from '@components/contexts/relay';
|
|
||||||
import { UserBase } from '@components/user/base';
|
import { UserBase } from '@components/user/base';
|
||||||
|
|
||||||
|
import { pool } from '@utils/pool';
|
||||||
|
import { createFollows, getAllRelays } from '@utils/storage';
|
||||||
|
|
||||||
import { CheckCircledIcon } from '@radix-ui/react-icons';
|
import { CheckCircledIcon } from '@radix-ui/react-icons';
|
||||||
import useLocalStorage from '@rehooks/local-storage';
|
|
||||||
import { createClient } from '@supabase/supabase-js';
|
import { createClient } from '@supabase/supabase-js';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { getEventHash, nip19, signEvent } from 'nostr-tools';
|
import { getEventHash, signEvent } from 'nostr-tools';
|
||||||
import {
|
import { JSXElementConstructor, Key, ReactElement, ReactFragment, ReactPortal, useEffect, useState } from 'react';
|
||||||
JSXElementConstructor,
|
|
||||||
Key,
|
|
||||||
ReactElement,
|
|
||||||
ReactFragment,
|
|
||||||
ReactPortal,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useState,
|
|
||||||
} from 'react';
|
|
||||||
|
|
||||||
const supabase = createClient(
|
const supabase = createClient(
|
||||||
'https://niwaazauwnrwiwmnocnn.supabase.co',
|
'https://niwaazauwnrwiwmnocnn.supabase.co',
|
||||||
@@ -62,12 +53,7 @@ const initialList = [
|
|||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { id, privkey }: any = router.query;
|
||||||
const { db }: any = useContext(DatabaseContext);
|
|
||||||
const relayPool: any = useContext(RelayContext);
|
|
||||||
|
|
||||||
const [currentUser]: any = useLocalStorage('current-user');
|
|
||||||
const [relays] = useLocalStorage('relays');
|
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [list, setList]: any = useState(initialList);
|
const [list, setList]: any = useState(initialList);
|
||||||
@@ -78,31 +64,19 @@ export default function Page() {
|
|||||||
const arr = follows.includes(pubkey) ? follows.filter((i) => i !== pubkey) : [...follows, pubkey];
|
const arr = follows.includes(pubkey) ? follows.filter((i) => i !== pubkey) : [...follows, pubkey];
|
||||||
setFollows(arr);
|
setFollows(arr);
|
||||||
};
|
};
|
||||||
// insert follow to database
|
|
||||||
const insertDB = async () => {
|
|
||||||
// self follow
|
|
||||||
await db.execute(
|
|
||||||
`INSERT OR IGNORE INTO follows (pubkey, account, kind) VALUES ("${currentUser.id}", "${currentUser.id}", "0")`
|
|
||||||
);
|
|
||||||
// follow selected
|
|
||||||
follows.forEach(async (pubkey) => {
|
|
||||||
await db.execute(
|
|
||||||
`INSERT OR IGNORE INTO follows (pubkey, account, kind) VALUES ("${pubkey}", "${currentUser.id}", "0")`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// build event tags
|
// build event tags
|
||||||
const createTags = () => {
|
const tags = () => {
|
||||||
const tags = [];
|
const arr = [];
|
||||||
// push item to tags
|
// push item to tags
|
||||||
follows.forEach((item) => {
|
follows.forEach((item) => {
|
||||||
tags.push(['p', item]);
|
arr.push(['p', item]);
|
||||||
});
|
});
|
||||||
|
return arr;
|
||||||
return tags;
|
|
||||||
};
|
};
|
||||||
// commit and publish to relays
|
|
||||||
const createFollows = () => {
|
// save follows to database then broadcast
|
||||||
|
const submit = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
// build event
|
// build event
|
||||||
@@ -110,21 +84,25 @@ export default function Page() {
|
|||||||
content: '',
|
content: '',
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
kind: 3,
|
kind: 3,
|
||||||
pubkey: currentUser.id,
|
pubkey: id,
|
||||||
tags: createTags(),
|
tags: tags(),
|
||||||
};
|
};
|
||||||
event.id = getEventHash(event);
|
event.id = getEventHash(event);
|
||||||
event.sig = signEvent(event, currentUser.privkey);
|
event.sig = signEvent(event, privkey);
|
||||||
|
|
||||||
insertDB().then(() => {
|
createFollows(follows, id, 0)
|
||||||
|
.then((res) => {
|
||||||
|
if (res === 'ok') {
|
||||||
|
getAllRelays()
|
||||||
|
.then((res) => {
|
||||||
// publish to relays
|
// publish to relays
|
||||||
relayPool.publish(event, relays);
|
pool(res).publish(event, res);
|
||||||
// redirect to home
|
|
||||||
setTimeout(() => {
|
|
||||||
setLoading(false);
|
|
||||||
router.push('/');
|
router.push('/');
|
||||||
}, 1000);
|
})
|
||||||
});
|
.catch(console.error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -174,7 +152,7 @@ export default function Page() {
|
|||||||
{follows.length >= 10 && (
|
{follows.length >= 10 && (
|
||||||
<div className="fixed bottom-0 left-0 z-10 flex h-24 w-full items-center justify-center">
|
<div className="fixed bottom-0 left-0 z-10 flex h-24 w-full items-center justify-center">
|
||||||
<button
|
<button
|
||||||
onClick={() => createFollows()}
|
onClick={() => submit()}
|
||||||
className="relative z-20 inline-flex w-36 transform items-center justify-center rounded-full bg-gradient-to-r from-fuchsia-300 via-orange-100 to-amber-300 px-3.5 py-2.5 font-medium text-zinc-800 shadow-xl active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-30"
|
className="relative z-20 inline-flex w-36 transform items-center justify-center rounded-full bg-gradient-to-r from-fuchsia-300 via-orange-100 to-amber-300 px-3.5 py-2.5 font-medium text-zinc-800 shadow-xl active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-30"
|
||||||
>
|
>
|
||||||
{loading === true ? (
|
{loading === true ? (
|
||||||
|
|||||||
@@ -1,77 +1,35 @@
|
|||||||
import BaseLayout from '@layouts/base';
|
import BaseLayout from '@layouts/base';
|
||||||
|
|
||||||
import { DatabaseContext } from '@components/contexts/database';
|
import { pool } from '@utils/pool';
|
||||||
import { RelayContext } from '@components/contexts/relay';
|
import { createAccount, createFollows, getAllRelays } from '@utils/storage';
|
||||||
|
import { truncate } from '@utils/truncate';
|
||||||
|
|
||||||
import { useLocalStorage, writeStorage } from '@rehooks/local-storage';
|
import destr from 'destr';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { getPublicKey, nip19 } from 'nostr-tools';
|
import { getPublicKey, nip19 } from 'nostr-tools';
|
||||||
import {
|
import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useEffect, useState } from 'react';
|
||||||
JSXElementConstructor,
|
|
||||||
ReactElement,
|
|
||||||
ReactFragment,
|
|
||||||
ReactPortal,
|
|
||||||
useCallback,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useState,
|
|
||||||
} from 'react';
|
|
||||||
|
|
||||||
export default function Page() {
|
const tags = (arr) => {
|
||||||
const { db }: any = useContext(DatabaseContext);
|
const newarr = [];
|
||||||
const relayPool: any = useContext(RelayContext);
|
// push item to newarr
|
||||||
|
arr.forEach((item) => {
|
||||||
const router = useRouter();
|
newarr.push(['p', item]);
|
||||||
const { privkey }: any = router.query;
|
|
||||||
|
|
||||||
const [relays] = useLocalStorage('relays');
|
|
||||||
const [profile, setProfile] = useState({ picture: '', display_name: '', username: '' });
|
|
||||||
|
|
||||||
const pubkey = useMemo(() => (privkey ? getPublicKey(privkey) : null), [privkey]);
|
|
||||||
|
|
||||||
// save account to database
|
|
||||||
const insertAccount = useCallback(
|
|
||||||
async (metadata) => {
|
|
||||||
const npub = privkey ? nip19.npubEncode(pubkey) : null;
|
|
||||||
const nsec = privkey ? nip19.nsecEncode(privkey) : null;
|
|
||||||
// insert to database
|
|
||||||
await db.execute('INSERT OR IGNORE INTO accounts (id, privkey, npub, nsec, metadata) VALUES (?, ?, ?, ?, ?)', [
|
|
||||||
pubkey,
|
|
||||||
privkey,
|
|
||||||
npub,
|
|
||||||
nsec,
|
|
||||||
metadata,
|
|
||||||
]);
|
|
||||||
// write to localstorage
|
|
||||||
writeStorage('current-user', { id: pubkey, privkey: privkey, npub: npub, nsec: nsec, metadata: metadata });
|
|
||||||
// update state
|
|
||||||
setProfile(JSON.parse(metadata));
|
|
||||||
},
|
|
||||||
[db, privkey, pubkey]
|
|
||||||
);
|
|
||||||
// save follows to database
|
|
||||||
const insertFollows = useCallback(
|
|
||||||
async (follows) => {
|
|
||||||
follows.forEach(async (item) => {
|
|
||||||
if (item) {
|
|
||||||
// insert to database
|
|
||||||
await db.execute(
|
|
||||||
`INSERT OR IGNORE INTO follows (pubkey, account, kind) VALUES ("${item[1]}", "${pubkey}", "0")`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
return newarr;
|
||||||
[db, pubkey]
|
|
||||||
);
|
|
||||||
// submit then redirect to home
|
|
||||||
const submit = () => {
|
|
||||||
router.push('/');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
const router = useRouter();
|
||||||
|
const privkey: any = router.query.privkey;
|
||||||
|
const pubkey = getPublicKey(privkey);
|
||||||
|
|
||||||
|
const [profile, setProfile] = useState(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribe = relayPool.subscribe(
|
getAllRelays()
|
||||||
|
.then((res) => {
|
||||||
|
pool(res).subscribe(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
authors: [pubkey],
|
authors: [pubkey],
|
||||||
@@ -79,26 +37,38 @@ export default function Page() {
|
|||||||
since: 0,
|
since: 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
relays,
|
res,
|
||||||
(event: any) => {
|
(event: any) => {
|
||||||
if (event.kind === 0) {
|
if (event.kind === 0) {
|
||||||
insertAccount(event.content);
|
const data = {
|
||||||
|
pubkey: pubkey,
|
||||||
|
privkey: privkey,
|
||||||
|
npub: nip19.npubEncode(pubkey),
|
||||||
|
nsec: nip19.nsecEncode(privkey),
|
||||||
|
metadata: event.content,
|
||||||
|
};
|
||||||
|
setProfile(destr(event.content));
|
||||||
|
createAccount(data);
|
||||||
} else {
|
} else {
|
||||||
if (event.tags.length > 0) {
|
if (event.tags.length > 0) {
|
||||||
insertFollows(event.tags);
|
createFollows(tags(event.tags), pubkey, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
undefined,
|
undefined,
|
||||||
(events: any, relayURL: any) => {
|
undefined,
|
||||||
console.log(events, relayURL);
|
{
|
||||||
|
unsubscribeOnEose: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
}, [privkey, pubkey]);
|
||||||
|
|
||||||
return () => {
|
// submit then redirect to home
|
||||||
unsubscribe();
|
const submit = () => {
|
||||||
|
router.push('/');
|
||||||
};
|
};
|
||||||
}, [insertAccount, insertFollows, pubkey, relayPool, relays]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid h-full w-full grid-rows-5">
|
<div className="grid h-full w-full grid-rows-5">
|
||||||
@@ -115,13 +85,13 @@ export default function Page() {
|
|||||||
<div className="w-full rounded-lg bg-zinc-900 p-4 shadow-input ring-1 ring-zinc-800">
|
<div className="w-full rounded-lg bg-zinc-900 p-4 shadow-input ring-1 ring-zinc-800">
|
||||||
<div className="flex space-x-4">
|
<div className="flex space-x-4">
|
||||||
<div className="relative h-10 w-10 rounded-full">
|
<div className="relative h-10 w-10 rounded-full">
|
||||||
<Image className="inline-block rounded-full" src={profile.picture} alt="" fill={true} />
|
<Image className="inline-block rounded-full" src={profile?.picture} alt="" fill={true} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 space-y-4 py-1">
|
<div className="flex-1 space-y-4 py-1">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<p className="font-semibold">{profile.display_name}</p>
|
<p className="font-semibold">{profile?.display_name || profile?.name}</p>
|
||||||
<span className="leading-tight text-zinc-500">·</span>
|
<span className="leading-tight text-zinc-500">·</span>
|
||||||
<p className="text-zinc-500">@{profile.username}</p>
|
<p className="text-zinc-500">@{profile?.username || truncate(pubkey, 16, ' .... ')}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="grid grid-cols-3 gap-4">
|
||||||
|
|||||||
6
src/utils/pool.tsx
Normal file
6
src/utils/pool.tsx
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { RelayPool } from 'nostr-relaypool';
|
||||||
|
|
||||||
|
export function pool({ relays }: { relays: any }) {
|
||||||
|
const createPool = new RelayPool(relays, { useEventCache: false, logSubscriptions: false });
|
||||||
|
return createPool;
|
||||||
|
}
|
||||||
@@ -15,17 +15,59 @@ export async function connect(): Promise<Database> {
|
|||||||
// get all relays
|
// get all relays
|
||||||
export async function getAllRelays() {
|
export async function getAllRelays() {
|
||||||
const db = await connect();
|
const db = await connect();
|
||||||
return await db.select('SELECT relay_url FROM relays WHERE relay_status = "1"');
|
const result: any = await db.select('SELECT relay_url FROM relays WHERE relay_status = "1";');
|
||||||
|
return result.reduce((relays, { relay_url }) => {
|
||||||
|
relays.push(relay_url);
|
||||||
|
return relays;
|
||||||
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get active account
|
// get active account
|
||||||
export async function getActiveAccount() {
|
export async function getActiveAccount() {
|
||||||
const db = await connect();
|
const db = await connect();
|
||||||
return await db.select(`SELECT * FROM accounts LIMIT 1`);
|
return await db.select(`SELECT * FROM accounts LIMIT 1;`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get all follows by account id
|
// get all follows by account id
|
||||||
export async function getAllFollowsByID(id: string) {
|
export async function getAllFollowsByID(id) {
|
||||||
const db = await connect();
|
const db = await connect();
|
||||||
return await db.select(`SELECT pubkey FROM follows WHERE account = "${id}"`);
|
return await db.select(`SELECT pubkey FROM follows WHERE account = "${id}";`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create account
|
||||||
|
export async function createAccount(data) {
|
||||||
|
const db = await connect();
|
||||||
|
return await db.execute(
|
||||||
|
'INSERT OR IGNORE INTO accounts (id, privkey, npub, nsec, metadata) VALUES (?, ?, ?, ?, ?);',
|
||||||
|
[data.pubkey, data.privkey, data.npub, data.nsec, data.metadata]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create follow
|
||||||
|
export async function createFollow(pubkey, account, kind) {
|
||||||
|
const db = await connect();
|
||||||
|
return await db.execute('INSERT OR IGNORE INTO follows (pubkey, account, kind) VALUES (?, ?, ?);', [
|
||||||
|
pubkey,
|
||||||
|
account,
|
||||||
|
kind || 0,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create follow
|
||||||
|
export async function createFollows(data, account, kind) {
|
||||||
|
const db = await connect();
|
||||||
|
data.forEach(async (item) => {
|
||||||
|
await db.execute('INSERT OR IGNORE INTO follows (pubkey, account, kind) VALUES (?, ?, ?);', [
|
||||||
|
item,
|
||||||
|
account,
|
||||||
|
kind || 0,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
return 'ok';
|
||||||
|
}
|
||||||
|
|
||||||
|
// create cache profile
|
||||||
|
export async function createCacheProfile(id, metadata) {
|
||||||
|
const db = await connect();
|
||||||
|
return await db.execute('INSERT OR IGNORE INTO cache_profiles (id, metadata) VALUES (?, ?);', [id, metadata]);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user