From 707e3a4927c83f15badf391db35ea090f2766427 Mon Sep 17 00:00:00 2001 From: Aleksander Date: Wed, 29 Jul 2026 21:53:00 +0200 Subject: [PATCH] dash-frontend: remove partially downloaded files, cancel download on Downloader view exit --- dash-frontend/src/frontend.rs | 6 ++--- .../src/util/networking/http_client.rs | 24 ++++++++++++++++++- dash-frontend/src/views/download_file.rs | 16 +++++++++---- uidev/src/testbed/testbed_dashboard.rs | 12 ++++++++-- wayvr/run | 6 ----- wayvr/src/backend/openvr/mod.rs | 1 + wayvr/src/backend/openxr/mod.rs | 1 + wayvr/src/overlays/dashboard.rs | 1 + wayvr/src/state.rs | 5 ++++ wlx-common/src/async_executor.rs | 4 ++++ 10 files changed, 58 insertions(+), 18 deletions(-) delete mode 100755 wayvr/run diff --git a/dash-frontend/src/frontend.rs b/dash-frontend/src/frontend.rs index 1a3e0a19..67f929f3 100644 --- a/dash-frontend/src/frontend.rs +++ b/dash-frontend/src/frontend.rs @@ -98,6 +98,7 @@ pub struct InitParams<'a, T> { pub has_monado: bool, pub theme: Rc, pub color_palette: &'a str, + pub executor: AsyncExecutor, } #[derive(Clone)] @@ -202,7 +203,7 @@ impl Frontend { toast_manager, window_audio_settings: WguiWindow::default(), view_audio_settings: None, - executor: Rc::new(smol::LocalExecutor::new()), + executor: params.executor, sounds_to_play: Vec::new(), }; @@ -254,9 +255,6 @@ impl Frontend { self.current_tab = Some(tab); } - // process async runtime tasks - while self.executor.try_tick() {} - let res = self.tick(params)?; self.ticks += 1; diff --git a/dash-frontend/src/util/networking/http_client.rs b/dash-frontend/src/util/networking/http_client.rs index 9ab865af..6cff1ea7 100644 --- a/dash-frontend/src/util/networking/http_client.rs +++ b/dash-frontend/src/util/networking/http_client.rs @@ -117,6 +117,7 @@ async fn start_download(url: &str, allow_missing_content_length: bool) -> anyhow std::thread::spawn(move || { let res = thread_http_client(&url, allow_missing_content_length, sender.clone()); let _ = sender.send_blocking(HttpClientData::Ended(res)); + log::debug!("thread_http_client exiting"); }); let file_size = match receiver.recv().await? { @@ -177,6 +178,20 @@ pub async fn get(mut params: GetParams<'_>) -> anyhow::Result, path: impl AsRef) let DownloadStream { file_size, receiver } = start_download(params.url, true).await?; + let mut file_cancel_guard = FileCancelGuard { + path: path.clone(), + should_delete: true, + }; + let mut file = smol::fs::File::create(&path) .await - .with_context(|| format!("failed to create download file {:?}", path,))?; + .with_context(|| format!("failed to create download file {:?}", path))?; let mut bytes_downloaded = 0_u64; @@ -234,6 +254,8 @@ pub async fn download_to_file(mut params: GetParams<'_>, path: impl AsRef) ); } + file_cancel_guard.should_delete = false; // we're good! + Ok(()) } diff --git a/dash-frontend/src/views/download_file.rs b/dash-frontend/src/views/download_file.rs index 35602d52..498a126e 100644 --- a/dash-frontend/src/views/download_file.rs +++ b/dash-frontend/src/views/download_file.rs @@ -51,6 +51,9 @@ pub struct View { id_content: WidgetID, on_close_request: Option>, on_downloaded: Option>, + + // will cancel on Drop + task_downloader: Option>>, } fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> { @@ -67,10 +70,12 @@ impl ViewTrait for View { match task { Task::StartDownload(url, path) => { if let Some(on_downloaded) = self.on_downloaded.take() { - self - .executor - .spawn(View::download(self.tasks.clone(), url, path, on_downloaded)) - .detach(); + self.task_downloader = Some(self.executor.spawn(View::download( + self.tasks.clone(), + url, + path, + on_downloaded, + ))); } } Task::SetStatusText(text) => { @@ -178,6 +183,7 @@ impl View { id_content, on_close_request: Some(on_close_request), on_downloaded: Some(par.on_downloaded), + task_downloader: None, }) } @@ -208,7 +214,7 @@ impl View { on_progress: Some(Box::new({ let tasks = tasks.clone(); move |data: ProgressFuncData| { - if tasks.len() < 50 { + if tasks.len() < 100 { tasks.push(Task::SetStatusText(format!( "{}/{} MiB ({}%)", data.bytes_downloaded / 1024 / 1024, diff --git a/uidev/src/testbed/testbed_dashboard.rs b/uidev/src/testbed/testbed_dashboard.rs index eb0f197d..55ea8e14 100644 --- a/uidev/src/testbed/testbed_dashboard.rs +++ b/uidev/src/testbed/testbed_dashboard.rs @@ -3,9 +3,13 @@ use std::rc::Rc; use crate::testbed::{Testbed, TestbedUpdateParams}; use dash_frontend::frontend::{self, FrontendUpdateParams}; use wgui::{layout::Layout, theme::WguiTheme}; -use wlx_common::{dash_interface_emulated::DashInterfaceEmulated, locale::WayVRLangProvider}; +use wlx_common::{ + async_executor::AsyncExecutor, dash_interface_emulated::DashInterfaceEmulated, + locale::WayVRLangProvider, +}; pub struct TestbedDashboard { + executor: AsyncExecutor, frontend: frontend::Frontend<()>, } @@ -14,6 +18,7 @@ impl TestbedDashboard { let interface = DashInterfaceEmulated::new(); let lang_provider = WayVRLangProvider::default(); let palette_name = std::env::var("PALETTE").unwrap_or_else(|_| "Default".to_string()); + let executor = wlx_common::async_executor::create_local(); let frontend = frontend::Frontend::new(frontend::InitParams { interface: Box::new(interface), @@ -22,8 +27,9 @@ impl TestbedDashboard { lang_provider: &lang_provider, theme: Rc::new(WguiTheme::default()), color_palette: &palette_name, + executor: executor.clone(), })?; - Ok(Self { frontend }) + Ok(Self { frontend, executor }) } } @@ -38,6 +44,8 @@ impl Testbed for TestbedDashboard { self .frontend .process_update(res, params.audio_system, params.audio_sample_player)?; + + while self.executor.try_tick() {} Ok(()) } diff --git a/wayvr/run b/wayvr/run deleted file mode 100755 index ea9d3697..00000000 --- a/wayvr/run +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - - - - -cargo run --profile=plain -- --show --replace diff --git a/wayvr/src/backend/openvr/mod.rs b/wayvr/src/backend/openvr/mod.rs index bf08d1d9..97782b90 100644 --- a/wayvr/src/backend/openvr/mod.rs +++ b/wayvr/src/backend/openvr/mod.rs @@ -247,6 +247,7 @@ pub fn openvr_run(args: &Args) -> Result<(), BackendError> { let universe = playspace.get_universe(); + while app.executor.try_tick() {} app.input_state.pre_update(); input_source.update( universe.clone(), diff --git a/wayvr/src/backend/openxr/mod.rs b/wayvr/src/backend/openxr/mod.rs index fd37819a..ebc3b6f4 100644 --- a/wayvr/src/backend/openxr/mod.rs +++ b/wayvr/src/backend/openxr/mod.rs @@ -267,6 +267,7 @@ pub fn openxr_run(args: &Args) -> Result<(), BackendError> { continue 'main_loop; } + while app.executor.try_tick() {} app.input_state.pre_update(); input_source.update(&xr_state, &mut app)?; app.input_state.post_update(&app.session); diff --git a/wayvr/src/overlays/dashboard.rs b/wayvr/src/overlays/dashboard.rs index fe972925..bbff2c88 100644 --- a/wayvr/src/overlays/dashboard.rs +++ b/wayvr/src/overlays/dashboard.rs @@ -95,6 +95,7 @@ impl DashFrontend { has_monado: matches!(app.xr_backend, XrBackend::OpenXR), theme: app.wgui_theme.clone(), color_palette: &*app.session.config.color_palette, + executor: app.executor.clone(), })?; frontend diff --git a/wayvr/src/state.rs b/wayvr/src/state.rs index e42ad4a9..22753a99 100644 --- a/wayvr/src/state.rs +++ b/wayvr/src/state.rs @@ -58,6 +58,8 @@ pub struct AppState { pub wgui_shared: WSharedContext, + pub executor: wlx_common::async_executor::AsyncExecutor, + pub input_state: InputState, pub screens: SmallVec<[ScreenMeta; 8]>, pub anchor: Affine3A, @@ -189,6 +191,8 @@ impl AppState { ) .ok(); + let executor = wlx_common::async_executor::create_local(); + let mut app_state = Self { tasks, gfx, @@ -209,6 +213,7 @@ impl AppState { load_palette(&*session.config.color_palette), )?, wgui_theme: Rc::new(theme), + executor, dbus, xr_backend, ipc_server, diff --git a/wlx-common/src/async_executor.rs b/wlx-common/src/async_executor.rs index 7ec2f737..158b3bbc 100644 --- a/wlx-common/src/async_executor.rs +++ b/wlx-common/src/async_executor.rs @@ -1,3 +1,7 @@ use std::rc::Rc; pub type AsyncExecutor = Rc>; + +pub fn create_local() -> AsyncExecutor { + Rc::new(smol::LocalExecutor::new()) +}