2023-02-24 10:26:33 +00:00
|
|
|
use relm4::prelude::*;
|
|
|
|
use relm4::component::*;
|
|
|
|
|
|
|
|
use adw::prelude::*;
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
use anime_launcher_sdk::components::*;
|
2023-03-15 21:11:32 +00:00
|
|
|
use anime_launcher_sdk::components::wine::WincompatlibWine;
|
2023-02-24 15:17:42 +00:00
|
|
|
use anime_launcher_sdk::anime_game_core::installer::prelude::*;
|
|
|
|
use anime_launcher_sdk::config;
|
|
|
|
use anime_launcher_sdk::wincompatlib::prelude::*;
|
|
|
|
|
|
|
|
use std::path::PathBuf;
|
2023-02-24 10:26:33 +00:00
|
|
|
|
|
|
|
use super::main::FirstRunAppMsg;
|
|
|
|
use crate::ui::components::*;
|
2023-02-24 16:21:03 +00:00
|
|
|
use crate::i18n::*;
|
2023-03-06 10:39:22 +00:00
|
|
|
use crate::*;
|
2023-02-24 10:26:33 +00:00
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
fn get_installer(uri: &str, temp: Option<&PathBuf>, speed_limit: u64) -> anyhow::Result<Installer> {
|
|
|
|
let mut installer = Installer::new(uri)?;
|
|
|
|
|
|
|
|
installer.downloader.set_downloading_speed(speed_limit)?;
|
|
|
|
|
|
|
|
if let Some(temp) = temp {
|
|
|
|
installer.set_temp_folder(temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(installer)
|
|
|
|
}
|
|
|
|
|
2023-02-24 10:26:33 +00:00
|
|
|
pub struct DownloadComponentsApp {
|
|
|
|
progress_bar: AsyncController<ProgressBar>,
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
wine_combo: adw::ComboRow,
|
|
|
|
dxvk_combo: adw::ComboRow,
|
|
|
|
|
2023-02-24 10:26:33 +00:00
|
|
|
wine_versions: Vec<wine::Version>,
|
|
|
|
dxvk_versions: Vec<dxvk::Version>,
|
|
|
|
|
2023-03-07 18:10:36 +00:00
|
|
|
selected_wine: Option<wine::Version>,
|
|
|
|
selected_dxvk: Option<dxvk::Version>,
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
/// `None` - default,
|
|
|
|
/// `Some(false)` - processing,
|
|
|
|
/// `Some(true)` - done
|
|
|
|
downloading_wine: Option<bool>,
|
2023-03-07 18:10:36 +00:00
|
|
|
downloading_wine_version: String,
|
2023-02-24 15:17:42 +00:00
|
|
|
|
|
|
|
/// `None` - default,
|
|
|
|
/// `Some(false)` - processing,
|
|
|
|
/// `Some(true)` - done
|
|
|
|
creating_prefix: Option<bool>,
|
2023-03-07 18:10:36 +00:00
|
|
|
creating_prefix_path: String,
|
2023-02-24 15:17:42 +00:00
|
|
|
|
|
|
|
/// `None` - default,
|
|
|
|
/// `Some(false)` - processing,
|
|
|
|
/// `Some(true)` - done
|
|
|
|
downloading_dxvk: Option<bool>,
|
2023-03-07 18:10:36 +00:00
|
|
|
downloading_dxvk_version: String,
|
2023-02-24 15:17:42 +00:00
|
|
|
|
|
|
|
/// `None` - default,
|
|
|
|
/// `Some(false)` - processing,
|
|
|
|
/// `Some(true)` - done
|
|
|
|
applying_dxvk: Option<bool>,
|
|
|
|
|
2023-02-24 10:26:33 +00:00
|
|
|
downloading: bool
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub enum DownloadComponentsAppMsg {
|
2023-03-07 11:07:22 +00:00
|
|
|
UpdateVersionsLists,
|
2023-02-24 15:17:42 +00:00
|
|
|
DownloadWine,
|
|
|
|
CreatePrefix,
|
|
|
|
DownloadDXVK,
|
|
|
|
ApplyDXVK,
|
|
|
|
Continue,
|
2023-02-24 10:26:33 +00:00
|
|
|
Exit
|
|
|
|
}
|
|
|
|
|
|
|
|
#[relm4::component(async, pub)]
|
|
|
|
impl SimpleAsyncComponent for DownloadComponentsApp {
|
|
|
|
type Init = ();
|
|
|
|
type Input = DownloadComponentsAppMsg;
|
|
|
|
type Output = FirstRunAppMsg;
|
|
|
|
|
|
|
|
view! {
|
|
|
|
adw::PreferencesPage {
|
|
|
|
set_hexpand: true,
|
|
|
|
|
|
|
|
add = &adw::PreferencesGroup {
|
2023-02-24 11:31:10 +00:00
|
|
|
set_valign: gtk::Align::Center,
|
|
|
|
set_vexpand: true,
|
|
|
|
|
2023-02-24 10:26:33 +00:00
|
|
|
gtk::Label {
|
2023-02-25 14:06:43 +00:00
|
|
|
set_label: &tr("download-components"),
|
2023-02-24 10:26:33 +00:00
|
|
|
add_css_class: "title-1"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
add = &adw::PreferencesGroup {
|
|
|
|
set_valign: gtk::Align::Center,
|
|
|
|
set_vexpand: true,
|
|
|
|
|
|
|
|
#[watch]
|
|
|
|
set_visible: !model.downloading,
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
#[local_ref]
|
|
|
|
wine_combo -> adw::ComboRow {
|
2023-02-25 14:06:43 +00:00
|
|
|
set_title: &tr("wine-version"),
|
2023-02-24 10:26:33 +00:00
|
|
|
|
|
|
|
#[watch]
|
|
|
|
set_model: Some(>k::StringList::new(model.wine_versions.iter()
|
|
|
|
.map(|version| version.title.as_ref())
|
|
|
|
.collect::<Vec<&str>>()
|
|
|
|
.as_slice()))
|
|
|
|
},
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
#[local_ref]
|
|
|
|
dxvk_combo -> adw::ComboRow {
|
2023-02-25 14:06:43 +00:00
|
|
|
set_title: &tr("dxvk-version"),
|
2023-02-24 10:26:33 +00:00
|
|
|
|
|
|
|
#[watch]
|
|
|
|
set_model: Some(>k::StringList::new(model.dxvk_versions.iter()
|
2023-02-24 15:17:42 +00:00
|
|
|
.map(|version| version.name.as_ref())
|
2023-02-24 10:26:33 +00:00
|
|
|
.collect::<Vec<&str>>()
|
|
|
|
.as_slice()))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
add = &adw::PreferencesGroup {
|
|
|
|
set_valign: gtk::Align::Center,
|
|
|
|
set_vexpand: true,
|
|
|
|
|
|
|
|
#[watch]
|
|
|
|
set_visible: !model.downloading,
|
|
|
|
|
|
|
|
gtk::Box {
|
|
|
|
set_orientation: gtk::Orientation::Horizontal,
|
|
|
|
set_halign: gtk::Align::Center,
|
|
|
|
set_spacing: 8,
|
|
|
|
|
|
|
|
gtk::Button {
|
2023-02-25 14:06:43 +00:00
|
|
|
set_label: &tr("download"),
|
2023-02-24 10:26:33 +00:00
|
|
|
set_css_classes: &["suggested-action", "pill"],
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
connect_clicked => DownloadComponentsAppMsg::DownloadWine
|
2023-02-24 10:26:33 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
gtk::Button {
|
2023-02-25 14:06:43 +00:00
|
|
|
set_label: &tr("exit"),
|
2023-02-24 10:26:33 +00:00
|
|
|
add_css_class: "pill",
|
|
|
|
|
|
|
|
connect_clicked => DownloadComponentsAppMsg::Exit
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
add = &adw::PreferencesGroup {
|
|
|
|
set_valign: gtk::Align::Center,
|
|
|
|
set_vexpand: true,
|
|
|
|
|
|
|
|
#[watch]
|
|
|
|
set_visible: model.downloading,
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
adw::ActionRow {
|
2023-02-25 14:06:43 +00:00
|
|
|
set_title: &tr("download-wine"),
|
2023-02-24 15:17:42 +00:00
|
|
|
|
2023-03-07 18:10:36 +00:00
|
|
|
#[watch]
|
|
|
|
set_subtitle: &model.downloading_wine_version,
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
#[watch]
|
|
|
|
set_icon_name: match model.downloading_wine {
|
2023-03-04 11:54:18 +00:00
|
|
|
Some(true) => Some("emblem-ok-symbolic"),
|
2023-02-24 17:23:49 +00:00
|
|
|
Some(false) => None, // Some("process-working"),
|
2023-02-24 15:17:42 +00:00
|
|
|
None => None
|
2023-02-24 17:23:49 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
add_prefix = >k::Spinner {
|
|
|
|
set_spinning: true,
|
|
|
|
|
|
|
|
#[watch]
|
|
|
|
set_visible: model.downloading_wine == Some(false),
|
2023-02-24 15:17:42 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
adw::ActionRow {
|
2023-02-25 14:06:43 +00:00
|
|
|
set_title: &tr("create-prefix"),
|
2023-02-24 15:17:42 +00:00
|
|
|
|
2023-03-07 18:10:36 +00:00
|
|
|
#[watch]
|
|
|
|
set_subtitle: &model.creating_prefix_path,
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
#[watch]
|
|
|
|
set_icon_name: match model.creating_prefix {
|
2023-03-04 11:54:18 +00:00
|
|
|
Some(true) => Some("emblem-ok-symbolic"),
|
2023-02-24 17:23:49 +00:00
|
|
|
Some(false) => None, // Some("process-working"),
|
2023-02-24 15:17:42 +00:00
|
|
|
None => None
|
2023-02-24 17:23:49 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
add_prefix = >k::Spinner {
|
|
|
|
set_spinning: true,
|
|
|
|
|
|
|
|
#[watch]
|
|
|
|
set_visible: model.creating_prefix == Some(false),
|
2023-02-24 15:17:42 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
adw::ActionRow {
|
2023-02-25 14:06:43 +00:00
|
|
|
set_title: &tr("download-dxvk"),
|
2023-02-24 15:17:42 +00:00
|
|
|
|
2023-03-07 18:10:36 +00:00
|
|
|
#[watch]
|
|
|
|
set_subtitle: &model.downloading_dxvk_version,
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
#[watch]
|
|
|
|
set_icon_name: match model.downloading_dxvk {
|
2023-03-04 11:54:18 +00:00
|
|
|
Some(true) => Some("emblem-ok-symbolic"),
|
2023-02-24 17:23:49 +00:00
|
|
|
Some(false) => None, // Some("process-working"),
|
2023-02-24 15:17:42 +00:00
|
|
|
None => None
|
2023-02-24 17:23:49 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
add_prefix = >k::Spinner {
|
|
|
|
set_spinning: true,
|
|
|
|
|
|
|
|
#[watch]
|
|
|
|
set_visible: model.downloading_dxvk == Some(false),
|
2023-02-24 15:17:42 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
adw::ActionRow {
|
2023-02-25 14:06:43 +00:00
|
|
|
set_title: &tr("apply-dxvk"),
|
2023-02-24 15:17:42 +00:00
|
|
|
|
|
|
|
#[watch]
|
|
|
|
set_icon_name: match model.applying_dxvk {
|
2023-03-04 11:54:18 +00:00
|
|
|
Some(true) => Some("emblem-ok-symbolic"),
|
2023-02-24 17:23:49 +00:00
|
|
|
Some(false) => None, // Some("process-working"),
|
2023-02-24 15:17:42 +00:00
|
|
|
None => None
|
2023-02-24 17:23:49 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
add_prefix = >k::Spinner {
|
|
|
|
set_spinning: true,
|
|
|
|
|
|
|
|
#[watch]
|
|
|
|
set_visible: model.applying_dxvk == Some(false),
|
2023-02-24 15:17:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
add = &adw::PreferencesGroup {
|
|
|
|
set_valign: gtk::Align::Start,
|
|
|
|
set_vexpand: true,
|
|
|
|
|
|
|
|
#[watch]
|
|
|
|
set_visible: model.downloading,
|
|
|
|
|
2023-02-24 10:26:33 +00:00
|
|
|
gtk::Box {
|
|
|
|
set_orientation: gtk::Orientation::Horizontal,
|
|
|
|
set_halign: gtk::Align::Center,
|
|
|
|
set_spacing: 20,
|
|
|
|
set_margin_top: 64,
|
|
|
|
|
|
|
|
append = model.progress_bar.widget(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn init(
|
|
|
|
_init: Self::Init,
|
|
|
|
root: Self::Root,
|
2023-02-24 15:17:42 +00:00
|
|
|
sender: AsyncComponentSender<Self>,
|
2023-02-24 10:26:33 +00:00
|
|
|
) -> AsyncComponentParts<Self> {
|
|
|
|
let model = Self {
|
|
|
|
progress_bar: ProgressBar::builder()
|
|
|
|
.launch(ProgressBarInit {
|
|
|
|
caption: None,
|
|
|
|
display_progress: true,
|
|
|
|
display_fraction: true,
|
|
|
|
visible: true
|
|
|
|
})
|
|
|
|
.detach(),
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
wine_combo: adw::ComboRow::new(),
|
|
|
|
dxvk_combo: adw::ComboRow::new(),
|
|
|
|
|
2023-03-07 11:07:22 +00:00
|
|
|
wine_versions: vec![],
|
|
|
|
dxvk_versions: vec![],
|
2023-02-24 10:26:33 +00:00
|
|
|
|
2023-03-07 18:10:36 +00:00
|
|
|
selected_wine: None,
|
|
|
|
selected_dxvk: None,
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
downloading_wine: None,
|
2023-03-07 18:10:36 +00:00
|
|
|
downloading_wine_version: String::new(),
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
creating_prefix: None,
|
2023-03-07 18:10:36 +00:00
|
|
|
creating_prefix_path: String::new(),
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
downloading_dxvk: None,
|
2023-03-07 18:10:36 +00:00
|
|
|
downloading_dxvk_version: String::new(),
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
applying_dxvk: None,
|
|
|
|
|
2023-02-24 10:26:33 +00:00
|
|
|
downloading: false
|
|
|
|
};
|
|
|
|
|
|
|
|
model.progress_bar.widget().set_width_request(360);
|
|
|
|
|
2023-02-24 15:17:42 +00:00
|
|
|
let wine_combo = &model.wine_combo;
|
|
|
|
let dxvk_combo = &model.dxvk_combo;
|
|
|
|
|
2023-02-24 10:26:33 +00:00
|
|
|
let widgets = view_output!();
|
|
|
|
|
|
|
|
AsyncComponentParts { model, widgets }
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn update(&mut self, msg: Self::Input, sender: AsyncComponentSender<Self>) {
|
|
|
|
match msg {
|
2023-03-07 11:07:22 +00:00
|
|
|
DownloadComponentsAppMsg::UpdateVersionsLists => {
|
2023-03-07 18:10:36 +00:00
|
|
|
// 4 latest versions of 4 first available wine group
|
|
|
|
self.wine_versions = wine::get_groups(&CONFIG.components.path).unwrap()
|
|
|
|
.into_iter()
|
|
|
|
.take(4)
|
|
|
|
.flat_map(|group| group.versions.into_iter().take(4))
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
// 4 latest versions of 4 first available dxvk group
|
|
|
|
self.dxvk_versions = dxvk::get_groups(&CONFIG.components.path).unwrap()
|
|
|
|
.into_iter()
|
|
|
|
.take(4)
|
|
|
|
.flat_map(|group| group.versions.into_iter().take(4))
|
|
|
|
.collect();
|
2023-03-07 11:07:22 +00:00
|
|
|
}
|
|
|
|
|
2023-02-24 10:26:33 +00:00
|
|
|
#[allow(unused_must_use)]
|
2023-02-24 15:17:42 +00:00
|
|
|
DownloadComponentsAppMsg::DownloadWine => {
|
2023-03-07 18:10:36 +00:00
|
|
|
let config = config::get().unwrap_or_default();
|
|
|
|
|
|
|
|
self.selected_wine = Some(self.wine_versions[self.wine_combo.selected() as usize].clone());
|
|
|
|
self.selected_dxvk = Some(self.dxvk_versions[self.dxvk_combo.selected() as usize].clone());
|
|
|
|
|
|
|
|
self.downloading_wine_version = self.selected_wine.clone().unwrap().title;
|
|
|
|
self.downloading_dxvk_version = self.selected_dxvk.clone().unwrap().name;
|
|
|
|
self.creating_prefix_path = config.game.wine.prefix.to_string_lossy().to_string();
|
|
|
|
|
2023-02-24 10:26:33 +00:00
|
|
|
self.downloading = true;
|
2023-02-24 15:17:42 +00:00
|
|
|
self.downloading_wine = Some(false);
|
|
|
|
|
2023-03-07 18:10:36 +00:00
|
|
|
let wine = self.selected_wine.clone().unwrap();
|
2023-02-24 15:17:42 +00:00
|
|
|
let progress_bar_input = self.progress_bar.sender().clone();
|
|
|
|
|
2023-03-11 07:41:28 +00:00
|
|
|
// Skip wine downloading if it was already done
|
|
|
|
if wine.is_downloaded_in(&config.game.wine.builds) {
|
|
|
|
tracing::info!("Wine already installed: {}", wine.name);
|
2023-02-24 16:21:03 +00:00
|
|
|
|
2023-03-11 07:41:28 +00:00
|
|
|
sender.input(DownloadComponentsAppMsg::CreatePrefix);
|
|
|
|
}
|
2023-02-24 16:21:03 +00:00
|
|
|
|
2023-03-11 07:41:28 +00:00
|
|
|
// Otherwise download wine
|
|
|
|
else {
|
|
|
|
std::thread::spawn(move || {
|
|
|
|
tracing::info!("Installing wine: {}", wine.name);
|
|
|
|
|
|
|
|
// Install wine
|
|
|
|
match get_installer(&wine.uri, config.launcher.temp.as_ref(), config.launcher.speed_limit) {
|
|
|
|
Ok(mut installer) => {
|
|
|
|
// Create wine builds folder
|
|
|
|
if config.game.wine.builds.exists() {
|
|
|
|
std::fs::create_dir_all(&config.game.wine.builds)
|
|
|
|
.expect("Failed to create wine builds directory");
|
|
|
|
}
|
|
|
|
|
|
|
|
installer.install(&config.game.wine.builds, move |update| {
|
|
|
|
match &update {
|
|
|
|
InstallerUpdate::DownloadingError(err) => {
|
|
|
|
tracing::error!("Failed to download wine: {err}");
|
|
|
|
|
2023-02-24 16:21:03 +00:00
|
|
|
sender.output(Self::Output::Toast {
|
2023-03-11 07:41:28 +00:00
|
|
|
title: tr("wine-download-error"),
|
2023-02-24 16:21:03 +00:00
|
|
|
description: Some(err.to_string())
|
|
|
|
});
|
|
|
|
}
|
2023-03-11 07:41:28 +00:00
|
|
|
|
|
|
|
InstallerUpdate::UnpackingError(err) => {
|
|
|
|
tracing::error!("Failed to unpack wine: {err}");
|
|
|
|
|
|
|
|
sender.output(Self::Output::Toast {
|
|
|
|
title: tr("wine-unpack-errror"),
|
|
|
|
description: Some(err.clone())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create prefix
|
|
|
|
InstallerUpdate::UnpackingFinished => {
|
|
|
|
let mut config = config::get().unwrap_or_default();
|
|
|
|
|
|
|
|
config.game.wine.selected = Some(wine.name.clone());
|
|
|
|
|
|
|
|
if let Err(err) = config::update_raw(config) {
|
|
|
|
sender.output(Self::Output::Toast {
|
|
|
|
title: tr("config-update-error"),
|
|
|
|
description: Some(err.to_string())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
sender.input(DownloadComponentsAppMsg::CreatePrefix);
|
|
|
|
},
|
|
|
|
|
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
|
|
|
|
progress_bar_input.send(ProgressBarMsg::UpdateFromState(update));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(err) => {
|
|
|
|
tracing::error!("Failed to initialize wine installer: {err}");
|
|
|
|
|
|
|
|
sender.output(Self::Output::Toast {
|
|
|
|
title: tr("wine-install-failed"),
|
|
|
|
description: Some(err.to_string())
|
|
|
|
});
|
|
|
|
}
|
2023-02-24 15:17:42 +00:00
|
|
|
}
|
2023-03-11 07:41:28 +00:00
|
|
|
});
|
|
|
|
}
|
2023-02-24 15:17:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(unused_must_use)]
|
|
|
|
DownloadComponentsAppMsg::CreatePrefix => {
|
|
|
|
self.downloading_wine = Some(true);
|
|
|
|
self.creating_prefix = Some(false);
|
|
|
|
|
|
|
|
let config = config::get().unwrap_or_default();
|
|
|
|
|
|
|
|
tracing::info!("Creating wine prefix");
|
|
|
|
|
2023-03-07 18:10:36 +00:00
|
|
|
let wine = self.selected_wine.as_ref().unwrap();
|
2023-02-24 15:17:42 +00:00
|
|
|
|
|
|
|
let wine = wine
|
2023-03-15 21:11:32 +00:00
|
|
|
.to_wine(config.components.path, Some(config.game.wine.builds.join(&wine.name)))
|
|
|
|
.with_prefix(&config.game.wine.prefix)
|
2023-02-24 15:17:42 +00:00
|
|
|
.with_loader(WineLoader::Current)
|
|
|
|
.with_arch(WineArch::Win64);
|
|
|
|
|
|
|
|
std::thread::spawn(move || {
|
2023-03-15 21:11:32 +00:00
|
|
|
match wine.update_prefix::<&str>(None) {
|
2023-02-24 15:17:42 +00:00
|
|
|
// Download DXVK
|
|
|
|
Ok(_) => sender.input(DownloadComponentsAppMsg::DownloadDXVK),
|
|
|
|
|
|
|
|
Err(err) => {
|
|
|
|
tracing::error!("Failed to create prefix: {err}");
|
|
|
|
|
|
|
|
sender.output(Self::Output::Toast {
|
2023-02-25 14:06:43 +00:00
|
|
|
title: tr("wine-prefix-update-failed"),
|
2023-02-24 15:17:42 +00:00
|
|
|
description: Some(err.to_string())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(unused_must_use)]
|
|
|
|
DownloadComponentsAppMsg::DownloadDXVK => {
|
|
|
|
self.creating_prefix = Some(true);
|
|
|
|
self.downloading_dxvk = Some(false);
|
|
|
|
|
|
|
|
let config = config::get().unwrap_or_default();
|
|
|
|
|
2023-03-07 18:10:36 +00:00
|
|
|
let dxvk = self.selected_dxvk.clone().unwrap();
|
2023-02-24 15:17:42 +00:00
|
|
|
let progress_bar_input = self.progress_bar.sender().clone();
|
|
|
|
|
2023-03-11 07:41:28 +00:00
|
|
|
if dxvk.is_downloaded_in(&config.game.dxvk.builds) {
|
|
|
|
tracing::info!("DXVK is already downloaded: {}", dxvk.name);
|
2023-02-24 15:17:42 +00:00
|
|
|
|
2023-03-11 07:41:28 +00:00
|
|
|
sender.input(DownloadComponentsAppMsg::ApplyDXVK);
|
|
|
|
}
|
2023-02-24 15:17:42 +00:00
|
|
|
|
2023-03-11 07:41:28 +00:00
|
|
|
else {
|
|
|
|
std::thread::spawn(move || {
|
|
|
|
// Install DXVK
|
|
|
|
tracing::info!("Installing DXVK: {}", dxvk.name);
|
|
|
|
|
|
|
|
match get_installer(&dxvk.uri, config.launcher.temp.as_ref(), config.launcher.speed_limit) {
|
|
|
|
Ok(mut installer) => {
|
|
|
|
let progress_bar_input = progress_bar_input.clone();
|
|
|
|
let sender = sender.clone();
|
|
|
|
|
|
|
|
// Create DXVK builds folder
|
|
|
|
if config.game.dxvk.builds.exists() {
|
|
|
|
std::fs::create_dir_all(&config.game.dxvk.builds)
|
|
|
|
.expect("Failed to create DXVK builds directory");
|
2023-02-24 15:17:42 +00:00
|
|
|
}
|
2023-03-11 07:41:28 +00:00
|
|
|
|
|
|
|
installer.install(&config.game.dxvk.builds, move |update| {
|
|
|
|
match &update {
|
|
|
|
InstallerUpdate::DownloadingError(err) => {
|
|
|
|
tracing::error!("Failed to download dxvk: {err}");
|
|
|
|
|
|
|
|
sender.output(Self::Output::Toast {
|
|
|
|
title: tr("dxvk-download-error"),
|
|
|
|
description: Some(err.to_string())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
InstallerUpdate::UnpackingError(err) => {
|
|
|
|
tracing::error!("Failed to unpack dxvk: {err}");
|
|
|
|
|
|
|
|
sender.output(Self::Output::Toast {
|
|
|
|
title: tr("dxvk-unpack-error"),
|
|
|
|
description: Some(err.clone())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Apply DXVK
|
|
|
|
InstallerUpdate::UnpackingFinished => {
|
|
|
|
sender.input(DownloadComponentsAppMsg::ApplyDXVK);
|
|
|
|
}
|
|
|
|
|
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
|
|
|
|
progress_bar_input.send(ProgressBarMsg::UpdateFromState(update));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(err) => {
|
|
|
|
tracing::error!("Failed to initialize dxvk installer: {err}");
|
|
|
|
|
|
|
|
sender.output(Self::Output::Toast {
|
|
|
|
title: tr("dxvk-install-failed"),
|
|
|
|
description: Some(err.to_string())
|
|
|
|
});
|
|
|
|
}
|
2023-02-24 15:17:42 +00:00
|
|
|
}
|
2023-03-11 07:41:28 +00:00
|
|
|
});
|
|
|
|
}
|
2023-02-24 15:17:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(unused_must_use)]
|
|
|
|
DownloadComponentsAppMsg::ApplyDXVK => {
|
|
|
|
self.downloading_dxvk = Some(true);
|
|
|
|
self.applying_dxvk = Some(false);
|
|
|
|
|
|
|
|
let config = config::get().unwrap_or_default();
|
|
|
|
|
|
|
|
tracing::info!("Applying DXVK");
|
|
|
|
|
2023-03-07 18:10:36 +00:00
|
|
|
let wine = self.selected_wine.clone().unwrap();
|
|
|
|
let dxvk = self.selected_dxvk.clone().unwrap();
|
2023-02-24 15:17:42 +00:00
|
|
|
|
2023-03-08 12:32:32 +00:00
|
|
|
let group = wine.find_group(&config.components.path).unwrap().unwrap();
|
|
|
|
|
|
|
|
// Apply DXVK if we need it
|
2023-03-15 21:11:32 +00:00
|
|
|
if wine.features_in(&group).unwrap_or_default().need_dxvk {
|
2023-03-08 12:32:32 +00:00
|
|
|
let wine = wine
|
2023-03-15 21:11:32 +00:00
|
|
|
.to_wine(config.components.path, Some(config.game.wine.builds.join(&wine.name)))
|
2023-03-08 12:32:32 +00:00
|
|
|
.with_loader(WineLoader::Current)
|
|
|
|
.with_arch(WineArch::Win64)
|
|
|
|
.with_prefix(config.game.wine.prefix);
|
|
|
|
|
|
|
|
std::thread::spawn(move || {
|
|
|
|
let params = InstallParams {
|
|
|
|
// We just created prefix so don't need to repair it
|
|
|
|
repair_dlls: false,
|
|
|
|
|
|
|
|
..InstallParams::default()
|
|
|
|
};
|
|
|
|
|
2023-03-15 21:11:32 +00:00
|
|
|
let WincompatlibWine::Default(wine) = wine else {
|
|
|
|
sender.input(DownloadComponentsAppMsg::Continue);
|
|
|
|
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
2023-03-08 12:32:32 +00:00
|
|
|
match wine.install_dxvk(config.game.dxvk.builds.join(&dxvk.name), params) {
|
|
|
|
// Go to next page
|
|
|
|
Ok(_) => sender.input(DownloadComponentsAppMsg::Continue),
|
|
|
|
|
|
|
|
Err(err) => {
|
|
|
|
tracing::error!("Failed to apply DXVK: {err}");
|
|
|
|
|
|
|
|
sender.output(Self::Output::Toast {
|
|
|
|
title: tr("dxvk-apply-error"),
|
|
|
|
description: Some(err.to_string())
|
|
|
|
});
|
|
|
|
}
|
2023-02-24 15:17:42 +00:00
|
|
|
}
|
2023-03-08 12:32:32 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip DXVK applying if we don't need it
|
|
|
|
else {
|
|
|
|
sender.input(DownloadComponentsAppMsg::Continue);
|
|
|
|
}
|
2023-02-24 15:17:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(unused_must_use)]
|
|
|
|
DownloadComponentsAppMsg::Continue => {
|
2023-02-24 17:23:49 +00:00
|
|
|
std::fs::remove_file(FIRST_RUN_FILE.as_path());
|
|
|
|
|
2023-02-24 16:21:03 +00:00
|
|
|
sender.output(Self::Output::ScrollToFinish);
|
2023-02-24 10:26:33 +00:00
|
|
|
}
|
|
|
|
|
2023-03-01 21:47:34 +00:00
|
|
|
DownloadComponentsAppMsg::Exit => relm4::main_application().quit()
|
2023-02-24 10:26:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|