From ed52105c02498630a15f95736f28676b9b60a8f9 Mon Sep 17 00:00:00 2001 From: reya Date: Mon, 12 Feb 2024 20:04:45 +0700 Subject: [PATCH] wip: migrate to desktop2 --- apps/desktop2/package.json | 5 ++ apps/desktop2/src/app.tsx | 30 ++++--- apps/desktop2/src/routes/__root.tsx | 11 +++ apps/desktop2/src/routes/app.tsx | 20 +++++ apps/desktop2/src/routes/app/space.lazy.tsx | 13 +++ apps/desktop2/src/routes/index.tsx | 12 +-- apps/desktop2/src/tree.gen.ts | 21 +++++ packages/ark/src/ark.ts | 10 +-- packages/ark/src/components/user/cover.tsx | 9 +- .../ark/src/components/user/followButton.tsx | 3 + packages/ark/src/components/user/nip05.tsx | 2 +- packages/ark/src/hooks/useRelayList.ts | 90 ------------------- packages/ui/package.json | 1 + packages/ui/src/account/active.tsx | 16 ++-- packages/ui/src/navigation.tsx | 59 ++++-------- pnpm-lock.yaml | 35 +++++++- src-tauri/src/main.rs | 10 ++- src-tauri/tauri.conf.json | 2 + 18 files changed, 172 insertions(+), 177 deletions(-) create mode 100644 apps/desktop2/src/routes/app.tsx create mode 100644 apps/desktop2/src/routes/app/space.lazy.tsx delete mode 100644 packages/ark/src/hooks/useRelayList.ts diff --git a/apps/desktop2/package.json b/apps/desktop2/package.json index 59d38dc0..b8147cb4 100644 --- a/apps/desktop2/package.json +++ b/apps/desktop2/package.json @@ -10,10 +10,15 @@ }, "dependencies": { "@lume/ark": "workspace:^", + "@lume/icons": "workspace:^", "@lume/storage": "workspace:^", + "@lume/ui": "workspace:^", + "@lume/utils": "workspace:^", + "@tanstack/react-query": "^5.18.1", "@tanstack/react-router": "^1.16.0", "i18next": "^23.8.2", "i18next-resources-to-backend": "^1.2.0", + "jotai": "^2.6.4", "react": "^18.2.0", "react-dom": "^18.2.0", "react-i18next": "^14.0.2" diff --git a/apps/desktop2/src/app.tsx b/apps/desktop2/src/app.tsx index 50a735ae..a01c53d9 100644 --- a/apps/desktop2/src/app.tsx +++ b/apps/desktop2/src/app.tsx @@ -1,5 +1,6 @@ import { ArkProvider } from "@lume/ark"; import { StorageProvider } from "@lume/storage"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { RouterProvider, createRouter } from "@tanstack/react-router"; import React, { StrictMode } from "react"; import ReactDOM from "react-dom/client"; @@ -10,30 +11,37 @@ import i18n from "./i18n"; // Import the generated route tree import { routeTree } from "./tree.gen"; -// Create a new router instance -const router = createRouter({ routeTree }); +const queryClient = new QueryClient(); +const router = createRouter({ + routeTree, + context: { + queryClient, + }, + defaultPreload: "intent", + defaultPreloadStaleTime: 0, +}); -// Register the router instance for type safety declare module "@tanstack/react-router" { interface Register { router: typeof router; } } -// Render the app // biome-ignore lint/style/noNonNullAssertion: const rootElement = document.getElementById("root")!; if (!rootElement.innerHTML) { const root = ReactDOM.createRoot(rootElement); root.render( - - - - - - - + + + + + + + + + , ); } diff --git a/apps/desktop2/src/routes/__root.tsx b/apps/desktop2/src/routes/__root.tsx index b88ac49e..680e8254 100644 --- a/apps/desktop2/src/routes/__root.tsx +++ b/apps/desktop2/src/routes/__root.tsx @@ -1,3 +1,4 @@ +import { LoaderIcon } from "@lume/icons"; import { Outlet, ScrollRestoration, @@ -11,4 +12,14 @@ export const Route = createRootRoute({ ), + pendingComponent: Pending, + wrapInSuspense: true, }); + +function Pending() { + return ( +
+ +
+ ); +} diff --git a/apps/desktop2/src/routes/app.tsx b/apps/desktop2/src/routes/app.tsx new file mode 100644 index 00000000..41e6c1c7 --- /dev/null +++ b/apps/desktop2/src/routes/app.tsx @@ -0,0 +1,20 @@ +import { Navigation } from "@lume/ui"; +import { Outlet, createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/app")({ + component: App, +}); + +function App() { + return ( +
+
+
+ +
+ +
+
+
+ ); +} diff --git a/apps/desktop2/src/routes/app/space.lazy.tsx b/apps/desktop2/src/routes/app/space.lazy.tsx new file mode 100644 index 00000000..a8a32bf2 --- /dev/null +++ b/apps/desktop2/src/routes/app/space.lazy.tsx @@ -0,0 +1,13 @@ +import { createLazyFileRoute } from "@tanstack/react-router"; + +export const Route = createLazyFileRoute("/app/space")({ + component: Space, +}); + +function Space() { + return ( +
+

Hello

+
+ ); +} diff --git a/apps/desktop2/src/routes/index.tsx b/apps/desktop2/src/routes/index.tsx index d3370bd6..1658326e 100644 --- a/apps/desktop2/src/routes/index.tsx +++ b/apps/desktop2/src/routes/index.tsx @@ -2,7 +2,6 @@ import { createFileRoute, redirect } from "@tanstack/react-router"; import { invoke } from "@tauri-apps/api/core"; export const Route = createFileRoute("/")({ - component: Index, beforeLoad: async ({ location }) => { const signer = await invoke("verify_signer"); if (!signer) { @@ -13,13 +12,8 @@ export const Route = createFileRoute("/")({ }, }); } + throw redirect({ + to: "/app/space", + }); }, }); - -function Index() { - return ( -
-

Welcome Home!

-
- ); -} diff --git a/apps/desktop2/src/tree.gen.ts b/apps/desktop2/src/tree.gen.ts index 4fa60d03..6d592000 100644 --- a/apps/desktop2/src/tree.gen.ts +++ b/apps/desktop2/src/tree.gen.ts @@ -13,6 +13,7 @@ import { createFileRoute } from '@tanstack/react-router' // Import Routes import { Route as rootRoute } from './routes/__root' +import { Route as AppImport } from './routes/app' import { Route as IndexImport } from './routes/index' import { Route as LandingIndexImport } from './routes/landing/index' @@ -20,9 +21,15 @@ import { Route as LandingIndexImport } from './routes/landing/index' const AuthImportLazyImport = createFileRoute('/auth/import')() const AuthCreateLazyImport = createFileRoute('/auth/create')() +const AppSpaceLazyImport = createFileRoute('/app/space')() // Create/Update Routes +const AppRoute = AppImport.update({ + path: '/app', + getParentRoute: () => rootRoute, +} as any) + const IndexRoute = IndexImport.update({ path: '/', getParentRoute: () => rootRoute, @@ -43,6 +50,11 @@ const AuthCreateLazyRoute = AuthCreateLazyImport.update({ getParentRoute: () => rootRoute, } as any).lazy(() => import('./routes/auth/create.lazy').then((d) => d.Route)) +const AppSpaceLazyRoute = AppSpaceLazyImport.update({ + path: '/space', + getParentRoute: () => AppRoute, +} as any).lazy(() => import('./routes/app/space.lazy').then((d) => d.Route)) + // Populate the FileRoutesByPath interface declare module '@tanstack/react-router' { @@ -51,6 +63,14 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof IndexImport parentRoute: typeof rootRoute } + '/app': { + preLoaderRoute: typeof AppImport + parentRoute: typeof rootRoute + } + '/app/space': { + preLoaderRoute: typeof AppSpaceLazyImport + parentRoute: typeof AppImport + } '/auth/create': { preLoaderRoute: typeof AuthCreateLazyImport parentRoute: typeof rootRoute @@ -70,6 +90,7 @@ declare module '@tanstack/react-router' { export const routeTree = rootRoute.addChildren([ IndexRoute, + AppRoute.addChildren([AppSpaceLazyRoute]), AuthCreateLazyRoute, AuthImportLazyRoute, LandingIndexRoute, diff --git a/packages/ark/src/ark.ts b/packages/ark/src/ark.ts index 8ab44aa7..50b13001 100644 --- a/packages/ark/src/ark.ts +++ b/packages/ark/src/ark.ts @@ -54,7 +54,7 @@ export class Ark { const event = JSON.parse(cmd) as Event; return event; } catch (e) { - console.error(String(e)); + return null; } } @@ -66,7 +66,7 @@ export class Ark { const cmd: Event[] = await invoke("get_text_events", { limit, until }); return cmd; } catch (e) { - console.error(String(e)); + return []; } } @@ -120,7 +120,7 @@ export class Ark { const cmd: Event[] = await invoke("get_event_thread", { id }); return cmd; } catch (e) { - console.error(String(e)); + return []; } } @@ -165,8 +165,8 @@ export class Ark { try { const cmd: Metadata = await invoke("get_profile", { id }); return cmd; - } catch (e) { - console.error(String(e)); + } catch { + return null; } } diff --git a/packages/ark/src/components/user/cover.tsx b/packages/ark/src/components/user/cover.tsx index f9e0ce0d..37199fc2 100644 --- a/packages/ark/src/components/user/cover.tsx +++ b/packages/ark/src/components/user/cover.tsx @@ -7,19 +7,14 @@ export function UserCover({ className }: { className?: string }) { if (!user) { return (
); } if (user && !user.profile.banner) { return ( -
+
); } diff --git a/packages/ark/src/components/user/followButton.tsx b/packages/ark/src/components/user/followButton.tsx index 2c5cfe68..082ac77b 100644 --- a/packages/ark/src/components/user/followButton.tsx +++ b/packages/ark/src/components/user/followButton.tsx @@ -2,11 +2,14 @@ import { LoaderIcon } from "@lume/icons"; import { cn } from "@lume/utils"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; +import { useArk } from "../../provider"; export function UserFollowButton({ target, className, }: { target: string; className?: string }) { + const ark = useArk(); + const [t] = useTranslation(); const [loading, setLoading] = useState(false); const [followed, setFollowed] = useState(false); diff --git a/packages/ark/src/components/user/nip05.tsx b/packages/ark/src/components/user/nip05.tsx index 924d9fb4..090a4eec 100644 --- a/packages/ark/src/components/user/nip05.tsx +++ b/packages/ark/src/components/user/nip05.tsx @@ -37,7 +37,7 @@ export function UserNip05({ className }: { className?: string }) { : user?.profile.nip05}

{!isLoading && verified ? ( - + ) : null}
); diff --git a/packages/ark/src/hooks/useRelayList.ts b/packages/ark/src/hooks/useRelayList.ts deleted file mode 100644 index 3ba660aa..00000000 --- a/packages/ark/src/hooks/useRelayList.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { useMutation, useQueryClient } from "@tanstack/react-query"; -import { useArk } from "../provider"; - -export function useRelaylist() { - const ark = useArk(); - const queryClient = useQueryClient(); - - const connectRelay = useMutation({ - mutationFn: async ( - relay: WebSocket["url"], - purpose?: "read" | "write" | undefined, - ) => { - // Cancel any outgoing refetches - await queryClient.cancelQueries({ - queryKey: ["relay-personal"], - }); - - const relayUrl = normalizeRelayUrl(relay); - - // Snapshot the previous value - const prevRelays: NDKTag[] = queryClient.getQueryData(["relay-personal"]); - - // create new relay list if not exist - if (!prevRelays) { - await ark.createEvent({ - kind: NDKKind.RelayList, - tags: [["r", relay, purpose ?? ""]], - }); - } - - // add relay to exist list - const index = prevRelays.findIndex((el) => el[1] === relay); - if (index > -1) return; - - await ark.createEvent({ - kind: NDKKind.RelayList, - tags: [...prevRelays, ["r", relayUrl, purpose ?? ""]], - }); - - // Optimistically update to the new value - queryClient.setQueryData(["relay-personal"], (prev: NDKTag[]) => [ - ...prev, - ["r", relayUrl, purpose ?? ""], - ]); - - // Return a context object with the snapshotted value - return { prevRelays }; - }, - onSettled: () => { - queryClient.invalidateQueries({ - queryKey: ["relay-personal"], - }); - }, - }); - - const removeRelay = useMutation({ - mutationFn: async (relay: WebSocket["url"]) => { - // Cancel any outgoing refetches - await queryClient.cancelQueries({ - queryKey: ["relay-personal"], - }); - - // Snapshot the previous value - const prevRelays: NDKTag[] = queryClient.getQueryData(["relay-personal"]); - - if (!prevRelays) return; - - const index = prevRelays.findIndex((el) => el[1] === relay); - if (index > -1) prevRelays.splice(index, 1); - - await ark.createEvent({ - kind: NDKKind.RelayList, - tags: prevRelays, - }); - - // Optimistically update to the new value - queryClient.setQueryData(["relay-personal"], prevRelays); - - // Return a context object with the snapshotted value - return { prevRelays }; - }, - onSettled: () => { - queryClient.invalidateQueries({ - queryKey: ["relay-personal"], - }); - }, - }); - - return { connectRelay, removeRelay }; -} diff --git a/packages/ui/package.json b/packages/ui/package.json index 4ceee4af..a5f31295 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -18,6 +18,7 @@ "@radix-ui/react-hover-card": "^1.0.7", "@radix-ui/react-popover": "^1.0.7", "@tanstack/react-query": "^5.18.1", + "@tanstack/react-router": "^1.16.0", "framer-motion": "^11.0.3", "jotai": "^2.6.4", "minidenticons": "^4.2.0", diff --git a/packages/ui/src/account/active.tsx b/packages/ui/src/account/active.tsx index 47aadc5f..e5cb60a2 100644 --- a/packages/ui/src/account/active.tsx +++ b/packages/ui/src/account/active.tsx @@ -15,13 +15,13 @@ export function ActiveAccount() { const svgURI = useMemo( () => `data:image/svg+xml;utf8,${encodeURIComponent( - minidenticon(ark.account.pubkey, 90, 50), + minidenticon(ark.account.npub, 90, 50), )}`, [], ); const { t } = useTranslation(); - const { user } = useProfile(ark.account.pubkey); + const { user } = useProfile(ark.account.npub); return ( @@ -30,24 +30,24 @@ export function ActiveAccount() { {ark.account.pubkey}
diff --git a/packages/ui/src/navigation.tsx b/packages/ui/src/navigation.tsx index 5367ec80..4d6567ec 100644 --- a/packages/ui/src/navigation.tsx +++ b/packages/ui/src/navigation.tsx @@ -2,8 +2,6 @@ import { ArrowUpSquareIcon, BellFilledIcon, BellIcon, - DepotFilledIcon, - DepotIcon, HomeFilledIcon, HomeIcon, PlusIcon, @@ -13,13 +11,13 @@ import { SettingsIcon, } from "@lume/icons"; import { cn, editorAtom, searchAtom } from "@lume/utils"; +import { Link } from "@tanstack/react-router"; import { confirm } from "@tauri-apps/plugin-dialog"; import { relaunch } from "@tauri-apps/plugin-process"; import { Update, check } from "@tauri-apps/plugin-updater"; import { useAtom } from "jotai"; import { useEffect, useState } from "react"; import { useHotkeys } from "react-hotkeys-hook"; -import { NavLink } from "react-router-dom"; import { ActiveAccount } from "./account/active"; import { UnreadActivity } from "./unread"; @@ -65,20 +63,19 @@ export function Navigation() { type="button" onClick={() => setIsEditorOpen((state) => !state)} className={cn( - "flex items-center justify-center h-auto w-full text-black aspect-square rounded-xl hover:text-white dark:text-white", + "flex items-center justify-center h-auto w-full aspect-square rounded-xl text-gray-normal", isEditorOpen - ? "bg-blue-500 text-white" - : "bg-black/5 hover:bg-blue-500 dark:bg-white/5 dark:hover:bg-blue-500", + ? "bg-blue-solid text-white" + : "bg-gray-4 hover:bg-blue-solid dark:bg-graydark-4", )} >
-
+
- {({ isActive }) => ( @@ -97,10 +94,9 @@ export function Navigation() { )}
)} - - + {({ isActive }) => ( @@ -120,29 +116,7 @@ export function Navigation() {
)} - - - {({ isActive }) => ( -
- {isActive ? ( - - ) : ( - - )} -
- )} -
+
@@ -152,10 +126,10 @@ export function Navigation() { onClick={installNewUpdate} className="relative inline-flex flex-col items-center justify-center" > - + Update -
+
@@ -180,9 +154,8 @@ export function Navigation() { )}
- {({ isActive }) => ( @@ -201,7 +174,7 @@ export function Navigation() { )}
)} - + ); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cbd8b2ac..f9300ee7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -259,9 +259,21 @@ importers: '@lume/ark': specifier: workspace:^ version: link:../../packages/ark + '@lume/icons': + specifier: workspace:^ + version: link:../../packages/icons '@lume/storage': specifier: workspace:^ version: link:../../packages/storage + '@lume/ui': + specifier: workspace:^ + version: link:../../packages/ui + '@lume/utils': + specifier: workspace:^ + version: link:../../packages/utils + '@tanstack/react-query': + specifier: ^5.18.1 + version: 5.18.1(react@18.2.0) '@tanstack/react-router': specifier: ^1.16.0 version: 1.16.0(react-dom@18.2.0)(react@18.2.0) @@ -271,6 +283,9 @@ importers: i18next-resources-to-backend: specifier: ^1.2.0 version: 1.2.0 + jotai: + specifier: ^2.6.4 + version: 2.6.4(@types/react@18.2.55)(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -1157,6 +1172,9 @@ importers: '@tanstack/react-query': specifier: ^5.18.1 version: 5.18.1(react@18.2.0) + '@tanstack/react-router': + specifier: ^1.16.0 + version: 1.16.0(react-dom@18.2.0)(react@18.2.0) framer-motion: specifier: ^11.0.3 version: 11.0.3(react-dom@18.2.0)(react@18.2.0) @@ -3616,7 +3634,6 @@ packages: '@types/prop-types': 15.7.11 '@types/scheduler': 0.16.8 csstype: 3.1.3 - dev: true /@types/scheduler@0.16.8: resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==} @@ -5099,6 +5116,22 @@ packages: react: 18.2.0 dev: false + /jotai@2.6.4(@types/react@18.2.55)(react@18.2.0): + resolution: {integrity: sha512-RniwQPX4893YlNR1muOtyUGHYaTD1fhEN4qnOuZJSrDHj6xdEMrqlRSN/hCm2fshwk78ruecB/P2l+NCVWe6TQ==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=17.0.0' + react: '>=17.0.0' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + dependencies: + '@types/react': 18.2.55 + react: 18.2.0 + dev: false + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 9e109eb2..61f02eef 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -164,8 +164,14 @@ fn main() { commands::folder::show_in_folder, commands::opg::fetch_opg, ]) - .run(ctx) - .expect("error while running tauri application"); + .build(ctx) + .expect("error while running tauri application") + .run(|_app_handle, event| match event { + tauri::RunEvent::ExitRequested { api, .. } => { + api.prevent_exit(); + } + _ => {} + }); } fn get_nsec_paths(dir: &Path) -> Result, Box> { diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 29258ac0..cc8f307e 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -32,6 +32,8 @@ } }, "trayIcon": { + "id": "lume-tray", + "tooltip": "Lume", "iconPath": "icons/tray.png" } },