mirror of https://github.com/wayvr-org/wayvr.git
dash-frontend: remove partially downloaded files, cancel download on Downloader view exit
This commit is contained in:
parent
0b4c59f1c7
commit
707e3a4927
|
|
@ -98,6 +98,7 @@ pub struct InitParams<'a, T> {
|
|||
pub has_monado: bool,
|
||||
pub theme: Rc<WguiTheme>,
|
||||
pub color_palette: &'a str,
|
||||
pub executor: AsyncExecutor,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
@ -202,7 +203,7 @@ impl<T: 'static> Frontend<T> {
|
|||
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<T: 'static> Frontend<T> {
|
|||
self.current_tab = Some(tab);
|
||||
}
|
||||
|
||||
// process async runtime tasks
|
||||
while self.executor.try_tick() {}
|
||||
|
||||
let res = self.tick(params)?;
|
||||
self.ticks += 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -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<HttpClientResponse
|
|||
Ok(HttpClientResponse { data })
|
||||
}
|
||||
|
||||
struct FileCancelGuard {
|
||||
path: std::path::PathBuf,
|
||||
should_delete: bool,
|
||||
}
|
||||
|
||||
impl Drop for FileCancelGuard {
|
||||
fn drop(&mut self) {
|
||||
if self.should_delete {
|
||||
log::warn!("Removing partially downloaded file {:?}", self.path);
|
||||
let _ = std::fs::remove_file(&self.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Downloads a response directly to a file.
|
||||
///
|
||||
/// Unlike `get`, this permits responses without a Content-Length header. In
|
||||
|
|
@ -189,9 +204,14 @@ pub async fn download_to_file(mut params: GetParams<'_>, path: impl AsRef<Path>)
|
|||
|
||||
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<Path>)
|
|||
);
|
||||
}
|
||||
|
||||
file_cancel_guard.should_delete = false; // we're good!
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@ pub struct View {
|
|||
id_content: WidgetID,
|
||||
on_close_request: Option<Box<dyn FnOnce()>>,
|
||||
on_downloaded: Option<Box<dyn FnOnce()>>,
|
||||
|
||||
// will cancel on Drop
|
||||
task_downloader: Option<smol::Task<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,
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
pub type AsyncExecutor = Rc<smol::LocalExecutor<'static>>;
|
||||
|
||||
pub fn create_local() -> AsyncExecutor {
|
||||
Rc::new(smol::LocalExecutor::new())
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue