mirror of
https://github.com/an-anime-team/sleepy-launcher.git
synced 2024-11-22 21:02:44 +03:00
Made some progress on adding game/voiceovers downloading
This commit is contained in:
parent
a4df021a2d
commit
9d5b3b27ed
3 changed files with 114 additions and 32 deletions
|
@ -38,7 +38,7 @@ impl Default for LauncherState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LauncherState {
|
impl LauncherState {
|
||||||
pub fn get(status_page: Option<adw::StatusPage>) -> std::io::Result<Self> {
|
pub fn get(status_page: Option<&adw::StatusPage>) -> std::io::Result<Self> {
|
||||||
let config = config::get()?;
|
let config = config::get()?;
|
||||||
let game = Game::new(&config.game.path);
|
let game = Game::new(&config.game.path);
|
||||||
|
|
||||||
|
|
146
src/ui/main.rs
146
src/ui/main.rs
|
@ -7,11 +7,14 @@ use gtk4::glib::clone;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
|
use anime_game_core::prelude::*;
|
||||||
|
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
|
|
||||||
use super::preferences::PreferencesStack;
|
use super::preferences::PreferencesStack;
|
||||||
use super::traits::toast_error::ToastError;
|
use super::traits::toast_error::ToastError;
|
||||||
|
|
||||||
|
use crate::lib::config;
|
||||||
use crate::lib::game;
|
use crate::lib::game;
|
||||||
use crate::lib::tasks;
|
use crate::lib::tasks;
|
||||||
use crate::lib::launcher::states::LauncherState;
|
use crate::lib::launcher::states::LauncherState;
|
||||||
|
@ -80,7 +83,7 @@ pub enum Actions {
|
||||||
OpenPreferencesPage,
|
OpenPreferencesPage,
|
||||||
PreferencesGoBack,
|
PreferencesGoBack,
|
||||||
PerformButtonEvent,
|
PerformButtonEvent,
|
||||||
LaunchGame,
|
DownloadDiff(Rc<VersionDiff>),
|
||||||
ShowProgressBar,
|
ShowProgressBar,
|
||||||
UpdateProgress { fraction: Rc<f64>, title: Rc<String> },
|
UpdateProgress { fraction: Rc<f64>, title: Rc<String> },
|
||||||
HideProgressBar
|
HideProgressBar
|
||||||
|
@ -136,12 +139,12 @@ impl App {
|
||||||
|
|
||||||
// Load initial launcher state
|
// Load initial launcher state
|
||||||
std::thread::spawn(clone!(@strong result => move || {
|
std::thread::spawn(clone!(@strong result => move || {
|
||||||
match LauncherState::get(Some(result.widgets.status_page.clone())) {
|
match LauncherState::get(Some(&result.widgets.status_page)) {
|
||||||
Ok(state) => {
|
Ok(state) => {
|
||||||
result.set_state(state);
|
result.set_state(state);
|
||||||
|
|
||||||
result.widgets.status_page.set_visible(false);
|
result.widgets.status_page.hide();
|
||||||
result.widgets.launcher_content.set_visible(true);
|
result.widgets.launcher_content.show();
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
glib::MainContext::default().invoke(move || {
|
glib::MainContext::default().invoke(move || {
|
||||||
|
@ -207,28 +210,111 @@ impl App {
|
||||||
|
|
||||||
match state {
|
match state {
|
||||||
LauncherState::Launch => {
|
LauncherState::Launch => {
|
||||||
this.update(Actions::LaunchGame);
|
|
||||||
},
|
|
||||||
LauncherState::PatchAvailable(_) => todo!(),
|
|
||||||
LauncherState::VoiceUpdateAvailable(_) => todo!(),
|
|
||||||
LauncherState::VoiceOutdated(_) => todo!(),
|
|
||||||
LauncherState::VoiceNotInstalled(_) => todo!(),
|
|
||||||
LauncherState::GameUpdateAvailable(_) => todo!(),
|
|
||||||
LauncherState::GameOutdated(_) => todo!(),
|
|
||||||
LauncherState::GameNotInstalled(_) => todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Actions::LaunchGame => {
|
|
||||||
// Display toast message if the game is failed to run
|
// Display toast message if the game is failed to run
|
||||||
if let Err(err) = game::run(false) {
|
if let Err(err) = game::run(false) {
|
||||||
this.toast_error("Failed to run game", err);
|
this.toast_error("Failed to run game", err);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
LauncherState::PatchAvailable(_) => todo!(),
|
||||||
|
|
||||||
|
LauncherState::VoiceUpdateAvailable(diff) |
|
||||||
|
LauncherState::VoiceNotInstalled(diff) |
|
||||||
|
LauncherState::GameUpdateAvailable(diff) |
|
||||||
|
LauncherState::GameNotInstalled(diff) => {
|
||||||
|
this.update(Actions::DownloadDiff(Rc::new(diff)));
|
||||||
|
},
|
||||||
|
|
||||||
|
LauncherState::GameOutdated(_) => (),
|
||||||
|
LauncherState::VoiceOutdated(_) => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Actions::DownloadDiff(diff) => {
|
||||||
|
match config::get() {
|
||||||
|
Ok(config) => {
|
||||||
|
fn to_gb(bytes: u64) -> f64 {
|
||||||
|
(bytes as f64 / 1024.0 / 1024.0 / 1024.0 * 100.0).ceil() / 100.0
|
||||||
|
}
|
||||||
|
|
||||||
|
let diff = (*diff).clone();
|
||||||
|
|
||||||
|
std::thread::spawn(clone!(@strong this => move || {
|
||||||
|
diff.install_to(config.game.path, clone!(@strong this => move |state| {
|
||||||
|
match state {
|
||||||
|
InstallerUpdate::DownloadingStarted(_) => {
|
||||||
|
this.update(Actions::ShowProgressBar);
|
||||||
|
|
||||||
|
this.update(Actions::UpdateProgress {
|
||||||
|
fraction: Rc::new(0.0),
|
||||||
|
title: Rc::new(String::from("Downloading..."))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {} GB)",
|
||||||
|
progress * 100.0,
|
||||||
|
to_gb(curr),
|
||||||
|
to_gb(total)
|
||||||
|
))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InstallerUpdate::UnpackingStarted(_) => {
|
||||||
|
this.update(Actions::UpdateProgress {
|
||||||
|
fraction: Rc::new(0.0),
|
||||||
|
title: Rc::new(String::from("Unpacking..."))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {} GB)",
|
||||||
|
progress * 100.0,
|
||||||
|
to_gb(curr),
|
||||||
|
to_gb(total)
|
||||||
|
))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
InstallerUpdate::DownloadingFinished => (),
|
||||||
|
|
||||||
|
InstallerUpdate::UnpackingFinished => {
|
||||||
|
this.update(Actions::HideProgressBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
InstallerUpdate::DownloadingError(err) => this.toast_error("Failed to download game", err),
|
||||||
|
InstallerUpdate::UnpackingError => this.toast_error("Failed to unpack game", "?")
|
||||||
|
}
|
||||||
|
})).unwrap();
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
glib::MainContext::default().invoke(clone!(@strong this => move || {
|
||||||
|
this.toast_error("Failed to load config", err);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Actions::ShowProgressBar => {
|
Actions::ShowProgressBar => {
|
||||||
this.widgets.launch_game_group.set_visible(false);
|
this.widgets.progress_bar.set_text(None);
|
||||||
this.widgets.progress_bar_group.set_visible(true);
|
this.widgets.progress_bar.set_fraction(0.0);
|
||||||
|
|
||||||
|
this.widgets.launch_game_group.hide();
|
||||||
|
this.widgets.progress_bar_group.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
Actions::UpdateProgress { fraction, title } => {
|
Actions::UpdateProgress { fraction, title } => {
|
||||||
|
@ -237,8 +323,8 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
Actions::HideProgressBar => {
|
Actions::HideProgressBar => {
|
||||||
this.widgets.launch_game_group.set_visible(true);
|
this.widgets.launch_game_group.show();
|
||||||
this.widgets.progress_bar_group.set_visible(false);
|
this.widgets.progress_bar_group.hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,24 +367,22 @@ impl App {
|
||||||
self.widgets.launch_game.set_label("Apply patch");
|
self.widgets.launch_game.set_label("Apply patch");
|
||||||
}
|
}
|
||||||
|
|
||||||
LauncherState::GameUpdateAvailable(_) => {
|
LauncherState::GameUpdateAvailable(_) |
|
||||||
self.widgets.launch_game.set_label("Update");
|
|
||||||
}
|
|
||||||
|
|
||||||
LauncherState::VoiceUpdateAvailable(_) => {
|
LauncherState::VoiceUpdateAvailable(_) => {
|
||||||
self.widgets.launch_game.set_label("Update");
|
self.widgets.launch_game.set_label("Update");
|
||||||
}
|
}
|
||||||
|
|
||||||
LauncherState::GameNotInstalled(_) => {
|
LauncherState::GameNotInstalled(_) |
|
||||||
self.widgets.launch_game.set_label("Download");
|
|
||||||
}
|
|
||||||
|
|
||||||
LauncherState::VoiceNotInstalled(_) => {
|
LauncherState::VoiceNotInstalled(_) => {
|
||||||
self.widgets.launch_game.set_label("Download");
|
self.widgets.launch_game.set_label("Download");
|
||||||
}
|
}
|
||||||
|
|
||||||
LauncherState::VoiceOutdated(_) => todo!(),
|
LauncherState::VoiceOutdated(_) |
|
||||||
LauncherState::GameOutdated(_) => todo!()
|
LauncherState::GameOutdated(_) => {
|
||||||
|
self.widgets.launch_game.set_label("Update");
|
||||||
|
self.widgets.launch_game.set_tooltip_text(Some("Version is too outdated and can't be updated"));
|
||||||
|
self.widgets.launch_game.set_sensitive(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut values = self.values.take();
|
let mut values = self.values.take();
|
||||||
|
|
|
@ -62,8 +62,6 @@ impl PreferencesStack {
|
||||||
/// Update page info before opening it
|
/// Update page info before opening it
|
||||||
///
|
///
|
||||||
/// Being called from the `MainApp` struct
|
/// Being called from the `MainApp` struct
|
||||||
///
|
|
||||||
/// TODO: do it asynchronously. The problem is that I somehow need to handle this function's error to display it as a toast
|
|
||||||
pub fn update(&self) -> Result<(), Error> {
|
pub fn update(&self) -> Result<(), Error> {
|
||||||
self.status_page.set_visible(true);
|
self.status_page.set_visible(true);
|
||||||
self.status_page.set_description(None);
|
self.status_page.set_description(None);
|
||||||
|
|
Loading…
Reference in a new issue