diff options
author | GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com> | 2023-04-10 21:17:00 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-10 21:17:00 +0200 |
commit | 2be2ef6ce5232ea859ae814c401cd99e87f57af9 (patch) | |
tree | b364b9ddf492f02d02f1fdb02fd9191a57a39d27 /src-tauri/src/lib.rs | |
parent | 6d58e6793d40df4fec518f37351868803a02a033 (diff) | |
download | FlightCore-2be2ef6ce5232ea859ae814c401cd99e87f57af9.tar.gz FlightCore-2be2ef6ce5232ea859ae814c401cd99e87f57af9.zip |
feat: Show download progress for installing Northstar (#200)
* chore: Bump libthermite to 0.5.3
This adds a change needed for making progressbar work on dowload
* wip: First attempt at showing download progress
Simply prints it to JavaScript console for now
* feat: Emit download progress at most every 250ms
If we spam emit too much we use a lot of extra resources, slowing down
the actual download
* feat: Initial messages for extracting
* feat: Add install state enum
* refactor: Change payload to current + total size
downloaded
* fix: Remove extra emit
* fix: Remove extra emit
* refactor: Rename struct
* refactor: Move struct to top of file
* feat: Add TypeScript bindings
* feat: Add console logs for printing state for now
* fix: Remove duplicate identifier
* feat: Initial progressbar in frontend
* fix: Remove event listener added for debugging
* feat: Display status and downloaded bytes
* feat: Set loading bar to indeterminate on extract
* fix: Phrasing in comment
* feat: Add i18n for progress state
* refactor: Adjust control flow
do not show downloaded size anymore during extraction
* fix: Manually specify progressbar size
* fix: Update download progress every 100ms
instead of 250ms
Gives impression of faster / more fluent download.
* feat: layout does not move when progress bar is hidden
* feat: fix progress bar width to 200px
* refactor: put services container in a flex container, for it not to overlap play button
* refactor: export progress bar to dedicated component file
* refactor: Update status first outside of branch
* fix: Proper typing of event payload
* fix: Do not assign to unused variable
---------
Co-authored-by: Rémy Raes <contact@remyraes.com>
Diffstat (limited to 'src-tauri/src/lib.rs')
-rw-r--r-- | src-tauri/src/lib.rs | 74 |
1 files changed, 71 insertions, 3 deletions
diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index a3553448..56bc590c 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,4 +1,4 @@ -use std::{env, fs, path::Path, time::Duration}; +use std::{cell::RefCell, env, fs, path::Path, time::Duration, time::Instant}; use anyhow::{anyhow, Context, Result}; @@ -52,6 +52,22 @@ pub struct NorthstarServer { pub player_count: i32, } +#[derive(Serialize, Deserialize, Debug, Clone, TS)] +#[ts(export)] +pub enum InstallState { + DOWNLOADING, + EXTRACTING, + DONE, +} + +#[derive(Serialize, Deserialize, Debug, Clone, TS)] +#[ts(export)] +struct InstallProgress { + current_downloaded: u64, + total_size: u64, + state: InstallState, +} + /// Check version number of a mod pub fn check_mod_version_number(path_to_mod_folder: String) -> Result<String, anyhow::Error> { // println!("{}", format!("{}/mod.json", path_to_mod_folder)); @@ -187,7 +203,11 @@ fn extract(zip_file: std::fs::File, target: &std::path::Path) -> Result<()> { ///Install N* from the provided mod /// ///Checks cache, else downloads the latest version -async fn do_install(nmod: &thermite::model::ModVersion, game_path: &std::path::Path) -> Result<()> { +async fn do_install( + window: tauri::Window, + nmod: &thermite::model::ModVersion, + game_path: &std::path::Path, +) -> Result<()> { let filename = format!("northstar-{}.zip", nmod.version); let download_directory = format!("{}/___flightcore-temp-download-dir/", game_path.display()); @@ -196,7 +216,43 @@ async fn do_install(nmod: &thermite::model::ModVersion, game_path: &std::path::P let download_path = format!("{}/{}", download_directory, filename); log::info!("Download path: {download_path}"); - let nfile = thermite::core::manage::download_file(&nmod.url, download_path).unwrap(); + let last_emit = RefCell::new(Instant::now()); // Keep track of the last time a signal was emitted + let nfile = thermite::core::manage::download_file_with_progress( + &nmod.url, + download_path, + |delta, current, total| { + if delta != 0 { + // Only emit a signal once every 100ms + // This way we don't bombard the frontend with events on fast download speeds + let time_since_last_emit = Instant::now().duration_since(*last_emit.borrow()); + if time_since_last_emit >= Duration::from_millis(100) { + window + .emit( + "northstar-install-download-progress", + InstallProgress { + current_downloaded: current, + total_size: total, + state: InstallState::DOWNLOADING, + }, + ) + .unwrap(); + *last_emit.borrow_mut() = Instant::now(); + } + } + }, + ) + .unwrap(); + + window + .emit( + "northstar-install-download-progress", + InstallProgress { + current_downloaded: 0, + total_size: 0, + state: InstallState::EXTRACTING, + }, + ) + .unwrap(); log::info!("Extracting Northstar..."); extract(nfile, game_path)?; @@ -206,11 +262,22 @@ async fn do_install(nmod: &thermite::model::ModVersion, game_path: &std::path::P std::fs::remove_dir_all(download_directory).unwrap(); log::info!("Done installing Northstar!"); + window + .emit( + "northstar-install-download-progress", + InstallProgress { + current_downloaded: 0, + total_size: 0, + state: InstallState::DONE, + }, + ) + .unwrap(); Ok(()) } pub async fn install_northstar( + window: tauri::Window, game_path: &str, northstar_package_name: Option<String>, ) -> Result<String, String> { @@ -235,6 +302,7 @@ pub async fn install_northstar( log::info!("Install path \"{}\"", game_path); match do_install( + window, nmod.versions.get(&nmod.latest).unwrap(), std::path::Path::new(game_path), ) |