Added temp folder path param to config

it fixes issue with huge data downloading. You can specify `null` as temp path
and then default system temp folder will be used
Also added `unwrap` everywhere I could add it
just not to see warnings in the code editor
This commit is contained in:
Observer KRypt0n_ 2022-07-23 22:03:11 +02:00
parent 5565e10eb6
commit 5fee051c43
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
7 changed files with 78 additions and 61 deletions

@ -1 +1 @@
Subproject commit fcb297e323bb2de70cb59d78e32f87ec8b0ec029 Subproject commit f4ad7711ac156c4c69bc8a14c896f07ad54a101c

View file

@ -112,7 +112,7 @@ impl Config {
None None
}, },
Err(err) => None Err(_) => None
} }
}, },
None => None None => None
@ -122,13 +122,15 @@ impl Config {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Launcher { pub struct Launcher {
pub language: String pub language: String,
pub temp: Option<String>
} }
impl Default for Launcher { impl Default for Launcher {
fn default() -> Self { fn default() -> Self {
Self { Self {
language: String::from("en-us") language: String::from("en-us"),
temp: launcher_dir()
} }
} }
} }

View file

@ -15,7 +15,7 @@ async fn main() {
// Create app // Create app
let application = gtk::Application::new( let application = gtk::Application::new(
Some("com.gitlab.an-anime-team.an-anime-game-launcher"), Some("com.gitlab.an-anime-team.an-anime-game-launcher-gtk"),
Default::default() Default::default()
); );

View file

@ -1,9 +1,6 @@
use gtk4::{self as gtk, prelude::*}; use gtk4::{self as gtk, prelude::*};
use libadwaita::{self as adw, prelude::*}; use libadwaita::{self as adw, prelude::*};
use gtk::glib;
use gtk::Align;
use crate::lib::wine::Group; use crate::lib::wine::Group;
use super::wine_row::WineRow; use super::wine_row::WineRow;

View file

@ -78,7 +78,7 @@ impl AppWidgets {
/// This enum is used to describe an action inside of this application /// This enum is used to describe an action inside of this application
/// ///
/// It may be helpful if you want to add the same event for several widgets, or call an action inside of another action /// It may be helpful if you want to add the same event for several widgets, or call an action inside of another action
#[derive(Debug, glib::Downgrade)] #[derive(Debug, Clone, glib::Downgrade)]
pub enum Actions { pub enum Actions {
OpenPreferencesPage, OpenPreferencesPage,
PreferencesGoBack, PreferencesGoBack,
@ -91,8 +91,8 @@ pub enum Actions {
impl Actions { impl Actions {
pub fn into_fn<T: gtk::glib::IsA<gtk::Widget>>(&self, app: &App) -> Box<dyn Fn(&T)> { pub fn into_fn<T: gtk::glib::IsA<gtk::Widget>>(&self, app: &App) -> Box<dyn Fn(&T)> {
Box::new(clone!(@weak self as action, @strong app => move |_| { Box::new(clone!(@strong self as action, @strong app => move |_| {
app.update(action); app.update(action.clone()).expect(&format!("Failed to execute action {:?}", &action));
})) }))
} }
} }
@ -138,21 +138,7 @@ impl App {
result.widgets.window.set_application(Some(app)); result.widgets.window.set_application(Some(app));
// Load initial launcher state // Load initial launcher state
std::thread::spawn(clone!(@strong result => move || { result.update_state();
match LauncherState::get(Some(&result.widgets.status_page)) {
Ok(state) => {
result.set_state(state);
result.widgets.status_page.hide();
result.widgets.launcher_content.show();
},
Err(err) => {
glib::MainContext::default().invoke(move || {
result.toast_error("Failed to get initial launcher state", err);
});
}
}
}));
Ok(result) Ok(result)
} }
@ -182,7 +168,10 @@ impl App {
receiver.attach(None, move |action| { receiver.attach(None, move |action| {
// Some debug output // Some debug output
println!("[main] [update] action: {:?}", &action); match &action {
Actions::UpdateProgress { .. } => (),
action => println!("[main] [update] action: {:?}", action)
}
match action { match action {
Actions::OpenPreferencesPage => { Actions::OpenPreferencesPage => {
@ -191,7 +180,8 @@ impl App {
tasks::run(clone!(@strong this => async move { tasks::run(clone!(@strong this => async move {
if let Err(err) = this.widgets.preferences_stack.update() { if let Err(err) = this.widgets.preferences_stack.update() {
glib::MainContext::default().invoke(move || { glib::MainContext::default().invoke(move || {
this.update(Actions::PreferencesGoBack); this.update(Actions::PreferencesGoBack).unwrap();
this.toast_error("Failed to update preferences", err); this.toast_error("Failed to update preferences", err);
}); });
} }
@ -222,7 +212,7 @@ impl App {
LauncherState::VoiceNotInstalled(diff) | LauncherState::VoiceNotInstalled(diff) |
LauncherState::GameUpdateAvailable(diff) | LauncherState::GameUpdateAvailable(diff) |
LauncherState::GameNotInstalled(diff) => { LauncherState::GameNotInstalled(diff) => {
this.update(Actions::DownloadDiff(Rc::new(diff))); this.update(Actions::DownloadDiff(Rc::new(diff))).unwrap();
}, },
LauncherState::GameOutdated(_) => (), LauncherState::GameOutdated(_) => (),
@ -238,17 +228,20 @@ impl App {
} }
let diff = (*diff).clone(); let diff = (*diff).clone();
let this = this.clone();
std::thread::spawn(clone!(@strong this => move || { std::thread::spawn(move || {
diff.install_to(config.game.path, clone!(@strong this => move |state| { let this = this.clone();
diff.install_to_by(config.game.path, config.launcher.temp, move |state| {
match state { match state {
InstallerUpdate::DownloadingStarted(_) => { InstallerUpdate::DownloadingStarted(_) => {
this.update(Actions::ShowProgressBar); this.update(Actions::ShowProgressBar).unwrap();
this.update(Actions::UpdateProgress { this.update(Actions::UpdateProgress {
fraction: Rc::new(0.0), fraction: Rc::new(0.0),
title: Rc::new(String::from("Downloading...")) title: Rc::new(String::from("Downloading..."))
}); }).unwrap();
} }
InstallerUpdate::DownloadingProgress(curr, total) => { InstallerUpdate::DownloadingProgress(curr, total) => {
@ -264,7 +257,7 @@ impl App {
to_gb(curr), to_gb(curr),
to_gb(total) to_gb(total)
)) ))
}); }).unwrap();
} }
} }
@ -272,7 +265,7 @@ impl App {
this.update(Actions::UpdateProgress { this.update(Actions::UpdateProgress {
fraction: Rc::new(0.0), fraction: Rc::new(0.0),
title: Rc::new(String::from("Unpacking...")) title: Rc::new(String::from("Unpacking..."))
}); }).unwrap();
} }
InstallerUpdate::UnpackingProgress(curr, total) => { InstallerUpdate::UnpackingProgress(curr, total) => {
@ -286,20 +279,21 @@ impl App {
to_gb(curr), to_gb(curr),
to_gb(total) to_gb(total)
)) ))
}); }).unwrap();
} }
InstallerUpdate::DownloadingFinished => (), InstallerUpdate::DownloadingFinished => (),
InstallerUpdate::UnpackingFinished => { InstallerUpdate::UnpackingFinished => {
this.update(Actions::HideProgressBar); this.update(Actions::HideProgressBar).unwrap();
this.update_state();
} }
InstallerUpdate::DownloadingError(err) => this.toast_error("Failed to download game", err), InstallerUpdate::DownloadingError(err) => this.toast_error("Failed to download game", err),
InstallerUpdate::UnpackingError => this.toast_error("Failed to unpack game", "?") InstallerUpdate::UnpackingError => this.toast_error("Failed to unpack game", "?")
} }
})).unwrap(); }).unwrap();
})); });
}, },
Err(err) => { Err(err) => {
glib::MainContext::default().invoke(clone!(@strong this => move || { glib::MainContext::default().invoke(clone!(@strong this => move || {
@ -391,6 +385,26 @@ impl App {
self.values.set(values); self.values.set(values);
} }
pub fn update_state(&self) {
let this = self.clone();
std::thread::spawn(move || {
match LauncherState::get(Some(&this.widgets.status_page)) {
Ok(state) => {
this.set_state(state);
this.widgets.status_page.hide();
this.widgets.launcher_content.show();
},
Err(err) => {
glib::MainContext::default().invoke(move || {
this.toast_error("Failed to get initial launcher state", err);
});
}
}
});
}
} }
impl ToastError for App { impl ToastError for App {

View file

@ -151,7 +151,7 @@ pub enum Actions {
impl Actions { impl Actions {
pub fn into_fn<T: gtk::glib::IsA<gtk::Widget>>(&self, app: &App) -> Box<dyn Fn(&T)> { pub fn into_fn<T: gtk::glib::IsA<gtk::Widget>>(&self, app: &App) -> Box<dyn Fn(&T)> {
Box::new(clone!(@strong self as action, @strong app => move |_| { Box::new(clone!(@strong self as action, @strong app => move |_| {
app.update(action.clone()); app.update(action.clone()).expect(&format!("Failed to execute action {:?}", &action));
})) }))
} }
} }
@ -202,7 +202,7 @@ impl App {
self.widgets.wine_selected.connect_selected_notify(clone!(@strong self as this => move |combo_row| { self.widgets.wine_selected.connect_selected_notify(clone!(@strong self as this => move |combo_row| {
if let Some(model) = combo_row.model() { if let Some(model) = combo_row.model() {
if model.n_items() > 0 { if model.n_items() > 0 {
this.update(Actions::SelectWineVersion(Rc::new(combo_row.selected() as usize))); this.update(Actions::SelectWineVersion(Rc::new(combo_row.selected() as usize))).unwrap();
} }
} }
})); }));
@ -210,7 +210,7 @@ impl App {
self.widgets.dxvk_selected.connect_selected_notify(clone!(@strong self as this => move |combo_row| { self.widgets.dxvk_selected.connect_selected_notify(clone!(@strong self as this => move |combo_row| {
if let Some(model) = combo_row.model() { if let Some(model) = combo_row.model() {
if model.n_items() > 0 { if model.n_items() > 0 {
this.update(Actions::SelectDxvkVersion(Rc::new(combo_row.selected() as usize))); this.update(Actions::SelectDxvkVersion(Rc::new(combo_row.selected() as usize))).unwrap();
} }
} }
})); }));
@ -254,12 +254,16 @@ impl App {
for (i, component) in components.into_iter().enumerate() { for (i, component) in components.into_iter().enumerate() {
component.button.connect_clicked(Actions::DxvkPerformAction(Rc::new(i)).into_fn(&self)); component.button.connect_clicked(Actions::DxvkPerformAction(Rc::new(i)).into_fn(&self));
component.apply_button.connect_clicked(clone!(@strong component.version as version, @strong self as this => move |_| { component.apply_button.connect_clicked(clone!(@strong component, @strong self as this => move |_| {
let config = config::get().expect("Failed to load config"); std::thread::spawn(clone!(@strong component, @strong this => move || {
let config = config::get().expect("Failed to load config");
if let Err(err) = version.apply(config.game.dxvk.builds, config.game.wine.prefix) { if let Err(err) = component.apply(config.game.dxvk.builds, config.game.wine.prefix) {
this.toast_error("Failed to apply DXVK", err); this.update(Actions::ToastError(Rc::new((
} String::from("Failed to apply DXVK"), err
)))).unwrap();
}
}));
})); }));
} }
@ -289,12 +293,12 @@ impl App {
if let Err(err) = component.delete(&config.game.dxvk.builds) { if let Err(err) = component.delete(&config.game.dxvk.builds) {
this.update(Actions::ToastError(Rc::new(( this.update(Actions::ToastError(Rc::new((
String::from("Failed to delete DXVK"), err String::from("Failed to delete DXVK"), err
)))); )))).unwrap();
} }
component.update_state(&config.game.dxvk.builds); component.update_state(&config.game.dxvk.builds);
this.update(Actions::UpdateDxvkComboRow); this.update(Actions::UpdateDxvkComboRow).unwrap();
} }
else { else {
@ -303,12 +307,12 @@ impl App {
if let Err(err) = component.apply(&config.game.dxvk.builds, &config.game.wine.prefix) { if let Err(err) = component.apply(&config.game.dxvk.builds, &config.game.wine.prefix) {
this.update(Actions::ToastError(Rc::new(( this.update(Actions::ToastError(Rc::new((
String::from("Failed to apply DXVK"), err String::from("Failed to apply DXVK"), err
)))); )))).unwrap();
} }
component.update_state(&config.game.dxvk.builds); component.update_state(&config.game.dxvk.builds);
this.update(Actions::UpdateDxvkComboRow); this.update(Actions::UpdateDxvkComboRow).unwrap();
})); }));
} }
} }
@ -323,12 +327,12 @@ impl App {
if let Err(err) = component.delete(&config.game.wine.builds) { if let Err(err) = component.delete(&config.game.wine.builds) {
this.update(Actions::ToastError(Rc::new(( this.update(Actions::ToastError(Rc::new((
String::from("Failed to delete wine"), err String::from("Failed to delete wine"), err
)))); )))).unwrap();
} }
component.update_state(&config.game.wine.builds); component.update_state(&config.game.wine.builds);
this.update(Actions::UpdateWineComboRow); this.update(Actions::UpdateWineComboRow).unwrap();
} }
else { else {
@ -336,7 +340,7 @@ impl App {
awaiter.then(clone!(@strong this => move |_| { awaiter.then(clone!(@strong this => move |_| {
component.update_state(&config.game.wine.builds); component.update_state(&config.game.wine.builds);
this.update(Actions::UpdateWineComboRow); this.update(Actions::UpdateWineComboRow).unwrap();
})); }));
} }
} }
@ -550,10 +554,10 @@ impl App {
} }
// Update downloaded wine versions // Update downloaded wine versions
self.update(Actions::UpdateWineComboRow); self.update(Actions::UpdateWineComboRow).unwrap();
// Update downloaded DXVK versions // Update downloaded DXVK versions
self.update(Actions::UpdateDxvkComboRow); self.update(Actions::UpdateDxvkComboRow).unwrap();
Ok(()) Ok(())
} }

View file

@ -57,15 +57,15 @@ pub trait DownloadComponent {
progress_bar.set_visible(false); progress_bar.set_visible(false);
button.set_visible(true); button.set_visible(true);
downl_send.send(DownloadingResult::Done); downl_send.send(DownloadingResult::Done).unwrap();
}, },
InstallerUpdate::DownloadingError(err) => { InstallerUpdate::DownloadingError(err) => {
downl_send.send(DownloadingResult::DownloadingError(err.into())); downl_send.send(DownloadingResult::DownloadingError(err.into())).unwrap();
}, },
InstallerUpdate::UnpackingError => { InstallerUpdate::UnpackingError => {
downl_send.send(DownloadingResult::UnpackingError); downl_send.send(DownloadingResult::UnpackingError).unwrap();
} }
} }
@ -77,13 +77,13 @@ pub trait DownloadComponent {
let installer = Installer::new(self.get_download_uri())?; let installer = Installer::new(self.get_download_uri())?;
let installation_path = installation_path.to_string(); let installation_path = installation_path.to_string();
send.send(installer); send.send(installer).unwrap();
std::thread::spawn(move || { std::thread::spawn(move || {
let mut installer = recv.recv().unwrap(); let mut installer = recv.recv().unwrap();
installer.install(installation_path, move |state| { installer.install(installation_path, move |state| {
sender.send(state); sender.send(state).unwrap();
}); });
}); });