diff --git a/bun.lockb b/bun.lockb
index 78029912..56a1718b 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/package.json b/package.json
index 30586057..35b8b5b1 100644
--- a/package.json
+++ b/package.json
@@ -41,6 +41,7 @@
"@void-cat/api": "^1.0.7",
"dayjs": "^1.11.9",
"destr": "^2.0.1",
+ "framer-motion": "^10.16.4",
"get-urls": "^12.1.0",
"html-to-text": "^9.0.5",
"light-bolt11-decoder": "^3.0.0",
diff --git a/src/app/auth/components/user.tsx b/src/app/auth/components/user.tsx
index 66175688..4b2b7c97 100644
--- a/src/app/auth/components/user.tsx
+++ b/src/app/auth/components/user.tsx
@@ -1,7 +1,6 @@
import { Image } from '@shared/image';
import { useProfile } from '@utils/hooks/useProfile';
-import { displayNpub } from '@utils/shortenKey';
export function User({ pubkey, fallback }: { pubkey: string; fallback?: string }) {
const { status, user } = useProfile(pubkey, fallback);
@@ -19,19 +18,19 @@ export function User({ pubkey, fallback }: { pubkey: string; fallback?: string }
}
return (
-
+
-
+
{user?.name || user?.display_name}
-
- {displayNpub(pubkey, 16)}
-
+
+ {user?.about || user?.bio || 'No bio'}
+
);
diff --git a/src/app/auth/create/step-1.tsx b/src/app/auth/create/step-1.tsx
index 1276cec6..837506e5 100644
--- a/src/app/auth/create/step-1.tsx
+++ b/src/app/auth/create/step-1.tsx
@@ -1,13 +1,14 @@
-import { BaseDirectory, writeTextFile } from '@tauri-apps/api/fs';
+import { writeText } from '@tauri-apps/api/clipboard';
+import { message, save } from '@tauri-apps/api/dialog';
+import { writeTextFile } from '@tauri-apps/api/fs';
+import { downloadDir } from '@tauri-apps/api/path';
import { generatePrivateKey, getPublicKey, nip19 } from 'nostr-tools';
import { useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useStorage } from '@libs/storage/provider';
-import { Button } from '@shared/button';
-import { EyeOffIcon, EyeOnIcon, LoaderIcon } from '@shared/icons';
-import { ArrowRightCircleIcon } from '@shared/icons/arrowRightCircle';
+import { CopyIcon } from '@shared/icons';
import { useOnboarding } from '@stores/onboarding';
import { useStronghold } from '@stores/stronghold';
@@ -21,8 +22,8 @@ export function CreateStep1Screen() {
const setPubkey = useOnboarding((state) => state.setPubkey);
const setStep = useOnboarding((state) => state.setStep);
- const [privkeyInput, setPrivkeyInput] = useState('password');
const [loading, setLoading] = useState(false);
+ const [copied, setCopied] = useState(false);
const [downloaded, setDownloaded] = useState(false);
const privkey = useMemo(() => generatePrivateKey(), []);
@@ -30,24 +31,36 @@ export function CreateStep1Screen() {
const npub = nip19.npubEncode(pubkey);
const nsec = nip19.nsecEncode(privkey);
- // toggle private key
- const showPrivateKey = () => {
- if (privkeyInput === 'password') {
- setPrivkeyInput('text');
- } else {
- setPrivkeyInput('password');
+ const download = async () => {
+ try {
+ const downloadPath = await downloadDir();
+ const fileName = `nostr_keys_${new Date().toISOString()}.txt`;
+ const filePath = await save({
+ defaultPath: downloadPath + '/' + fileName,
+ });
+
+ if (filePath) {
+ await writeTextFile(
+ filePath,
+ `Generated by Lume (lume.nu)\nPublic key: ${npub}\nPrivate key: ${nsec}`
+ );
+
+ setDownloaded(true);
+ } // else { user cancel action }
+ } catch (e) {
+ await message(e, { title: 'Cannot download account keys', type: 'error' });
}
};
- const download = async () => {
- await writeTextFile(
- `nostr_keys_${new Date().toISOString().slice(0, 10)}.txt`,
- `Generated by Lume (lume.nu)\nPublic key: ${npub}\nPrivate key: ${nsec}`,
- {
- dir: BaseDirectory.Download,
- }
- );
- setDownloaded(true);
+ const copyPrivkey = async () => {
+ try {
+ await writeText(nsec);
+ setCopied(true);
+
+ setTimeout(() => setCopied(false), 3000);
+ } catch (e) {
+ await message(e, { title: 'Cannot copy private key', type: 'error' });
+ }
};
const submit = () => {
@@ -72,76 +85,68 @@ export function CreateStep1Screen() {
return (
-
-
Save your access key!
+
+
+ This is your new Nostr account
+
+
+ Your private key is your password. If you lose this key, you will lose access to
+ your account! Copy it and keep it in a safe place. There is no way to reset your
+ private key.
+
+
+ Public key is used for sharing with other people so that they can find you using
+ the public key.
+
-
-
- Public Key
-
-
-
-
Private Key
-
+
+
+
+
Private Key
+
+
+ copyPrivkey()}
+ className="group absolute right-2 top-1/2 inline-flex h-7 -translate-y-1/2 transform items-center gap-1.5 rounded-md bg-white/20 px-2.5 text-sm hover:bg-white/30"
+ >
+
+ {copied ? 'Copied' : 'Copy'}
+
+
+
+
+ Public Key
- showPrivateKey()}
- className="group absolute right-2 top-1/2 -translate-y-1/2 transform rounded p-1 backdrop-blur-xl hover:bg-white/10"
- >
- {privkeyInput === 'password' ? (
-
- ) : (
-
- )}
-
-
-
-
- Your private key is your password. If you lose this key, you will lose
- access to your account! Copy it and keep it in a safe place. There is no way
- to reset your private key.
-
submit()}
- className="inline-flex h-11 w-full items-center justify-between gap-2 rounded-lg bg-fuchsia-500 px-6 font-medium leading-none text-white hover:bg-fuchsia-600 focus:outline-none"
+ onClick={() => download()}
+ className="inline-flex h-12 w-full items-center justify-center rounded-lg bg-fuchsia-500 px-6 font-medium leading-none text-white hover:bg-fuchsia-600 focus:outline-none"
>
- {loading ? (
- <>
-
- Creating...
-
- >
- ) : (
- <>
-
- I have saved my key, continue
-
- >
- )}
+ {downloaded ? 'Downloaded' : 'Download account keys'}
- {downloaded ? (
-
- Saved in Download folder
-
- ) : (
-
download()}>
- Download
-
- )}
+
submit()}
+ className="inline-flex h-12 w-full items-center justify-center rounded-lg border-t border-white/10 bg-white/20 px-6 font-medium leading-none text-white hover:bg-white/30 focus:outline-none"
+ >
+ {loading ? 'Creating...' : 'Continue'}
+
+
+ By clicking 'Continue', you are ensuring that your keys are saved in
+ a safe place. You cannot recover these keys if they are lost.
+
diff --git a/src/app/auth/create/step-2.tsx b/src/app/auth/create/step-2.tsx
index 34586420..6f810353 100644
--- a/src/app/auth/create/step-2.tsx
+++ b/src/app/auth/create/step-2.tsx
@@ -86,10 +86,16 @@ export function CreateStep2Screen() {
return (
-
-
+
+
Set password to secure your key
+
+ Password is not related to your Nostr account. It is only used to secure your
+ keys stored on your local machine and to unlock the app (like unlocking your
+ phone with a passcode). When you move to other Nostr clients, you just need to
+ copy your private key.
+
-
-
- Password is use to secure your key store in local machine, when you move
- to other clients, you just need to copy your private key as nsec or
- hexstring
-
-
{errors.password && {errors.password.message}
}
@@ -127,12 +126,12 @@ export function CreateStep2Screen() {
{loading ? (
<>
- Creating...
+ Securing your account...
>
) : (
diff --git a/src/app/auth/create/step-3.tsx b/src/app/auth/create/step-3.tsx
index e22364b0..f9c08c1c 100644
--- a/src/app/auth/create/step-3.tsx
+++ b/src/app/auth/create/step-3.tsx
@@ -61,15 +61,22 @@ export function CreateStep3Screen() {
return (
-
-
Create your profile
+
+
+ Personalize your Nostr profile
+
+
+ Nostr profile is synchronous across all Nostr clients. If you create a profile
+ on Lume, it will also work well with other Nostr clients. If you update your
+ profile on another Nostr client, it will also sync to Lume.
+