From 57d9b827fde3bf587e3a0b146f0ec70ddb52f5aa Mon Sep 17 00:00:00 2001 From: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com> Date: Thu, 11 May 2023 19:04:37 +0200 Subject: refactor: Move NS install code into own module (#345) * refactor: Move NS install code into own module Moves the code in question out from main into its own module * fix: Address clippy errors --- src-tauri/bindings/InstallState.ts | 2 +- src-tauri/src/main.rs | 148 ++------------------------ src-tauri/src/northstar/install.rs | 144 +++++++++++++++++++++++++ src-tauri/src/northstar/mod.rs | 1 + src-vue/src/components/InstallProgressBar.vue | 12 +-- 5 files changed, 161 insertions(+), 146 deletions(-) create mode 100644 src-tauri/src/northstar/install.rs diff --git a/src-tauri/bindings/InstallState.ts b/src-tauri/bindings/InstallState.ts index 21dbc0c7..553aa53b 100644 --- a/src-tauri/bindings/InstallState.ts +++ b/src-tauri/bindings/InstallState.ts @@ -1,3 +1,3 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -export type InstallState = "DOWNLOADING" | "EXTRACTING" | "DONE"; \ No newline at end of file +export type InstallState = "Downloading" | "Extracting" | "Done"; \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 3b1504bf..4fcb4b63 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -355,7 +355,14 @@ async fn install_northstar_caller( }) .unwrap_or("Northstar".to_string()); - match install_northstar(window, &game_path, northstar_package_name, version_number).await { + match northstar::install::install_northstar( + window, + &game_path, + northstar_package_name, + version_number, + ) + .await + { Ok(_) => Ok(true), Err(err) => { log::error!("{}", err); @@ -535,7 +542,7 @@ async fn get_available_northstar_versions() -> Result Result<()> { Ok(()) } -/// Copied from `papa` source code and modified -///Install N* from the provided mod -/// -///Checks cache, else downloads the latest version -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()); - - std::fs::create_dir_all(download_directory.clone())?; - - let download_path = format!("{}/{}", download_directory, filename); - log::info!("Download path: {download_path}"); - - 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)?; - - // Delete old copy - log::info!("Delete temp folder again"); - 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: String, - version_number: Option, -) -> Result { - let index = thermite::api::get_package_index().unwrap().to_vec(); - let nmod = index - .iter() - .find(|f| f.name.to_lowercase() == northstar_package_name.to_lowercase()) - .ok_or_else(|| panic!("Couldn't find Northstar on thunderstore???")) - .unwrap(); - - // Use passed version or latest if no version was passed - let version = version_number.as_ref().unwrap_or(&nmod.latest); - - log::info!("Install path \"{}\"", game_path); - - match do_install( - window, - nmod.versions.get(version).unwrap(), - std::path::Path::new(game_path), - ) - .await - { - Ok(_) => (), - Err(err) => { - if game_path - .to_lowercase() - .contains(&r#"C:\Program Files\"#.to_lowercase()) - // default is `C:\Program Files\EA Games\Titanfall2` - { - return Err( - "Cannot install to default EA App install path, please move Titanfall2 to a different install location.".to_string(), - ); - } else { - return Err(err.to_string()); - } - } - } - - Ok(nmod.latest.clone()) -} - /// Returns identifier of host OS FlightCore is running on pub fn get_host_os() -> String { env::consts::OS.to_string() diff --git a/src-tauri/src/northstar/install.rs b/src-tauri/src/northstar/install.rs new file mode 100644 index 00000000..7de49eb5 --- /dev/null +++ b/src-tauri/src/northstar/install.rs @@ -0,0 +1,144 @@ +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use std::time::Duration; +use std::{cell::RefCell, time::Instant}; +use ts_rs::TS; + +use crate::extract; + +#[derive(Serialize, Deserialize, Debug, Clone, TS)] +#[ts(export)] +enum InstallState { + Downloading, + Extracting, + Done, +} + +#[derive(Serialize, Deserialize, Debug, Clone, TS)] +#[ts(export)] +struct InstallProgress { + current_downloaded: u64, + total_size: u64, + state: InstallState, +} + +/// Copied from `papa` source code and modified +///Install N* from the provided mod +/// +///Checks cache, else downloads the latest version +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()); + + std::fs::create_dir_all(download_directory.clone())?; + + let download_path = format!("{}/{}", download_directory, filename); + log::info!("Download path: {download_path}"); + + 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)?; + + // Delete old copy + log::info!("Delete temp folder again"); + 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: String, + version_number: Option, +) -> Result { + let index = thermite::api::get_package_index().unwrap().to_vec(); + let nmod = index + .iter() + .find(|f| f.name.to_lowercase() == northstar_package_name.to_lowercase()) + .ok_or_else(|| panic!("Couldn't find Northstar on thunderstore???")) + .unwrap(); + + // Use passed version or latest if no version was passed + let version = version_number.as_ref().unwrap_or(&nmod.latest); + + log::info!("Install path \"{}\"", game_path); + + match do_install( + window, + nmod.versions.get(version).unwrap(), + std::path::Path::new(game_path), + ) + .await + { + Ok(_) => (), + Err(err) => { + if game_path + .to_lowercase() + .contains(&r#"C:\Program Files\"#.to_lowercase()) + // default is `C:\Program Files\EA Games\Titanfall2` + { + return Err( + "Cannot install to default EA App install path, please move Titanfall2 to a different install location.".to_string(), + ); + } else { + return Err(err.to_string()); + } + } + } + + Ok(nmod.latest.clone()) +} diff --git a/src-tauri/src/northstar/mod.rs b/src-tauri/src/northstar/mod.rs index 0fd4743e..c4dc9b82 100644 --- a/src-tauri/src/northstar/mod.rs +++ b/src-tauri/src/northstar/mod.rs @@ -1,5 +1,6 @@ //! This module deals with handling things around Northstar such as //! - getting version number +pub mod install; use crate::{check_origin_running, constants::CORE_MODS, get_host_os, GameInstall, InstallType}; use anyhow::anyhow; diff --git a/src-vue/src/components/InstallProgressBar.vue b/src-vue/src/components/InstallProgressBar.vue index d0c2047c..21901ac0 100644 --- a/src-vue/src/components/InstallProgressBar.vue +++ b/src-vue/src/components/InstallProgressBar.vue @@ -30,13 +30,13 @@ export default defineComponent({ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; }, formatText() { - if (this.status == "DOWNLOADING") { + if (this.status == "Downloading") { const current_downloaded_string = this.formatBytes(this.current_downloaded); const total_size_string = this.formatBytes(this.total_size); const status = this.$t("generic.downloading"); return `${status}: ${current_downloaded_string}/${total_size_string}`; } - if (this.status == "EXTRACTING") { + if (this.status == "Extracting") { return this.$t("generic.extracting"); } return "Inactive"; // Needed to keep same size format when progress bar is hidden @@ -49,17 +49,17 @@ export default defineComponent({ this.install_or_update = true; let progress = payload; this.status = progress.state; - if (progress.state == "DOWNLOADING") { + if (progress.state == "Downloading") { this.percentage = ((Number(progress.current_downloaded) / Number(progress.total_size)) * 100); this.color = '#409EFF'; this.current_downloaded = Number(progress.current_downloaded); this.total_size = Number(progress.total_size); } - if (progress.state == "EXTRACTING") { + if (progress.state == "Extracting") { this.percentage = 100; this.color = '#67C23A'; } - if (progress.state == "DONE") { + if (progress.state == "Done") { // Clear state again this.install_or_update = false } @@ -75,7 +75,7 @@ export default defineComponent({ :format="formatText" :percentage="percentage" :color="color" - :indeterminate="status === 'EXTRACTING'" + :indeterminate="status === 'Extracting'" :duration="1" > -- cgit v1.2.3