diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 24bd96b5..7f552233 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -30,6 +30,7 @@ pub mod common; pub struct Nostr { client: Client, queue: RwLock>, + is_syncing: RwLock, settings: RwLock, } @@ -218,11 +219,19 @@ fn main() { let _ = client.add_discovery_relay("wss://user.kindpag.es/").await; // Connect - client.connect_with_timeout(Duration::from_secs(10)).await; + client.connect().await; client }); + // Create global state + app.manage(Nostr { + client, + queue: RwLock::new(HashSet::new()), + is_syncing: RwLock::new(false), + settings: RwLock::new(Settings::default()), + }); + // Trigger some actions for window events main_window.on_window_event(move |event| match event { tauri::WindowEvent::Focused(focused) => { @@ -233,6 +242,36 @@ fn main() { let state = handle.state::(); let client = &state.client; + if *state.is_syncing.read().await { + return; + } + + let mut is_syncing = state.is_syncing.write().await; + + // Mark sync in progress + *is_syncing = true; + + let opts = SyncOptions::default(); + let accounts = get_all_accounts(); + + if !accounts.is_empty() { + let public_keys: Vec = accounts + .iter() + .filter_map(|acc| PublicKey::from_str(acc).ok()) + .collect(); + + let filter = Filter::new().pubkeys(public_keys).kinds(vec![ + Kind::TextNote, + Kind::Repost, + Kind::Reaction, + Kind::ZapReceipt, + ]); + + if let Ok(output) = client.sync(filter, &opts).await { + println!("Received: {}", output.received.len()) + } + } + let filter = Filter::new().kinds(vec![ Kind::TextNote, Kind::Repost, @@ -254,24 +293,38 @@ fn main() { } let authors = chunk.to_owned(); + let filter = Filter::new() - .authors(authors) + .authors(authors.clone()) .kinds(vec![ Kind::Metadata, - Kind::TextNote, Kind::FollowSet, Kind::Interests, Kind::InterestSet, ]) - .limit(2000); + .limit(1000); - let opts = SyncOptions::default(); + if let Ok(output) = client.sync(filter, &opts).await { + println!("Received: {}", output.received.len()) + } - if let Err(e) = client.sync(filter, &opts).await { - println!("Sync error: {}", e) + let filter = Filter::new() + .authors(authors) + .kinds(vec![ + Kind::TextNote, + Kind::Repost, + Kind::EventDeletion, + ]) + .limit(500); + + if let Ok(output) = client.sync(filter, &opts).await { + println!("Received: {}", output.received.len()) } } } + + // Mark sync is done + *is_syncing = false; }); } } @@ -279,13 +332,6 @@ fn main() { _ => {} }); - // Create global state - app.manage(Nostr { - client, - queue: RwLock::new(HashSet::new()), - settings: RwLock::new(Settings::default()), - }); - // Listen for request metadata app.listen_any("request_metadata", move |event| { let payload = event.payload(); @@ -295,28 +341,37 @@ fn main() { tauri::async_runtime::spawn(async move { let state = handle.state::(); let client = &state.client; - let mut write_queue = state.queue.write().await; if let Ok(public_key) = PublicKey::parse(parsed_payload.id) { + let mut write_queue = state.queue.write().await; write_queue.insert(public_key); - } + }; + // Wait for [QUEUE_DELAY] sleep(Duration::from_millis(QUEUE_DELAY)).await; let read_queue = state.queue.read().await; - let filter_opts = FilterOptions::WaitDurationAfterEOSE(Duration::from_secs(2)); - let opts = SubscribeAutoCloseOptions::default().filter(filter_opts); + if !read_queue.is_empty() { + let authors: HashSet = read_queue.iter().copied().collect(); - let limit = read_queue.len() * 2; - let authors: Vec = read_queue.iter().copied().collect(); - let filter = Filter::new() - .authors(authors) - .kind(Kind::Metadata) - .limit(limit); + let filter = Filter::new() + .authors(authors) + .kind(Kind::Metadata) + .limit(200); - if client.subscribe(vec![filter], Some(opts)).await.is_ok() { + let opts = SubscribeAutoCloseOptions::default() + .filter(FilterOptions::WaitDurationAfterEOSE(Duration::from_secs(2))); + + // Drop queue, you don't need it at this time anymore + drop(read_queue); + // Clear queue + let mut write_queue = state.queue.write().await; write_queue.clear(); + + if let Err(e) = client.subscribe(vec![filter], Some(opts)).await { + println!("Subscribe error: {}", e); + } } }); }); @@ -351,7 +406,7 @@ fn main() { .subscribe_with_id(subscription_id, vec![filter], None) .await { - println!("Error: {}", e) + println!("Subscribe error: {}", e) } } @@ -397,7 +452,7 @@ fn main() { } } else if event.kind == Kind::Metadata { if let Err(e) = handle_clone.emit("metadata", event.as_json()) { - println!("Emitter error: {}", e) + println!("Emit error: {}", e) } } else if event.kind != Kind::RelayList { let payload = RichEvent { @@ -414,7 +469,7 @@ fn main() { "event", payload, ) { - println!("Emitter error: {}", e) + println!("Emit error: {}", e) } } } diff --git a/src/components/note/preview/images.tsx b/src/components/note/preview/images.tsx index 7fcf6b37..92591448 100644 --- a/src/components/note/preview/images.tsx +++ b/src/components/note/preview/images.tsx @@ -32,10 +32,15 @@ export function Images({ urls }: { urls: string[] }) { return `https://wsrv.nl?url=${url}&ll&af&default=1&n=-1`; }); } else { - newUrls = urls.map( - (url) => - `https://wsrv.nl?url=${url}&w=480&h=640&ll&af&default=1&n=-1`, - ); + newUrls = urls.map((url) => { + if (url.includes("_next/")) { + return url; + } + if (url.includes("bsky.network")) { + return url; + } + return `https://wsrv.nl?url=${url}&ll&af&default=1&n=-1`; + }); } return newUrls; diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 2b234383..b2dc41d4 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -42,11 +42,16 @@ function Screen() { const unlisten = getCurrentWindow().listen( "metadata", async (data) => { - const payload = data.payload; - const event: NostrEvent = JSON.parse(payload); + const event: NostrEvent = JSON.parse(data.payload); const metadata: Metadata = JSON.parse(event.content); + // Update query cache queryClient.setQueryData(["profile", event.pubkey], () => metadata); + + // Reset query cache + await queryClient.invalidateQueries({ + queryKey: ["profile", event.pubkey], + }); }, ); diff --git a/src/system/useProfile.ts b/src/system/useProfile.ts index eca37dc6..c061bcb9 100644 --- a/src/system/useProfile.ts +++ b/src/system/useProfile.ts @@ -29,25 +29,26 @@ export function useProfile(pubkey: string, data?: string) { const { isLoading, data: profile } = useQuery({ queryKey: ["profile", hex], queryFn: async () => { - if (data) { + if (data?.length) { const metadata: Metadata = JSON.parse(data); return metadata; } - const query = await commands.getProfile(hex); + const res = await commands.getProfile(hex); - if (query.status === "ok") { - const metadata: Metadata = JSON.parse(query.data); + if (res.status === "ok") { + const metadata: Metadata = JSON.parse(res.data); return metadata; } else { await getCurrentWindow().emit("request_metadata", { id: hex }); - return {}; + throw new Error(res.error); } }, refetchOnMount: false, refetchOnWindowFocus: false, refetchOnReconnect: false, enabled: !!hex, + retry: false, }); return { isLoading, profile };