diff --git a/apps/desktop/package.json b/apps/desktop/package.json
index ad2263a2..1cd02ced 100644
--- a/apps/desktop/package.json
+++ b/apps/desktop/package.json
@@ -59,6 +59,7 @@
"react-router-dom": "^6.21.1",
"smol-toml": "^1.1.3",
"sonner": "^1.3.1",
+ "unique-names-generator": "^4.7.1",
"virtua": "^0.18.1"
},
"devDependencies": {
diff --git a/apps/desktop/src/router.tsx b/apps/desktop/src/router.tsx
index 8a10a20a..b934ee9b 100644
--- a/apps/desktop/src/router.tsx
+++ b/apps/desktop/src/router.tsx
@@ -1,7 +1,6 @@
import { useArk, useStorage } from "@lume/ark";
import { LoaderIcon } from "@lume/icons";
import { AppLayout, AuthLayout, HomeLayout, SettingsLayout } from "@lume/ui";
-import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";
import { fetch } from "@tauri-apps/plugin-http";
import {
RouterProvider,
@@ -24,7 +23,7 @@ export default function Router() {
element: ,
errorElement: ,
loader: async () => {
- if (!storage.account) return redirect("auth/welcome");
+ if (!storage.account) return redirect("auth");
return null;
},
children: [
@@ -171,7 +170,7 @@ export default function Router() {
errorElement: ,
children: [
{
- path: "welcome",
+ index: true,
async lazy() {
const { WelcomeScreen } = await import("./routes/auth/welcome");
return { Component: WelcomeScreen };
@@ -180,23 +179,7 @@ export default function Router() {
{
path: "create",
loader: async () => {
- const trusted: NDKEvent[] = [];
-
- const services = await ark.ndk.fetchEvents({
- kinds: [NDKKind.AppHandler],
- "#k": ["24133"],
- });
-
- for (const service of services) {
- const nip05 = JSON.parse(service.content).nip05;
- const validate = await ark.validateNIP05({
- pubkey: service.pubkey,
- nip05,
- });
- if (validate) trusted.push(service);
- }
-
- return trusted;
+ return await ark.getOAuthServices();
},
async lazy() {
const { CreateAccountScreen } = await import(
@@ -205,15 +188,6 @@ export default function Router() {
return { Component: CreateAccountScreen };
},
},
- {
- path: "create-profile",
- async lazy() {
- const { CreateProfileScreen } = await import(
- "./routes/auth/create-profile"
- );
- return { Component: CreateProfileScreen };
- },
- },
{
path: "import",
async lazy() {
@@ -232,20 +206,6 @@ export default function Router() {
return { Component: OnboardingScreen };
},
},
- {
- path: "follow",
- async lazy() {
- const { FollowScreen } = await import("./routes/auth/follow");
- return { Component: FollowScreen };
- },
- },
- {
- path: "finish",
- async lazy() {
- const { FinishScreen } = await import("./routes/auth/finish");
- return { Component: FinishScreen };
- },
- },
{
path: "tutorials/note",
async lazy() {
diff --git a/apps/desktop/src/routes/auth/create-profile.tsx b/apps/desktop/src/routes/auth/create-profile.tsx
deleted file mode 100644
index 33dc23ef..00000000
--- a/apps/desktop/src/routes/auth/create-profile.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-export function CreateProfileScreen() {
- return (
-
WIP
- );
-}
diff --git a/apps/desktop/src/routes/auth/create.tsx b/apps/desktop/src/routes/auth/create.tsx
index f429785d..2da7ec88 100644
--- a/apps/desktop/src/routes/auth/create.tsx
+++ b/apps/desktop/src/routes/auth/create.tsx
@@ -1,12 +1,17 @@
-import { useStorage } from "@lume/ark";
+import { useArk, useStorage } from "@lume/ark";
import { CheckIcon, ChevronDownIcon, LoaderIcon } from "@lume/icons";
import NDK, {
NDKEvent,
+ NDKKind,
NDKNip46Signer,
NDKPrivateKeySigner,
} from "@nostr-dev-kit/ndk";
import * as Select from "@radix-ui/react-select";
+import { downloadDir } from "@tauri-apps/api/path";
import { Window } from "@tauri-apps/api/window";
+import { save } from "@tauri-apps/plugin-dialog";
+import { writeTextFile } from "@tauri-apps/plugin-fs";
+import { getPublicKey, nip19 } from "nostr-tools";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { useLoaderData, useNavigate } from "react-router-dom";
@@ -29,17 +34,18 @@ const Item = ({ event }: { event: NDKEvent }) => {
};
export function CreateAccountScreen() {
+ const ark = useArk();
const storage = useStorage();
- const services = useLoaderData() as NDKEvent[];
const navigate = useNavigate();
+ const services = useLoaderData() as NDKEvent[];
- const [serviceId, setServiceId] = useState(services[0].id);
+ const [serviceId, setServiceId] = useState(services?.[0]?.id);
const [loading, setIsLoading] = useState(false);
const {
register,
handleSubmit,
- formState: { isDirty, isValid },
+ formState: { isValid },
} = useForm();
const getDomainName = (id: string) => {
@@ -47,6 +53,31 @@ export function CreateAccountScreen() {
return JSON.parse(event.content).nip05.replace("_@", "") as string;
};
+ const generateNostrKeys = async () => {
+ const signer = NDKPrivateKeySigner.generate();
+ const pubkey = getPublicKey(signer.privateKey);
+
+ const npub = nip19.npubEncode(pubkey);
+ const nsec = nip19.nsecEncode(signer.privateKey);
+
+ ark.updateNostrSigner({ signer });
+
+ const downloadPath = await downloadDir();
+ const fileName = `nostr_keys_${new Date().getTime().toString(36)}.txt`;
+ const filePath = await save({
+ defaultPath: `${downloadPath}/${fileName}`,
+ });
+
+ if (filePath) {
+ await writeTextFile(
+ filePath,
+ `Nostr account, generated by Lume (lume.nu)\nPublic key: ${npub}\nPrivate key: ${nsec}`,
+ );
+ } // else { user cancel action }
+
+ return navigate("/auth/onboarding");
+ };
+
const onSubmit = async (data: { username: string; email: string }) => {
setIsLoading(true);
@@ -71,19 +102,18 @@ export function CreateAccountScreen() {
localSigner,
);
+ let authWindow: Window;
+
remoteSigner.addListener("authUrl", (authUrl: string) => {
- const authWindow = new Window("auth", {
+ authWindow = new Window(`auth-${serviceId}`, {
url: authUrl,
title: domain,
titleBarStyle: "overlay",
width: 415,
height: 600,
- center: true
+ center: true,
+ closable: false,
});
- authWindow.listen(
- "tauri://close-requested",
- async () => await authWindow.close(),
- );
});
const account = await remoteSigner.createAccount(
@@ -93,7 +123,9 @@ export function CreateAccountScreen() {
);
if (!account) {
+ authWindow.close();
setIsLoading(false);
+
return toast.error("Failed to create new account, try again later");
}
@@ -103,15 +135,19 @@ export function CreateAccountScreen() {
privkey: localSigner.privateKey,
});
+ ark.updateNostrSigner({ signer: remoteSigner });
+
+ authWindow.close();
setIsLoading(false);
- return navigate("/auth/create-profile");
+
+ return navigate("/auth/onboarding");
};
return (
-
-
+
+
Let's get you set up on Nostr.
@@ -119,101 +155,109 @@ export function CreateAccountScreen() {
you want.
-