diff --git a/apps/desktop/src/app.tsx b/apps/desktop/src/app.tsx index ad5e2c88..1c342ab0 100644 --- a/apps/desktop/src/app.tsx +++ b/apps/desktop/src/app.tsx @@ -1,4 +1,4 @@ -import { LumeProvider } from "@lume/ark"; +import { ColumnProvider, LumeProvider } from "@lume/ark"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { Toaster } from "sonner"; import Router from "./router"; @@ -16,7 +16,9 @@ export default function App() { - + + + ); diff --git a/apps/desktop/src/routes/auth/create.tsx b/apps/desktop/src/routes/auth/create.tsx index 27631f31..ef75026e 100644 --- a/apps/desktop/src/routes/auth/create.tsx +++ b/apps/desktop/src/routes/auth/create.tsx @@ -140,6 +140,8 @@ export function CreateAccountScreen() { return toast.error("Failed to create new account, try again later"); } + authWindow.close(); + // add account to storage await storage.createSetting("nsecbunker", "1"); await storage.createAccount({ @@ -162,8 +164,6 @@ export function CreateAccountScreen() { setOnboarding(true); setIsLoading(false); - authWindow.close(); - return navigate("/auth/onboarding"); } catch (e) { setIsLoading(false); diff --git a/packages/ark/src/ark.ts b/packages/ark/src/ark.ts index 0764ddfb..52a811a1 100644 --- a/packages/ark/src/ark.ts +++ b/packages/ark/src/ark.ts @@ -111,8 +111,10 @@ export class Ark { public async getUserProfile(pubkey?: string) { try { // get clean pubkey without any special characters - let hexstring = pubkey.replace(/[^a-zA-Z0-9]/g, "").replace("nostr:", ""); const currentUserPubkey = this.#storage.account.pubkey; + let hexstring = pubkey + ? pubkey.replace(/[^a-zA-Z0-9]/g, "").replace("nostr:", "") + : currentUserPubkey; if ( hexstring.startsWith("npub1") || @@ -127,7 +129,7 @@ export class Ark { } const user = this.ndk.getUser({ - pubkey: pubkey ? hexstring : currentUserPubkey, + pubkey: hexstring, }); const profile = await user.fetchProfile({ @@ -144,8 +146,10 @@ export class Ark { public async getUserContacts(pubkey?: string) { try { // get clean pubkey without any special characters - let hexstring = pubkey.replace(/[^a-zA-Z0-9]/g, "").replace("nostr:", ""); const currentUserPubkey = this.#storage.account.pubkey; + let hexstring = pubkey + ? pubkey.replace(/[^a-zA-Z0-9]/g, "").replace("nostr:", "") + : currentUserPubkey; if ( hexstring.startsWith("npub1") || @@ -160,7 +164,7 @@ export class Ark { } const user = this.ndk.getUser({ - pubkey: pubkey ? hexstring : currentUserPubkey, + pubkey: hexstring, }); const contacts = [...(await user.follows())].map((user) => user.pubkey); diff --git a/packages/ark/src/components/column/live.tsx b/packages/ark/src/components/column/live.tsx index 7dbd4721..444799d2 100644 --- a/packages/ark/src/components/column/live.tsx +++ b/packages/ark/src/components/column/live.tsx @@ -41,7 +41,7 @@ export function ColumnLiveWidget({ className="inline-flex items-center justify-center h-8 gap-1 pl-2 pr-2.5 text-sm font-semibold rounded-full w-max bg-neutral-950 dark:bg-neutral-50 hover:bg-neutral-900 dark:hover:bg-neutral-100 text-neutral-50 dark:text-neutral-950" > - {events.length} {events.length === 1 ? "new event" : "new events"} + {events.length} {events.length === 1 ? "new note" : "new notes"} ); diff --git a/packages/icons/index.ts b/packages/icons/index.ts index 30c3ca05..354f522e 100644 --- a/packages/icons/index.ts +++ b/packages/icons/index.ts @@ -104,3 +104,5 @@ export * from "./src/column"; export * from "./src/addMedia"; export * from "./src/check"; export * from "./src/popperFilled"; +export * from "./src/composeFilled"; +export * from "./src/settingsFilled"; diff --git a/packages/icons/src/compose.tsx b/packages/icons/src/compose.tsx index 1b2917f3..2da7ea86 100644 --- a/packages/icons/src/compose.tsx +++ b/packages/icons/src/compose.tsx @@ -1,19 +1,24 @@ -import { SVGProps } from 'react'; +import { SVGProps } from "react"; -export function ComposeIcon(props: JSX.IntrinsicAttributes & SVGProps) { - return ( - - - - ); +export function ComposeIcon( + props: JSX.IntrinsicAttributes & SVGProps, +) { + return ( + + + + ); } diff --git a/packages/icons/src/composeFilled.tsx b/packages/icons/src/composeFilled.tsx new file mode 100644 index 00000000..e7289918 --- /dev/null +++ b/packages/icons/src/composeFilled.tsx @@ -0,0 +1,25 @@ +import { SVGProps } from "react"; + +export function ComposeFilledIcon( + props: JSX.IntrinsicAttributes & SVGProps, +) { + return ( + + + + + ); +} diff --git a/packages/icons/src/nwc.tsx b/packages/icons/src/nwc.tsx index 9a1394e5..8f6247fe 100644 --- a/packages/icons/src/nwc.tsx +++ b/packages/icons/src/nwc.tsx @@ -1,18 +1,20 @@ export function NwcIcon(props: JSX.IntrinsicElements["svg"]) { return ( - + ); } diff --git a/packages/icons/src/settingsFilled.tsx b/packages/icons/src/settingsFilled.tsx new file mode 100644 index 00000000..1908a07f --- /dev/null +++ b/packages/icons/src/settingsFilled.tsx @@ -0,0 +1,21 @@ +import { SVGProps } from "react"; + +export function SettingsFilledIcon( + props: JSX.IntrinsicAttributes & SVGProps, +) { + return ( + + + + ); +} diff --git a/packages/lume-column-thread/src/home.tsx b/packages/lume-column-thread/src/home.tsx index 3158199b..cb2dd4f1 100644 --- a/packages/lume-column-thread/src/home.tsx +++ b/packages/lume-column-thread/src/home.tsx @@ -6,7 +6,7 @@ export function HomeRoute({ id }: { id: string }) { return (
-
+
diff --git a/packages/ui/src/account/active.tsx b/packages/ui/src/account/active.tsx index 1075bd78..13af5852 100644 --- a/packages/ui/src/account/active.tsx +++ b/packages/ui/src/account/active.tsx @@ -17,33 +17,30 @@ export function ActiveAccount() { )}`; return ( -
- - - - - {storage.account.pubkey} - - - + + - - -
+ + {storage.account.pubkey} + + + + ); } diff --git a/packages/ui/src/editor/form.tsx b/packages/ui/src/editor/form.tsx index f1008ef6..e242dd03 100644 --- a/packages/ui/src/editor/form.tsx +++ b/packages/ui/src/editor/form.tsx @@ -1,7 +1,7 @@ -import { MentionNote, useArk, useStorage } from "@lume/ark"; -import { TrashIcon } from "@lume/icons"; +import { MentionNote, useArk, useColumnContext, useStorage } from "@lume/ark"; +import { LoaderIcon, TrashIcon } from "@lume/icons"; import { NDKCacheUserProfile } from "@lume/types"; -import { cn, editorValueAtom } from "@lume/utils"; +import { COL_TYPES, cn, editorValueAtom } from "@lume/utils"; import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; import { useAtom } from "jotai"; import { useEffect, useRef, useState } from "react"; @@ -195,10 +195,13 @@ export function EditorForm() { const [target, setTarget] = useState(); const [index, setIndex] = useState(0); const [search, setSearch] = useState(""); + const [loading, setLoading] = useState(false); const [editor] = useState(() => withMentions(withNostrEvent(withImages(withReact(createEditor())))), ); + const { addColumn } = useColumnContext(); + const filters = contacts ?.filter((c) => c?.name?.toLowerCase().startsWith(search.toLowerCase())) ?.slice(0, 10); @@ -234,19 +237,35 @@ export function EditorForm() { }; const submit = async () => { - const event = new NDKEvent(ark.ndk); - event.kind = NDKKind.Text; - event.content = serialize(editor.children); + try { + setLoading(true); - const publish = await event.publish(); + const event = new NDKEvent(ark.ndk); + event.kind = NDKKind.Text; + event.content = serialize(editor.children); - if (!publish) toast.error("Failed to publish event, try again later."); + const publish = await event.publish(); - toast.success( - `Event has been published successfully to ${publish.size} relays.`, - ); + if (publish) { + toast.success( + `Event has been published successfully to ${publish.size} relays.`, + ); - reset(); + // add current post as column thread + addColumn({ + kind: COL_TYPES.thread, + content: event.id, + title: "Thread", + }); + + setLoading(false); + + return reset(); + } + } catch (e) { + setLoading(false); + toast.error(String(e)); + } }; useEffect(() => { @@ -300,7 +319,31 @@ export function EditorForm() { setTarget(null); }} > -
+
+
+

+ New Post +

+
+
+
+ +
+
+ +
+
+
)}
-
-
-
-
- -
-
- -
-
); diff --git a/packages/ui/src/layouts/home.tsx b/packages/ui/src/layouts/home.tsx index a765a44f..7d65efc4 100644 --- a/packages/ui/src/layouts/home.tsx +++ b/packages/ui/src/layouts/home.tsx @@ -1,14 +1,13 @@ -import { ColumnProvider } from "@lume/ark"; import { Outlet } from "react-router-dom"; import { OnboardingModal } from "../onboarding/modal"; export function HomeLayout() { return ( - + <>
-
+ ); } diff --git a/packages/ui/src/navigation.tsx b/packages/ui/src/navigation.tsx index 52f4cea8..c28feafd 100644 --- a/packages/ui/src/navigation.tsx +++ b/packages/ui/src/navigation.tsx @@ -1,34 +1,52 @@ import { + ComposeFilledIcon, + ComposeIcon, DepotFilledIcon, DepotIcon, HomeFilledIcon, HomeIcon, NwcFilledIcon, NwcIcon, - PlusIcon, RelayFilledIcon, RelayIcon, + SettingsFilledIcon, + SettingsIcon, } from "@lume/icons"; import { cn, editorAtom } from "@lume/utils"; -import { useSetAtom } from "jotai"; +import { useAtom } from "jotai"; import { useHotkeys } from "react-hotkeys-hook"; import { NavLink } from "react-router-dom"; import { ActiveAccount } from "./account/active"; export function Navigation() { - const setIsEditorOpen = useSetAtom(editorAtom); + const [isEditorOpen, setIsEditorOpen] = useAtom(editorAtom); useHotkeys("meta+n", () => setIsEditorOpen((state) => !state), []); return (
-
- - {({ isActive }) => ( - <> +
+
+ + +
+
+
+ + {({ isActive }) => (
{isActive ? ( - + ) : ( )}
-
- Home -
- - )} -
- - {({ isActive }) => ( - <> + )} + + + {({ isActive }) => (
)}
-
- Relays -
- - )} -
- - {({ isActive }) => ( - <> + )} + + + {({ isActive }) => (
)}
-
- Depot -
- - )} -
- - {({ isActive }) => ( - <> + )} + + + {({ isActive }) => (
- {isActive ? ( - - ) : ( - - )} +
-
- Wallet -
- + )} +
+
+
+
+ + {({ isActive }) => ( +
+ {isActive ? ( + + ) : ( + + )} +
)}
-
- - -
); } diff --git a/packages/ui/src/onboarding/finish.tsx b/packages/ui/src/onboarding/finish.tsx index d9c394e2..4d976df3 100644 --- a/packages/ui/src/onboarding/finish.tsx +++ b/packages/ui/src/onboarding/finish.tsx @@ -1,21 +1,33 @@ -import { CheckIcon } from "@lume/icons"; +import { useStorage } from "@lume/ark"; +import { CheckIcon, LoaderIcon } from "@lume/icons"; import { onboardingAtom } from "@lume/utils"; import { useQueryClient } from "@tanstack/react-query"; import { motion } from "framer-motion"; import { useSetAtom } from "jotai"; +import { useState } from "react"; export function OnboardingFinishScreen() { + const storage = useStorage(); const queryClient = useQueryClient(); const setOnboarding = useSetAtom(onboardingAtom); + const [loading, setLoading] = useState(false); + const finish = async () => { + setLoading(true); + const queryCache = queryClient.getQueryCache(); const queryKeys = queryCache.getAll().map((cache) => cache.queryKey); + await queryClient.refetchQueries({ + queryKey: ["user", storage.account.pubkey], + }); + for (const key of queryKeys) { await queryClient.refetchQueries({ queryKey: key }); } + setLoading(false); setOnboarding(false); }; @@ -39,7 +51,7 @@ export function OnboardingFinishScreen() { onClick={finish} className="inline-flex items-center justify-center gap-2 w-44 font-medium h-11 rounded-xl bg-blue-100 text-blue-500 hover:bg-blue-200 dark:bg-blue-900 dark:text-blue-500 dark:hover:bg-blue-800" > - Close + {loading ? : "Close"}