From 6581ffb92b371e15b6b83aaa26a1d20799c315dc Mon Sep 17 00:00:00 2001 From: reya Date: Tue, 16 Jan 2024 14:49:00 +0700 Subject: [PATCH] feat: polish --- apps/desktop/src/router.tsx | 137 +++-- .../settings/components/avatarUpload.tsx | 43 ++ .../settings/components/coverUpload.tsx | 43 ++ apps/desktop/src/routes/settings/index.tsx | 19 - .../settings/{editProfile.tsx => profile.tsx} | 129 ++--- packages/ark/src/ark.ts | 44 +- packages/ark/src/components/column/header.tsx | 12 +- .../ark/src/components/note/buttons/reply.tsx | 30 +- .../src/components/note/buttons/repost.tsx | 108 +++- .../ark/src/components/note/mentions/note.tsx | 9 +- .../ark/src/components/note/mentions/user.tsx | 6 +- packages/ark/src/components/note/menu.tsx | 45 +- .../ark/src/components/note/preview/link.tsx | 4 +- .../src/components/note/primitives/repost.tsx | 2 +- packages/ark/src/hooks/useEvent.ts | 2 +- packages/ark/src/provider.tsx | 4 +- packages/icons/src/logout.tsx | 42 +- packages/ndk-cache-tauri/index.ts | 8 +- packages/storage/src/storage.ts | 6 + packages/ui/src/account/active.tsx | 88 ++-- packages/ui/src/account/logout.tsx | 4 +- packages/ui/src/layouts/settings.tsx | 72 +-- packages/ui/src/navigation.tsx | 4 +- pnpm-lock.yaml | 480 +++++++++++++++++- 24 files changed, 944 insertions(+), 397 deletions(-) create mode 100644 apps/desktop/src/routes/settings/components/avatarUpload.tsx create mode 100644 apps/desktop/src/routes/settings/components/coverUpload.tsx delete mode 100644 apps/desktop/src/routes/settings/index.tsx rename apps/desktop/src/routes/settings/{editProfile.tsx => profile.tsx} (67%) diff --git a/apps/desktop/src/router.tsx b/apps/desktop/src/router.tsx index 79f4e666..3fd3b071 100644 --- a/apps/desktop/src/router.tsx +++ b/apps/desktop/src/router.tsx @@ -35,81 +35,70 @@ export default function Router() { return { Component: HomeScreen }; }, }, + ], + }, + { + path: "settings", + element: , + children: [ { - path: "settings", - element: , - children: [ - { - index: true, - async lazy() { - const { UserSettingScreen } = await import( - "./routes/settings" - ); - return { Component: UserSettingScreen }; - }, - }, - { - path: "edit-profile", - async lazy() { - const { EditProfileScreen } = await import( - "./routes/settings/editProfile" - ); - return { Component: EditProfileScreen }; - }, - }, - { - path: "edit-contact", - async lazy() { - const { EditContactScreen } = await import( - "./routes/settings/editContact" - ); - return { Component: EditContactScreen }; - }, - }, - { - path: "general", - async lazy() { - const { GeneralSettingScreen } = await import( - "./routes/settings/general" - ); - return { Component: GeneralSettingScreen }; - }, - }, - { - path: "backup", - async lazy() { - const { BackupSettingScreen } = await import( - "./routes/settings/backup" - ); - return { Component: BackupSettingScreen }; - }, - }, - { - path: "advanced", - async lazy() { - const { AdvancedSettingScreen } = await import( - "./routes/settings/advanced" - ); - return { Component: AdvancedSettingScreen }; - }, - }, - { - path: "nwc", - async lazy() { - const { NWCScreen } = await import("./routes/settings/nwc"); - return { Component: NWCScreen }; - }, - }, - { - path: "about", - async lazy() { - const { AboutScreen } = await import( - "./routes/settings/about" - ); - return { Component: AboutScreen }; - }, - }, - ], + index: true, + async lazy() { + const { GeneralSettingScreen } = await import( + "./routes/settings/general" + ); + return { Component: GeneralSettingScreen }; + }, + }, + { + path: "profile", + async lazy() { + const { ProfileSettingScreen } = await import( + "./routes/settings/profile" + ); + return { Component: ProfileSettingScreen }; + }, + }, + { + path: "edit-contact", + async lazy() { + const { EditContactScreen } = await import( + "./routes/settings/editContact" + ); + return { Component: EditContactScreen }; + }, + }, + { + path: "backup", + async lazy() { + const { BackupSettingScreen } = await import( + "./routes/settings/backup" + ); + return { Component: BackupSettingScreen }; + }, + }, + { + path: "advanced", + async lazy() { + const { AdvancedSettingScreen } = await import( + "./routes/settings/advanced" + ); + return { Component: AdvancedSettingScreen }; + }, + }, + { + path: "nwc", + async lazy() { + const { NWCScreen } = await import("./routes/settings/nwc"); + return { Component: NWCScreen }; + }, + }, + { + path: "about", + async lazy() { + const { AboutScreen } = await import("./routes/settings/about"); + return { Component: AboutScreen }; + }, }, ], }, diff --git a/apps/desktop/src/routes/settings/components/avatarUpload.tsx b/apps/desktop/src/routes/settings/components/avatarUpload.tsx new file mode 100644 index 00000000..54ae1618 --- /dev/null +++ b/apps/desktop/src/routes/settings/components/avatarUpload.tsx @@ -0,0 +1,43 @@ +import { useArk } from "@lume/ark"; +import { LoaderIcon } from "@lume/icons"; +import { useState } from "react"; +import { toast } from "sonner"; + +export function AvatarUpload({ setPicture }) { + const ark = useArk(); + const [loading, setLoading] = useState(false); + + const upload = async () => { + try { + setLoading(true); + + // upload image to nostr.build server + // #TODO: support multiple server + const image = await ark.upload({ fileExts: [] }); + + if (!image) + toast.error("Failed to upload image, please try again later."); + + setPicture(image); + setLoading(false); + } catch (e) { + setLoading(false); + toast.error("Failed to upload image, please try again later."); + } + }; + + return ( + + ); +} diff --git a/apps/desktop/src/routes/settings/components/coverUpload.tsx b/apps/desktop/src/routes/settings/components/coverUpload.tsx new file mode 100644 index 00000000..88f1ebf8 --- /dev/null +++ b/apps/desktop/src/routes/settings/components/coverUpload.tsx @@ -0,0 +1,43 @@ +import { useArk } from "@lume/ark"; +import { LoaderIcon } from "@lume/icons"; +import { useState } from "react"; +import { toast } from "sonner"; + +export function CoverUpload({ setBanner }) { + const ark = useArk(); + const [loading, setLoading] = useState(false); + + const upload = async () => { + try { + setLoading(true); + + // upload image to nostr.build server + // #TODO: support multiple server + const image = await ark.upload({ fileExts: [] }); + + if (!image) + toast.error("Failed to upload image, please try again later."); + + setBanner(image); + setLoading(false); + } catch (e) { + setLoading(false); + toast.error("Failed to upload image, please try again later."); + } + }; + + return ( + + ); +} diff --git a/apps/desktop/src/routes/settings/index.tsx b/apps/desktop/src/routes/settings/index.tsx deleted file mode 100644 index 9ec682df..00000000 --- a/apps/desktop/src/routes/settings/index.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { ContactCard } from "./components/contactCard"; -import { PostCard } from "./components/postCard"; -import { ProfileCard } from "./components/profileCard"; -import { RelayCard } from "./components/relayCard"; -import { ZapCard } from "./components/zapCard"; - -export function UserSettingScreen() { - return ( -
- -
- - - - -
-
- ); -} diff --git a/apps/desktop/src/routes/settings/editProfile.tsx b/apps/desktop/src/routes/settings/profile.tsx similarity index 67% rename from apps/desktop/src/routes/settings/editProfile.tsx rename to apps/desktop/src/routes/settings/profile.tsx index 6e01f923..99e48ed4 100644 --- a/apps/desktop/src/routes/settings/editProfile.tsx +++ b/apps/desktop/src/routes/settings/profile.tsx @@ -5,25 +5,27 @@ import { PlusIcon, UnverifiedIcon, } from "@lume/icons"; +import { useStorage } from "@lume/storage"; import { NDKKind, NDKUserProfile } from "@nostr-dev-kit/ndk"; import { useQueryClient } from "@tanstack/react-query"; -import { message } from "@tauri-apps/plugin-dialog"; import { useState } from "react"; import { useForm } from "react-hook-form"; -import { useNavigate } from "react-router-dom"; +import { AvatarUpload } from "./components/avatarUpload"; +import { CoverUpload } from "./components/coverUpload"; + +export function ProfileSettingScreen() { + const ark = useArk(); + const storage = useStorage(); + const queryClient = useQueryClient(); -export function EditProfileScreen() { const [loading, setLoading] = useState(false); const [picture, setPicture] = useState(""); const [banner, setBanner] = useState(""); const [nip05, setNIP05] = useState({ verified: true, text: "" }); - const ark = useArk(); - const { register, handleSubmit, - reset, setError, formState: { isValid, errors }, } = useForm({ @@ -45,48 +47,6 @@ export function EditProfileScreen() { }, }); - const queryClient = useQueryClient(); - const navigate = useNavigate(); - - const uploadAvatar = async () => { - try { - if (!ark.ndk.signer) return navigate("/new/privkey"); - - setLoading(true); - - const image = await ark.upload({ fileExts: [] }); - if (image) { - setPicture(image); - setLoading(false); - } - } catch (e) { - setLoading(false); - await message(`Upload failed, error: ${e}`, { - title: "Lume", - type: "error", - }); - } - }; - - const uploadBanner = async () => { - try { - setLoading(true); - - const image = await ark.upload({ fileExts: [] }); - - if (image) { - setBanner(image); - setLoading(false); - } - } catch (e) { - setLoading(false); - await message(`Upload failed, error: ${e}`, { - title: "Lume", - type: "error", - }); - } - }; - const onSubmit = async (data: NDKUserProfile) => { // start loading setLoading(true); @@ -94,9 +54,12 @@ export function EditProfileScreen() { let content = { ...data, username: data.name, - display_name: data.name, + display_name: data.displayName, bio: data.about, - image: data.picture, + image: picture, + cover: banner, + picture, + banner, }; if (data.nip05) { @@ -104,13 +67,14 @@ export function EditProfileScreen() { pubkey: ark.account.pubkey, nip05: data.nip05, }); + if (verify) { content = { ...content, nip05: data.nip05 }; } else { setNIP05((prev) => ({ ...prev, verified: false })); setError("nip05", { type: "manual", - message: "Can't verify your Lume ID / NIP-05, please check again", + message: "Can't verify your NIP-05, please check again", }); } } @@ -123,76 +87,59 @@ export function EditProfileScreen() { if (publish) { // invalid cache - queryClient.invalidateQueries({ + await storage.clearProfileCache(ark.account.pubkey); + await queryClient.invalidateQueries({ queryKey: ["user", ark.account.pubkey], }); - // reset form - reset(); + // reset state - setLoading(false); setPicture(null); setBanner(null); - } else { - setLoading(false); } + + setLoading(false); }; return ( -
+
- - -
-
+
+
{banner ? ( user's banner ) : ( -
+
)} -
- +
+
-
-
+
+
user's avatar -
- -
+
@@ -282,17 +229,17 @@ export function EditProfileScreen() {