preferences: made settings sections separate components

- now `General` and `Enhancements` sections are relm4 components
- this change improves code structure and should help
  adding dynamic data loading on app start in future
- settings components are also not async from now because they don't need to
This commit is contained in:
Observer KRypt0n_ 2023-02-22 20:13:58 +02:00
parent 3d5cf4a8f7
commit ba75180811
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
7 changed files with 383 additions and 354 deletions

View file

@ -91,7 +91,7 @@ impl SimpleComponent for AboutDialog {
) -> ComponentParts<Self> {
tracing::info!("Initializing about dialog");
let model = AboutDialog {
let model = Self {
visible: false
};

View file

@ -4,15 +4,15 @@ use relm4::component::*;
use adw::prelude::*;
#[derive(Debug, Clone)]
pub struct ComponentsListInit {
pub struct ComponentsListInit<T> {
pub pattern: super::ComponentsListPattern,
pub on_downloaded: Option<crate::ui::preferences::main::AppMsg>,
pub on_deleted: Option<crate::ui::preferences::main::AppMsg>
pub on_downloaded: Option<T>,
pub on_deleted: Option<T>
}
pub struct ComponentsList {
pub struct ComponentsList<T> {
pub show_recommended_only: bool,
pub init: ComponentsListInit,
pub init: ComponentsListInit<T>,
pub groups: Vec<AsyncController<super::ComponentGroup>>
}
@ -25,10 +25,10 @@ pub enum AppMsg {
}
#[relm4::component(async, pub)]
impl SimpleAsyncComponent for ComponentsList {
type Init = ComponentsListInit;
impl<T: std::fmt::Debug + Clone + 'static> SimpleAsyncComponent for ComponentsList<T> {
type Init = ComponentsListInit<T>;
type Input = AppMsg;
type Output = crate::ui::preferences::main::AppMsg;
type Output = T;
view! {
group = adw::PreferencesGroup {}

View file

@ -1,6 +1,5 @@
use relm4::{
prelude::*,
component::*,
actions::*,
MessageBroker
};
@ -24,7 +23,7 @@ relm4::new_stateless_action!(ConfigFile, WindowActionGroup, "config_file");
relm4::new_stateless_action!(About, WindowActionGroup, "about");
static mut PREFERENCES_WINDOW: Option<AsyncController<PreferencesApp>> = None;
static mut PREFERENCES_WINDOW: Option<Controller<PreferencesApp>> = None;
static mut ABOUT_DIALOG: Option<Controller<AboutDialog>> = None;
pub struct App {

View file

@ -8,10 +8,14 @@ use anime_launcher_sdk::config::prelude::*;
use crate::i18n::tr;
use crate::*;
// TODO: change to relm4::SimpleComponent
pub struct Enhancements;
#[relm4::component(pub)]
impl SimpleComponent for Enhancements {
type Init = ();
type Input = ();
type Output = ();
#[relm4::widget_template(pub)]
impl WidgetTemplate for Enhancements {
view! {
adw::PreferencesPage {
set_title: &tr("enhancements"),
@ -393,4 +397,21 @@ impl WidgetTemplate for Enhancements {
}
}
}
fn init(
_init: Self::Init,
root: &Self::Root,
_sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
tracing::info!("Initializing about dialog");
let model = Self;
let widgets = view_output!();
ComponentParts { model, widgets }
}
fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) {
tracing::debug!("Called enhancements settings event: {:?}", msg);
}
}

View file

@ -1,18 +1,59 @@
use relm4::prelude::*;
use relm4::component::*;
use gtk::prelude::*;
use adw::prelude::*;
use anime_launcher_sdk::config;
use anime_launcher_sdk::config::launcher::LauncherStyle;
use anime_launcher_sdk::anime_game_core::prelude::*;
use anime_launcher_sdk::components::*;
use anime_launcher_sdk::wincompatlib::prelude::*;
use crate::ui::components;
use crate::ui::components::*;
use crate::i18n::*;
use crate::*;
// TODO: change to relm4::SimpleComponent
pub struct General {
wine_components: AsyncController<ComponentsList<AppMsg>>,
dxvk_components: AsyncController<ComponentsList<AppMsg>>,
style: LauncherStyle,
downloaded_wine_versions: Vec<wine::Version>,
downloaded_dxvk_versions: Vec<dxvk::Version>,
selected_wine_version: u32,
selected_dxvk_version: u32,
selecting_wine_version: bool,
selecting_dxvk_version: bool
}
#[derive(Debug, Clone)]
pub enum AppMsg {
Toast {
title: String,
description: Option<String>
},
UpdateLauncherStyle(LauncherStyle),
WineRecommendedOnly(bool),
DxvkRecommendedOnly(bool),
UpdateDownloadedWine,
UpdateDownloadedDxvk,
SelectWine(usize),
SelectDxvk(usize),
ResetWineSelection(usize),
ResetDxvkSelection(usize)
}
#[relm4::component(pub)]
impl SimpleComponent for General {
type Init = ();
type Input = AppMsg;
type Output = super::main::AppMsg;
#[relm4::widget_template(pub)]
impl WidgetTemplate for General {
view! {
adw::PreferencesPage {
set_title: &tr("general"),
@ -30,16 +71,20 @@ impl WidgetTemplate for General {
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
#[name(modern_style_button)]
gtk::ToggleButton {
add_css_class: "card",
set_width_request: 180,
set_height_request: 120,
#[watch]
set_active: model.style == LauncherStyle::Modern,
gtk::Image {
set_from_resource: Some("/org/app/images/modern.svg")
}
},
connect_clicked => AppMsg::UpdateLauncherStyle(LauncherStyle::Modern)
},
gtk::Label {
@ -52,16 +97,20 @@ impl WidgetTemplate for General {
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
#[name(classic_style_button)]
gtk::ToggleButton {
add_css_class: "card",
set_width_request: 180,
set_height_request: 120,
#[watch]
set_active: model.style == LauncherStyle::Classic,
gtk::Image {
set_from_resource: Some("/org/app/images/classic.svg")
}
},
connect_clicked => AppMsg::UpdateLauncherStyle(LauncherStyle::Classic)
},
gtk::Label {
@ -73,8 +122,10 @@ impl WidgetTemplate for General {
}
},
#[name(classic_appearance_params)]
add = &adw::PreferencesGroup {
#[watch]
set_visible: model.style == LauncherStyle::Classic,
adw::ActionRow {
set_title: &tr("update-background"),
set_subtitle: &tr("update-background-description"),
@ -290,48 +341,301 @@ impl WidgetTemplate for General {
add = &adw::PreferencesGroup {
set_title: &tr("wine-version"),
#[name(wine_version_selector)]
adw::ComboRow {
set_title: &tr("selected-version")
set_title: &tr("selected-version"),
#[watch]
#[block_signal(wine_selected_notify)]
set_model: Some(&gtk::StringList::new(&model.downloaded_wine_versions.iter().map(|version| version.title.as_str()).collect::<Vec<&str>>())),
#[watch]
#[block_signal(wine_selected_notify)]
set_selected: model.selected_wine_version,
#[watch]
set_activatable: !model.selecting_wine_version,
#[watch]
set_icon_name: if model.selecting_wine_version {
Some("process-working")
} else {
None
},
connect_selected_notify[sender] => move |row| {
if is_ready() {
sender.input(AppMsg::SelectWine(row.selected() as usize));
}
} @wine_selected_notify
},
adw::ActionRow {
set_title: &tr("recommended-only"),
set_subtitle: &tr("wine-recommended-description"),
#[name(wine_recommended_only)]
add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center,
set_state: true
set_state: true,
connect_state_notify[sender] => move |switch| {
sender.input(AppMsg::WineRecommendedOnly(switch.state()));
}
}
}
},
#[name(wine_versions)]
add = &adw::PreferencesGroup {},
add = &adw::PreferencesGroup {
add = model.wine_components.widget(),
},
add = &adw::PreferencesGroup {
set_title: &tr("dxvk-version"),
#[name(dxvk_version_selector)]
adw::ComboRow {
set_title: &tr("selected-version")
set_title: &tr("selected-version"),
#[watch]
#[block_signal(dxvk_selected_notify)]
set_model: Some(&gtk::StringList::new(&model.downloaded_dxvk_versions.iter().map(|version| version.name.as_str()).collect::<Vec<&str>>())),
#[watch]
#[block_signal(dxvk_selected_notify)]
set_selected: model.selected_dxvk_version,
#[watch]
set_activatable: !model.selecting_dxvk_version,
#[watch]
set_icon_name: if model.selecting_dxvk_version {
Some("process-working")
} else {
None
},
connect_selected_notify[sender] => move |row| {
if is_ready() {
sender.input(AppMsg::SelectDxvk(row.selected() as usize));
}
} @dxvk_selected_notify
},
adw::ActionRow {
set_title: &tr("recommended-only"),
set_subtitle: &tr("dxvk-recommended-description"),
#[name(dxvk_recommended_only)]
add_suffix = &gtk::Switch {
set_valign: gtk::Align::Center,
set_state: true
set_state: true,
connect_state_notify[sender] => move |switch| {
sender.input(AppMsg::DxvkRecommendedOnly(switch.state()));
}
}
}
},
#[name(dxvk_versions)]
add = &adw::PreferencesGroup {},
add = &adw::PreferencesGroup {
add = model.dxvk_components.widget(),
},
}
}
fn init(
_init: Self::Init,
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
tracing::info!("Initializing about dialog");
let model = Self {
wine_components: ComponentsList::builder()
.launch(ComponentsListInit {
pattern: ComponentsListPattern {
download_folder: CONFIG.game.wine.builds.clone(),
groups: wine::get_groups().into_iter().map(|group| group.into()).collect()
},
on_downloaded: Some(AppMsg::UpdateDownloadedWine),
on_deleted: Some(AppMsg::UpdateDownloadedWine)
})
.forward(sender.input_sender(), std::convert::identity),
dxvk_components: ComponentsList::builder()
.launch(ComponentsListInit {
pattern: ComponentsListPattern {
download_folder: CONFIG.game.dxvk.builds.clone(),
groups: dxvk::get_groups().into_iter().map(|group| group.into()).collect()
},
on_downloaded: Some(AppMsg::UpdateDownloadedDxvk),
on_deleted: Some(AppMsg::UpdateDownloadedDxvk)
})
.forward(sender.input_sender(), std::convert::identity),
style: CONFIG.launcher.style,
downloaded_wine_versions: vec![],
downloaded_dxvk_versions: vec![],
selected_wine_version: 0,
selected_dxvk_version: 0,
selecting_wine_version: false,
selecting_dxvk_version: false
};
let widgets = view_output!();
ComponentParts { model, widgets }
}
fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>) {
tracing::debug!("Called enhancements settings event: {:?}", msg);
match msg {
#[allow(unused_must_use)]
AppMsg::UpdateLauncherStyle(style) => {
if let Ok(mut config) = config::get() {
config.launcher.style = style;
config::update(config);
}
self.style = style;
sender.output(Self::Output::UpdateLauncherStyle(style));
}
#[allow(unused_must_use)]
AppMsg::Toast { title, description } => {
sender.output(Self::Output::Toast { title, description });
}
AppMsg::WineRecommendedOnly(state) => {
// todo
self.wine_components.sender().send(components::list::AppMsg::ShowRecommendedOnly(state)).unwrap();
}
AppMsg::DxvkRecommendedOnly(state) => {
// todo
self.dxvk_components.sender().send(components::list::AppMsg::ShowRecommendedOnly(state)).unwrap();
}
AppMsg::UpdateDownloadedWine => {
self.downloaded_wine_versions = wine::get_downloaded(&CONFIG.game.wine.builds).unwrap_or_default();
self.selected_wine_version = if let Some(selected) = &CONFIG.game.wine.selected {
let mut index = 0;
for (i, version) in self.downloaded_wine_versions.iter().enumerate() {
if &version.name == selected {
index = i;
break;
}
}
index as u32
}
else {
0
};
}
AppMsg::UpdateDownloadedDxvk => {
self.downloaded_dxvk_versions = dxvk::get_downloaded(&CONFIG.game.dxvk.builds).unwrap_or_default();
self.selected_dxvk_version = if let Ok(Some(selected)) = CONFIG.try_get_selected_dxvk_info() {
let mut index = 0;
for (i, version) in self.downloaded_dxvk_versions.iter().enumerate() {
if version.name == selected.name {
index = i;
break;
}
}
index as u32
}
else {
0
};
}
AppMsg::SelectWine(index) => {
if let Ok(mut config) = config::get() {
if let Some(version) = self.downloaded_wine_versions.get(index) {
if config.game.wine.selected.as_ref().unwrap_or(&String::new()) != &version.title {
self.selecting_wine_version = true;
let wine = version.to_wine(Some(config.game.wine.builds.join(&version.name)));
let wine_name = version.name.to_string();
std::thread::spawn(move || {
match wine.update_prefix(&config.game.wine.prefix) {
Ok(_) => {
config.game.wine.selected = Some(wine_name);
config::update(config);
}
Err(err) => {
sender.input(AppMsg::Toast {
title: tr("wine-prefix-update-failed"),
description: Some(err.to_string())
});
}
}
sender.input(AppMsg::ResetWineSelection(index));
});
}
}
}
}
AppMsg::ResetWineSelection(index) => {
self.selecting_wine_version = false;
self.selected_wine_version = index as u32;
}
AppMsg::SelectDxvk(index) => {
if let Ok(config) = config::get() {
if let Some(version) = self.downloaded_dxvk_versions.get(index) {
if let Ok(selected) = config.try_get_selected_dxvk_info() {
if selected.is_none() || selected.unwrap().name != version.name {
self.selecting_dxvk_version = true;
let mut wine = match config.try_get_selected_wine_info() {
Some(version) => version.to_wine(Some(config.game.wine.builds.join(&version.name))),
None => Wine::default()
};
wine = wine.with_prefix(config.game.wine.prefix);
let dxvk_folder = config.game.dxvk.builds.join(&version.name);
std::thread::spawn(move || {
if let Err(err) = Dxvk::install(&wine, dxvk_folder, InstallParams::default()) {
sender.input(AppMsg::Toast {
title: tr("dxvk-install-failed"),
description: Some(err.to_string())
});
}
sender.input(AppMsg::ResetDxvkSelection(index));
});
}
}
}
}
}
AppMsg::ResetDxvkSelection(index) => {
self.selecting_dxvk_version = false;
self.selected_dxvk_version = index as u32;
}
}
}
}

View file

@ -1,36 +1,17 @@
use relm4::prelude::*;
use relm4::component::*;
use gtk::prelude::*;
use adw::prelude::*;
use anime_launcher_sdk::config;
use anime_launcher_sdk::config::launcher::LauncherStyle;
use anime_launcher_sdk::components::*;
use anime_launcher_sdk::wincompatlib::prelude::*;
use crate::ui::components::{self, *};
use crate::i18n::tr;
use crate::is_ready;
use crate::CONFIG;
pub static mut PREFERENCES_WINDOW: Option<adw::PreferencesWindow> = None;
pub struct App {
wine_components: AsyncController<ComponentsList>,
dxvk_components: AsyncController<ComponentsList>,
style: LauncherStyle,
downloaded_wine_versions: Vec<wine::Version>,
downloaded_dxvk_versions: Vec<dxvk::Version>,
selected_wine_version: u32,
selected_dxvk_version: u32,
selecting_wine_version: bool,
selecting_dxvk_version: bool
general: Controller<super::general::General>,
enhancements: Controller<super::enhancements::Enhancements>
}
#[derive(Debug, Clone)]
@ -39,19 +20,11 @@ pub enum AppMsg {
title: String,
description: Option<String>
},
UpdateLauncherStyle(LauncherStyle),
WineRecommendedOnly(bool),
DxvkRecommendedOnly(bool),
UpdateDownloadedWine,
UpdateDownloadedDxvk,
SelectWine(usize),
SelectDxvk(usize),
ResetWineSelection(usize),
ResetDxvkSelection(usize)
UpdateLauncherStyle(LauncherStyle)
}
#[relm4::component(async, pub)]
impl SimpleAsyncComponent for App {
#[relm4::component(pub)]
impl SimpleComponent for App {
type Init = gtk::Window;
type Input = AppMsg;
type Output = crate::ui::main::AppMsg;
@ -63,115 +36,8 @@ impl SimpleAsyncComponent for App {
set_hide_on_close: true,
set_modal: true,
#[template]
add = &super::general::General {
// Here technically it's AdwPreferencesGroup inside of AdwPreferencesGroup
// but I have no idea how to do it other way
// There're no graphical glitches so don't care
#[template_child]
modern_style_button {
#[watch]
set_active: model.style == LauncherStyle::Modern,
connect_clicked => AppMsg::UpdateLauncherStyle(LauncherStyle::Modern)
},
#[template_child]
classic_style_button {
#[watch]
set_active: model.style == LauncherStyle::Classic,
connect_clicked => AppMsg::UpdateLauncherStyle(LauncherStyle::Classic)
},
#[template_child]
classic_appearance_params {
#[watch]
set_visible: model.style == LauncherStyle::Classic
},
#[template_child]
wine_versions {
add = model.wine_components.widget(),
},
#[template_child]
wine_version_selector {
#[watch]
#[block_signal(wine_selected_notify)]
set_model: Some(&gtk::StringList::new(&model.downloaded_wine_versions.iter().map(|version| version.title.as_str()).collect::<Vec<&str>>())),
#[watch]
#[block_signal(wine_selected_notify)]
set_selected: model.selected_wine_version,
#[watch]
set_activatable: !model.selecting_wine_version,
#[watch]
set_icon_name: if model.selecting_wine_version {
Some("process-working")
} else {
None
},
connect_selected_notify[sender] => move |row| {
if is_ready() {
sender.input(AppMsg::SelectWine(row.selected() as usize));
}
} @wine_selected_notify
},
#[template_child]
wine_recommended_only {
connect_state_notify[sender] => move |switch| {
sender.input(AppMsg::WineRecommendedOnly(switch.state()));
}
},
#[template_child]
dxvk_versions {
add = model.dxvk_components.widget(),
},
#[template_child]
dxvk_version_selector {
#[watch]
#[block_signal(dxvk_selected_notify)]
set_model: Some(&gtk::StringList::new(&model.downloaded_dxvk_versions.iter().map(|version| version.name.as_str()).collect::<Vec<&str>>())),
#[watch]
#[block_signal(dxvk_selected_notify)]
set_selected: model.selected_dxvk_version,
#[watch]
set_activatable: !model.selecting_dxvk_version,
#[watch]
set_icon_name: if model.selecting_dxvk_version {
Some("process-working")
} else {
None
},
connect_selected_notify[sender] => move |row| {
if is_ready() {
sender.input(AppMsg::SelectDxvk(row.selected() as usize));
}
} @dxvk_selected_notify
},
#[template_child]
dxvk_recommended_only {
connect_state_notify[sender] => move |switch| {
sender.input(AppMsg::DxvkRecommendedOnly(switch.state()));
}
},
},
#[template]
add = &super::enhancements::Enhancements,
add = model.general.widget(),
add = model.enhancements.widget(),
connect_close_request[sender] => move |_| {
if let Err(err) = anime_launcher_sdk::config::flush() {
@ -186,47 +52,21 @@ impl SimpleAsyncComponent for App {
}
}
#[allow(clippy::redundant_clone)]
async fn init(
fn init(
parent: Self::Init,
root: Self::Root,
sender: AsyncComponentSender<Self>,
) -> AsyncComponentParts<Self> {
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
tracing::info!("Initializing preferences window");
let model = App {
wine_components: ComponentsList::builder()
.launch(ComponentsListInit {
pattern: ComponentsListPattern {
download_folder: CONFIG.game.wine.builds.clone(),
groups: wine::get_groups().into_iter().map(|group| group.into()).collect()
},
on_downloaded: Some(AppMsg::UpdateDownloadedWine),
on_deleted: Some(AppMsg::UpdateDownloadedWine)
})
let model = Self {
general: super::general::General::builder()
.launch(())
.forward(sender.input_sender(), std::convert::identity),
dxvk_components: ComponentsList::builder()
.launch(ComponentsListInit {
pattern: ComponentsListPattern {
download_folder: CONFIG.game.dxvk.builds.clone(),
groups: dxvk::get_groups().into_iter().map(|group| group.into()).collect()
},
on_downloaded: Some(AppMsg::UpdateDownloadedDxvk),
on_deleted: Some(AppMsg::UpdateDownloadedDxvk)
})
.forward(sender.input_sender(), std::convert::identity),
style: CONFIG.launcher.style,
downloaded_wine_versions: vec![],
downloaded_dxvk_versions: vec![],
selected_wine_version: 0,
selected_dxvk_version: 0,
selecting_wine_version: false,
selecting_dxvk_version: false
enhancements: super::enhancements::Enhancements::builder()
.launch(())
.detach()
};
let widgets = view_output!();
@ -237,13 +77,15 @@ impl SimpleAsyncComponent for App {
PREFERENCES_WINDOW = Some(widgets.preferences_window.clone());
}
sender.input(AppMsg::UpdateDownloadedWine);
sender.input(AppMsg::UpdateDownloadedDxvk);
#[allow(unused_must_use)] {
model.general.sender().send(super::general::AppMsg::UpdateDownloadedWine);
model.general.sender().send(super::general::AppMsg::UpdateDownloadedDxvk);
}
AsyncComponentParts { model, widgets }
ComponentParts { model, widgets }
}
async fn update(&mut self, msg: Self::Input, sender: AsyncComponentSender<Self>) {
fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>) {
tracing::debug!("Called preferences window event: {:?}", msg);
match msg {
@ -283,144 +125,8 @@ impl SimpleAsyncComponent for App {
#[allow(unused_must_use)]
AppMsg::UpdateLauncherStyle(style) => {
if let Ok(mut config) = config::get() {
config.launcher.style = style;
config::update(config);
}
self.style = style;
sender.output(Self::Output::UpdateLauncherStyle(style));
}
AppMsg::WineRecommendedOnly(state) => {
// todo
self.wine_components.sender().send(components::list::AppMsg::ShowRecommendedOnly(state)).unwrap();
}
AppMsg::DxvkRecommendedOnly(state) => {
// todo
self.dxvk_components.sender().send(components::list::AppMsg::ShowRecommendedOnly(state)).unwrap();
}
AppMsg::UpdateDownloadedWine => {
self.downloaded_wine_versions = wine::get_downloaded(&CONFIG.game.wine.builds).unwrap_or_default();
self.selected_wine_version = if let Some(selected) = &CONFIG.game.wine.selected {
let mut index = 0;
for (i, version) in self.downloaded_wine_versions.iter().enumerate() {
if &version.name == selected {
index = i;
break;
}
}
index as u32
}
else {
0
};
}
AppMsg::UpdateDownloadedDxvk => {
self.downloaded_dxvk_versions = dxvk::get_downloaded(&CONFIG.game.dxvk.builds).unwrap_or_default();
self.selected_dxvk_version = if let Ok(Some(selected)) = CONFIG.try_get_selected_dxvk_info() {
let mut index = 0;
for (i, version) in self.downloaded_dxvk_versions.iter().enumerate() {
if version.name == selected.name {
index = i;
break;
}
}
index as u32
}
else {
0
};
}
AppMsg::SelectWine(index) => {
if let Ok(mut config) = config::get() {
if let Some(version) = self.downloaded_wine_versions.get(index) {
if config.game.wine.selected.as_ref().unwrap_or(&String::new()) != &version.title {
self.selecting_wine_version = true;
let wine = version.to_wine(Some(config.game.wine.builds.join(&version.name)));
let wine_name = version.name.to_string();
std::thread::spawn(move || {
match wine.update_prefix(&config.game.wine.prefix) {
Ok(_) => {
config.game.wine.selected = Some(wine_name);
config::update(config);
}
Err(err) => {
sender.input(AppMsg::Toast {
title: tr("wine-prefix-update-failed"),
description: Some(err.to_string())
});
}
}
sender.input(AppMsg::ResetWineSelection(index));
});
}
}
}
}
AppMsg::ResetWineSelection(index) => {
self.selecting_wine_version = false;
self.selected_wine_version = index as u32;
}
AppMsg::SelectDxvk(index) => {
if let Ok(config) = config::get() {
if let Some(version) = self.downloaded_dxvk_versions.get(index) {
if let Ok(selected) = config.try_get_selected_dxvk_info() {
if selected.is_none() || selected.unwrap().name != version.name {
self.selecting_dxvk_version = true;
let mut wine = match config.try_get_selected_wine_info() {
Some(version) => version.to_wine(Some(config.game.wine.builds.join(&version.name))),
None => Wine::default()
};
wine = wine.with_prefix(config.game.wine.prefix);
let dxvk_folder = config.game.dxvk.builds.join(&version.name);
std::thread::spawn(move || {
if let Err(err) = Dxvk::install(&wine, dxvk_folder, InstallParams::default()) {
sender.input(AppMsg::Toast {
title: tr("dxvk-install-failed"),
description: Some(err.to_string())
});
}
sender.input(AppMsg::ResetDxvkSelection(index));
});
}
}
}
}
}
AppMsg::ResetDxvkSelection(index) => {
self.selecting_dxvk_version = false;
self.selected_dxvk_version = index as u32;
}
}
}
}

View file

@ -1,4 +1,3 @@
pub mod main;
mod general;
mod enhancements;
pub mod general;
pub mod enhancements;