mirror of
https://github.com/lumehq/lume.git
synced 2025-03-28 18:52:33 +01:00
[tauri-sql] updated onboarding pages
This commit is contained in:
parent
075fbcf507
commit
fc1101f97b
@ -4,7 +4,8 @@ import { RelayContext } from '@components/relaysProvider';
|
|||||||
import { UserBase } from '@components/user/base';
|
import { UserBase } from '@components/user/base';
|
||||||
|
|
||||||
import { fetchProfileMetadata } from '@utils/hooks/useProfileMetadata';
|
import { fetchProfileMetadata } from '@utils/hooks/useProfileMetadata';
|
||||||
import { followsTag } from '@utils/transform';
|
import { createPleb, updateAccount } from '@utils/storage';
|
||||||
|
import { arrayToNIP02 } from '@utils/transform';
|
||||||
|
|
||||||
import { createClient } from '@supabase/supabase-js';
|
import { createClient } from '@supabase/supabase-js';
|
||||||
import { CheckCircle } from 'iconoir-react';
|
import { CheckCircle } from 'iconoir-react';
|
||||||
@ -52,10 +53,13 @@ const initialList = [
|
|||||||
{ pubkey: 'ff04a0e6cd80c141b0b55825fed127d4532a6eecdb7e743a38a3c28bf9f44609' },
|
{ pubkey: 'ff04a0e6cd80c141b0b55825fed127d4532a6eecdb7e743a38a3c28bf9f44609' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function Page({ params }: { params: { id: string; pubkey: string; privkey: string } }) {
|
export default function Page({ params }: { params: { slug: string } }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [pool, relays]: any = useContext(RelayContext);
|
|
||||||
|
|
||||||
|
const pubkey = params.slug[0];
|
||||||
|
const privkey = params.slug[1];
|
||||||
|
|
||||||
|
const [pool, relays]: any = useContext(RelayContext);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [list, setList]: any = useState(initialList);
|
const [list, setList]: any = useState(initialList);
|
||||||
const [follows, setFollows] = useState([]);
|
const [follows, setFollows] = useState([]);
|
||||||
@ -68,18 +72,17 @@ export default function Page({ params }: { params: { id: string; pubkey: string;
|
|||||||
|
|
||||||
// save follows to database then broadcast
|
// save follows to database then broadcast
|
||||||
const submit = useCallback(async () => {
|
const submit = useCallback(async () => {
|
||||||
const { createPleb } = await import('@utils/bindings');
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
const nip02 = arrayToNIP02(follows);
|
||||||
|
|
||||||
for (const follow of follows) {
|
// update account's folllows with nip03 tag list
|
||||||
const metadata: any = await fetchProfileMetadata(follow);
|
updateAccount('follows', nip02, pubkey);
|
||||||
createPleb({
|
|
||||||
pleb_id: follow + '-lume' + params.id,
|
// create pleb
|
||||||
pubkey: follow,
|
for (const tag of follows) {
|
||||||
kind: 0,
|
fetchProfileMetadata(tag)
|
||||||
metadata: metadata.content,
|
.then((res: any) => createPleb(tag, res.content))
|
||||||
account_id: parseInt(params.id),
|
.catch(console.error);
|
||||||
}).catch(console.error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// build event
|
// build event
|
||||||
@ -87,15 +90,17 @@ export default function Page({ params }: { params: { id: string; pubkey: string;
|
|||||||
content: '',
|
content: '',
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
kind: 3,
|
kind: 3,
|
||||||
pubkey: params.pubkey,
|
pubkey: pubkey,
|
||||||
tags: followsTag(follows),
|
tags: nip02,
|
||||||
};
|
};
|
||||||
|
console.log(event);
|
||||||
event.id = getEventHash(event);
|
event.id = getEventHash(event);
|
||||||
event.sig = signEvent(event, params.privkey);
|
event.sig = signEvent(event, privkey);
|
||||||
|
// broadcast
|
||||||
pool.publish(event, relays);
|
pool.publish(event, relays);
|
||||||
|
// redirect to splashscreen
|
||||||
router.replace('/');
|
router.replace('/');
|
||||||
}, [params.pubkey, params.privkey, params.id, follows, pool, relays, router]);
|
}, [pubkey, privkey, follows, pool, relays, router]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
import { RelayContext } from '@components/relaysProvider';
|
import { RelayContext } from '@components/relaysProvider';
|
||||||
|
|
||||||
import { ArrowLeft, EyeClose, EyeEmpty } from 'iconoir-react';
|
import { createAccount } from '@utils/storage';
|
||||||
|
|
||||||
|
import { EyeClose, EyeEmpty } from 'iconoir-react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { generatePrivateKey, getEventHash, getPublicKey, nip19, signEvent } from 'nostr-tools';
|
import { generatePrivateKey, getEventHash, getPublicKey, nip19, signEvent } from 'nostr-tools';
|
||||||
@ -20,16 +22,12 @@ export default function Page() {
|
|||||||
const [type, setType] = useState('password');
|
const [type, setType] = useState('password');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const [privKey] = useState(() => generatePrivateKey());
|
const privkey = useMemo(() => generatePrivateKey(), []);
|
||||||
const [name] = useState(() => uniqueNamesGenerator(config).toString());
|
const name = useMemo(() => uniqueNamesGenerator(config).toString(), []);
|
||||||
|
|
||||||
const pubKey = getPublicKey(privKey);
|
const pubkey = getPublicKey(privkey);
|
||||||
const npub = nip19.npubEncode(pubKey);
|
const npub = nip19.npubEncode(pubkey);
|
||||||
const nsec = nip19.nsecEncode(privKey);
|
const nsec = nip19.nsecEncode(privkey);
|
||||||
|
|
||||||
const goBack = () => {
|
|
||||||
router.back();
|
|
||||||
};
|
|
||||||
|
|
||||||
// auto-generated profile metadata
|
// auto-generated profile metadata
|
||||||
const metadata: any = useMemo(
|
const metadata: any = useMemo(
|
||||||
@ -53,7 +51,6 @@ export default function Page() {
|
|||||||
|
|
||||||
// create account and broadcast to all relays
|
// create account and broadcast to all relays
|
||||||
const submit = useCallback(async () => {
|
const submit = useCallback(async () => {
|
||||||
const { createAccount } = await import('@utils/bindings');
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
// build event
|
// build event
|
||||||
@ -61,36 +58,25 @@ export default function Page() {
|
|||||||
content: JSON.stringify(metadata),
|
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,
|
||||||
tags: [],
|
tags: [],
|
||||||
};
|
};
|
||||||
event.id = getEventHash(event);
|
event.id = getEventHash(event);
|
||||||
event.sig = signEvent(event, privKey);
|
event.sig = signEvent(event, privkey);
|
||||||
|
// insert to database
|
||||||
// insert to database then broadcast
|
createAccount(pubkey, privkey, metadata);
|
||||||
createAccount({ pubkey: pubKey, privkey: privKey, metadata: metadata })
|
// broadcast
|
||||||
.then((res) => {
|
pool.publish(event, relays);
|
||||||
pool.publish(event, relays);
|
// redirect to next step
|
||||||
router.push(`/onboarding/create/${res.id}/${res.pubkey}/${res.privkey}`);
|
router.push(`/onboarding/create/${pubkey}/${privkey}`);
|
||||||
})
|
}, [pool, pubkey, privkey, metadata, relays, router]);
|
||||||
.catch(console.error);
|
|
||||||
}, [pool, pubKey, privKey, metadata, relays, router]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid h-full w-full grid-rows-5">
|
<div className="grid h-full w-full grid-rows-5">
|
||||||
<div className="row-span-1 mx-auto flex w-full max-w-md items-center justify-between">
|
<div className="row-span-1 mx-auto flex w-full max-w-md items-center justify-center">
|
||||||
<button
|
<h1 className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
|
||||||
onClick={() => goBack()}
|
Create new account
|
||||||
className="group inline-flex h-6 w-6 items-center justify-center rounded-md hover:bg-zinc-900"
|
</h1>
|
||||||
>
|
|
||||||
<ArrowLeft width={16} height={16} className="text-zinc-500 group-hover:text-zinc-300" />
|
|
||||||
</button>
|
|
||||||
<div>
|
|
||||||
<h1 className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
|
|
||||||
Create new account
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="row-span-4">
|
<div className="row-span-4">
|
||||||
<div className="mx-auto w-full max-w-md">
|
<div className="mx-auto w-full max-w-md">
|
||||||
|
@ -6,81 +6,72 @@ import { DEFAULT_AVATAR } from '@stores/constants';
|
|||||||
|
|
||||||
import { fetchProfileMetadata } from '@utils/hooks/useProfileMetadata';
|
import { fetchProfileMetadata } from '@utils/hooks/useProfileMetadata';
|
||||||
import { shortenKey } from '@utils/shortenKey';
|
import { shortenKey } from '@utils/shortenKey';
|
||||||
|
import { createAccount, createPleb } from '@utils/storage';
|
||||||
|
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { getPublicKey } from 'nostr-tools';
|
import { getPublicKey } from 'nostr-tools';
|
||||||
import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
|
||||||
export default function Page({ params }: { params: { privkey: string } }) {
|
export default function Page({ params }: { params: { privkey: string } }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const [pool, relays]: any = useContext(RelayContext);
|
const [pool, relays]: any = useContext(RelayContext);
|
||||||
|
|
||||||
const pubkey = useMemo(() => (params.privkey ? getPublicKey(params.privkey) : null), [params.privkey]);
|
const pubkey = useMemo(() => (params.privkey ? getPublicKey(params.privkey) : null), [params.privkey]);
|
||||||
|
const eose = useRef(0);
|
||||||
|
|
||||||
const [profile, setProfile] = useState({ id: null, metadata: null });
|
const [profile, setProfile] = useState({ metadata: null });
|
||||||
const [done, setDone] = useState(false);
|
const [done, setDone] = useState(false);
|
||||||
|
|
||||||
const insertAccountToStorage = useCallback(async (pubkey, privkey, metadata) => {
|
const createPlebs = useCallback(async (tags: string[]) => {
|
||||||
const { createAccount } = await import('@utils/bindings');
|
for (const tag of tags) {
|
||||||
createAccount({ pubkey: pubkey, privkey: privkey, metadata: metadata })
|
fetchProfileMetadata(tag[1])
|
||||||
.then((res) =>
|
.then((res: any) => createPleb(tag[1], res))
|
||||||
setProfile({
|
.catch(console.error);
|
||||||
id: res.id,
|
}
|
||||||
metadata: JSON.parse(res.metadata),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.catch(console.error);
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const insertFollowsToStorage = useCallback(
|
|
||||||
async (tags) => {
|
|
||||||
const { createPleb } = await import('@utils/bindings');
|
|
||||||
if (profile?.id !== null) {
|
|
||||||
for (const tag of tags) {
|
|
||||||
const metadata: any = await fetchProfileMetadata(tag[1]);
|
|
||||||
createPleb({
|
|
||||||
pleb_id: tag[1] + '-lume' + profile.id.toString(),
|
|
||||||
pubkey: tag[1],
|
|
||||||
kind: 0,
|
|
||||||
metadata: metadata.content,
|
|
||||||
account_id: profile.id,
|
|
||||||
}).catch(console.error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[profile.id]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribe = pool.subscribe(
|
const unsubscribe = pool.subscribe(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
authors: [pubkey],
|
authors: [pubkey],
|
||||||
kinds: [0, 3],
|
kinds: [0, 3],
|
||||||
since: 0,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
relays,
|
relays,
|
||||||
(event: any) => {
|
(event: any) => {
|
||||||
if (event.kind === 0) {
|
if (event.kind === 0) {
|
||||||
insertAccountToStorage(pubkey, params.privkey, event.content);
|
// create account
|
||||||
|
createAccount(pubkey, params.privkey, event.content);
|
||||||
|
// update state
|
||||||
|
setProfile({
|
||||||
|
metadata: JSON.parse(event.metadata),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
if (event.tags.length > 0) {
|
if (event.tags.length > 0) {
|
||||||
insertFollowsToStorage(event.tags);
|
createPlebs(event.tags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
undefined,
|
undefined,
|
||||||
() => {
|
() => {
|
||||||
setDone(true);
|
if (eose.current > 5) {
|
||||||
|
setDone(true);
|
||||||
|
} else {
|
||||||
|
eose.current += 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
unsubscribeOnEose: true,
|
||||||
|
logAllEvents: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
unsubscribe;
|
unsubscribe;
|
||||||
};
|
};
|
||||||
}, [insertAccountToStorage, insertFollowsToStorage, pool, relays, pubkey, params.privkey]);
|
}, [pool, relays, pubkey, params.privkey, createPlebs]);
|
||||||
|
|
||||||
// submit then redirect to home
|
// submit then redirect to home
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
@ -90,11 +81,9 @@ export default function Page({ params }: { params: { privkey: string } }) {
|
|||||||
return (
|
return (
|
||||||
<div className="grid h-full w-full grid-rows-5">
|
<div className="grid h-full w-full grid-rows-5">
|
||||||
<div className="row-span-1 flex items-center justify-center">
|
<div className="row-span-1 flex items-center justify-center">
|
||||||
<div>
|
<h1 className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
|
||||||
<h1 className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
|
Bringing back your profile...
|
||||||
Bringing back your profile...
|
</h1>
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="row-span-4 flex flex-col gap-8">
|
<div className="row-span-4 flex flex-col gap-8">
|
||||||
<div className="mx-auto w-full max-w-md">
|
<div className="mx-auto w-full max-w-md">
|
@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { ArrowLeft, CableTag } from 'iconoir-react';
|
import { CableTag } from 'iconoir-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { nip19 } from 'nostr-tools';
|
import { nip19 } from 'nostr-tools';
|
||||||
import { Resolver, useForm } from 'react-hook-form';
|
import { Resolver, useForm } from 'react-hook-form';
|
||||||
@ -32,10 +32,6 @@ export default function Page() {
|
|||||||
formState: { errors, isDirty, isValid, isSubmitting },
|
formState: { errors, isDirty, isValid, isSubmitting },
|
||||||
} = useForm<FormValues>({ resolver });
|
} = useForm<FormValues>({ resolver });
|
||||||
|
|
||||||
const goBack = () => {
|
|
||||||
router.back();
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSubmit = async (data: any) => {
|
const onSubmit = async (data: any) => {
|
||||||
let privkey = data['key'];
|
let privkey = data['key'];
|
||||||
|
|
||||||
@ -55,19 +51,10 @@ export default function Page() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid h-full w-full grid-rows-5">
|
<div className="grid h-full w-full grid-rows-5">
|
||||||
<div className="row-span-1 mx-auto flex w-full max-w-md items-center justify-between">
|
<div className="row-span-1 mx-auto flex w-full max-w-md items-center justify-center">
|
||||||
<button
|
<h1 className="bg-gradient-to-br from-zinc-200 via-white to-zinc-300 bg-clip-text text-3xl font-semibold text-transparent">
|
||||||
onClick={() => goBack()}
|
Login with Private Key
|
||||||
className="group inline-flex h-6 w-6 items-center justify-center rounded-md hover:bg-zinc-900"
|
</h1>
|
||||||
>
|
|
||||||
<ArrowLeft width={16} height={16} className="text-zinc-500 group-hover:text-zinc-300" />
|
|
||||||
</button>
|
|
||||||
<div>
|
|
||||||
<h1 className="bg-gradient-to-br from-zinc-200 via-white to-zinc-300 bg-clip-text text-3xl font-semibold text-transparent">
|
|
||||||
Login with Private Key
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
</div>
|
||||||
<form onSubmit={handleSubmit(onSubmit)} className="row-span-4">
|
<form onSubmit={handleSubmit(onSubmit)} className="row-span-4">
|
||||||
<div className="mx-auto w-full max-w-md">
|
<div className="mx-auto w-full max-w-md">
|
||||||
|
@ -15,7 +15,7 @@ const relays = [
|
|||||||
'wss://offchain.pub',
|
'wss://offchain.pub',
|
||||||
'wss://relay.current.fyi',
|
'wss://relay.current.fyi',
|
||||||
'wss://nostr.bitcoiner.social',
|
'wss://nostr.bitcoiner.social',
|
||||||
'wss://relay.nostr.info',
|
//'wss://relay.nostr.info',
|
||||||
'wss://nostr-01.dorafactory.org',
|
'wss://nostr-01.dorafactory.org',
|
||||||
'wss://nostr.zhongwen.world',
|
'wss://nostr.zhongwen.world',
|
||||||
'wss://nostro.cc',
|
'wss://nostro.cc',
|
||||||
|
@ -21,19 +21,19 @@ export async function getActiveAccount() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create account
|
// create account
|
||||||
export async function createAccount(data: { pubkey: string; privkey: string; metadata: string }) {
|
export async function createAccount(pubkey: string, privkey: string, metadata: string) {
|
||||||
const db = await connect();
|
const db = await connect();
|
||||||
return await db.execute('INSERT OR IGNORE INTO accounts (pubkey, privkey, metadata) VALUES (?, ?, ?);', [
|
return await db.execute('INSERT OR IGNORE INTO accounts (pubkey, privkey, metadata) VALUES (?, ?, ?);', [
|
||||||
data.pubkey,
|
pubkey,
|
||||||
data.privkey,
|
privkey,
|
||||||
data.metadata,
|
metadata,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update account
|
// update account
|
||||||
export async function updateAccount(column: string, value: string, pubkey: string) {
|
export async function updateAccount(column: string, value: string | string[], pubkey: string) {
|
||||||
const db = await connect();
|
const db = await connect();
|
||||||
return await db.execute(`UPDATE accounts SET ${column} = "${value}" WHERE pubkey = "${pubkey}";`);
|
return await db.execute(`UPDATE accounts SET ${column} = '${JSON.stringify(value)}' WHERE pubkey = "${pubkey}";`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create pleb
|
// create pleb
|
||||||
|
@ -9,13 +9,13 @@ export const tagsToArray = (arr) => {
|
|||||||
return newarr;
|
return newarr;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const followsTag = (arr) => {
|
// convert array to NIP-02 tag list
|
||||||
const newarr = [];
|
export const arrayToNIP02 = (arr: string[]) => {
|
||||||
// push item to tags
|
const nip03_array = [];
|
||||||
arr.forEach((item) => {
|
arr.forEach((item) => {
|
||||||
newarr.push(['p', item]);
|
nip03_array.push(['p', item]);
|
||||||
});
|
});
|
||||||
return newarr;
|
return nip03_array;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const pubkeyArray = (arr) => {
|
export const pubkeyArray = (arr) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user