feat: new flow (#235)

* feat: redesign initial screen

* feat: improve login process
This commit is contained in:
雨宮蓮
2024-10-02 14:56:26 +07:00
committed by GitHub
parent 0c19ada1ab
commit e098743d43
9 changed files with 221 additions and 140 deletions

View File

@@ -20,7 +20,7 @@ export function NoteOpenThread() {
</Tooltip.Trigger>
<Tooltip.Portal>
<Tooltip.Content className="inline-flex h-7 select-none text-neutral-50 dark:text-neutral-950 items-center justify-center rounded-md bg-neutral-950 dark:bg-neutral-50 px-3.5 text-sm will-change-[transform,opacity] data-[state=delayed-open]:data-[side=bottom]:animate-slideUpAndFade data-[state=delayed-open]:data-[side=left]:animate-slideRightAndFade data-[state=delayed-open]:data-[side=right]:animate-slideLeftAndFade data-[state=delayed-open]:data-[side=top]:animate-slideDownAndFade">
Open
View thread
<Tooltip.Arrow className="fill-neutral-950 dark:fill-neutral-50" />
</Tooltip.Content>
</Tooltip.Portal>

View File

@@ -15,6 +15,9 @@ export function UserAvatar({ className }: { className?: string }) {
const picture = useMemo(() => {
if (service?.length && user.profile?.picture?.length) {
if (user.profile?.picture.includes("_next/")) {
return user.profile?.picture;
}
return `${service}?url=${user.profile?.picture}&w=100&h=100&n=-1&default=${user.profile?.picture}`;
} else {
return user.profile?.picture;

View File

@@ -2,7 +2,7 @@ import { commands } from "@/commands.gen";
import { appSettings, displayNpub } from "@/commons";
import { Frame, Spinner, User } from "@/components";
import { ArrowRight, DotsThree, GearSix, Plus } from "@phosphor-icons/react";
import { Link, createLazyFileRoute } from "@tanstack/react-router";
import { createLazyFileRoute } from "@tanstack/react-router";
import { Menu, MenuItem } from "@tauri-apps/api/menu";
import { message } from "@tauri-apps/plugin-dialog";
import {
@@ -37,6 +37,32 @@ function Screen() {
const [password, setPassword] = useState("");
const [isPending, startTransition] = useTransition();
const showContextMenu = useCallback(
async (e: React.MouseEvent, account: string) => {
e.stopPropagation();
const menuItems = await Promise.all([
MenuItem.new({
text: "Reset password",
enabled: !account.includes("_nostrconnect"),
// @ts-ignore, this is tanstack router bug
action: () => navigate({ to: "/reset", search: { account } }),
}),
MenuItem.new({
text: "Delete account",
action: async () => await deleteAccount(account),
}),
]);
const menu = await Menu.new({
items: menuItems,
});
await menu.popup().catch((e) => console.error(e));
},
[],
);
const deleteAccount = async (account: string) => {
const res = await commands.deleteAccount(account);
@@ -69,12 +95,14 @@ function Screen() {
if (status) {
navigate({
to: "/$account/home",
// @ts-ignore, this is tanstack router bug
params: { account: res.data },
replace: true,
});
} else {
navigate({
to: "/loading",
// @ts-ignore, this is tanstack router bug
search: { account: res.data },
replace: true,
});
@@ -86,31 +114,6 @@ function Screen() {
});
};
const showContextMenu = useCallback(
async (e: React.MouseEvent, account: string) => {
e.stopPropagation();
const menuItems = await Promise.all([
MenuItem.new({
text: "Reset password",
enabled: !account.includes("_nostrconnect"),
action: () => navigate({ to: "/reset", search: { account } }),
}),
MenuItem.new({
text: "Delete account",
action: async () => await deleteAccount(account),
}),
]);
const menu = await Menu.new({
items: menuItems,
});
await menu.popup().catch((e) => console.error(e));
},
[],
);
useEffect(() => {
if (autoLogin) {
loginWith();
@@ -204,8 +207,8 @@ function Screen() {
</div>
</div>
))}
<Link
to="/new"
<a
href="/new"
className="flex items-center justify-between hover:bg-black/5 dark:hover:bg-white/5"
>
<div className="flex items-center gap-2.5 p-3">
@@ -216,17 +219,17 @@ function Screen() {
New account
</span>
</div>
</Link>
</a>
</Frame>
</div>
<div className="absolute bottom-2 right-2">
<Link
to="/bootstrap-relays"
<a
href="/bootstrap-relays"
className="h-8 w-max text-xs px-3 inline-flex items-center justify-center gap-1.5 bg-black/5 hover:bg-black/10 dark:bg-white/5 dark:hover:bg-white/10 rounded-full"
>
<GearSix className="size-4" />
Manage Relays
</Link>
</a>
</div>
</div>
);

View File

@@ -1,4 +1,4 @@
import { Spinner } from "@/components";
import { Frame, Spinner } from "@/components";
import { createFileRoute } from "@tanstack/react-router";
import { listen } from "@tauri-apps/api/event";
import { useEffect } from "react";
@@ -24,6 +24,7 @@ function Screen() {
const unlisten = listen("synchronized", () => {
navigate({
to: "/$account/home",
// @ts-ignore, this is tanstack router bug
params: { account: search.account },
replace: true,
});
@@ -36,12 +37,15 @@ function Screen() {
return (
<div className="size-full flex items-center justify-center">
<div className="flex flex-col gap-2 items-center justify-center text-center">
<Frame
className="p-6 h-36 flex flex-col gap-2 items-center justify-center text-center rounded-xl overflow-hidden"
shadow
>
<Spinner />
<p className="text-sm">
<p className="text-sm text-neutral-600 dark:text-neutral-40">
Fetching necessary data for the first time login...
</p>
</div>
</Frame>
</div>
);
}

View File

@@ -1,6 +1,4 @@
import { GoBack } from "@/components";
import { ArrowLeft } from "@phosphor-icons/react";
import { Link, createLazyFileRoute } from "@tanstack/react-router";
import { createLazyFileRoute } from "@tanstack/react-router";
export const Route = createLazyFileRoute("/new")({
component: Screen,
@@ -10,42 +8,79 @@ function Screen() {
return (
<div
data-tauri-drag-region
className="relative size-full flex items-center justify-center"
className="bg-white/50 dark:bg-black/50 relative size-full flex items-center justify-center"
>
<div className="w-[320px] flex flex-col gap-8">
<div className="w-[350px] flex flex-col gap-8">
<div className="flex flex-col gap-1 text-center">
<h1 className="leading-tight text-xl font-semibold">
Welcome to Nostr.
<h1 className="leading-tight text-lg font-semibold">
How would you like to use Lume?
</h1>
</div>
<div className="flex flex-col gap-4">
<Link
to="/auth/new"
className="w-full h-10 bg-blue-500 font-medium hover:bg-blue-600 text-white rounded-lg inline-flex items-center justify-center shadow"
<a
href="/auth/connect"
className="w-full p-4 rounded-xl hover:shadow-lg hover:ring-0 hover:bg-white dark:hover:bg-neutral-900 ring-1 ring-black/5 dark:ring-white/5"
>
Create a new identity
</Link>
<div className="w-full h-px bg-black/5 dark:bg-white/5" />
<h3 className="mb-1.5 font-medium">Continue with Nostr Connect</h3>
<div className="text-sm">
<p className="text-neutral-500 dark:text-neutral-600">
Your account will be handled by a remote signer. Lume will not
store your account keys.
</p>
</div>
</a>
<a
href="/auth/import"
className="w-full p-4 rounded-xl hover:shadow-lg hover:ring-0 hover:bg-white dark:hover:bg-neutral-900 ring-1 ring-black/5 dark:ring-white/5"
>
<h3 className="mb-1.5 font-medium">Continue with Secret Key</h3>
<div className="text-sm">
<p className="text-neutral-500 dark:text-neutral-600">
Lume will store your keys in secure storage. You can provide a
password to add extra security.
</p>
</div>
</a>
<div className="flex items-center justify-between gap-2">
<div className="flex-1 h-px bg-black/5 dark:bg-white/5" />
<div className="shrink-0 text-sm text-neutral-500 dark:text-neutral-400">
Do you not have a Nostr account yet?
</div>
<div className="flex-1 h-px bg-black/5 dark:bg-white/5" />
</div>
<div className="flex flex-col gap-2">
<Link
to="/auth/connect"
className="w-full h-10 bg-white hover:bg-neutral-100 dark:hover:bg-neutral-100 dark:text-black rounded-lg inline-flex items-center justify-center"
<a
href="https://nsec.app"
target="_blank"
rel="noreferrer"
className="text-sm bg-black/5 dark:bg-white/5 hover:bg-black/10 dark:hover:bg-white/10 rounded-lg flex items-center gap-1.5 h-9 px-1"
>
Login with Nostr Connect
</Link>
<Link
to="/auth/import"
className="w-full h-10 bg-white hover:bg-neutral-100 dark:hover:bg-neutral-100 dark:text-black rounded-lg inline-flex items-center justify-center"
<div className="size-7 rounded-md bg-black inline-flex items-center justify-center">
<img src="/nsec_app.svg" alt="nsec.app" className="size-5" />
</div>
Create one with nsec.app
</a>
<a
href="https://nosta.me"
target="_blank"
rel="noreferrer"
className="text-sm bg-black/5 dark:bg-white/5 hover:bg-black/10 dark:hover:bg-white/10 rounded-lg flex items-center gap-1.5 h-9 px-1"
>
Login with Private Key
</Link>
<div className="size-7 rounded-md bg-black overflow-hidden">
<img
src="/nosta.jpg"
alt="nosta"
className="size-7 object-cover"
/>
</div>
Create one with nosta.me
</a>
<p className="text-xs text-neutral-400 dark:text-neutral-600">
Or you can create account from other Nostr clients.
</p>
</div>
</div>
</div>
<GoBack className="fixed top-11 left-2 flex items-center gap-1.5 text-sm font-medium">
<ArrowLeft className="size-5" />
Back
</GoBack>
</div>
);
}