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]
|
[package]
|
||||||
name = "anime-game-launcher"
|
name = "anime-game-launcher"
|
||||||
version = "0.2.1"
|
version = "0.3.0"
|
||||||
description = "Anime Game launcher"
|
description = "Anime Game launcher"
|
||||||
authors = ["Nikita Podvirnyy <suimin.tu.mu.ga.mi@gmail.com>"]
|
authors = ["Nikita Podvirnyy <suimin.tu.mu.ga.mi@gmail.com>"]
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
|
|
|
@ -42,16 +42,19 @@ impl LauncherState {
|
||||||
pub fn get(status_page: Option<&libadwaita::StatusPage>) -> std::io::Result<Self> {
|
pub fn get(status_page: Option<&libadwaita::StatusPage>) -> std::io::Result<Self> {
|
||||||
let config = config::get()?;
|
let config = config::get()?;
|
||||||
|
|
||||||
|
// Check wine existance
|
||||||
if config.game.wine.selected == None {
|
if config.game.wine.selected == None {
|
||||||
return Ok(Self::WineNotInstalled);
|
return Ok(Self::WineNotInstalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check prefix existance
|
||||||
let prefix = WinePrefix::new(&config.game.wine.prefix);
|
let prefix = WinePrefix::new(&config.game.wine.prefix);
|
||||||
|
|
||||||
if !prefix.exists() {
|
if !prefix.exists() {
|
||||||
return Ok(Self::PrefixNotExists);
|
return Ok(Self::PrefixNotExists);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check game installation status
|
||||||
if let Some(status_page) = &status_page {
|
if let Some(status_page) = &status_page {
|
||||||
status_page.set_description(Some("Updating game info..."));
|
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();
|
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| {
|
wine_version_installer.install(&config.game.wine.builds, move |state| {
|
||||||
sender.send(state).unwrap();
|
sender.send(state).unwrap();
|
||||||
});
|
});
|
||||||
|
@ -242,6 +246,10 @@ impl App {
|
||||||
// Prepare DXVK downloader
|
// Prepare DXVK downloader
|
||||||
let mut dxvk_version_installer = Installer::new(&dxvk_version.uri).unwrap();
|
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 dxvk_version = dxvk_version.clone();
|
||||||
let progress_bar = progress_bar.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::game;
|
||||||
use crate::lib::tasks;
|
use crate::lib::tasks;
|
||||||
use crate::lib::launcher::states::LauncherState;
|
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
|
/// This structure is used to describe widgets used in application
|
||||||
///
|
///
|
||||||
|
@ -124,7 +129,6 @@ pub enum Actions {
|
||||||
OpenPreferencesPage,
|
OpenPreferencesPage,
|
||||||
PreferencesGoBack,
|
PreferencesGoBack,
|
||||||
PerformButtonEvent,
|
PerformButtonEvent,
|
||||||
DownloadDiff(Rc<VersionDiff>),
|
|
||||||
ShowProgressBar,
|
ShowProgressBar,
|
||||||
UpdateProgress { fraction: Rc<f64>, title: Rc<String> },
|
UpdateProgress { fraction: Rc<f64>, title: Rc<String> },
|
||||||
HideProgressBar,
|
HideProgressBar,
|
||||||
|
@ -214,12 +218,7 @@ impl App {
|
||||||
|
|
||||||
receiver.attach(None, move |action| {
|
receiver.attach(None, move |action| {
|
||||||
// Some debug output
|
// Some debug output
|
||||||
match &action {
|
println!("[main] [update] action: {:?}", action);
|
||||||
// Actions::UpdateProgress { .. } |
|
|
||||||
// Actions::UpdateProgressByState(_) => (),
|
|
||||||
|
|
||||||
action => println!("[main] [update] action: {:?}", action)
|
|
||||||
}
|
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
Actions::OpenPreferencesPage => {
|
Actions::OpenPreferencesPage => {
|
||||||
|
@ -248,57 +247,159 @@ impl App {
|
||||||
|
|
||||||
this.values.set(values);
|
this.values.set(values);
|
||||||
|
|
||||||
match state {
|
match config::get() {
|
||||||
LauncherState::Launch => {
|
Ok(mut config) => {
|
||||||
// Display toast message if the game is failed to run
|
match state {
|
||||||
if let Err(err) = game::run(false) {
|
LauncherState::Launch => {
|
||||||
this.toast_error("Failed to run game", err);
|
// 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(_) => ()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Err(err) => this.toast_error("Failed to load config", err)
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,6 +452,9 @@ impl App {
|
||||||
pub fn set_state(&self, state: LauncherState) {
|
pub fn set_state(&self, state: LauncherState) {
|
||||||
println!("[main] [set_state] state: {:?}", &state);
|
println!("[main] [set_state] state: {:?}", &state);
|
||||||
|
|
||||||
|
self.widgets.launch_game.set_tooltip_text(None);
|
||||||
|
self.widgets.launch_game.set_sensitive(true);
|
||||||
|
|
||||||
match state {
|
match state {
|
||||||
LauncherState::Launch => {
|
LauncherState::Launch => {
|
||||||
self.widgets.launch_game.set_label("Launch");
|
self.widgets.launch_game.set_label("Launch");
|
||||||
|
@ -396,6 +500,9 @@ impl App {
|
||||||
pub fn update_state(&self) {
|
pub fn update_state(&self) {
|
||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
|
|
||||||
|
this.widgets.status_page.show();
|
||||||
|
this.widgets.launcher_content.hide();
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
match LauncherState::get(Some(&this.widgets.status_page)) {
|
match LauncherState::get(Some(&this.widgets.status_page)) {
|
||||||
Ok(state) => {
|
Ok(state) => {
|
||||||
|
|
|
@ -7,6 +7,8 @@ use std::path::Path;
|
||||||
use anime_game_core::prelude::*;
|
use anime_game_core::prelude::*;
|
||||||
use wait_not_await::Await;
|
use wait_not_await::Await;
|
||||||
|
|
||||||
|
use crate::lib::config;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum DownloadingResult {
|
pub enum DownloadingResult {
|
||||||
DownloadingError(std::io::Error),
|
DownloadingError(std::io::Error),
|
||||||
|
@ -73,7 +75,12 @@ pub trait DownloadComponent {
|
||||||
|
|
||||||
let (send, recv) = std::sync::mpsc::channel();
|
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();
|
let installation_path = installation_path.to_string();
|
||||||
|
|
||||||
send.send(installer).unwrap();
|
send.send(installer).unwrap();
|
||||||
|
|
Loading…
Reference in a new issue