diff --git a/src/components/navigatorBar/profileMenu.tsx b/src/components/navigatorBar/profileMenu.tsx index 6f65c1f1..3aa65138 100644 --- a/src/components/navigatorBar/profileMenu.tsx +++ b/src/components/navigatorBar/profileMenu.tsx @@ -12,6 +12,13 @@ export const ProfileMenu = memo(function ProfileMenu({ pubkey }: { pubkey: strin router.push(`/profile/${pubkey}`); }; + const updateProfile = () => { + router.push({ + pathname: '/profile/update', + query: { pubkey: pubkey }, + }); + }; + const copyPubkey = async () => { const npub = nip19.npubEncode(pubkey); await writeText(npub); @@ -33,6 +40,11 @@ export const ProfileMenu = memo(function ProfileMenu({ pubkey }: { pubkey: strin className="group relative flex h-[30px] select-none items-center rounded px-1 pl-6 text-sm leading-none text-zinc-100 outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-zinc-700 data-[highlighted]:text-fuchsia-400 data-[disabled]:text-zinc-400"> View profile + updateProfile()} + className="group relative flex h-[30px] select-none items-center rounded px-1 pl-6 text-sm leading-none text-zinc-100 outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-zinc-700 data-[highlighted]:text-fuchsia-400 data-[disabled]:text-zinc-400"> + Update profile + copyPubkey()} className="group relative flex h-[30px] select-none items-center rounded px-1 pl-6 text-sm leading-none text-zinc-100 outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-zinc-700 data-[highlighted]:text-fuchsia-400 data-[disabled]:text-zinc-400"> diff --git a/src/layouts/newsfeedLayout.tsx b/src/layouts/newsfeedLayout.tsx new file mode 100644 index 00000000..54246b21 --- /dev/null +++ b/src/layouts/newsfeedLayout.tsx @@ -0,0 +1,21 @@ +import AccountBar from '@components/accountBar'; +import NavigatorBar from '@components/navigatorBar'; + +export default function NewsFeedLayout({ children }: { children: React.ReactNode }) { + return ( +
+
+
+ +
+
+
+ +
+
+
{children}
+
+
+
+ ); +} diff --git a/src/layouts/userLayout.tsx b/src/layouts/userLayout.tsx index 631d1fd8..b04a159b 100644 --- a/src/layouts/userLayout.tsx +++ b/src/layouts/userLayout.tsx @@ -1,7 +1,14 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import AccountBar from '@components/accountBar'; -import NavigatorBar from '@components/navigatorBar'; +import ActiveLink from '@components/activeLink'; + +import { currentUser } from '@stores/currentUser'; + +import { useStore } from '@nanostores/react'; export default function UserLayout({ children }: { children: React.ReactNode }) { + const $currentUser: any = useStore(currentUser); + return (
@@ -10,7 +17,31 @@ export default function UserLayout({ children }: { children: React.ReactNode })
- +
+ {/* main */} +
+ {/* menu */} +
+
+

Menu

+
+
+ + Personal Page + + + Update Profile + +
+
+
+
{children}
diff --git a/src/pages/feed/following.tsx b/src/pages/feed/following.tsx index 8f56d2b8..00766a4a 100644 --- a/src/pages/feed/following.tsx +++ b/src/pages/feed/following.tsx @@ -1,5 +1,5 @@ import BaseLayout from '@layouts/baseLayout'; -import UserLayout from '@layouts/userLayout'; +import NewsFeedLayout from '@layouts/newsfeedLayout'; import { Placeholder } from '@components/note/placeholder'; import { Thread } from '@components/thread'; @@ -52,7 +52,7 @@ Page.getLayout = function getLayout( ) { return ( - {page} + {page} ); }; diff --git a/src/pages/feed/global.tsx b/src/pages/feed/global.tsx index 0c590cf0..c8ce0a63 100644 --- a/src/pages/feed/global.tsx +++ b/src/pages/feed/global.tsx @@ -1,5 +1,5 @@ import BaseLayout from '@layouts/baseLayout'; -import UserLayout from '@layouts/userLayout'; +import NewsFeedLayout from '@layouts/newsfeedLayout'; import { Placeholder } from '@components/note/placeholder'; import { Thread } from '@components/thread'; @@ -48,7 +48,7 @@ Page.getLayout = function getLayout( ) { return ( - {page} + {page} ); }; diff --git a/src/pages/profile/update.tsx b/src/pages/profile/update.tsx new file mode 100644 index 00000000..4d220a38 --- /dev/null +++ b/src/pages/profile/update.tsx @@ -0,0 +1,244 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import BaseLayout from '@layouts/baseLayout'; +import UserLayout from '@layouts/userLayout'; + +import { currentUser } from '@stores/currentUser'; + +import { useStore } from '@nanostores/react'; +import { useRouter } from 'next/router'; +import { dateToUnix, useNostr } from 'nostr-react'; +import { getEventHash, signEvent } from 'nostr-tools'; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useState } from 'react'; +import { useForm } from 'react-hook-form'; +import Database from 'tauri-plugin-sql-api'; + +type FormValues = { + display_name: string; + name: string; + username: string; + picture: string; + banner: string; + about: string; + website: string; +}; + +// TODO: update the design +export default function Page() { + const router = useRouter(); + const { publish } = useNostr(); + const [loading, setLoading] = useState(false); + + const $currentUser: any = useStore(currentUser); + const profile = JSON.parse($currentUser.metadata); + + const { + register, + handleSubmit, + formState: { errors, isDirty, isValid }, + } = useForm(); + + const onSubmit = async (data: any) => { + setLoading(true); + + // publish account to relays + const event: any = { + content: JSON.stringify(data), + created_at: dateToUnix(), + kind: 0, + pubkey: $currentUser.pubkey, + tags: [], + }; + event.id = getEventHash(event); + event.sig = signEvent(event, $currentUser.privkey); + publish(event); + + // save account to database + const db = await Database.load('sqlite:lume.db'); + await db.execute( + `UPDATE accounts SET metadata = '${JSON.stringify(data)}' WHERE pubkey = "${ + $currentUser.pubkey + }"` + ); + await db.close(); + + // set currentUser in global state + currentUser.set({ + metadata: JSON.stringify(data), + npub: $currentUser.npub, + privkey: $currentUser.privkey, + pubkey: $currentUser.pubkey, + }); + + // redirect to newsfeed + setTimeout(() => { + setLoading(false); + router.push('/feed/following'); + }, 1500); + }; + + return ( +
+
+

+ Update profile +

+

+ Your profile will be published to all relays, as long as you have the private key, you + always can recover your profile in any client +

+
+
+
+
+ +
+
+
+ +
+ + {errors.display_name &&

{errors.display_name.message}

} +
+
+
+
+
+ +
+
+
+ +
+ + {errors.name &&

{errors.name.message}

} +
+
+
+
+
+ +
+
+
+ +
+ + {errors.username &&

{errors.username.message}

} +
+
+
+
+
+ +
+
+
+ +
+ + {errors.picture &&

{errors.picture.message}

} +
+
+
+
+
+ +
+
+
+ +
+ + {errors.banner &&

{errors.banner.message}

} +
+
+
+
+
+ +
+
+
+