From 29c7075f227f0ba10221656c066414d7c4e59fd6 Mon Sep 17 00:00:00 2001
From: Ren Amamiya <123083837+reyamir@users.noreply.github.com>
Date: Thu, 23 Mar 2023 08:37:39 +0700
Subject: [PATCH] updated profile page
---
src/components/columns/account/active.tsx | 5 +-
src/components/profile/followers.tsx | 24 ++
src/components/profile/follows.tsx | 23 ++
src/components/profile/metadata.tsx | 68 ++++++
src/components/profile/notes.tsx | 31 +++
src/components/user/extend.tsx | 13 +-
src/pages/profile/update.tsx | 227 ------------------
.../{profile/index.tsx => users/[id].tsx} | 56 ++---
8 files changed, 173 insertions(+), 274 deletions(-)
create mode 100644 src/components/profile/followers.tsx
create mode 100644 src/components/profile/follows.tsx
create mode 100644 src/components/profile/metadata.tsx
create mode 100644 src/components/profile/notes.tsx
delete mode 100644 src/pages/profile/update.tsx
rename src/pages/{profile/index.tsx => users/[id].tsx} (53%)
diff --git a/src/components/columns/account/active.tsx b/src/components/columns/account/active.tsx
index fdbce148..2c3e744a 100644
--- a/src/components/columns/account/active.tsx
+++ b/src/components/columns/account/active.tsx
@@ -19,10 +19,7 @@ export const ActiveAccount = memo(function ActiveAccount({ user }: { user: any }
const [currentUser]: any = useLocalStorage('current-user');
const openProfile = () => {
- router.push({
- pathname: '/profile',
- query: { id: currentUser.id },
- });
+ router.push(`/users/${currentUser.id}`);
};
// save follows to database
diff --git a/src/components/profile/followers.tsx b/src/components/profile/followers.tsx
new file mode 100644
index 00000000..febb62c7
--- /dev/null
+++ b/src/components/profile/followers.tsx
@@ -0,0 +1,24 @@
+import { RelayContext } from '@components/contexts/relay';
+
+import useLocalStorage from '@rehooks/local-storage';
+import destr from 'destr';
+import { Author } from 'nostr-relaypool';
+import { useContext, useEffect, useState } from 'react';
+
+export default function ProfileFollowers({ id }: { id: string }) {
+ const relayPool: any = useContext(RelayContext);
+ const [relays]: any = useLocalStorage('relays');
+
+ const [followers, setFollowers] = useState(null);
+
+ useEffect(() => {
+ const user = new Author(relayPool, relays, id);
+ user.followers((res) => setFollowers(destr(res.tags)), 0, 100);
+ }, [id, relayPool, relays]);
+
+ return (
+
+ {followers && followers.map((follower, index) =>
{follower[1]}
)}
+
+ );
+}
diff --git a/src/components/profile/follows.tsx b/src/components/profile/follows.tsx
new file mode 100644
index 00000000..9ba8b4ed
--- /dev/null
+++ b/src/components/profile/follows.tsx
@@ -0,0 +1,23 @@
+import { RelayContext } from '@components/contexts/relay';
+
+import useLocalStorage from '@rehooks/local-storage';
+import { Author } from 'nostr-relaypool';
+import { useContext, useEffect, useState } from 'react';
+
+export default function ProfileFollows({ id }: { id: string }) {
+ const relayPool: any = useContext(RelayContext);
+ const [relays]: any = useLocalStorage('relays');
+
+ const [follows, setFollows] = useState(null);
+
+ useEffect(() => {
+ const user = new Author(relayPool, relays, id);
+ user.follows((res) => setFollows(res), 0);
+ }, [id, relayPool, relays]);
+
+ return (
+
+ {follows && follows.map((follow, index) =>
{follow.pubkey}
)}
+
+ );
+}
diff --git a/src/components/profile/metadata.tsx b/src/components/profile/metadata.tsx
new file mode 100644
index 00000000..8b3b3cdc
--- /dev/null
+++ b/src/components/profile/metadata.tsx
@@ -0,0 +1,68 @@
+import { RelayContext } from '@components/contexts/relay';
+import { ImageWithFallback } from '@components/imageWithFallback';
+
+import { truncate } from '@utils/truncate';
+
+import useLocalStorage from '@rehooks/local-storage';
+import Avatar from 'boring-avatars';
+import destr from 'destr';
+import Image from 'next/image';
+import { Author } from 'nostr-relaypool';
+import { useContext, useEffect, useState } from 'react';
+
+const DEFAULT_BANNER = 'https://bafybeiacwit7hjmdefqggxqtgh6ht5dhth7ndptwn2msl5kpkodudsr7py.ipfs.w3s.link/banner-1.jpg';
+
+export default function ProfileMetadata({ id }: { id: string }) {
+ const relayPool: any = useContext(RelayContext);
+ const [relays]: any = useLocalStorage('relays');
+
+ const [profile, setProfile] = useState(null);
+
+ useEffect(() => {
+ const user = new Author(relayPool, relays, id);
+ user.metaData((res) => setProfile(destr(res.content)), 0);
+ }, [id, relayPool, relays]);
+
+ return (
+ <>
+
+
+
+
+
+
+ {profile?.picture ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+ {profile?.display_name || profile?.name}
+
+
+ {profile?.username || (id && truncate(id, 16, ' .... '))}
+
+
+
{profile?.about}
+
+
+ >
+ );
+}
diff --git a/src/components/profile/notes.tsx b/src/components/profile/notes.tsx
new file mode 100644
index 00000000..f3f9c979
--- /dev/null
+++ b/src/components/profile/notes.tsx
@@ -0,0 +1,31 @@
+import { RelayContext } from '@components/contexts/relay';
+import { Content } from '@components/note/content';
+
+import useLocalStorage from '@rehooks/local-storage';
+import { Author } from 'nostr-relaypool';
+import { useContext, useEffect, useState } from 'react';
+
+export default function ProfileNotes({ id }: { id: string }) {
+ const relayPool: any = useContext(RelayContext);
+ const [relays]: any = useLocalStorage('relays');
+
+ const [data, setData] = useState([]);
+
+ useEffect(() => {
+ const user = new Author(relayPool, relays, id);
+ user.text((res) => setData((data) => [...data, res]), 0, 100);
+ }, [id, relayPool, relays]);
+
+ return (
+
+ {data.map((item) => (
+
+
+
+ ))}
+
+ );
+}
diff --git a/src/components/user/extend.tsx b/src/components/user/extend.tsx
index 48a1ea70..8adca8b4 100644
--- a/src/components/user/extend.tsx
+++ b/src/components/user/extend.tsx
@@ -8,14 +8,21 @@ import { fetch } from '@tauri-apps/api/http';
import Avatar from 'boring-avatars';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
+import { useRouter } from 'next/router';
import { memo, useCallback, useContext, useEffect, useState } from 'react';
dayjs.extend(relativeTime);
export const UserExtend = memo(function UserExtend({ pubkey, time }: { pubkey: string; time: any }) {
+ const router = useRouter();
const { db }: any = useContext(DatabaseContext);
const [profile, setProfile] = useState(null);
+ const openUserPage = (e) => {
+ e.stopPropagation();
+ router.push(`/users/${pubkey}`);
+ };
+
const fetchProfile = useCallback(async (id: string) => {
const res = await fetch(`https://rbr.bio/${id}/metadata.json`, {
method: 'GET',
@@ -54,8 +61,8 @@ export const UserExtend = memo(function UserExtend({ pubkey, time }: { pubkey: s
}, [fetchProfile, getCacheProfile, insertCacheProfile, pubkey]);
return (
-
-
+
openUserPage(e)} className="group flex items-start gap-2">
+
{profile?.picture ? (
-
+
{profile?.display_name || profile?.name || truncate(pubkey, 16, ' .... ')}
ยท
diff --git a/src/pages/profile/update.tsx b/src/pages/profile/update.tsx
deleted file mode 100644
index 31ca0fa5..00000000
--- a/src/pages/profile/update.tsx
+++ /dev/null
@@ -1,227 +0,0 @@
-import BaseLayout from '@layouts/base';
-import UserLayout from '@layouts/user';
-
-import { RelayContext } from '@components/contexts/relay';
-
-import { dateToUnix } from '@utils/getDate';
-
-import { useLocalStorage } from '@rehooks/local-storage';
-import { useRouter } from 'next/router';
-import { getEventHash, signEvent } from 'nostr-tools';
-import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, 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 relayPool: any = useContext(RelayContext);
- const [relays]: any = useLocalStorage('relays');
-
- const router = useRouter();
- const [loading, setLoading] = useState(false);
-
- const [currentUser]: any = useLocalStorage('current-user');
- const profile =
- currentUser.metadata !== undefined ? JSON.parse(currentUser.metadata) : { display_name: null, username: null };
-
- 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.id,
- tags: [],
- };
-
- event.id = getEventHash(event);
- event.sig = signEvent(event, currentUser.privkey);
-
- relayPool.publish(event, relays);
-
- // 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.id}"`);
-
- // set currentUser in global state
- currentUser.set({
- metadata: JSON.stringify(data),
- npub: currentUser.npub,
- privkey: currentUser.privkey,
- pubkey: currentUser.id,
- });
-
- // redirect to newsfeed
- setTimeout(() => {
- setLoading(false);
- router.reload();
- }, 1500);
- };
-
- return (
-
- );
-}
-
-Page.getLayout = function getLayout(
- page:
- | string
- | number
- | boolean
- | ReactElement>
- | ReactFragment
- | ReactPortal
-) {
- return (
-
- {page}
-
- );
-};
diff --git a/src/pages/profile/index.tsx b/src/pages/users/[id].tsx
similarity index 53%
rename from src/pages/profile/index.tsx
rename to src/pages/users/[id].tsx
index 446a4040..39eac01d 100644
--- a/src/pages/profile/index.tsx
+++ b/src/pages/users/[id].tsx
@@ -1,46 +1,22 @@
import BaseLayout from '@layouts/base';
import WithSidebarLayout from '@layouts/withSidebar';
-import { RelayContext } from '@components/contexts/relay';
+import ProfileFollowers from '@components/profile/followers';
+import ProfileFollows from '@components/profile/follows';
+import ProfileMetadata from '@components/profile/metadata';
+import ProfileNotes from '@components/profile/notes';
import * as Tabs from '@radix-ui/react-tabs';
-import useLocalStorage from '@rehooks/local-storage';
-import Image from 'next/image';
-import { Author } from 'nostr-relaypool';
-import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useMemo } from 'react';
+import { useRouter } from 'next/router';
+import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal } from 'react';
export default function Page() {
- const relayPool: any = useContext(RelayContext);
-
- const [relays]: any = useLocalStorage('relays');
- const [currentUser]: any = useLocalStorage('current-user');
-
- const user = new Author(relayPool, relays, currentUser.id);
- const userProfile = JSON.parse(currentUser.metadata);
+ const router = useRouter();
+ const id: any = router.query.id;
return (
-
-
-
- {userProfile.banner && (
-
- )}
-
-
-
-
-
-
-
-
-
{userProfile.display_name}
- @{userProfile.username}
-
-
{userProfile.about}
-
-
+
+
-
- Notes
+
+
-
- Followers
+
+
-
- Following
+
+