diff --git a/package.json b/package.json index e67b2bf..bd50031 100644 --- a/package.json +++ b/package.json @@ -1,51 +1,51 @@ { - "name": "coop", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc && vite build", - "preview": "vite preview", - "tauri": "tauri" - }, - "dependencies": { - "@phosphor-icons/react": "^2.1.7", - "@radix-ui/react-avatar": "^1.1.0", - "@radix-ui/react-scroll-area": "^1.1.0", - "@tanstack/react-query": "^5.51.11", - "@tanstack/react-router": "^1.45.8", - "@tauri-apps/api": ">=2.0.0-beta.0", - "@tauri-apps/plugin-clipboard-manager": "2.1.0-beta.5", - "@tauri-apps/plugin-dialog": "2.0.0-beta.7", - "@tauri-apps/plugin-os": "2.0.0-beta.7", - "@tauri-apps/plugin-shell": ">=2.0.0-beta.0", - "dayjs": "^1.11.12", - "minidenticons": "^4.2.1", - "nostr-tools": "^2.7.1", - "react": "19.0.0-rc-d025ddd3-20240722", - "react-dom": "19.0.0-rc-d025ddd3-20240722", - "virtua": "^0.33.3" - }, - "devDependencies": { - "@biomejs/biome": "1.8.3", - "@tanstack/router-plugin": "^1.45.8", - "@tauri-apps/cli": ">=2.0.0-beta.0", - "@types/react": "npm:types-react@rc", - "@types/react-dom": "npm:types-react-dom@rc", - "@vitejs/plugin-react": "^4.2.1", - "autoprefixer": "^10.4.19", - "babel-plugin-react-compiler": "0.0.0-experimental-696af53-20240625", - "clsx": "^2.1.1", - "postcss": "^8.4.39", - "tailwind-merge": "^2.4.0", - "tailwindcss": "^3.4.6", - "typescript": "^5.2.2", - "vite": "^5.3.1", - "vite-tsconfig-paths": "^4.3.2" - }, - "overrides": { - "@types/react": "npm:types-react@rc", - "@types/react-dom": "npm:types-react-dom@rc" - } + "name": "coop", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "tauri": "tauri" + }, + "dependencies": { + "@phosphor-icons/react": "^2.1.7", + "@radix-ui/react-avatar": "^1.1.0", + "@radix-ui/react-scroll-area": "^1.1.0", + "@tanstack/react-query": "^5.51.11", + "@tanstack/react-router": "^1.45.8", + "@tauri-apps/api": ">=2.0.0-beta.0", + "@tauri-apps/plugin-clipboard-manager": "2.1.0-beta.5", + "@tauri-apps/plugin-dialog": "2.0.0-beta.7", + "@tauri-apps/plugin-os": "2.0.0-beta.7", + "@tauri-apps/plugin-shell": ">=2.0.0-beta.0", + "dayjs": "^1.11.12", + "minidenticons": "^4.2.1", + "nostr-tools": "^2.7.1", + "react": "19.0.0-rc-d025ddd3-20240722", + "react-dom": "19.0.0-rc-d025ddd3-20240722", + "virtua": "^0.33.3" + }, + "devDependencies": { + "@biomejs/biome": "1.8.3", + "@tanstack/router-plugin": "^1.45.8", + "@tauri-apps/cli": ">=2.0.0-beta.0", + "@types/react": "npm:types-react@rc", + "@types/react-dom": "npm:types-react-dom@rc", + "@vitejs/plugin-react": "^4.2.1", + "autoprefixer": "^10.4.19", + "babel-plugin-react-compiler": "0.0.0-experimental-696af53-20240625", + "clsx": "^2.1.1", + "postcss": "^8.4.39", + "tailwind-merge": "^2.4.0", + "tailwindcss": "^3.4.6", + "typescript": "^5.2.2", + "vite": "^5.3.1", + "vite-tsconfig-paths": "^4.3.2" + }, + "overrides": { + "@types/react": "npm:types-react@rc", + "@types/react-dom": "npm:types-react-dom@rc" + } } diff --git a/src-tauri/src/commands/account.rs b/src-tauri/src/commands/account.rs index 2463390..be894bd 100644 --- a/src-tauri/src/commands/account.rs +++ b/src-tauri/src/commands/account.rs @@ -149,78 +149,17 @@ pub async fn login( state: State<'_, Nostr>, handle: tauri::AppHandle, ) -> Result { + let app = handle.app_handle().clone(); let client = &state.client; let public_key = PublicKey::parse(&id).map_err(|e| e.to_string())?; + let hex = public_key.to_hex(); let keyring = Entry::new(&id, "nostr_secret").expect("Unexpected."); - let password = match keyring.get_password() { - Ok(pw) => pw, - Err(_) => return Err("Cancelled".into()), - }; - - match bunker { - Some(uri) => { - let app_keys = - Keys::parse(password).expect("Secret Key is modified, please check again."); - - match NostrConnectURI::parse(uri) { - Ok(bunker_uri) => { - match Nip46Signer::new(bunker_uri, app_keys, Duration::from_secs(30), None) - .await - { - Ok(signer) => client.set_signer(Some(signer.into())).await, - Err(err) => return Err(err.to_string()), - } - } - Err(err) => return Err(err.to_string()), - } - } - None => { - let keys = Keys::parse(password).expect("Secret Key is modified, please check again."); - let signer = NostrSigner::Keys(keys); - - // Update signer - client.set_signer(Some(signer)).await; - } - } - - let hex = public_key.to_hex(); - let inbox = Filter::new().kind(Kind::Custom(10050)).author(public_key).limit(1); - - if let Ok(events) = client.get_events_of(vec![inbox], None).await { - if let Some(event) = events.into_iter().next() { - for tag in &event.tags { - if let Some(TagStandard::Relay(url)) = tag.as_standardized() { - let url = url.to_string(); - - if client.add_relay(&url).await.is_ok() { - println!("Adding relay {} ...", url); - - if client.connect_relay(&url).await.is_ok() { - println!("Connecting relay {} ...", url); - } - } - } - } - } - } - tauri::async_runtime::spawn(async move { - let window = handle.get_webview_window("main").expect("Window is terminated."); + let window = app.get_webview_window("main").expect("Window is terminated."); let state = window.state::(); let client = &state.client; - let old = Filter::new().kind(Kind::GiftWrap).pubkey(public_key); - let new = Filter::new().kind(Kind::GiftWrap).pubkey(public_key).limit(0); - - if client.reconcile(old, NegentropyOptions::default()).await.is_ok() { - println!("Sync done.") - }; - - if client.subscribe(vec![new], None).await.is_ok() { - println!("Waiting for new message...") - }; - client .handle_notifications(|notification| async { if let RelayPoolNotification::Message { message, relay_url } = notification { @@ -265,5 +204,64 @@ pub async fn login( .await }); + let password = match keyring.get_password() { + Ok(pw) => pw, + Err(_) => return Err("Cancelled".into()), + }; + + match bunker { + Some(uri) => { + let app_keys = + Keys::parse(password).expect("Secret Key is modified, please check again."); + + match NostrConnectURI::parse(uri) { + Ok(bunker_uri) => { + match Nip46Signer::new(bunker_uri, app_keys, Duration::from_secs(30), None) + .await + { + Ok(signer) => client.set_signer(Some(signer.into())).await, + Err(err) => return Err(err.to_string()), + } + } + Err(err) => return Err(err.to_string()), + } + } + None => { + let keys = Keys::parse(password).expect("Secret Key is modified, please check again."); + let signer = NostrSigner::Keys(keys); + + // Update signer + client.set_signer(Some(signer)).await; + } + } + + let inbox = Filter::new().kind(Kind::Custom(10050)).author(public_key).limit(1); + let old = Filter::new().kind(Kind::GiftWrap).pubkey(public_key); + let new = Filter::new().kind(Kind::GiftWrap).pubkey(public_key).limit(0); + + let mut relays = Vec::new(); + + if let Ok(events) = client.get_events_of(vec![inbox], None).await { + if let Some(event) = events.into_iter().next() { + for tag in &event.tags { + if let Some(TagStandard::Relay(relay)) = tag.as_standardized() { + let url = relay.to_string(); + if client.add_relay(&url).await.is_ok() { + relays.push(url) + } + } + } + } + } + + if client.reconcile_with(relays.clone(), old, NegentropyOptions::default()).await.is_ok() { + handle.emit("synchronized", ()).unwrap(); + println!("synchronized"); + }; + + if client.subscribe_to(relays, vec![new], None).await.is_ok() { + println!("Waiting for new message...") + }; + Ok(hex) } diff --git a/src-tauri/src/commands/chat.rs b/src-tauri/src/commands/chat.rs index b4971f5..6212408 100644 --- a/src-tauri/src/commands/chat.rs +++ b/src-tauri/src/commands/chat.rs @@ -16,7 +16,7 @@ pub async fn get_chats(state: State<'_, Nostr>) -> Result, String> { let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key); - match client.database().query(vec![filter], Order::Desc).await { + match client.get_events_of(vec![filter], None).await { Ok(events) => { let rumors = stream::iter(events) .filter_map(|ev| async move { @@ -51,14 +51,13 @@ pub async fn get_chat_messages( state: State<'_, Nostr>, ) -> Result, String> { let client = &state.client; - let database = client.database(); let signer = client.signer().await.map_err(|e| e.to_string())?; let receiver_pk = signer.public_key().await.map_err(|e| e.to_string())?; let sender_pk = PublicKey::parse(sender).map_err(|e| e.to_string())?; let filter = Filter::new().kind(Kind::GiftWrap).pubkeys(vec![receiver_pk, sender_pk]); - match database.query(vec![filter], Order::Desc).await { + match client.get_events_of(vec![filter], None).await { Ok(events) => { let rumors = stream::iter(events) .filter_map(|ev| async move { @@ -84,14 +83,18 @@ pub async fn get_chat_messages( #[tauri::command] #[specta::specta] -pub async fn subscribe_to(id: String, state: State<'_, Nostr>) -> Result<(), String> { +pub async fn subscribe_to( + id: String, + relays: Vec, + state: State<'_, Nostr>, +) -> Result<(), String> { let client = &state.client; let public_key = PublicKey::parse(&id).map_err(|e| e.to_string())?; let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key).limit(0); let subscription_id = SubscriptionId::new(&id[..6]); - if client.subscribe_with_id(subscription_id, vec![filter], None).await.is_ok() { + if client.subscribe_with_id_to(relays, subscription_id, vec![filter], None).await.is_ok() { println!("Watching ... {}", id) }; @@ -126,8 +129,6 @@ pub async fn get_inboxes(id: String, state: State<'_, Nostr>) -> Result) -> Result, state: State<'_, Nostr>) -> Result<(), ()> { - let client = &state.client; - - for relay in relays.iter() { - let _ = client.disconnect_relay(relay).await; - } - - Ok(()) -} - #[tauri::command] #[specta::specta] pub async fn send_message( diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index fc8e8af..37b540e 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -35,7 +35,6 @@ fn main() { send_message, subscribe_to, unsubscribe, - drop_inbox ]); #[cfg(debug_assertions)] @@ -71,9 +70,10 @@ fn main() { // Config let opts = Options::new() - .automatic_authentication(true) + .autoconnect(true) + .automatic_authentication(false) .timeout(Duration::from_secs(5)) - .send_timeout(Some(Duration::from_secs(5))) + .send_timeout(Some(Duration::from_secs(50))) .connection_timeout(Some(Duration::from_secs(20))); // Setup nostr client @@ -83,11 +83,8 @@ fn main() { }; // Add bootstrap relay - let _ = client.add_relay("wss://relay.damus.io/").await; - let _ = client.add_relay("wss://relay.nostr.net/").await; - - // Connect - client.connect().await; + let _ = + client.add_relays(["wss://relay.damus.io/", "wss://relay.nostr.net/"]).await; // Create global state app.handle().manage(Nostr { client, contact_list: Mutex::new(vec![]) }) diff --git a/src/assets/react.svg b/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/commands.ts b/src/commands.ts index 2bf36e1..a0fc3ec 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -79,9 +79,9 @@ try { else return { status: "error", error: e as any }; } }, -async subscribeTo(id: string) : Promise> { +async subscribeTo(id: string, relays: string[]) : Promise> { try { - return { status: "ok", data: await TAURI_INVOKE("subscribe_to", { id }) }; + return { status: "ok", data: await TAURI_INVOKE("subscribe_to", { id, relays }) }; } catch (e) { if(e instanceof Error) throw e; else return { status: "error", error: e as any }; @@ -94,14 +94,6 @@ try { if(e instanceof Error) throw e; else return { status: "error", error: e as any }; } -}, -async dropInbox(relays: string[]) : Promise> { -try { - return { status: "ok", data: await TAURI_INVOKE("drop_inbox", { relays }) }; -} catch (e) { - if(e instanceof Error) throw e; - else return { status: "error", error: e as any }; -} } } diff --git a/src/commons.ts b/src/commons.ts index 463d509..dae9dcc 100644 --- a/src/commons.ts +++ b/src/commons.ts @@ -1,8 +1,10 @@ +import { useQuery } from "@tanstack/react-query"; import { type ClassValue, clsx } from "clsx"; import dayjs from "dayjs"; import relativeTime from "dayjs/plugin/relativeTime"; import updateLocale from "dayjs/plugin/updateLocale"; import { twMerge } from "tailwind-merge"; +import { commands } from "./commands"; dayjs.extend(relativeTime); dayjs.extend(updateLocale); @@ -72,3 +74,20 @@ export function getReceivers(tags: string[][]) { const p = tags.map((tag) => tag[0] === "p" && tag[1]); return p; } + +export const useRelays = (id: string) => + useQuery({ + queryKey: ["relays", id], + queryFn: async () => { + const res = await commands.getInboxes(id); + + if (res.status === "ok") { + return res.data; + } else { + throw new Error(res.error); + } + }, + refetchOnWindowFocus: false, + refetchOnMount: false, + refetchOnReconnect: false, + }); diff --git a/src/components/spinner.tsx b/src/components/spinner.tsx index 3342142..a107e44 100644 --- a/src/components/spinner.tsx +++ b/src/components/spinner.tsx @@ -1,14 +1,11 @@ import { cn } from "@/commons"; -import type { ReactNode } from "react"; export function Spinner({ - children, className, }: { - children?: ReactNode; className?: string; }) { - const spinner = ( + return ( @@ -20,28 +17,4 @@ export function Spinner({ ); - - if (children === undefined) return spinner; - - return ( -
- - {/** - * `display: contents` removes the content from the accessibility tree in some browsers, - * so we force remove it with `aria-hidden` - */} - - {children} - -
- {spinner} -
-
-
- ); } diff --git a/src/components/user/avatar.tsx b/src/components/user/avatar.tsx index 3119164..a5904f7 100644 --- a/src/components/user/avatar.tsx +++ b/src/components/user/avatar.tsx @@ -21,13 +21,15 @@ export function UserAvatar({ className }: { className?: string }) { className, )} > - + {user?.profile?.picture ? ( + + ) : null} ) { + return ( + + + + ); +} diff --git a/src/routes.gen.ts b/src/routes.gen.ts index 2d95daf..5a398ed 100644 --- a/src/routes.gen.ts +++ b/src/routes.gen.ts @@ -22,6 +22,7 @@ const NewLazyImport = createFileRoute('/new')() const ImportKeyLazyImport = createFileRoute('/import-key')() const CreateAccountLazyImport = createFileRoute('/create-account')() const AccountChatsLazyImport = createFileRoute('/$account/chats')() +const AccountChatsNewLazyImport = createFileRoute('/$account/chats/new')() const AccountChatsIdLazyImport = createFileRoute('/$account/chats/$id')() // Create/Update Routes @@ -60,6 +61,13 @@ const AccountChatsLazyRoute = AccountChatsLazyImport.update({ import('./routes/$account.chats.lazy').then((d) => d.Route), ) +const AccountChatsNewLazyRoute = AccountChatsNewLazyImport.update({ + path: '/new', + getParentRoute: () => AccountChatsLazyRoute, +} as any).lazy(() => + import('./routes/$account.chats.new.lazy').then((d) => d.Route), +) + const AccountChatsIdLazyRoute = AccountChatsIdLazyImport.update({ path: '/$id', getParentRoute: () => AccountChatsLazyRoute, @@ -120,6 +128,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AccountChatsIdLazyImport parentRoute: typeof AccountChatsLazyImport } + '/$account/chats/new': { + id: '/$account/chats/new' + path: '/new' + fullPath: '/$account/chats/new' + preLoaderRoute: typeof AccountChatsNewLazyImport + parentRoute: typeof AccountChatsLazyImport + } } } @@ -133,6 +148,7 @@ export const routeTree = rootRoute.addChildren({ NostrConnectLazyRoute, AccountChatsLazyRoute: AccountChatsLazyRoute.addChildren({ AccountChatsIdLazyRoute, + AccountChatsNewLazyRoute, }), }) @@ -170,12 +186,17 @@ export const routeTree = rootRoute.addChildren({ "/$account/chats": { "filePath": "$account.chats.lazy.tsx", "children": [ - "/$account/chats/$id" + "/$account/chats/$id", + "/$account/chats/new" ] }, "/$account/chats/$id": { "filePath": "$account.chats.$id.lazy.tsx", "parent": "/$account/chats" + }, + "/$account/chats/new": { + "filePath": "$account.chats.new.lazy.tsx", + "parent": "/$account/chats" } } } diff --git a/src/routes/$account.chats.$id.lazy.tsx b/src/routes/$account.chats.$id.lazy.tsx index 25cfe67..85ca79d 100644 --- a/src/routes/$account.chats.$id.lazy.tsx +++ b/src/routes/$account.chats.$id.lazy.tsx @@ -1,5 +1,5 @@ import { commands } from "@/commands"; -import { cn, getReceivers, time } from "@/commons"; +import { cn, getReceivers, time, useRelays } from "@/commons"; import { Spinner } from "@/components/spinner"; import { ArrowUp, CloudArrowUp, Paperclip } from "@phosphor-icons/react"; import * as ScrollArea from "@radix-ui/react-scroll-area"; @@ -23,14 +23,17 @@ export const Route = createLazyFileRoute("/$account/chats/$id")({ function Screen() { const { id } = Route.useParams(); + const { isLoading, data: relays } = useRelays(id); useEffect(() => { - commands.subscribeTo(id).then(() => console.log("sub: ", id)); + if (!isLoading && relays?.length) + commands.subscribeTo(id, relays).then(() => console.log("sub: ", id)); return () => { - commands.unsubscribe(id).then(() => console.log("unsub: ", id)); + if (!isLoading && relays?.length) + commands.unsubscribe(id).then(() => console.log("unsub: ", id)); }; - }, []); + }, [isLoading, relays]); return (
@@ -43,6 +46,7 @@ function Screen() { function List() { const { account, id } = Route.useParams(); + const { isLoading: rl, isError: rE } = useRelays(id); const { isLoading, isError, data } = useQuery({ queryKey: ["chats", id], queryFn: async () => { @@ -59,18 +63,20 @@ function List() { throw new Error(res.error); } }, + enabled: !rl && !rE, + refetchOnWindowFocus: false, }); const queryClient = useQueryClient(); const ref = useRef(null); const renderItem = useCallback( - (item: NostrEvent) => { + (item: NostrEvent, idx: number) => { const self = account === item.pubkey; return (
- {isLoading ? ( -

Loading...

- ) : isError || !data ? ( -

Error

+ {isLoading || !data ? ( +
+
+ + Loading message... +
+
+ ) : isError ? ( +
+
+ Cannot load message. Please try again later. +
+
) : ( - data.map((item) => renderItem(item)) + data.map((item, idx) => renderItem(item, idx)) )}
@@ -161,25 +176,7 @@ function List() { function Form() { const { id } = Route.useParams(); - const { - isLoading, - isError, - data: relays, - } = useQuery({ - queryKey: ["inboxes", id], - queryFn: async () => { - const res = await commands.getInboxes(id); - - if (res.status === "ok") { - return res.data; - } else { - throw new Error(res.error); - } - }, - refetchOnWindowFocus: false, - refetchOnMount: false, - refetchOnReconnect: false, - }); + const { isLoading, isError, data: relays } = useRelays(id); const [newMessage, setNewMessage] = useState(""); const [isPending, startTransition] = useTransition(); diff --git a/src/routes/$account.chats.lazy.tsx b/src/routes/$account.chats.lazy.tsx index 1f158bb..6fb3fd4 100644 --- a/src/routes/$account.chats.lazy.tsx +++ b/src/routes/$account.chats.lazy.tsx @@ -80,27 +80,40 @@ function ChatList() { throw new Error(res.error); } }, + refetchOnWindowFocus: false, }); const queryClient = useQueryClient(); + useEffect(() => { + const unlisten = listen("synchronized", async () => { + await queryClient.refetchQueries({ queryKey: ["chats"] }); + }); + + return () => { + unlisten.then((f) => f()); + }; + }, []); + useEffect(() => { const unlisten = listen("event", async (data) => { const event: NostrEvent = JSON.parse(data.payload.event); const chats: NostrEvent[] = await queryClient.getQueryData(["chats"]); - const exist = chats.find((ev) => ev.pubkey === event.pubkey); - if (!exist) { - await queryClient.setQueryData( - ["chats"], - (prevEvents: NostrEvent[]) => { - if (!prevEvents) return prevEvents; - if (event.pubkey === account) return; + if (chats) { + const exist = chats.find((ev) => ev.pubkey === event.pubkey); - return [event, ...prevEvents]; - // queryClient.invalidateQueries(['chats', id]); - }, - ); + if (!exist) { + await queryClient.setQueryData( + ["chats"], + (prevEvents: NostrEvent[]) => { + if (!prevEvents) return prevEvents; + if (event.pubkey === account) return; + + return [event, ...prevEvents]; + }, + ); + } } }); diff --git a/src/routes/$account.chats.new.lazy.tsx b/src/routes/$account.chats.new.lazy.tsx new file mode 100644 index 0000000..066bbd1 --- /dev/null +++ b/src/routes/$account.chats.new.lazy.tsx @@ -0,0 +1,14 @@ +import { createLazyFileRoute } from "@tanstack/react-router"; +import { CoopIcon } from "@/icons/coop"; + +export const Route = createLazyFileRoute("/$account/chats/new")({ + component: Screen, +}); + +function Screen() { + return ( +
+ +
+ ); +} diff --git a/src/routes/create-account.lazy.tsx b/src/routes/create-account.lazy.tsx index 5b045b0..7a9af5c 100644 --- a/src/routes/create-account.lazy.tsx +++ b/src/routes/create-account.lazy.tsx @@ -82,7 +82,7 @@ function Screen() { type="button" onClick={() => submit()} disabled={isPending} - className="inline-flex items-center justify-center w-full h-10 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50" + className="inline-flex items-center justify-center w-full h-9 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50" > {isPending ? : "Continue"} diff --git a/src/routes/import-key.lazy.tsx b/src/routes/import-key.lazy.tsx index ae1bf12..dfafd97 100644 --- a/src/routes/import-key.lazy.tsx +++ b/src/routes/import-key.lazy.tsx @@ -90,7 +90,7 @@ function Screen() { type="button" onClick={() => submit()} disabled={isPending} - className="inline-flex items-center justify-center w-full h-10 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50" + className="inline-flex items-center justify-center w-full h-9 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50" > {isPending ? : "Continue"} diff --git a/src/routes/index.tsx b/src/routes/index.tsx index b32ddbe..d4b563d 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -49,7 +49,7 @@ function Screen() { if (res.status === "ok") { navigate({ - to: "/$account/chats", + to: "/$account/chats/new", params: { account: res.data }, replace: true, }); diff --git a/src/routes/new.lazy.tsx b/src/routes/new.lazy.tsx index fac252b..d053a77 100644 --- a/src/routes/new.lazy.tsx +++ b/src/routes/new.lazy.tsx @@ -16,13 +16,13 @@ function Screen() {
Create a new identity Login with Nostr Connect diff --git a/src/routes/nostr-connect.lazy.tsx b/src/routes/nostr-connect.lazy.tsx index 878516f..487e704 100644 --- a/src/routes/nostr-connect.lazy.tsx +++ b/src/routes/nostr-connect.lazy.tsx @@ -76,7 +76,7 @@ function Screen() { type="button" onClick={() => submit()} disabled={isPending} - className="inline-flex items-center justify-center w-full h-10 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50" + className="inline-flex items-center justify-center w-full h-9 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50" > {isPending ? : "Continue"} diff --git a/tsconfig.json b/tsconfig.json index 21f42b5..16059bf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,40 +1,38 @@ { - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": [ - "ES2020", - "DOM", - "DOM.Iterable" - ], - "module": "ESNext", - "skipLibCheck": true, - "baseUrl": "./", - "paths": { - "@/*": [ - "./src/*" - ] - }, - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "strictNullChecks": false - }, - "include": [ - "src" - ], - "references": [ - { - "path": "./tsconfig.node.json" - } - ] + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": [ + "ES2020", + "DOM", + "DOM.Iterable" + ], + "module": "ESNext", + "skipLibCheck": true, + "baseUrl": "./", + "paths": { + "@/*": [ + "./src/*" + ] + }, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "strictNullChecks": false + }, + "include": [ + "src" + ], + "references": [ + { + "path": "./tsconfig.node.json" + } + ], } diff --git a/tsconfig.node.json b/tsconfig.node.json index 42872c5..d37a14f 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -1,10 +1,12 @@ { - "compilerOptions": { - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true - }, - "include": ["vite.config.ts"] + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": [ + "vite.config.ts" + ] }