From 962faef06466baf9f8a82a17be2612eb167f9e8a Mon Sep 17 00:00:00 2001 From: hrzlgnm Date: Tue, 3 Dec 2024 23:46:55 +0100 Subject: [PATCH] WiP Browse many --- src-tauri/src/lib.rs | 213 +++++++++++++++++++++++++++++-------------- src/app.rs | 47 +++++++++- 2 files changed, 185 insertions(+), 75 deletions(-) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 2f0859f..d42251a 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -41,76 +41,6 @@ fn get_shared_daemon() -> SharedServiceDaemon { Arc::new(Mutex::new(daemon)) } -#[tauri::command] -fn browse_types(window: Window, state: State) { - if let Ok(mdns) = state.daemon.lock() { - let mdns_for_thread = mdns.clone(); - std::thread::spawn(move || { - let receiver = mdns_for_thread - .browse(MDNS_SD_META_SERVICE) - .expect("Failed to browse"); - while let Ok(event) = receiver.recv() { - match event { - ServiceEvent::ServiceFound(_service_type, full_name) => { - log::debug!("Service type found: {}", full_name); - window - .emit( - "service-type-found", - &ServiceTypeFoundEvent { - service_type: full_name, - }, - ) - .expect("To emit"); - } - ServiceEvent::ServiceRemoved(_service_type, full_name) => { - log::debug!("Service type removed: {}", full_name); - window - .emit( - "service-type-removed", - &ServiceTypeRemovedEvent { - service_type: full_name, - }, - ) - .expect("To emit"); - } - ServiceEvent::SearchStopped(service_type) => { - if service_type == MDNS_SD_META_SERVICE { - break; - } - } - _ => (), - } - } - log::debug!("Browse type thread ending."); - }); - } -} - -#[tauri::command] -fn stop_browse(service_type: String, state: State) { - if service_type.is_empty() { - return; - } - if let Ok(mdns) = state.daemon.lock() { - if let Ok(mut running_browsers) = state.running_browsers.lock() { - if running_browsers.contains(&service_type) { - mdns.stop_browse(service_type.as_str()) - .expect("To stop browsing"); - running_browsers.retain(|s| s != &service_type); - } - } - } -} - -#[tauri::command] -fn verify(instance_fullname: String, state: State) { - log::debug!("verifying {}", instance_fullname); - if let Ok(mdns) = state.daemon.lock() { - mdns.verify(instance_fullname, VERIFY_TIMEOUT) - .expect("To verify an instance"); - } -} - fn from_service_info(info: &ServiceInfo) -> ResolvedService { let mut sorted_addresses: Vec = info.get_addresses().clone().drain().collect(); sorted_addresses.sort(); @@ -200,6 +130,147 @@ fn browse(service_type: String, window: Window, state: State) { } } +#[tauri::command] +fn browse_types(window: Window, state: State) { + if let Ok(mdns) = state.daemon.lock() { + let mdns_for_thread = mdns.clone(); + std::thread::spawn(move || { + let receiver = mdns_for_thread + .browse(MDNS_SD_META_SERVICE) + .expect("Failed to browse"); + while let Ok(event) = receiver.recv() { + match event { + ServiceEvent::ServiceFound(_service_type, full_name) => { + log::debug!("Service type found: {}", full_name); + window + .emit( + "service-type-found", + &ServiceTypeFoundEvent { + service_type: full_name, + }, + ) + .expect("To emit"); + } + ServiceEvent::ServiceRemoved(_service_type, full_name) => { + log::debug!("Service type removed: {}", full_name); + window + .emit( + "service-type-removed", + &ServiceTypeRemovedEvent { + service_type: full_name.clone(), + }, + ) + .expect("To emit"); + } + ServiceEvent::SearchStopped(service_type) => { + if service_type == MDNS_SD_META_SERVICE { + break; + } + } + _ => (), + } + } + log::debug!("Browse type thread ending."); + }); + } +} + +#[tauri::command] +fn stop_browse(service_type: String, state: State) { + if service_type.is_empty() { + return; + } + if let Ok(mdns) = state.daemon.lock() { + if let Ok(mut running_browsers) = state.running_browsers.lock() { + if running_browsers.contains(&service_type) { + mdns.stop_browse(service_type.as_str()) + .expect("To stop browsing"); + running_browsers.retain(|s| s != &service_type); + } + } + } +} + +#[tauri::command] +fn verify(instance_fullname: String, state: State) { + log::debug!("verifying {}", instance_fullname); + if let Ok(mdns) = state.daemon.lock() { + mdns.verify(instance_fullname, VERIFY_TIMEOUT) + .expect("To verify an instance"); + } +} + +#[tauri::command] +fn browse_many(service_types: Vec, window: Window, state: State) { + for service_type in service_types { + if let Ok(mdns) = state.daemon.lock() { + if let Ok(mut running_browsers) = state.running_browsers.lock() { + if !running_browsers.contains(&service_type) { + running_browsers.push(service_type.clone()); + let receiver = mdns.browse(service_type.as_str()).expect("To browse"); + let window = window.clone(); + std::thread::spawn(move || { + while let Ok(event) = receiver.recv() { + match event { + ServiceEvent::ServiceFound(_service_type, instance_name) => { + window + .emit( + "service-found", + &ServiceFoundEvent { + instance_name, + at_ms: timestamp_millis(), + }, + ) + .expect("To emit"); + } + ServiceEvent::SearchStarted(service_type) => { + window + .emit( + "search-started", + &SearchStartedEvent { service_type }, + ) + .expect("to emit"); + } + ServiceEvent::ServiceResolved(info) => { + window + .emit( + "service-resolved", + &ServiceResolvedEvent { + service: from_service_info(&info), + }, + ) + .expect("To emit"); + } + ServiceEvent::ServiceRemoved(_service_type, instance_name) => { + window + .emit( + "service-removed", + &ServiceRemovedEvent { + instance_name, + at_ms: timestamp_millis(), + }, + ) + .expect("To emit"); + } + ServiceEvent::SearchStopped(service_type) => { + window + .emit( + "search-stopped", + &SearchStoppedEvent { service_type }, + ) + .expect("To emit"); + break; + } + } + } + log::debug!("Browse thread for {} ending.", &service_type); + }); + } + } + } + } +} + #[tauri::command] fn send_metrics(window: Window, state: State) { if let Ok(mdns) = state.daemon.lock() { @@ -478,6 +549,7 @@ pub fn run() { app_updates::fetch_update, app_updates::install_update, browse, + browse_many, browse_types, can_auto_update, copy_to_clipboard, @@ -501,6 +573,7 @@ pub fn run_mobile() { .manage(ManagedState::new()) .invoke_handler(tauri::generate_handler![ browse, + browse_many, browse_types, copy_to_clipboard, is_desktop, diff --git a/src/app.rs b/src/app.rs index de3db46..c5234d6 100644 --- a/src/app.rs +++ b/src/app.rs @@ -47,7 +47,7 @@ async fn listen_on_metrics_event(event_writer: WriteSignal>) } async fn listen_on_service_type_event_result( - event_writer: WriteSignal, + event_writer: RwSignal, ) -> Result<(), Error> { let found = listen::("service-type-found").await?; let removed = listen::("service-type-removed").await?; @@ -84,7 +84,7 @@ async fn listen_on_service_type_event_result( Ok(()) } -async fn listen_on_service_type_events(event_writer: WriteSignal) { +async fn listen_on_service_type_events(event_writer: RwSignal) { log::debug!("listen on service type events"); let result = listen_on_service_type_event_result(event_writer).await; match result { @@ -156,6 +156,22 @@ async fn browse(service_type: String) { .await; } +#[derive(Serialize, Deserialize)] +#[allow(non_snake_case)] +struct BrowseManyArgs { + serviceTypes: Vec, +} + +async fn browse_many(service_types: Vec) { + let _ = invoke::<()>( + "browse_many", + &BrowseManyArgs { + serviceTypes: service_types, + }, + ) + .await; +} + async fn stop_browse(service_type: String) { let _ = invoke::<()>( "stop_browse", @@ -270,8 +286,11 @@ fn AutoCompleteServiceType( #[prop(optional, into)] comp_ref: ComponentRef, ) -> impl IntoView { log::debug!("AutoCompleteServiceType"); - let (service_types, set_service_types) = create_signal(ServiceTypes::new()); - create_resource(move || set_service_types, listen_on_service_type_events); + let service_types = use_context::() + .expect("service_tyxpes context to exist") + .0; + + create_resource(move || service_types, listen_on_service_type_events); let service_type_options = create_memo(move |_| { service_types @@ -445,11 +464,16 @@ fn ResolvedServiceGridItem(resolved_service: ResolvedService) -> impl IntoView { } } +#[derive(Clone, Debug)] +pub struct ServiceTypesSignal(RwSignal); + /// Component that allows for mdns browsing using events #[component] fn Browse() -> impl IntoView { log::debug!("Browse"); let (resolved, set_resolved) = create_signal(ResolvedServices::new()); + let service_types = create_rw_signal(ServiceTypes::new()); + provide_context(ServiceTypesSignal(service_types)); create_resource(move || set_resolved, listen_on_resolve_events); let is_desktop = use_context::() .expect("is_desktop context to exist") @@ -484,6 +508,16 @@ fn Browse() -> impl IntoView { browse_action.dispatch(value); }; + let browse_many_action = create_action(|input: &ServiceTypes| { + let input = input.clone(); + async move { browse_many(input.clone()).await } + }); + + let on_browse_many_click = move |_| { + let value = service_types.get_untracked(); + browse_many_action.dispatch(value); + }; + let stop_browse_action = create_action(|input: &String| { let input = input.clone(); async move { stop_browse(input.clone()).await } @@ -532,7 +566,10 @@ fn Browse() -> impl IntoView { - + +