From eb6e3e52df7b14582feb6c87e26a61e11b4b7764 Mon Sep 17 00:00:00 2001 From: reya Date: Sun, 27 Oct 2024 09:57:56 +0700 Subject: [PATCH] update --- src-tauri/resources/relays.txt | 1 + src-tauri/src/commands/event.rs | 24 +++-- src-tauri/src/commands/metadata.rs | 98 +++++++------------ src-tauri/src/commands/window.rs | 40 +------- src-tauri/src/main.rs | 84 ++++------------ src/commands.gen.ts | 8 +- src/routes/__root.tsx | 23 +++++ .../columns/_layout/launchpad.$id.lazy.tsx | 44 +++------ 8 files changed, 113 insertions(+), 209 deletions(-) diff --git a/src-tauri/resources/relays.txt b/src-tauri/resources/relays.txt index 11c3ec13..bcadd81e 100644 --- a/src-tauri/resources/relays.txt +++ b/src-tauri/resources/relays.txt @@ -1,3 +1,4 @@ wss://relay.damus.io, wss://relay.primal.net, +wss://relay.nostr.band, wss://nostr.fmt.wiz.biz, diff --git a/src-tauri/src/commands/event.rs b/src-tauri/src/commands/event.rs index 57ac03b2..8ffe664b 100644 --- a/src-tauri/src/commands/event.rs +++ b/src-tauri/src/commands/event.rs @@ -31,11 +31,10 @@ pub async fn get_event(id: String, state: State<'_, Nostr>) -> Result { @@ -48,7 +47,7 @@ pub async fn get_event(id: String, state: State<'_, Nostr>) -> Result Err(err.to_string()), @@ -99,7 +98,10 @@ pub async fn get_all_events_by_author( .author(author) .limit(limit as usize); - match client.database().query(vec![filter]).await { + match client + .fetch_events(vec![filter], Some(Duration::from_secs(3))) + .await + { Ok(events) => Ok(process_event(client, events, false).await), Err(err) => Err(err.to_string()), } @@ -130,7 +132,10 @@ pub async fn get_all_events_by_authors( .until(as_of) .authors(authors); - match client.database().query(vec![filter]).await { + match client + .fetch_events(vec![filter], Some(Duration::from_secs(3))) + .await + { Ok(events) => Ok(process_event(client, events, false).await), Err(err) => Err(err.to_string()), } @@ -156,7 +161,10 @@ pub async fn get_all_events_by_hashtags( .until(as_of) .hashtags(hashtags); - match client.database().query(vec![filter]).await { + match client + .fetch_events(vec![filter], Some(Duration::from_secs(3))) + .await + { Ok(events) => Ok(process_event(client, events, false).await), Err(err) => Err(err.to_string()), } diff --git a/src-tauri/src/commands/metadata.rs b/src-tauri/src/commands/metadata.rs index de8f89e2..3ad752b9 100644 --- a/src-tauri/src/commands/metadata.rs +++ b/src-tauri/src/commands/metadata.rs @@ -6,7 +6,7 @@ use std::{str::FromStr, time::Duration}; use tauri::{Emitter, Manager, State}; use crate::{ - common::{get_all_accounts, get_latest_event, process_event}, + common::{get_latest_event, process_event}, Nostr, RichEvent, Settings, }; @@ -36,36 +36,12 @@ pub async fn get_profile(id: String, state: State<'_, Nostr>) -> Result { - if let Some(event) = events.iter().next() { - let metadata = Metadata::from_json(&event.content).map_err(|e| e.to_string())?; - Ok(metadata.as_json()) - } else { - match client - .fetch_events(vec![filter], Some(Duration::from_secs(5))) - .await - { - Ok(events) => { - if let Some(event) = events.iter().next() { - let metadata = - Metadata::from_json(&event.content).map_err(|e| e.to_string())?; - Ok(metadata.as_json()) - } else { - Err("Profile not found.".into()) - } - } - Err(err) => Err(err.to_string()), - } - } - } - Err(e) => Err(e.to_string()), - } + Ok(metadata.as_json()) } #[tauri::command] @@ -102,7 +78,10 @@ pub async fn get_contact_list(id: String, state: State<'_, Nostr>) -> Result = Vec::new(); - match client.database().query(vec![filter]).await { + match client + .fetch_events(vec![filter], Some(Duration::from_secs(3))) + .await + { Ok(events) => { if let Some(event) = events.into_iter().next() { for tag in event.tags.into_iter() { @@ -288,7 +267,10 @@ pub async fn get_group(id: String, state: State<'_, Nostr>) -> Result match get_latest_event(&events) { Some(ev) => Ok(ev.as_json()), None => Err("Not found.".to_string()), @@ -299,22 +281,15 @@ pub async fn get_group(id: String, state: State<'_, Nostr>) -> Result) -> Result, String> { +pub async fn get_all_groups(id: String, state: State<'_, Nostr>) -> Result, String> { let client = &state.client; - let accounts = get_all_accounts(); - let authors: Vec = accounts - .iter() - .filter_map(|acc| { - if let Ok(pk) = PublicKey::from_str(acc) { - Some(pk) - } else { - None - } - }) - .collect(); - let filter = Filter::new().kind(Kind::FollowSet).authors(authors); + let public_key = PublicKey::parse(&id).map_err(|e| e.to_string())?; + let filter = Filter::new().kind(Kind::FollowSet).author(public_key); - match client.database().query(vec![filter]).await { + match client + .fetch_events(vec![filter], Some(Duration::from_secs(3))) + .await + { Ok(events) => Ok(process_event(client, events, false).await), Err(e) => Err(e.to_string()), } @@ -384,7 +359,10 @@ pub async fn get_interest(id: String, state: State<'_, Nostr>) -> Result match get_latest_event(&events) { Some(ev) => Ok(ev.as_json()), None => Err("Not found.".to_string()), @@ -395,24 +373,20 @@ pub async fn get_interest(id: String, state: State<'_, Nostr>) -> Result) -> Result, String> { +pub async fn get_all_interests( + id: String, + state: State<'_, Nostr>, +) -> Result, String> { let client = &state.client; - let accounts = get_all_accounts(); - let authors: Vec = accounts - .iter() - .filter_map(|acc| { - if let Ok(pk) = PublicKey::from_str(acc) { - Some(pk) - } else { - None - } - }) - .collect(); + let public_key = PublicKey::parse(&id).map_err(|e| e.to_string())?; let filter = Filter::new() .kinds(vec![Kind::InterestSet, Kind::Interests]) - .authors(authors); + .author(public_key); - match client.database().query(vec![filter]).await { + match client + .fetch_events(vec![filter], Some(Duration::from_secs(3))) + .await + { Ok(events) => Ok(process_event(client, events, false).await), Err(e) => Err(e.to_string()), } @@ -600,7 +574,7 @@ pub async fn get_notifications(id: String, state: State<'_, Nostr>) -> Result(); let client = &state.client; - let relays = &state.bootstrap_relays.lock().unwrap().clone(); if is_newsfeed { if let Ok(contact_list) = client.database().contacts_public_keys(public_key).await { - let opts = SyncOptions::default(); let subscription_id = SubscriptionId::new(webview.label()); + let filter = Filter::new().authors(contact_list).kinds(vec![ Kind::TextNote, @@ -90,34 +89,6 @@ pub async fn create_column( { println!("Subscription error: {}", e); } - - if let Ok(output) = client - .sync_with(relays, filter.limit(1000), &opts) - .await - { - println!("Success: {:?}", output.success.len()); - } - } - } else { - let opts = SyncOptions::default(); - let filter = Filter::new() - .author(public_key) - .kinds(vec![ - Kind::Interests, - Kind::InterestSet, - Kind::FollowSet, - Kind::Bookmarks, - Kind::BookmarkSet, - Kind::TextNote, - Kind::Repost, - Kind::Custom(30315), - ]) - .limit(500); - - if let Ok(output) = - client.sync_with(relays, filter, &opts).await - { - println!("Success: {:?}", output.success.len()); } } }); @@ -125,10 +96,9 @@ pub async fn create_column( tauri::async_runtime::spawn(async move { let state = webview.state::(); let client = &state.client; - let relays = &state.bootstrap_relays.lock().unwrap().clone(); - let opts = SyncOptions::default(); let subscription_id = SubscriptionId::new(webview.label()); + let filter = Filter::new() .event(event_id) .kinds(vec![Kind::TextNote, Kind::Custom(1111)]); @@ -143,12 +113,6 @@ pub async fn create_column( { println!("Subscription error: {}", e); } - - if let Ok(output) = - client.sync_with(relays, filter, &opts).await - { - println!("Success: {:?}", output.success.len()); - } }); } } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index cc2db04c..35c85067 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -21,7 +21,7 @@ use std::{ use tauri::{path::BaseDirectory, Emitter, EventTarget, Manager}; use tauri_plugin_decorum::WebviewWindowExt; use tauri_plugin_notification::{NotificationExt, PermissionState}; -use tauri_specta::{collect_commands, Builder, Event as TauriEvent}; +use tauri_specta::{collect_commands, Builder}; pub mod commands; pub mod common; @@ -64,11 +64,6 @@ impl Default for Settings { } } -#[derive(Serialize, Deserialize, Type, TauriEvent)] -struct Sync { - id: String, -} - pub const DEFAULT_DIFFICULTY: u8 = 0; pub const FETCH_LIMIT: usize = 50; pub const NOTIFICATION_SUB_ID: &str = "lume_notification"; @@ -181,13 +176,13 @@ fn main() { // Config let opts = Options::new() - .gossip(true) - .max_avg_latency(Duration::from_millis(500)) - .automatic_authentication(false) - .connection_timeout(Some(Duration::from_secs(20))) + .gossip(false) + .max_avg_latency(Duration::from_millis(300)) + .automatic_authentication(true) + .connection_timeout(Some(Duration::from_secs(5))) .send_timeout(Some(Duration::from_secs(10))) .wait_for_send(false) - .timeout(Duration::from_secs(12)); + .timeout(Duration::from_secs(5)); // Setup nostr client let client = ClientBuilder::default() @@ -266,7 +261,7 @@ fn main() { .collect(); // Subscribe for new notification - if let Ok(e) = client + if let Err(e) = client .subscribe_with_id( SubscriptionId::new(NOTIFICATION_SUB_ID), vec![Filter::new().pubkeys(public_keys).since(Timestamp::now())], @@ -274,7 +269,7 @@ fn main() { ) .await { - println!("Subscribed for notification on {} relays", e.success.len()) + println!("Error: {}", e) } } @@ -290,54 +285,14 @@ fn main() { }; let notification_id = SubscriptionId::new(NOTIFICATION_SUB_ID); - let mut notifications = client.pool().notifications(); - while let Ok(notification) = notifications.recv().await { - match notification { - RelayPoolNotification::Message { relay_url, message } => { - if let RelayMessage::Auth { challenge } = message { - match client.auth(challenge, relay_url.clone()).await { - Ok(..) => { - if let Ok(relay) = client.relay(&relay_url).await { - let msg = - format!("Authenticated to {} relay.", relay_url); - let opts = RelaySendOptions::new() - .skip_send_confirmation(true); - - if let Err(e) = relay.resubscribe(opts).await { - println!("Error: {}", e); - } - - if allow_notification { - if let Err(e) = &handle_clone - .notification() - .builder() - .body(&msg) - .title("Lume") - .show() - { - println!("Error: {}", e); - } - } - } - } - Err(e) => { - if allow_notification { - if let Err(e) = &handle_clone - .notification() - .builder() - .body(e.to_string()) - .title("Lume") - .show() - { - println!("Error: {}", e); - } - } - } - } - } else if let RelayMessage::Event { - subscription_id, + let _ = client + .handle_notifications(|notification| async { + #[allow(clippy::collapsible_match)] + if let RelayPoolNotification::Message { message, .. } = notification { + if let RelayMessage::Event { event, + subscription_id, } = message { // Handle events from notification subscription @@ -358,7 +313,7 @@ fn main() { &handle_clone, ); } - } else { + } else if event.kind != Kind::RelayList { let payload = RichEvent { raw: event.as_json(), parsed: if event.kind == Kind::TextNote { @@ -376,12 +331,11 @@ fn main() { println!("Emitter error: {}", e) } } - }; + } } - RelayPoolNotification::Shutdown => break, - _ => (), - } - } + Ok(false) + }) + .await; }); Ok(()) diff --git a/src/commands.gen.ts b/src/commands.gen.ts index 76ac3e11..5c8d26ce 100644 --- a/src/commands.gen.ts +++ b/src/commands.gen.ts @@ -200,9 +200,9 @@ async getGroup(id: string) : Promise> { else return { status: "error", error: e as any }; } }, -async getAllGroups() : Promise> { +async getAllGroups(id: string) : Promise> { try { - return { status: "ok", data: await TAURI_INVOKE("get_all_groups") }; + return { status: "ok", data: await TAURI_INVOKE("get_all_groups", { id }) }; } catch (e) { if(e instanceof Error) throw e; else return { status: "error", error: e as any }; @@ -224,9 +224,9 @@ async getInterest(id: string) : Promise> { else return { status: "error", error: e as any }; } }, -async getAllInterests() : Promise> { +async getAllInterests(id: string) : Promise> { try { - return { status: "ok", data: await TAURI_INVOKE("get_all_interests") }; + return { status: "ok", data: await TAURI_INVOKE("get_all_interests", { id }) }; } catch (e) { if(e instanceof Error) throw e; else return { status: "error", error: e as any }; diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 4ea3ade4..01cef664 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -1,7 +1,11 @@ +import type { RichEvent } from "@/commands.gen"; import { Spinner } from "@/components"; import type { QueryClient } from "@tanstack/react-query"; import { Outlet, createRootRouteWithContext } from "@tanstack/react-router"; +import { listen } from "@tauri-apps/api/event"; import type { OsType } from "@tauri-apps/plugin-os"; +import { nip19 } from "nostr-tools"; +import { useEffect } from "react"; interface RouterContext { queryClient: QueryClient; @@ -15,6 +19,25 @@ export const Route = createRootRouteWithContext()({ }); function Screen() { + const { queryClient } = Route.useRouteContext(); + + useEffect(() => { + const unlisten = listen("event", async (data) => { + const event = JSON.parse(data.payload.raw); + + if (event.kind === 0) { + const npub = nip19.npubEncode(event.pubkey); + await queryClient.invalidateQueries({ + queryKey: ["profile", npub, event.pubkey], + }); + } + }); + + return () => { + unlisten.then((f) => f()); + }; + }, []); + return ; } diff --git a/src/routes/columns/_layout/launchpad.$id.lazy.tsx b/src/routes/columns/_layout/launchpad.$id.lazy.tsx index 15ab3dde..c1b03ffd 100644 --- a/src/routes/columns/_layout/launchpad.$id.lazy.tsx +++ b/src/routes/columns/_layout/launchpad.$id.lazy.tsx @@ -4,35 +4,19 @@ import { Spinner, User } from "@/components"; import { LumeWindow } from "@/system"; import type { LumeColumn, NostrEvent } from "@/types"; import { ArrowClockwise, Plus } from "@phosphor-icons/react"; -import * as Progress from "@radix-ui/react-progress"; import * as ScrollArea from "@radix-ui/react-scroll-area"; import { useQuery } from "@tanstack/react-query"; import { createLazyFileRoute } from "@tanstack/react-router"; -import { Channel } from "@tauri-apps/api/core"; import { resolveResource } from "@tauri-apps/api/path"; import { readTextFile } from "@tauri-apps/plugin-fs"; import { nanoid } from "nanoid"; -import { useCallback, useEffect, useState } from "react"; +import { useCallback } from "react"; export const Route = createLazyFileRoute("/columns/_layout/launchpad/$id")({ component: Screen, }); function Screen() { - const { id } = Route.useParams(); - const { isLoading, data: isSync } = useQuery({ - queryKey: ["is-sync", id], - queryFn: async () => { - const res = await commands.isAccountSync(id); - - if (res.status === "ok") { - return res.data; - } else { - return false; - } - }, - }); - return ( - {isLoading ? ( - - ) : !isSync ? ( - - ) : ( - <> - - - - - )} + + + ); } +*/ function Groups() { + const { id } = Route.useParams(); const { isLoading, isError, error, data, refetch, isRefetching } = useQuery({ - queryKey: ["others", "groups"], + queryKey: ["others", "groups", id], queryFn: async () => { - const res = await commands.getAllGroups(); + const res = await commands.getAllGroups(id); if (res.status === "ok") { const data = toLumeEvents(res.data); @@ -254,10 +233,11 @@ function Groups() { } function Interests() { + const { id } = Route.useParams(); const { isLoading, isError, error, data, refetch, isRefetching } = useQuery({ - queryKey: ["others", "interests"], + queryKey: ["others", "interests", id], queryFn: async () => { - const res = await commands.getAllInterests(); + const res = await commands.getAllInterests(id); if (res.status === "ok") { const data = toLumeEvents(res.data);