mirror of
https://github.com/an-anime-team/an-anime-game-launcher.git
synced 2024-11-22 04:46:08 +03:00
Several changes
- added new wine versions - added automatic default folder creation - added `latest` methods for DXVK/Wine versions - added `wine_prefix` mod with `WinePrefix` struct to manage what do you think what - spent lots of time trying to make the launcher download default wine version, create prefix and apply DXVK but it just pauses actions flow after ~400 KB of downloaded wine version progress
This commit is contained in:
parent
daac4c8ff0
commit
744f234acd
7 changed files with 394 additions and 59 deletions
|
@ -3,6 +3,45 @@
|
||||||
"title": "Wine-GE-Proton",
|
"title": "Wine-GE-Proton",
|
||||||
"subtitle": null,
|
"subtitle": null,
|
||||||
"versions": [
|
"versions": [
|
||||||
|
{
|
||||||
|
"family": "Wine-GE-Proton",
|
||||||
|
"name": "lutris-GE-Proton7-22-x86_64",
|
||||||
|
"title": "Wine-GE-Proton 7-22",
|
||||||
|
"uri": "https://github.com/GloriousEggroll/wine-ge-custom/releases/download/GE-Proton7-22/wine-lutris-GE-Proton7-22-x86_64.tar.xz",
|
||||||
|
"files": {
|
||||||
|
"wine": "bin/wine64",
|
||||||
|
"wineserver": "bin/wineserver",
|
||||||
|
"wineboot": "bin/wineboot",
|
||||||
|
"winecfg": "lib64/wine/x86_64-windows/winecfg.exe"
|
||||||
|
},
|
||||||
|
"recommended": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"family": "Wine-GE-Proton",
|
||||||
|
"name": "lutris-GE-Proton7-20-x86_64",
|
||||||
|
"title": "Wine-GE-Proton 7-20",
|
||||||
|
"uri": "https://github.com/GloriousEggroll/wine-ge-custom/releases/download/GE-Proton7-20/wine-lutris-GE-Proton7-20-x86_64.tar.xz",
|
||||||
|
"files": {
|
||||||
|
"wine": "bin/wine64",
|
||||||
|
"wineserver": "bin/wineserver",
|
||||||
|
"wineboot": "bin/wineboot",
|
||||||
|
"winecfg": "lib64/wine/x86_64-windows/winecfg.exe"
|
||||||
|
},
|
||||||
|
"recommended": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"family": "Wine-GE-Proton",
|
||||||
|
"name": "lutris-GE-Proton7-18-x86_64",
|
||||||
|
"title": "Wine-GE-Proton 7-18",
|
||||||
|
"uri": "https://github.com/GloriousEggroll/wine-ge-custom/releases/download/GE-Proton7-18/wine-lutris-GE-Proton7-18-x86_64.tar.xz",
|
||||||
|
"files": {
|
||||||
|
"wine": "bin/wine64",
|
||||||
|
"wineserver": "bin/wineserver",
|
||||||
|
"wineboot": "bin/wineboot",
|
||||||
|
"winecfg": "lib64/wine/x86_64-windows/winecfg.exe"
|
||||||
|
},
|
||||||
|
"recommended": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"family": "Wine-GE-Proton",
|
"family": "Wine-GE-Proton",
|
||||||
"name": "lutris-GE-Proton7-16-x86_64",
|
"name": "lutris-GE-Proton7-16-x86_64",
|
||||||
|
@ -204,6 +243,32 @@
|
||||||
"title": "GE-Proton",
|
"title": "GE-Proton",
|
||||||
"subtitle": "This version includes its own DXVK builds and you can use DXVK_ASYNC variable",
|
"subtitle": "This version includes its own DXVK builds and you can use DXVK_ASYNC variable",
|
||||||
"versions": [
|
"versions": [
|
||||||
|
{
|
||||||
|
"family": "GE-Proton",
|
||||||
|
"name": "GE-Proton7-26",
|
||||||
|
"title": "GE-Proton 7-26",
|
||||||
|
"uri": "https://github.com/GloriousEggroll/proton-ge-custom/releases/download/GE-Proton7-26/GE-Proton7-26.tar.gz",
|
||||||
|
"files": {
|
||||||
|
"wine": "files/bin/wine64",
|
||||||
|
"wineserver": "files/bin/wineserver",
|
||||||
|
"wineboot": "files/bin/wineboot",
|
||||||
|
"winecfg": "files/lib64/wine/x86_64-windows/winecfg.exe"
|
||||||
|
},
|
||||||
|
"recommended": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"family": "GE-Proton",
|
||||||
|
"name": "GE-Proton7-24",
|
||||||
|
"title": "GE-Proton 7-24",
|
||||||
|
"uri": "https://github.com/GloriousEggroll/proton-ge-custom/releases/download/GE-Proton7-24/GE-Proton7-24.tar.gz",
|
||||||
|
"files": {
|
||||||
|
"wine": "files/bin/wine64",
|
||||||
|
"wineserver": "files/bin/wineserver",
|
||||||
|
"wineboot": "files/bin/wineboot",
|
||||||
|
"winecfg": "files/lib64/wine/x86_64-windows/winecfg.exe"
|
||||||
|
},
|
||||||
|
"recommended": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"family": "GE-Proton",
|
"family": "GE-Proton",
|
||||||
"name": "GE-Proton7-20",
|
"name": "GE-Proton7-20",
|
||||||
|
@ -431,6 +496,19 @@
|
||||||
"title": "Lutris",
|
"title": "Lutris",
|
||||||
"subtitle": null,
|
"subtitle": null,
|
||||||
"versions": [
|
"versions": [
|
||||||
|
{
|
||||||
|
"family": "Lutris",
|
||||||
|
"name": "lutris-7.2-2-x86_64",
|
||||||
|
"title": "Lutris 7.2-2",
|
||||||
|
"uri": "https://github.com/lutris/wine/releases/download/lutris-wine-7.2-2/wine-lutris-7.2-2-x86_64.tar.xz",
|
||||||
|
"files": {
|
||||||
|
"wine": "bin/wine64",
|
||||||
|
"wineserver": "bin/wineserver",
|
||||||
|
"wineboot": "bin/wineboot",
|
||||||
|
"winecfg": "lib64/wine/x86_64-windows/winecfg.exe"
|
||||||
|
},
|
||||||
|
"recommended": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"family": "Lutris",
|
"family": "Lutris",
|
||||||
"name": "lutris-7.2-x86_64",
|
"name": "lutris-7.2-x86_64",
|
||||||
|
|
|
@ -61,6 +61,10 @@ pub struct Version {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Version {
|
impl Version {
|
||||||
|
pub fn latest() -> Result<Self, serde_json::Error> {
|
||||||
|
Ok(List::get()?.vanilla[0].clone())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_downloaded_in<T: ToString>(&self, folder: T) -> bool {
|
pub fn is_downloaded_in<T: ToString>(&self, folder: T) -> bool {
|
||||||
std::path::Path::new(&format!("{}/{}", folder.to_string(), self.name)).exists()
|
std::path::Path::new(&format!("{}/{}", folder.to_string(), self.name)).exists()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,4 +4,5 @@ pub mod tasks;
|
||||||
pub mod game;
|
pub mod game;
|
||||||
pub mod dxvk;
|
pub mod dxvk;
|
||||||
pub mod wine;
|
pub mod wine;
|
||||||
|
pub mod wine_prefix;
|
||||||
pub mod launcher;
|
pub mod launcher;
|
||||||
|
|
|
@ -53,6 +53,10 @@ pub struct Version {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Version {
|
impl Version {
|
||||||
|
pub fn latest() -> Result<Self, serde_json::Error> {
|
||||||
|
Ok(List::get()?[0].versions[0].clone())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_downloaded_in<T: ToString>(&self, folder: T) -> bool {
|
pub fn is_downloaded_in<T: ToString>(&self, folder: T) -> bool {
|
||||||
std::path::Path::new(&format!("{}/{}", folder.to_string(), self.name)).exists()
|
std::path::Path::new(&format!("{}/{}", folder.to_string(), self.name)).exists()
|
||||||
}
|
}
|
||||||
|
|
51
src/lib/wine_prefix.rs
Normal file
51
src/lib/wine_prefix.rs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
use std::path::Path;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
pub struct WinePrefix {
|
||||||
|
pub path: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinePrefix {
|
||||||
|
pub fn new<T: ToString>(path: T) -> Self {
|
||||||
|
Self { path: path.to_string() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exists(&self) -> bool {
|
||||||
|
Path::new(&format!("{}/drive_c", self.path)).exists()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wineboot<T: ToString>(&self, runners_folder: T, runner: super::wine::Version, command: &str) -> std::io::Result<()> {
|
||||||
|
let runners_folder = runners_folder.to_string();
|
||||||
|
|
||||||
|
let wineboot = format!("{}/{}", &runners_folder, runner.files.wineboot);
|
||||||
|
let wineserver = format!("{}/{}", &runners_folder, runner.files.wineserver);
|
||||||
|
|
||||||
|
Command::new(wineboot)
|
||||||
|
.env("WINESERVER", wineserver)
|
||||||
|
.env("WINEPREFIX", &self.path)
|
||||||
|
.arg(command)
|
||||||
|
.output()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update<T: ToString>(&self, runners_folder: T, runner: super::wine::Version) -> std::io::Result<()> {
|
||||||
|
self.wineboot(runners_folder, runner, "-u")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end<T: ToString>(&self, runners_folder: T, runner: super::wine::Version) -> std::io::Result<()> {
|
||||||
|
self.wineboot(runners_folder, runner, "-e")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kill<T: ToString>(&self, runners_folder: T, runner: super::wine::Version) -> std::io::Result<()> {
|
||||||
|
self.wineboot(runners_folder, runner, "-k")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn restart<T: ToString>(&self, runners_folder: T, runner: super::wine::Version) -> std::io::Result<()> {
|
||||||
|
self.wineboot(runners_folder, runner, "-r")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shutdown<T: ToString>(&self, runners_folder: T, runner: super::wine::Version) -> std::io::Result<()> {
|
||||||
|
self.wineboot(runners_folder, runner, "-s")
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,6 +27,13 @@ async fn main() {
|
||||||
// FIXME: doesn't work?
|
// FIXME: doesn't work?
|
||||||
set_application_name("An Anime Game Launcher");
|
set_application_name("An Anime Game Launcher");
|
||||||
|
|
||||||
|
// Create default launcher folder if needed
|
||||||
|
let launcher_dir = lib::consts::launcher_dir().unwrap();
|
||||||
|
|
||||||
|
if !std::path::Path::new(&launcher_dir).exists() {
|
||||||
|
std::fs::create_dir_all(launcher_dir).expect("Failed to create default launcher dir");
|
||||||
|
}
|
||||||
|
|
||||||
// Create app
|
// Create app
|
||||||
let application = gtk::Application::new(
|
let application = gtk::Application::new(
|
||||||
Some(APP_ID),
|
Some(APP_ID),
|
||||||
|
|
308
src/ui/main.rs
308
src/ui/main.rs
|
@ -6,6 +6,7 @@ use gtk4::glib::clone;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
use std::io::Error;
|
||||||
|
|
||||||
use anime_game_core::prelude::*;
|
use anime_game_core::prelude::*;
|
||||||
|
|
||||||
|
@ -18,6 +19,36 @@ 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_prefix::WinePrefix;
|
||||||
|
use crate::lib::wine::Version as WineVersion;
|
||||||
|
use crate::lib::dxvk::Version as DxvkVersion;
|
||||||
|
|
||||||
|
fn prettify_bytes(bytes: u64) -> String {
|
||||||
|
if bytes > 1024 * 1024 * 1024 {
|
||||||
|
format!("{:.2} GB", bytes as f64 / 1024.0 / 1024.0 / 1024.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
else if bytes > 1024 * 1024 {
|
||||||
|
format!("{:.2} MB", bytes as f64 / 1024.0 / 1024.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
else if bytes > 1024 {
|
||||||
|
format!("{:.2} KB", bytes as f64 / 1024.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
format!("{:.2} B", 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
|
/// This structure is used to describe widgets used in application
|
||||||
///
|
///
|
||||||
|
@ -104,6 +135,7 @@ impl AppWidgets {
|
||||||
format!("GTK version: {}.{}.{}", gtk::major_version(), gtk::minor_version(), gtk::micro_version()),
|
format!("GTK version: {}.{}.{}", gtk::major_version(), gtk::minor_version(), gtk::micro_version()),
|
||||||
format!("Libadwaita version: {}.{}.{}", adw::major_version(), adw::minor_version(), adw::micro_version()),
|
format!("Libadwaita version: {}.{}.{}", adw::major_version(), adw::minor_version(), adw::micro_version()),
|
||||||
format!("Pango version: {}", gtk::pango::version_string().unwrap_or("?".into())),
|
format!("Pango version: {}", gtk::pango::version_string().unwrap_or("?".into())),
|
||||||
|
format!("Cairo version: {}", gtk::cairo::version_string()),
|
||||||
].join("\n")));
|
].join("\n")));
|
||||||
|
|
||||||
// Add preferences page to the leaflet
|
// Add preferences page to the leaflet
|
||||||
|
@ -122,9 +154,11 @@ pub enum Actions {
|
||||||
PreferencesGoBack,
|
PreferencesGoBack,
|
||||||
PerformButtonEvent,
|
PerformButtonEvent,
|
||||||
DownloadDiff(Rc<VersionDiff>),
|
DownloadDiff(Rc<VersionDiff>),
|
||||||
|
UpdateProgressByState(Rc<(InstallerUpdate, Option<String>)>),
|
||||||
ShowProgressBar,
|
ShowProgressBar,
|
||||||
UpdateProgress { fraction: Rc<f64>, title: Rc<String> },
|
UpdateProgress { fraction: Rc<f64>, title: Rc<String> },
|
||||||
HideProgressBar
|
HideProgressBar,
|
||||||
|
ToastError(Rc<(String, Error)>)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Actions {
|
impl Actions {
|
||||||
|
@ -211,7 +245,9 @@ impl App {
|
||||||
receiver.attach(None, move |action| {
|
receiver.attach(None, move |action| {
|
||||||
// Some debug output
|
// Some debug output
|
||||||
match &action {
|
match &action {
|
||||||
Actions::UpdateProgress { .. } => (),
|
// Actions::UpdateProgress { .. } |
|
||||||
|
// Actions::UpdateProgressByState(_) => (),
|
||||||
|
|
||||||
action => println!("[main] [update] action: {:?}", action)
|
action => println!("[main] [update] action: {:?}", action)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,76 +302,156 @@ impl App {
|
||||||
|
|
||||||
Actions::DownloadDiff(diff) => {
|
Actions::DownloadDiff(diff) => {
|
||||||
match config::get() {
|
match config::get() {
|
||||||
Ok(config) => {
|
Ok(mut 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();
|
let diff = (*diff).clone();
|
||||||
let this = this.clone();
|
let this = this.clone();
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
let this = this.clone();
|
let this = this.clone();
|
||||||
|
|
||||||
diff.install_to_by(config.game.path, config.launcher.temp, move |state| {
|
this.update(Actions::ShowProgressBar).unwrap();
|
||||||
match state {
|
|
||||||
InstallerUpdate::DownloadingStarted(_) => {
|
|
||||||
this.update(Actions::ShowProgressBar).unwrap();
|
|
||||||
|
|
||||||
this.update(Actions::UpdateProgress {
|
// Download wine version if not installed
|
||||||
fraction: Rc::new(0.0),
|
match WineVersion::latest() {
|
||||||
title: Rc::new(String::from("Downloading..."))
|
Ok(wine) => match Installer::new(wine.uri) {
|
||||||
}).unwrap();
|
Ok(mut installer) => {
|
||||||
}
|
let (send, recv) = std::sync::mpsc::channel();
|
||||||
|
let wine_title = wine.title.clone();
|
||||||
|
|
||||||
InstallerUpdate::DownloadingProgress(curr, total) => {
|
installer.install(&config.game.wine.builds, clone!(@strong this => move |state| {
|
||||||
// To reduce amount of action requests
|
match state {
|
||||||
if curr % 10000 < 200 {
|
InstallerUpdate::UnpackingFinished => {
|
||||||
let progress = curr as f64 / total as f64;
|
send.send(true).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
this.update(Actions::UpdateProgress {
|
InstallerUpdate::DownloadingError(_) |
|
||||||
fraction: Rc::new(progress),
|
InstallerUpdate::UnpackingError => {
|
||||||
title: Rc::new(format!(
|
send.send(false).unwrap();
|
||||||
"Downloading: {:.2}% ({} of {} GB)",
|
}
|
||||||
progress * 100.0,
|
|
||||||
to_gb(curr),
|
_ => ()
|
||||||
to_gb(total)
|
}
|
||||||
))
|
|
||||||
}).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());
|
||||||
|
|
||||||
InstallerUpdate::UnpackingStarted(_) => {
|
return;
|
||||||
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 {} GB)",
|
|
||||||
progress * 100.0,
|
|
||||||
to_gb(curr),
|
|
||||||
to_gb(total)
|
|
||||||
))
|
|
||||||
}).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
InstallerUpdate::DownloadingFinished => (),
|
|
||||||
|
|
||||||
InstallerUpdate::UnpackingFinished => {
|
|
||||||
this.update(Actions::HideProgressBar).unwrap();
|
|
||||||
this.update_state();
|
|
||||||
}
|
|
||||||
|
|
||||||
InstallerUpdate::DownloadingError(err) => this.toast_error("Failed to download game", err),
|
|
||||||
InstallerUpdate::UnpackingError => this.toast_error("Failed to unpack game", "?")
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download diff
|
||||||
|
diff.install_to_by(config.game.path, config.launcher.temp, move |state| {
|
||||||
|
this.update(Actions::UpdateProgressByState(Rc::new((state, None)))).unwrap();
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -347,6 +463,74 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Actions::UpdateProgressByState(state) => {
|
||||||
|
// 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 => {
|
Actions::ShowProgressBar => {
|
||||||
this.widgets.progress_bar.set_text(None);
|
this.widgets.progress_bar.set_text(None);
|
||||||
this.widgets.progress_bar.set_fraction(0.0);
|
this.widgets.progress_bar.set_fraction(0.0);
|
||||||
|
@ -364,6 +548,12 @@ impl App {
|
||||||
this.widgets.launch_game_group.show();
|
this.widgets.launch_game_group.show();
|
||||||
this.widgets.progress_bar_group.hide();
|
this.widgets.progress_bar_group.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Actions::ToastError(toast) => {
|
||||||
|
let (msg, err) = (toast.0.clone(), toast.1.to_string());
|
||||||
|
|
||||||
|
this.toast_error(msg, err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glib::Continue(true)
|
glib::Continue(true)
|
||||||
|
|
Loading…
Reference in a new issue