mirror of
https://github.com/an-anime-team/sleepy-launcher.git
synced 2024-11-29 09:29:06 +03:00
0.3.0
- added usage of config's temp path to all the installers - added processing of `WineNotInstalled` and `PrefixNotExists` actions - added (forgotten) launcher states updating
This commit is contained in:
parent
69e1c719e5
commit
2ce9e44a86
5 changed files with 183 additions and 58 deletions
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "anime-game-launcher"
|
||||
version = "0.2.1"
|
||||
version = "0.3.0"
|
||||
description = "Anime Game launcher"
|
||||
authors = ["Nikita Podvirnyy <suimin.tu.mu.ga.mi@gmail.com>"]
|
||||
license = "GPL-3.0"
|
||||
|
|
|
@ -42,16 +42,19 @@ impl LauncherState {
|
|||
pub fn get(status_page: Option<&libadwaita::StatusPage>) -> std::io::Result<Self> {
|
||||
let config = config::get()?;
|
||||
|
||||
// Check wine existance
|
||||
if config.game.wine.selected == None {
|
||||
return Ok(Self::WineNotInstalled);
|
||||
}
|
||||
|
||||
// Check prefix existance
|
||||
let prefix = WinePrefix::new(&config.game.wine.prefix);
|
||||
|
||||
if !prefix.exists() {
|
||||
return Ok(Self::PrefixNotExists);
|
||||
}
|
||||
|
||||
// Check game installation status
|
||||
if let Some(status_page) = &status_page {
|
||||
status_page.set_description(Some("Updating game info..."));
|
||||
}
|
||||
|
|
|
@ -214,6 +214,10 @@ impl App {
|
|||
|
||||
let mut wine_version_installer = Installer::new(&wine_version_copy.uri).unwrap();
|
||||
|
||||
if let Some(temp_folder) = config.launcher.temp {
|
||||
wine_version_installer.temp_folder = temp_folder;
|
||||
}
|
||||
|
||||
wine_version_installer.install(&config.game.wine.builds, move |state| {
|
||||
sender.send(state).unwrap();
|
||||
});
|
||||
|
@ -242,6 +246,10 @@ impl App {
|
|||
// Prepare DXVK downloader
|
||||
let mut dxvk_version_installer = Installer::new(&dxvk_version.uri).unwrap();
|
||||
|
||||
if let Some(temp_folder) = config.launcher.temp {
|
||||
dxvk_version_installer.temp_folder = temp_folder;
|
||||
}
|
||||
|
||||
let dxvk_version = dxvk_version.clone();
|
||||
let progress_bar = progress_bar.clone();
|
||||
|
||||
|
|
219
src/ui/main.rs
219
src/ui/main.rs
|
@ -20,6 +20,11 @@ use crate::lib::config;
|
|||
use crate::lib::game;
|
||||
use crate::lib::tasks;
|
||||
use crate::lib::launcher::states::LauncherState;
|
||||
use crate::lib::wine::{
|
||||
Version as WineVersion,
|
||||
List as WineList
|
||||
};
|
||||
use crate::lib::wine_prefix::WinePrefix;
|
||||
|
||||
/// This structure is used to describe widgets used in application
|
||||
///
|
||||
|
@ -124,7 +129,6 @@ pub enum Actions {
|
|||
OpenPreferencesPage,
|
||||
PreferencesGoBack,
|
||||
PerformButtonEvent,
|
||||
DownloadDiff(Rc<VersionDiff>),
|
||||
ShowProgressBar,
|
||||
UpdateProgress { fraction: Rc<f64>, title: Rc<String> },
|
||||
HideProgressBar,
|
||||
|
@ -214,12 +218,7 @@ impl App {
|
|||
|
||||
receiver.attach(None, move |action| {
|
||||
// Some debug output
|
||||
match &action {
|
||||
// Actions::UpdateProgress { .. } |
|
||||
// Actions::UpdateProgressByState(_) => (),
|
||||
|
||||
action => println!("[main] [update] action: {:?}", action)
|
||||
}
|
||||
println!("[main] [update] action: {:?}", action);
|
||||
|
||||
match action {
|
||||
Actions::OpenPreferencesPage => {
|
||||
|
@ -248,57 +247,159 @@ impl App {
|
|||
|
||||
this.values.set(values);
|
||||
|
||||
match state {
|
||||
LauncherState::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);
|
||||
match config::get() {
|
||||
Ok(mut config) => {
|
||||
match state {
|
||||
LauncherState::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);
|
||||
}
|
||||
},
|
||||
|
||||
LauncherState::PatchAvailable(_) => todo!(),
|
||||
|
||||
LauncherState::WineNotInstalled => {
|
||||
match WineList::list_downloaded(&config.game.wine.builds) {
|
||||
Ok(list) => {
|
||||
for version in list {
|
||||
if version.recommended {
|
||||
config.game.wine.selected = Some(version.name);
|
||||
|
||||
config::update(config.clone());
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if config.game.wine.selected == None {
|
||||
match WineVersion::latest() {
|
||||
Ok(wine) => {
|
||||
match Installer::new(wine.uri) {
|
||||
Ok(mut installer) => {
|
||||
if let Some(temp_folder) = config.launcher.temp {
|
||||
installer.temp_folder = temp_folder;
|
||||
}
|
||||
|
||||
let (sender, receiver) = glib::MainContext::channel::<InstallerUpdate>(glib::PRIORITY_DEFAULT);
|
||||
let this = this.clone();
|
||||
|
||||
this.update(Actions::ShowProgressBar).unwrap();
|
||||
|
||||
// Download wine version
|
||||
// We need to update components from the main thread
|
||||
receiver.attach(None, move |state| {
|
||||
match this.widgets.progress_bar.update_from_state(state) {
|
||||
ProgressUpdateResult::Updated => (),
|
||||
|
||||
ProgressUpdateResult::Error(msg, err) => {
|
||||
this.update(Actions::ToastError(Rc::new((msg, err)))).unwrap();
|
||||
this.update(Actions::HideProgressBar).unwrap();
|
||||
}
|
||||
|
||||
ProgressUpdateResult::Finished => {
|
||||
let mut config = config::get().unwrap();
|
||||
|
||||
config.game.wine.selected = Some(wine.name.clone());
|
||||
|
||||
config::update(config);
|
||||
|
||||
this.update(Actions::HideProgressBar).unwrap();
|
||||
this.update_state();
|
||||
}
|
||||
}
|
||||
|
||||
glib::Continue(true)
|
||||
});
|
||||
|
||||
// Download wine version in separate thread to not to freeze the main one
|
||||
std::thread::spawn(move || {
|
||||
installer.install(config.game.wine.builds, move |state| {
|
||||
sender.send(state).unwrap();
|
||||
});
|
||||
});
|
||||
},
|
||||
Err(err) => this.toast_error("Failed to init wine version installer", err)
|
||||
}
|
||||
},
|
||||
Err(err) => this.toast_error("Failed to get latest wine version", err)
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
this.update_state();
|
||||
}
|
||||
},
|
||||
Err(err) => this.toast_error("Failed to list downloaded wine versions", err)
|
||||
}
|
||||
}
|
||||
|
||||
LauncherState::PrefixNotExists => {
|
||||
let prefix = WinePrefix::new(&config.game.wine.prefix);
|
||||
|
||||
match config.try_get_selected_wine_info() {
|
||||
Some(wine) => {
|
||||
let this = this.clone();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
this.widgets.launch_game.set_sensitive(false);
|
||||
|
||||
if let Err(err) = prefix.update(&config.game.wine.builds, wine) {
|
||||
this.toast_error("Failed to create wine prefix", err);
|
||||
}
|
||||
|
||||
this.widgets.launch_game.set_sensitive(true);
|
||||
|
||||
this.update_state();
|
||||
});
|
||||
},
|
||||
None => this.toast_error("Failed to get selected wine version", Error::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
LauncherState::VoiceUpdateAvailable(diff) |
|
||||
LauncherState::VoiceNotInstalled(diff) |
|
||||
LauncherState::GameUpdateAvailable(diff) |
|
||||
LauncherState::GameNotInstalled(diff) => {
|
||||
let (sender, receiver) = glib::MainContext::channel::<InstallerUpdate>(glib::PRIORITY_DEFAULT);
|
||||
let this = this.clone();
|
||||
|
||||
this.update(Actions::ShowProgressBar).unwrap();
|
||||
|
||||
// Download diff
|
||||
// We need to update components from the main thread
|
||||
receiver.attach(None, move |state| {
|
||||
match this.widgets.progress_bar.update_from_state(state) {
|
||||
ProgressUpdateResult::Updated => (),
|
||||
|
||||
ProgressUpdateResult::Error(msg, err) => {
|
||||
this.update(Actions::ToastError(Rc::new((msg, err)))).unwrap();
|
||||
this.update(Actions::HideProgressBar).unwrap();
|
||||
}
|
||||
|
||||
ProgressUpdateResult::Finished => {
|
||||
this.update(Actions::HideProgressBar).unwrap();
|
||||
|
||||
this.update_state();
|
||||
}
|
||||
}
|
||||
|
||||
glib::Continue(true)
|
||||
});
|
||||
|
||||
// Download diff in separate thread to not to freeze the main one
|
||||
std::thread::spawn(move || {
|
||||
diff.install_to_by(config.game.path, config.launcher.temp, move |state| {
|
||||
sender.send(state).unwrap();
|
||||
}).unwrap();
|
||||
});
|
||||
},
|
||||
|
||||
LauncherState::GameOutdated(_) => (),
|
||||
LauncherState::VoiceOutdated(_) => ()
|
||||
}
|
||||
},
|
||||
|
||||
LauncherState::PatchAvailable(_) => todo!(),
|
||||
|
||||
LauncherState::WineNotInstalled => todo!(),
|
||||
LauncherState::PrefixNotExists => todo!(),
|
||||
|
||||
LauncherState::VoiceUpdateAvailable(diff) |
|
||||
LauncherState::VoiceNotInstalled(diff) |
|
||||
LauncherState::GameUpdateAvailable(diff) |
|
||||
LauncherState::GameNotInstalled(diff) => {
|
||||
this.update(Actions::DownloadDiff(Rc::new(diff))).unwrap();
|
||||
},
|
||||
|
||||
LauncherState::GameOutdated(_) => (),
|
||||
LauncherState::VoiceOutdated(_) => ()
|
||||
}
|
||||
}
|
||||
|
||||
Actions::DownloadDiff(diff) => {
|
||||
match config::get() {
|
||||
Ok(config) => {
|
||||
let diff = (*diff).clone();
|
||||
let this = this.clone();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let this = this.clone();
|
||||
|
||||
this.update(Actions::ShowProgressBar).unwrap();
|
||||
|
||||
// Download diff
|
||||
diff.install_to_by(config.game.path, config.launcher.temp, move |state| {
|
||||
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();
|
||||
});
|
||||
},
|
||||
Err(err) => {
|
||||
this.update(Actions::ToastError(Rc::new((
|
||||
String::from("Failed to load config"), err
|
||||
)))).unwrap();
|
||||
}
|
||||
Err(err) => this.toast_error("Failed to load config", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,6 +452,9 @@ impl App {
|
|||
pub fn set_state(&self, state: LauncherState) {
|
||||
println!("[main] [set_state] state: {:?}", &state);
|
||||
|
||||
self.widgets.launch_game.set_tooltip_text(None);
|
||||
self.widgets.launch_game.set_sensitive(true);
|
||||
|
||||
match state {
|
||||
LauncherState::Launch => {
|
||||
self.widgets.launch_game.set_label("Launch");
|
||||
|
@ -396,6 +500,9 @@ impl App {
|
|||
pub fn update_state(&self) {
|
||||
let this = self.clone();
|
||||
|
||||
this.widgets.status_page.show();
|
||||
this.widgets.launcher_content.hide();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
match LauncherState::get(Some(&this.widgets.status_page)) {
|
||||
Ok(state) => {
|
||||
|
|
|
@ -7,6 +7,8 @@ use std::path::Path;
|
|||
use anime_game_core::prelude::*;
|
||||
use wait_not_await::Await;
|
||||
|
||||
use crate::lib::config;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DownloadingResult {
|
||||
DownloadingError(std::io::Error),
|
||||
|
@ -73,7 +75,12 @@ pub trait DownloadComponent {
|
|||
|
||||
let (send, recv) = std::sync::mpsc::channel();
|
||||
|
||||
let installer = Installer::new(self.get_download_uri())?;
|
||||
let mut installer = Installer::new(self.get_download_uri())?;
|
||||
|
||||
if let Some(temp_folder) = config::get()?.launcher.temp {
|
||||
installer.temp_folder = temp_folder;
|
||||
}
|
||||
|
||||
let installation_path = installation_path.to_string();
|
||||
|
||||
send.send(installer).unwrap();
|
||||
|
|
Loading…
Reference in a new issue