diff --git a/Cargo.toml b/Cargo.toml index 5b97ba3..3cbef66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "anime-game-launcher" -version = "0.2.0" +version = "0.2.1" description = "Anime Game launcher" authors = ["Nikita Podvirnyy "] license = "GPL-3.0" diff --git a/assets/ui/first_run.blp b/assets/ui/first_run.blp index ace81e0..8f42701 100644 --- a/assets/ui/first_run.blp +++ b/assets/ui/first_run.blp @@ -242,7 +242,7 @@ Adw.ApplicationWindow window { text: "Downloading: 37% (3.7 of 10 GB)"; show-text: true; - width-request: 260; + width-request: 360; fraction: 0.37; valign: center; } diff --git a/assets/ui/main.blp b/assets/ui/main.blp index 1686e02..83e612b 100644 --- a/assets/ui/main.blp +++ b/assets/ui/main.blp @@ -95,7 +95,7 @@ Adw.ApplicationWindow window { text: "Downloading: 37% (3.7 of 10 GB)"; show-text: true; - width-request: 260; + width-request: 360; fraction: 0.37; valign: center; } diff --git a/src/lib/launcher/executors/create_prefix.rs b/src/lib/launcher/executors/create_prefix.rs deleted file mode 100644 index 60b5938..0000000 --- a/src/lib/launcher/executors/create_prefix.rs +++ /dev/null @@ -1,34 +0,0 @@ -use std::io::Error; - -use wait_not_await::Await; - -use crate::ui::components::progress_bar::ProgressBar; - -use crate::lib::wine_prefix::WinePrefix; -use crate::lib::config::Config; - -pub fn create_prefix(config: Config, progress_bar: ProgressBar) -> Await> { - Await::new(move || { - // Create prefix if needed - let prefix = WinePrefix::new(&config.game.wine.prefix); - - if !prefix.exists() { - progress_bar.update(0.0, Some("Creating prefix...")); - - match config.try_get_selected_wine_info() { - Some(wine_version) => match prefix.update(&config.game.wine.builds, wine_version) { - Ok(_) => Ok(()), - Err(err) => Err((String::from("Failed to create prefix"), err)) - }, - None => { - // TODO: download default wine - todo!() - } - } - } - - else { - Ok(()) - } - }) -} diff --git a/src/lib/launcher/executors/download_diff.rs b/src/lib/launcher/executors/download_diff.rs deleted file mode 100644 index f5a1e00..0000000 --- a/src/lib/launcher/executors/download_diff.rs +++ /dev/null @@ -1,64 +0,0 @@ -use std::io::Error; - -use anime_game_core::prelude::*; -use wait_not_await::Await; - -use crate::ui::components::progress_bar::ProgressBar; -use crate::lib::prettify_bytes::prettify_bytes; - -/*pub fn download_diff(diff: &VersionDiff, progress_bar: ProgressBar, suffix: Option) -> Await> { - let (send, recv) = std::sync::mpsc::channel(); - - diff.install(move |state| { - match state { - InstallerUpdate::DownloadingStarted(_) => progress_bar.update(0.0, Some("Downloading...")), - - InstallerUpdate::DownloadingProgress(curr, total) => { - // To reduce amount of action requests - // if curr % 10000 < 200 { - let progress = curr as f64 / total as f64; - - progress_bar.update(progress, Some(&format!( - "Downloading{}: {:.2}% ({} of {})", - if let Some(suffix) = suffix { format!(" {}", suffix) } else { String::new() }, - progress * 100.0, - prettify_bytes(curr), - prettify_bytes(total) - ))); - // } - } - - InstallerUpdate::UnpackingStarted(_) => progress_bar.update(0.0, Some("Unpacking...")), - - InstallerUpdate::UnpackingProgress(curr, total) => { - let progress = curr as f64 / total as f64; - - progress_bar.update(progress, Some(&format!( - "Unpacking{}: {:.2}% ({} of {})", - if let Some(suffix) = suffix { format!(" {}", suffix) } else { String::new() }, - progress * 100.0, - prettify_bytes(curr), - prettify_bytes(total) - ))); - } - - InstallerUpdate::DownloadingFinished => (), - - InstallerUpdate::UnpackingFinished => { - send.send(Ok(())); - }, - - InstallerUpdate::DownloadingError(err) => { - send.send(Err((String::from("Failed to download"), err.into()))); - } - - InstallerUpdate::UnpackingError => { - send.send(Err((String::from("Failed to unpack"), Error::last_os_error()))); - } - } - }); - - Await::new(move || { - recv.recv().unwrap() - }) -}*/ diff --git a/src/lib/launcher/executors/mod.rs b/src/lib/launcher/executors/mod.rs deleted file mode 100644 index b1898f3..0000000 --- a/src/lib/launcher/executors/mod.rs +++ /dev/null @@ -1,32 +0,0 @@ -mod create_prefix; -mod download_diff; - -pub use create_prefix::*; -pub use download_diff::*; - -use crate::lib::config; -use crate::lib::wine_prefix::WinePrefix; - -#[derive(Debug, Clone, Copy)] -pub enum Component { - Wine, - DXVK, - Prefix -} - -#[derive(Debug, Clone)] -pub struct ComponentsChain { - pub chain: Vec -} - -impl ComponentsChain { - pub fn get() -> std::io::Result { - let config = config::get()?; - - let wine_prefix = WinePrefix::new(&config.game.wine.prefix); - - - - todo!(); - } -} diff --git a/src/lib/launcher/mod.rs b/src/lib/launcher/mod.rs index 3cd5d62..2039478 100644 --- a/src/lib/launcher/mod.rs +++ b/src/lib/launcher/mod.rs @@ -1,2 +1 @@ pub mod states; -pub mod executors; diff --git a/src/lib/launcher/states.rs b/src/lib/launcher/states.rs index d2c5276..c7529a4 100644 --- a/src/lib/launcher/states.rs +++ b/src/lib/launcher/states.rs @@ -4,17 +4,18 @@ use libadwaita::{self as adw, prelude::*}; use std::io::{Error, ErrorKind}; use anime_game_core::prelude::*; -use wait_not_await::Await; -use crate::ui::components::progress_bar::ProgressBar; use crate::lib::config; -use crate::lib::prettify_bytes::prettify_bytes; +use crate::lib::wine_prefix::WinePrefix; #[derive(Debug, Clone)] pub enum LauncherState { Launch, PatchAvailable(Patch), + WineNotInstalled, + PrefixNotExists, + // Always contains `VersionDiff::Diff` VoiceUpdateAvailable(VersionDiff), @@ -43,12 +44,22 @@ impl Default for LauncherState { impl LauncherState { pub fn get(status_page: Option<&adw::StatusPage>) -> std::io::Result { let config = config::get()?; - let game = Game::new(&config.game.path); + + if config.game.wine.selected == None { + return Ok(Self::WineNotInstalled); + } + + let prefix = WinePrefix::new(&config.game.wine.prefix); + + if !prefix.exists() { + return Ok(Self::PrefixNotExists); + } if let Some(status_page) = &status_page { status_page.set_description(Some("Updating game info...")); } + let game = Game::new(&config.game.path); let diff = game.try_get_diff()?; Ok(match diff { @@ -105,171 +116,4 @@ impl LauncherState { VersionDiff::NotInstalled { .. } => Self::GameNotInstalled(diff) }) } - - /*pub fn execute(&self, progress_bar: &ProgressBar) -> Await> { - match self { - Self::Launch => { - // Display toast message if the game is failed to run - /*if let Err(err) = game::run(false) { - this.toast_error("Failed to run game", err); - }*/ - - todo!(); - }, - - Self::PatchAvailable(_) => todo!(), - - Self::VoiceUpdateAvailable(diff) | - Self::VoiceNotInstalled(diff) | - Self::GameUpdateAvailable(diff) | - Self::GameNotInstalled(diff) => { - // this.update(Actions::DownloadDiff(Rc::new(diff))).unwrap(); - - // Download wine version if not installed - match WineVersion::latest() { - Ok(wine) => match Installer::new(wine.uri) { - Ok(mut installer) => { - let (send, recv) = std::sync::mpsc::channel(); - let wine_title = wine.title.clone(); - - installer.install(&config.game.wine.builds, clone!(@strong this => move |state| { - match state { - InstallerUpdate::UnpackingFinished => { - send.send(true).unwrap(); - } - - InstallerUpdate::DownloadingError(_) | - InstallerUpdate::UnpackingError => { - send.send(false).unwrap(); - } - - _ => () - } - - this.update(Actions::UpdateProgressByState(Rc::new((state, Some(wine_title.clone()))))).unwrap(); - })); - - // Block thread until downloading finished - if recv.recv().unwrap() { - config.game.wine.selected = Some(wine.name); - - config::update(config.clone()); - } - - else { - println!("I'm tired, Boss!"); - - return; - } - }, - Err(err) => { - toast_error(&this, "Failed to init wine version installer", err.into()); - - return; - } - }, - Err(err) => { - toast_error(&this, "Failed to load wine versions list", err.into()); - - return; - } - } - - // Create prefix if needed - let prefix = WinePrefix::new(&config.game.wine.prefix); - - if !prefix.exists() { - this.update(Actions::UpdateProgress { - fraction: Rc::new(0.0), - title: Rc::new(String::from("Creating prefix...")) - }).unwrap(); - - match config.try_get_selected_wine_info() { - Some(wine_version) => { - if let Err(err) = prefix.update(&config.game.wine.builds, wine_version) { - toast_error(&this, "Failed to create wineprefix", err); - - return; - } - }, - None => return - } - } - - // Download and apply DXVK if not installed - match DxvkVersion::latest() { - Ok(dxvk) => match Installer::new(&dxvk.uri) { - Ok(mut installer) => { - let (send, recv) = std::sync::mpsc::channel(); - let dxvk_title = dxvk.name.clone(); - - installer.install(&config.game.dxvk.builds, clone!(@strong this => move |state| { - match state { - InstallerUpdate::UnpackingFinished => { - send.send(true).unwrap(); - } - - InstallerUpdate::DownloadingError(_) | - InstallerUpdate::UnpackingError => { - send.send(false).unwrap(); - } - - _ => () - } - - this.update(Actions::UpdateProgressByState(Rc::new((state, Some(dxvk_title.clone()))))).unwrap(); - })); - - // Block thread until downloading finished - if recv.recv().unwrap() { - config.game.dxvk.selected = Some(dxvk.name.clone()); - - config::update(config.clone()); - } - - else { - return; - } - - // Apply DXVK - this.update(Actions::UpdateProgress { - fraction: Rc::new(100.0), - title: Rc::new(String::from("Applying DXVK...")) - }).unwrap(); - - match dxvk.apply(&config.game.dxvk.builds, &config.game.wine.prefix) { - Ok(_) => { - config.game.dxvk.selected = Some(dxvk.name); - - config::update(config.clone()); - }, - Err(err) => { - toast_error(&this, "Failed to apply DXVK", err); - - return; - } - } - }, - Err(err) => { - toast_error(&this, "Failed to init wine version installer", err.into()); - - return; - } - }, - Err(err) => { - toast_error(&this, "Failed to load wine versions list", err.into()); - - return; - } - } - - todo!(); - }, - - Self::GameOutdated(_) => (), - Self::VoiceOutdated(_) => () - } - - todo!(); - }*/ } diff --git a/src/ui/main.rs b/src/ui/main.rs index 00f4b03..006fd68 100644 --- a/src/ui/main.rs +++ b/src/ui/main.rs @@ -14,25 +14,12 @@ use crate::ui::*; use super::preferences::PreferencesStack; use super::traits::toast_error::ToastError; -use super::components::progress_bar::ProgressBar; +use super::components::progress_bar::*; use crate::lib::config; use crate::lib::game; use crate::lib::tasks; use crate::lib::launcher::states::LauncherState; -use crate::lib::wine_prefix::WinePrefix; -use crate::lib::wine::Version as WineVersion; -use crate::lib::dxvk::Version as DxvkVersion; -use crate::lib::prettify_bytes::prettify_bytes; - -fn toast_error(app: &App, msg: &str, err: Error) { - app.update(Actions::ToastError(Rc::new(( - String::from(msg), err - )))).unwrap(); - - app.update(Actions::HideProgressBar).unwrap(); - app.update_state(); -} /// This structure is used to describe widgets used in application /// @@ -138,7 +125,6 @@ pub enum Actions { PreferencesGoBack, PerformButtonEvent, DownloadDiff(Rc), - UpdateProgressByState(Rc<(InstallerUpdate, Option)>), ShowProgressBar, UpdateProgress { fraction: Rc, title: Rc }, HideProgressBar, @@ -272,6 +258,9 @@ impl App { LauncherState::PatchAvailable(_) => todo!(), + LauncherState::WineNotInstalled => todo!(), + LauncherState::PrefixNotExists => todo!(), + LauncherState::VoiceUpdateAvailable(diff) | LauncherState::VoiceNotInstalled(diff) | LauncherState::GameUpdateAvailable(diff) | @@ -286,7 +275,7 @@ impl App { Actions::DownloadDiff(diff) => { match config::get() { - Ok(mut config) => { + Ok(config) => { let diff = (*diff).clone(); let this = this.clone(); @@ -297,7 +286,11 @@ impl App { // Download diff diff.install_to_by(config.game.path, config.launcher.temp, move |state| { - this.update(Actions::UpdateProgressByState(Rc::new((state, None)))).unwrap(); + match this.widgets.progress_bar.update_from_state(state) { + ProgressUpdateResult::Updated => (), + ProgressUpdateResult::Error(msg, err) => this.update(Actions::ToastError(Rc::new((msg, err)))).unwrap(), + ProgressUpdateResult::Finished => this.update(Actions::HideProgressBar).unwrap() + } }).unwrap(); }); }, @@ -309,75 +302,6 @@ impl App { } } - Actions::UpdateProgressByState(state) => { - todo!(); - // let (state, suffix) = (&*state).clone(); - - match &state.0 { - InstallerUpdate::DownloadingStarted(_) => { - this.update(Actions::UpdateProgress { - fraction: Rc::new(0.0), - title: Rc::new(String::from("Downloading...")) - }).unwrap(); - } - - InstallerUpdate::DownloadingProgress(curr, total) => { - // To reduce amount of action requests - // if curr % 10000 < 200 { - let progress = *curr as f64 / *total as f64; - - this.update(Actions::UpdateProgress { - fraction: Rc::new(progress), - title: Rc::new(format!( - "Downloading{}: {:.2}% ({} of {})", - if let Some(suffix) = &state.1 { format!(" {}", suffix) } else { String::new() }, - progress * 100.0, - prettify_bytes(*curr), - prettify_bytes(*total) - )) - }).unwrap(); - // } - } - - InstallerUpdate::UnpackingStarted(_) => { - this.update(Actions::UpdateProgress { - fraction: Rc::new(0.0), - title: Rc::new(String::from("Unpacking...")) - }).unwrap(); - } - - InstallerUpdate::UnpackingProgress(curr, total) => { - let progress = *curr as f64 / *total as f64; - - this.update(Actions::UpdateProgress { - fraction: Rc::new(progress), - title: Rc::new(format!( - "Unpacking{}: {:.2}% ({} of {})", - if let Some(suffix) = &state.1 { format!(" {}", suffix) } else { String::new() }, - progress * 100.0, - prettify_bytes(*curr), - prettify_bytes(*total) - )) - }).unwrap(); - } - - InstallerUpdate::DownloadingFinished => (), - - InstallerUpdate::UnpackingFinished => { - this.update(Actions::HideProgressBar).unwrap(); - this.update_state(); - } - - InstallerUpdate::DownloadingError(err) => { - toast_error(&this, "Failed to download", err.clone().into()); - } - - InstallerUpdate::UnpackingError => { - toast_error(&this, "Failed to unpack", Error::last_os_error()); - } - } - } - Actions::ShowProgressBar => { this.widgets.progress_bar.show(); } @@ -436,6 +360,14 @@ impl App { self.widgets.launch_game.set_label("Apply patch"); } + LauncherState::WineNotInstalled => { + self.widgets.launch_game.set_label("Download wine"); + } + + LauncherState::PrefixNotExists => { + self.widgets.launch_game.set_label("Create prefix"); + } + LauncherState::GameUpdateAvailable(_) | LauncherState::VoiceUpdateAvailable(_) => { self.widgets.launch_game.set_label("Update"); diff --git a/src/ui/traits/download_component.rs b/src/ui/traits/download_component.rs index e59f380..dce97d3 100644 --- a/src/ui/traits/download_component.rs +++ b/src/ui/traits/download_component.rs @@ -1,5 +1,4 @@ use gtk4::{self as gtk, prelude::*}; -use libadwaita::{self as adw, prelude::*}; use gtk::glib;