updated onboarding flow

This commit is contained in:
Ren Amamiya 2023-02-22 21:12:37 +07:00
parent c0889456a3
commit 247f28ae75
4 changed files with 182 additions and 29 deletions

View File

@ -0,0 +1,125 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import BaseLayout from '@layouts/baseLayout';
import OnboardingLayout from '@layouts/onboardingLayout';
import { motion } from 'framer-motion';
import { useRouter } from 'next/router';
import { useNostrEvents } from 'nostr-react';
import {
JSXElementConstructor,
ReactElement,
ReactFragment,
ReactPortal,
useEffect,
useState,
} from 'react';
import Database from 'tauri-plugin-sql-api';
export default function Page() {
const [follows, setFollows] = useState([null]);
const [loading, setLoading] = useState(false);
const router = useRouter();
const { pubkey }: any = router.query;
const { onEvent } = useNostrEvents({
filter: {
authors: [pubkey],
kinds: [3],
},
});
onEvent((rawMetadata) => {
try {
setFollows(rawMetadata.tags);
} catch (err) {
console.error(err, rawMetadata);
}
});
useEffect(() => {
setLoading(true);
const insertDB = async () => {
const db = await Database.load('sqlite:lume.db');
follows.forEach(async (item) => {
if (item) {
await db.execute(
`INSERT INTO followings (pubkey, account) VALUES ("${item[1]}", "${pubkey}")`
);
}
});
};
if (follows !== null && follows.length > 0) {
insertDB()
.then(() => {
setTimeout(() => {
setLoading(false);
router.push('/feed/following');
}, 1500);
})
.catch(console.error);
}
}, [follows, pubkey, router]);
return (
<div className="flex h-full flex-col justify-between px-8">
<div>{/* spacer */}</div>
<motion.div layoutId="form">
<div className="mb-8 flex flex-col gap-3">
<motion.h1
layoutId="title"
className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
Fetching your follows...
</motion.h1>
<motion.h2 layoutId="subtitle" className="w-3/4 text-zinc-400">
Not only profile, every nostr client can sync your follows list when you move to a new
client, so please keep your key safely (again)
</motion.h2>
</div>
</motion.div>
<motion.div layoutId="action" className="pb-5">
<div className="flex h-10 items-center">
{loading === true ? (
<svg
className="h-5 w-5 animate-spin text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24">
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
) : (
<></>
)}
</div>
</motion.div>
</div>
);
}
Page.getLayout = function getLayout(
page:
| string
| number
| boolean
| ReactElement<unknown, string | JSXElementConstructor<unknown>>
| ReactFragment
| ReactPortal
) {
return (
<BaseLayout>
<OnboardingLayout>{page}</OnboardingLayout>
</BaseLayout>
);
};

View File

@ -11,13 +11,14 @@ import {
ReactElement,
ReactFragment,
ReactPortal,
useCallback,
useEffect,
useState,
} from 'react';
import Database from 'tauri-plugin-sql-api';
export default function Page() {
const [account, setAccount] = useState(null);
const [loading, setLoading] = useState(false);
const router = useRouter();
const { privkey }: any = router.query;
@ -42,19 +43,32 @@ export default function Page() {
}
});
const insertAccount = useCallback(async () => {
// save account to database
const db = await Database.load('sqlite:lume.db');
await db.execute(
`INSERT INTO accounts (privkey, pubkey, npub, nsec, metadata) VALUES ("${privkey}", "${pubkey}", "${npub}", "${nsec}", '${JSON.stringify(
account
)}')`
);
await db.close();
useEffect(() => {
setLoading(true);
const insertDB = async () => {
// save account to database
const db = await Database.load('sqlite:lume.db');
await db.execute(
`INSERT INTO accounts (privkey, pubkey, npub, nsec, metadata) VALUES ("${privkey}", "${pubkey}", "${npub}", "${nsec}", '${JSON.stringify(
account
)}')`
);
await db.close();
};
setTimeout(() => {
router.push('/feed/following');
}, 500);
if (account !== null) {
insertDB()
.then(() => {
setTimeout(() => {
setLoading(false);
router.push({
pathname: '/onboarding/fetch-follows',
query: { pubkey: pubkey },
});
}, 1500);
})
.catch(console.error);
}
}, [account, npub, nsec, privkey, pubkey, router]);
return (
@ -65,26 +79,37 @@ export default function Page() {
<motion.h1
layoutId="title"
className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
Getting your old profile
Fetching your profile...
</motion.h1>
<motion.h2 layoutId="subtitle" className="w-3/4 text-zinc-400">
As long as you have private key, you alway can recover your profile as well as follows
list when you move to new nostr client
As long as you have private key, you alway can sync your profile on every nostr client,
so please keep your key safely
</motion.h2>
</div>
<div className="flex flex-col gap-4">
<p>#TODO: show profile</p>
</div>
</motion.div>
<motion.div layoutId="action" className="pb-5">
<div className="flex h-10 items-center">
<div className="relative shrink-0 before:pointer-events-none before:absolute before:-inset-1 before:rounded-[11px] before:border before:border-blue-500 before:opacity-0 before:ring-2 before:ring-blue-500/20 before:transition after:pointer-events-none after:absolute after:inset-px after:rounded-[7px] after:shadow-highlight after:shadow-white/5 after:transition focus-within:before:opacity-100 focus-within:after:shadow-blue-500/100 dark:focus-within:after:shadow-blue-500/20">
<button
onClick={() => insertAccount()}
className="transform rounded-lg border border-white/10 bg-[radial-gradient(ellipse_at_bottom_right,_var(--tw-gradient-stops))] from-gray-300 via-fuchsia-600 to-orange-600 px-3.5 py-2 font-medium shadow-input shadow-black/5 active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-50 dark:shadow-black/10">
<span className="drop-shadow-lg">Finish </span>
</button>
</div>
{loading === true ? (
<svg
className="h-5 w-5 animate-spin text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24">
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
) : (
<></>
)}
</div>
</motion.div>
</div>

View File

@ -37,11 +37,14 @@ export default function Page() {
const onSubmit = async (data: any) => {
let privKey = data['key'];
if (privKey.substring(0, 4) === 'nsec') {
privKey = nip19.decode(privKey).data;
}
try {
const pubKey = getPublicKey(privKey);
if (pubKey) {
router.push({
pathname: '/onboarding/fetch-profile',
@ -75,8 +78,8 @@ export default function Page() {
<div className="relative shrink-0 before:pointer-events-none before:absolute before:-inset-1 before:rounded-[11px] before:border before:border-blue-500 before:opacity-0 before:ring-2 before:ring-blue-500/20 before:transition after:pointer-events-none after:absolute after:inset-px after:rounded-[7px] after:shadow-highlight after:shadow-white/5 after:transition focus-within:before:opacity-100 focus-within:after:shadow-blue-500/100 dark:focus-within:after:shadow-blue-500/20">
<input
{...register('key', { required: true, minLength: 32 })}
placeholder="Paste key here..."
className="relative w-full rounded-lg border border-black/5 px-3.5 py-2 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"
placeholder="Paste nsec or hex key here..."
className="relative w-full rounded-lg border border-black/5 px-3.5 py-2 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-500"
/>
</div>
<span className="text-sm text-red-400">{errors.key && <p>{errors.key.message}</p>}</span>

View File

@ -34,7 +34,7 @@ export default function Page() {
<Link
href="/onboarding/import"
className="hover:bg-zinc-900/2.5 transform rounded-lg border border-black/5 bg-zinc-800 px-3.5 py-2 font-medium ring-1 ring-inset ring-zinc-900/10 hover:text-zinc-900 active:translate-y-1 dark:text-zinc-300 dark:ring-white/10 dark:hover:bg-zinc-700 dark:hover:text-white">
Login
Login with private key
</Link>
</motion.div>
</div>