mirror of
https://github.com/an-anime-team/sleepy-launcher.git
synced 2024-11-25 22:30:22 +03:00
feat(ui): moved sandbox, environment and game settings into separate pages
This commit is contained in:
parent
3a418126c2
commit
e520d8678b
9 changed files with 512 additions and 352 deletions
|
@ -482,7 +482,7 @@ impl SimpleComponent for App {
|
|||
#[watch]
|
||||
set_sensitive: !model.disabled_buttons,
|
||||
|
||||
set_width_request: 48,
|
||||
set_width_request: 44,
|
||||
|
||||
add_css_class: "circular",
|
||||
set_icon_name: "emblem-system-symbolic",
|
||||
|
|
|
@ -4,6 +4,8 @@ use relm4::factory::*;
|
|||
|
||||
use adw::prelude::*;
|
||||
|
||||
use super::EnhancementsAppMsg;
|
||||
|
||||
use crate::i18n::tr;
|
||||
use crate::*;
|
||||
|
||||
|
@ -16,10 +18,10 @@ struct Variable {
|
|||
#[relm4::factory(async)]
|
||||
impl AsyncFactoryComponent for Variable {
|
||||
type Init = (String, String);
|
||||
type Input = EnvironmentAppMsg;
|
||||
type Output = EnvironmentAppMsg;
|
||||
type Input = EnvironmentPageMsg;
|
||||
type Output = EnvironmentPageMsg;
|
||||
type CommandOutput = ();
|
||||
type ParentInput = EnvironmentAppMsg;
|
||||
type ParentInput = EnvironmentPageMsg;
|
||||
type ParentWidget = adw::PreferencesGroup;
|
||||
|
||||
view! {
|
||||
|
@ -33,7 +35,7 @@ impl AsyncFactoryComponent for Variable {
|
|||
set_valign: gtk::Align::Center,
|
||||
|
||||
connect_clicked[sender, index] => move |_| {
|
||||
sender.output(EnvironmentAppMsg::Remove(index.clone()));
|
||||
sender.output(EnvironmentPageMsg::Remove(index.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +57,7 @@ impl AsyncFactoryComponent for Variable {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct EnvironmentApp {
|
||||
pub struct EnvironmentPage {
|
||||
variables: AsyncFactoryVecDeque<Variable>,
|
||||
|
||||
name_entry: adw::EntryRow,
|
||||
|
@ -63,76 +65,95 @@ pub struct EnvironmentApp {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum EnvironmentAppMsg {
|
||||
pub enum EnvironmentPageMsg {
|
||||
Add,
|
||||
Remove(DynamicIndex)
|
||||
}
|
||||
|
||||
#[relm4::component(async, pub)]
|
||||
impl SimpleAsyncComponent for EnvironmentApp {
|
||||
impl SimpleAsyncComponent for EnvironmentPage {
|
||||
type Init = ();
|
||||
type Input = EnvironmentAppMsg;
|
||||
type Output = ();
|
||||
type Input = EnvironmentPageMsg;
|
||||
type Output = EnhancementsAppMsg;
|
||||
|
||||
view! {
|
||||
adw::PreferencesPage {
|
||||
set_title: &tr("environment"),
|
||||
set_icon_name: Some("document-properties-symbolic"),
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("game-command"),
|
||||
set_description: Some(&tr("game-command-description")),
|
||||
adw::HeaderBar {
|
||||
#[wrap(Some)]
|
||||
set_title_widget = &adw::WindowTitle {
|
||||
set_title: &tr("environment")
|
||||
},
|
||||
|
||||
adw::EntryRow {
|
||||
set_title: "%command%",
|
||||
set_text: CONFIG.game.command.as_ref().unwrap_or(&String::new()).trim(),
|
||||
pack_start = >k::Button {
|
||||
set_icon_name: "go-previous-symbolic",
|
||||
|
||||
connect_changed => |entry| {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
let command = entry.text().trim().to_string();
|
||||
|
||||
config.game.command = if command.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(command)
|
||||
};
|
||||
|
||||
Config::update(config);
|
||||
}
|
||||
connect_clicked[sender] => move |_| {
|
||||
sender.output(EnhancementsAppMsg::OpenMainPage).unwrap();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("new-variable"),
|
||||
adw::PreferencesPage {
|
||||
set_title: &tr("environment"),
|
||||
set_icon_name: Some("document-properties-symbolic"),
|
||||
|
||||
#[wrap(Some)]
|
||||
set_header_suffix = >k::Button {
|
||||
add_css_class: "flat",
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("game-command"),
|
||||
set_description: Some(&tr("game-command-description")),
|
||||
|
||||
set_valign: gtk::Align::Center,
|
||||
adw::EntryRow {
|
||||
set_title: "%command%",
|
||||
set_text: CONFIG.game.command.as_ref().unwrap_or(&String::new()).trim(),
|
||||
|
||||
adw::ButtonContent {
|
||||
set_icon_name: "list-add-symbolic",
|
||||
set_label: &tr("add")
|
||||
connect_changed => |entry| {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
let command = entry.text().trim().to_string();
|
||||
|
||||
config.game.command = if command.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(command)
|
||||
};
|
||||
|
||||
Config::update(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("new-variable"),
|
||||
|
||||
#[wrap(Some)]
|
||||
set_header_suffix = >k::Button {
|
||||
add_css_class: "flat",
|
||||
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
adw::ButtonContent {
|
||||
set_icon_name: "list-add-symbolic",
|
||||
set_label: &tr("add")
|
||||
},
|
||||
|
||||
connect_clicked => EnvironmentPageMsg::Add
|
||||
},
|
||||
|
||||
connect_clicked => EnvironmentAppMsg::Add
|
||||
#[local_ref]
|
||||
name_entry -> adw::EntryRow {
|
||||
set_title: &tr("name")
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
value_entry -> adw::EntryRow {
|
||||
set_title: &tr("value")
|
||||
}
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
name_entry -> adw::EntryRow {
|
||||
set_title: &tr("name")
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
value_entry -> adw::EntryRow {
|
||||
set_title: &tr("value")
|
||||
}
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
add = variables -> adw::PreferencesGroup {}
|
||||
add = variables -> adw::PreferencesGroup {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,7 +187,7 @@ impl SimpleAsyncComponent for EnvironmentApp {
|
|||
|
||||
async fn update(&mut self, msg: Self::Input, _sender: AsyncComponentSender<Self>) {
|
||||
match msg {
|
||||
EnvironmentAppMsg::Add => {
|
||||
EnvironmentPageMsg::Add => {
|
||||
let name = self.name_entry.text().trim().to_string();
|
||||
let value = self.value_entry.text().trim().to_string();
|
||||
|
||||
|
@ -184,7 +205,7 @@ impl SimpleAsyncComponent for EnvironmentApp {
|
|||
}
|
||||
}
|
||||
|
||||
EnvironmentAppMsg::Remove(index) => {
|
||||
EnvironmentPageMsg::Remove(index) => {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
if let Some(var) = self.variables.guard().get(index.current_index()) {
|
||||
config.game.environment.remove(&var.key);
|
|
@ -7,7 +7,7 @@ use adw::prelude::*;
|
|||
use anime_launcher_sdk::sessions::SessionsExt;
|
||||
use anime_launcher_sdk::genshin::sessions::Sessions;
|
||||
|
||||
use super::main::PreferencesAppMsg;
|
||||
use super::EnhancementsAppMsg;
|
||||
|
||||
use crate::i18n::tr;
|
||||
use crate::*;
|
||||
|
@ -21,10 +21,10 @@ struct GameSession {
|
|||
#[relm4::factory(async)]
|
||||
impl AsyncFactoryComponent for GameSession {
|
||||
type Init = GameSession;
|
||||
type Input = GameAppMsg;
|
||||
type Output = GameAppMsg;
|
||||
type Input = GamePageMsg;
|
||||
type Output = GamePageMsg;
|
||||
type CommandOutput = ();
|
||||
type ParentInput = GameAppMsg;
|
||||
type ParentInput = GamePageMsg;
|
||||
type ParentWidget = adw::PreferencesGroup;
|
||||
|
||||
view! {
|
||||
|
@ -45,7 +45,7 @@ impl AsyncFactoryComponent for GameSession {
|
|||
set_valign: gtk::Align::Center,
|
||||
|
||||
connect_clicked[sender, index] => move |_| {
|
||||
sender.output(GameAppMsg::UpdateSession(index.clone()));
|
||||
sender.output(GamePageMsg::UpdateSession(index.clone()));
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -58,7 +58,7 @@ impl AsyncFactoryComponent for GameSession {
|
|||
set_valign: gtk::Align::Center,
|
||||
|
||||
connect_clicked[sender, index] => move |_| {
|
||||
sender.output(GameAppMsg::RemoveSession(index.clone()));
|
||||
sender.output(GamePageMsg::RemoveSession(index.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ impl AsyncFactoryComponent for GameSession {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct GameApp {
|
||||
pub struct GamePage {
|
||||
sessions: AsyncFactoryVecDeque<GameSession>,
|
||||
|
||||
sessions_names: Vec<String>,
|
||||
|
@ -87,7 +87,7 @@ pub struct GameApp {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum GameAppMsg {
|
||||
pub enum GamePageMsg {
|
||||
AddSession,
|
||||
UpdateSession(DynamicIndex),
|
||||
RemoveSession(DynamicIndex),
|
||||
|
@ -96,50 +96,69 @@ pub enum GameAppMsg {
|
|||
}
|
||||
|
||||
#[relm4::component(async, pub)]
|
||||
impl SimpleAsyncComponent for GameApp {
|
||||
impl SimpleAsyncComponent for GamePage {
|
||||
type Init = ();
|
||||
type Input = GameAppMsg;
|
||||
type Output = PreferencesAppMsg;
|
||||
type Input = GamePageMsg;
|
||||
type Output = EnhancementsAppMsg;
|
||||
|
||||
view! {
|
||||
adw::PreferencesPage {
|
||||
set_title: &tr("game"),
|
||||
set_icon_name: Some("applications-games-symbolic"),
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("game-sessions"),
|
||||
adw::HeaderBar {
|
||||
#[wrap(Some)]
|
||||
set_title_widget = &adw::WindowTitle {
|
||||
set_title: &tr("game")
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
sessions_combo -> adw::ComboRow {
|
||||
set_title: &tr("active-sessions"),
|
||||
set_subtitle: &tr("active-session-description"),
|
||||
pack_start = >k::Button {
|
||||
set_icon_name: "go-previous-symbolic",
|
||||
|
||||
connect_selected_notify[sender] => move |row| {
|
||||
if is_ready() {
|
||||
sender.input(GameAppMsg::SetCurrent(row.selected()));
|
||||
connect_clicked[sender] => move |_| {
|
||||
sender.output(EnhancementsAppMsg::OpenMainPage).unwrap();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
adw::PreferencesPage {
|
||||
set_title: &tr("game"),
|
||||
set_icon_name: Some("applications-games-symbolic"),
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("game-sessions"),
|
||||
|
||||
#[local_ref]
|
||||
sessions_combo -> adw::ComboRow {
|
||||
set_title: &tr("active-sessions"),
|
||||
set_subtitle: &tr("active-session-description"),
|
||||
|
||||
connect_selected_notify[sender] => move |row| {
|
||||
if is_ready() {
|
||||
sender.input(GamePageMsg::SetCurrent(row.selected()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
#[local_ref]
|
||||
session_name_entry -> adw::EntryRow {
|
||||
set_title: &tr("name"),
|
||||
|
||||
add_suffix = >k::Button {
|
||||
set_icon_name: "list-add-symbolic",
|
||||
add_css_class: "flat",
|
||||
|
||||
set_valign: gtk::Align::Center,
|
||||
},
|
||||
|
||||
connect_clicked => GameAppMsg::AddSession
|
||||
add = &adw::PreferencesGroup {
|
||||
#[local_ref]
|
||||
session_name_entry -> adw::EntryRow {
|
||||
set_title: &tr("name"),
|
||||
|
||||
add_suffix = >k::Button {
|
||||
set_icon_name: "list-add-symbolic",
|
||||
add_css_class: "flat",
|
||||
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
connect_clicked => GamePageMsg::AddSession
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
add = sessions -> adw::PreferencesGroup {},
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
add = sessions -> adw::PreferencesGroup {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,14 +192,14 @@ impl SimpleAsyncComponent for GameApp {
|
|||
|
||||
let widgets = view_output!();
|
||||
|
||||
sender.input(GameAppMsg::UpdateCombo);
|
||||
sender.input(GamePageMsg::UpdateCombo);
|
||||
|
||||
AsyncComponentParts { model, widgets }
|
||||
}
|
||||
|
||||
async fn update(&mut self, msg: Self::Input, sender: AsyncComponentSender<Self>) {
|
||||
match msg {
|
||||
GameAppMsg::AddSession => {
|
||||
GamePageMsg::AddSession => {
|
||||
let name = self.session_name_entry.text().trim().to_string();
|
||||
|
||||
if !name.is_empty() {
|
||||
|
@ -194,46 +213,43 @@ impl SimpleAsyncComponent for GameApp {
|
|||
description: None
|
||||
});
|
||||
|
||||
sender.input(GameAppMsg::UpdateCombo);
|
||||
sender.input(GamePageMsg::UpdateCombo);
|
||||
}
|
||||
|
||||
#[allow(unused_must_use)]
|
||||
Err(err) => {
|
||||
sender.output(PreferencesAppMsg::Toast {
|
||||
sender.output(EnhancementsAppMsg::Toast {
|
||||
title: tr("game-session-add-failed"),
|
||||
description: Some(err.to_string())
|
||||
});
|
||||
}).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GameAppMsg::UpdateSession(index) => {
|
||||
GamePageMsg::UpdateSession(index) => {
|
||||
if let Some(session) = self.sessions.guard().get(index.current_index()) {
|
||||
if let Ok(config) = Config::get() {
|
||||
#[allow(unused_must_use)]
|
||||
if let Err(err) = Sessions::update(session.name.clone(), config.get_wine_prefix_path()) {
|
||||
sender.output(PreferencesAppMsg::Toast {
|
||||
sender.output(EnhancementsAppMsg::Toast {
|
||||
title: tr("game-session-update-failed"),
|
||||
description: Some(err.to_string())
|
||||
});
|
||||
}).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GameAppMsg::RemoveSession(index) => {
|
||||
GamePageMsg::RemoveSession(index) => {
|
||||
if let Some(session) = self.sessions.guard().get(index.current_index()) {
|
||||
match Sessions::remove(&session.name) {
|
||||
Ok(()) => sender.input(GameAppMsg::UpdateCombo),
|
||||
Ok(()) => sender.input(GamePageMsg::UpdateCombo),
|
||||
|
||||
#[allow(unused_must_use)]
|
||||
Err(err) => {
|
||||
sender.output(PreferencesAppMsg::Toast {
|
||||
sender.output(EnhancementsAppMsg::Toast {
|
||||
title: tr("game-session-remove-failed"),
|
||||
description: Some(err.to_string())
|
||||
});
|
||||
}).unwrap();
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -243,32 +259,30 @@ impl SimpleAsyncComponent for GameApp {
|
|||
self.sessions.guard().remove(index.current_index());
|
||||
}
|
||||
|
||||
GameAppMsg::SetCurrent(id) => {
|
||||
GamePageMsg::SetCurrent(id) => {
|
||||
if let Some(name) = self.sessions_names.get(id as usize) {
|
||||
if let Ok(config) = Config::get() {
|
||||
#[allow(unused_must_use)]
|
||||
if let Err(err) = Sessions::set_current(name.to_owned()) {
|
||||
sender.output(PreferencesAppMsg::Toast {
|
||||
sender.output(EnhancementsAppMsg::Toast {
|
||||
title: tr("game-session-set-current-failed"),
|
||||
description: Some(err.to_string())
|
||||
});
|
||||
}).unwrap();
|
||||
|
||||
// Prevent session applying
|
||||
return;
|
||||
}
|
||||
|
||||
#[allow(unused_must_use)]
|
||||
if let Err(err) = Sessions::apply(name.to_owned(), config.get_wine_prefix_path()) {
|
||||
sender.output(PreferencesAppMsg::Toast {
|
||||
sender.output(EnhancementsAppMsg::Toast {
|
||||
title: tr("game-session-apply-failed"),
|
||||
description: Some(err.to_string())
|
||||
});
|
||||
}).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GameAppMsg::UpdateCombo => {
|
||||
GamePageMsg::UpdateCombo => {
|
||||
let sessions = Sessions::get_sessions().unwrap_or_default();
|
||||
|
||||
self.sessions_names = sessions.sessions.into_keys().collect::<Vec<String>>();
|
|
@ -5,37 +5,102 @@ use adw::prelude::*;
|
|||
|
||||
use anime_launcher_sdk::config::ConfigExt;
|
||||
use anime_launcher_sdk::genshin::config::Config;
|
||||
|
||||
use anime_launcher_sdk::config::schema_blanks::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::is_available;
|
||||
|
||||
pub mod game;
|
||||
pub mod sandbox;
|
||||
pub mod environment;
|
||||
|
||||
use game::*;
|
||||
use sandbox::*;
|
||||
use environment::*;
|
||||
|
||||
use crate::i18n::tr;
|
||||
use crate::*;
|
||||
|
||||
use super::gamescope::*;
|
||||
use super::main::PreferencesAppMsg;
|
||||
|
||||
pub struct EnhancementsApp {
|
||||
gamescope: AsyncController<GamescopeApp>
|
||||
gamescope: AsyncController<GamescopeApp>,
|
||||
game_page: AsyncController<GamePage>,
|
||||
sandbox_page: AsyncController<SandboxPage>,
|
||||
environment_page: AsyncController<EnvironmentPage>
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum EnhancementsAppMsg {
|
||||
SetGamescopeParent(adw::PreferencesWindow),
|
||||
OpenGamescope
|
||||
|
||||
OpenGamescope,
|
||||
OpenMainPage,
|
||||
OpenGameSettingsPage,
|
||||
OpenSandboxSettingsPage,
|
||||
OpenEnvironmentSettingsPage,
|
||||
|
||||
Toast {
|
||||
title: String,
|
||||
description: Option<String>
|
||||
}
|
||||
}
|
||||
|
||||
#[relm4::component(async, pub)]
|
||||
impl SimpleAsyncComponent for EnhancementsApp {
|
||||
type Init = ();
|
||||
type Input = EnhancementsAppMsg;
|
||||
type Output = ();
|
||||
type Output = PreferencesAppMsg;
|
||||
|
||||
view! {
|
||||
#[root]
|
||||
adw::PreferencesPage {
|
||||
set_title: &tr("enhancements"),
|
||||
set_icon_name: Some("applications-graphics-symbolic"),
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: "Options",
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: "Game settings",
|
||||
set_subtitle: "Manage in-game settings and account session",
|
||||
|
||||
add_suffix = >k::Image {
|
||||
set_icon_name: Some("go-next-symbolic")
|
||||
},
|
||||
|
||||
set_activatable: true,
|
||||
|
||||
connect_activated => EnhancementsAppMsg::OpenGameSettingsPage
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: "Sandbox settings",
|
||||
set_subtitle: "Run the game in a bubblewrap sandbox, similar to what Flatpak does",
|
||||
|
||||
add_suffix = >k::Image {
|
||||
set_icon_name: Some("go-next-symbolic")
|
||||
},
|
||||
|
||||
set_activatable: true,
|
||||
|
||||
connect_activated => EnhancementsAppMsg::OpenSandboxSettingsPage
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: "Environment settings",
|
||||
set_subtitle: "Specify environment variables and game launching command",
|
||||
|
||||
add_suffix = >k::Image {
|
||||
set_icon_name: Some("go-next-symbolic")
|
||||
},
|
||||
|
||||
set_activatable: true,
|
||||
|
||||
connect_activated => EnhancementsAppMsg::OpenEnvironmentSettingsPage
|
||||
}
|
||||
},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("wine"),
|
||||
|
||||
|
@ -498,7 +563,16 @@ impl SimpleAsyncComponent for EnhancementsApp {
|
|||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
game_page -> gtk::Box {},
|
||||
|
||||
#[local_ref]
|
||||
sandbox_page -> gtk::Box {},
|
||||
|
||||
#[local_ref]
|
||||
environment_page -> gtk::Box {}
|
||||
}
|
||||
|
||||
async fn init(
|
||||
|
@ -511,15 +585,31 @@ impl SimpleAsyncComponent for EnhancementsApp {
|
|||
let model = Self {
|
||||
gamescope: GamescopeApp::builder()
|
||||
.launch(())
|
||||
.detach()
|
||||
.detach(),
|
||||
|
||||
game_page: GamePage::builder()
|
||||
.launch(())
|
||||
.forward(sender.input_sender(), std::convert::identity),
|
||||
|
||||
sandbox_page: SandboxPage::builder()
|
||||
.launch(())
|
||||
.forward(sender.input_sender(), std::convert::identity),
|
||||
|
||||
environment_page: EnvironmentPage::builder()
|
||||
.launch(())
|
||||
.forward(sender.input_sender(), std::convert::identity)
|
||||
};
|
||||
|
||||
let game_page = model.game_page.widget();
|
||||
let sandbox_page = model.sandbox_page.widget();
|
||||
let environment_page = model.environment_page.widget();
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
AsyncComponentParts { model, widgets }
|
||||
}
|
||||
|
||||
async fn update(&mut self, msg: Self::Input, _sender: AsyncComponentSender<Self>) {
|
||||
async fn update(&mut self, msg: Self::Input, sender: AsyncComponentSender<Self>) {
|
||||
match msg {
|
||||
EnhancementsAppMsg::SetGamescopeParent(parent) => {
|
||||
self.gamescope.widget().set_transient_for(Some(&parent));
|
||||
|
@ -528,6 +618,41 @@ impl SimpleAsyncComponent for EnhancementsApp {
|
|||
EnhancementsAppMsg::OpenGamescope => {
|
||||
self.gamescope.widget().present();
|
||||
}
|
||||
|
||||
EnhancementsAppMsg::OpenMainPage => unsafe {
|
||||
PREFERENCES_WINDOW.as_ref()
|
||||
.unwrap_unchecked()
|
||||
.widget()
|
||||
.close_subpage();
|
||||
}
|
||||
|
||||
EnhancementsAppMsg::OpenGameSettingsPage => unsafe {
|
||||
PREFERENCES_WINDOW.as_ref()
|
||||
.unwrap_unchecked()
|
||||
.widget()
|
||||
.present_subpage(self.game_page.widget());
|
||||
}
|
||||
|
||||
EnhancementsAppMsg::OpenSandboxSettingsPage => unsafe {
|
||||
PREFERENCES_WINDOW.as_ref()
|
||||
.unwrap_unchecked()
|
||||
.widget()
|
||||
.present_subpage(self.sandbox_page.widget());
|
||||
}
|
||||
|
||||
EnhancementsAppMsg::OpenEnvironmentSettingsPage => unsafe {
|
||||
PREFERENCES_WINDOW.as_ref()
|
||||
.unwrap_unchecked()
|
||||
.widget()
|
||||
.present_subpage(self.environment_page.widget());
|
||||
}
|
||||
|
||||
EnhancementsAppMsg::Toast { title, description } => {
|
||||
sender.output(PreferencesAppMsg::Toast {
|
||||
title,
|
||||
description
|
||||
}).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ use adw::prelude::*;
|
|||
|
||||
use anime_launcher_sdk::is_available;
|
||||
|
||||
use super::main::PreferencesAppMsg;
|
||||
use super::EnhancementsAppMsg;
|
||||
|
||||
use crate::i18n::tr;
|
||||
use crate::*;
|
||||
|
@ -22,10 +22,10 @@ macro_rules! impl_directory {
|
|||
#[relm4::factory(async)]
|
||||
impl AsyncFactoryComponent for $name {
|
||||
type Init = (String, Option<String>);
|
||||
type Input = SandboxAppMsg;
|
||||
type Output = SandboxAppMsg;
|
||||
type Input = SandboxPageMsg;
|
||||
type Output = SandboxPageMsg;
|
||||
type CommandOutput = ();
|
||||
type ParentInput = SandboxAppMsg;
|
||||
type ParentInput = SandboxPageMsg;
|
||||
type ParentWidget = adw::PreferencesGroup;
|
||||
|
||||
view! {
|
||||
|
@ -66,11 +66,11 @@ macro_rules! impl_directory {
|
|||
}
|
||||
}
|
||||
|
||||
impl_directory!(PrivateDirectory, SandboxAppMsg::RemovePrivate);
|
||||
impl_directory!(SharedDirectory, SandboxAppMsg::RemoveShared);
|
||||
impl_directory!(SymlinkPath, SandboxAppMsg::RemoveSymlink);
|
||||
impl_directory!(PrivateDirectory, SandboxPageMsg::RemovePrivate);
|
||||
impl_directory!(SharedDirectory, SandboxPageMsg::RemoveShared);
|
||||
impl_directory!(SymlinkPath, SandboxPageMsg::RemoveSymlink);
|
||||
|
||||
pub struct SandboxApp {
|
||||
pub struct SandboxPage {
|
||||
private_paths: AsyncFactoryVecDeque<PrivateDirectory>,
|
||||
shared_paths: AsyncFactoryVecDeque<SharedDirectory>,
|
||||
symlink_paths: AsyncFactoryVecDeque<SymlinkPath>,
|
||||
|
@ -86,7 +86,7 @@ pub struct SandboxApp {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum SandboxAppMsg {
|
||||
pub enum SandboxPageMsg {
|
||||
AddPrivate,
|
||||
RemovePrivate(DynamicIndex),
|
||||
|
||||
|
@ -98,214 +98,233 @@ pub enum SandboxAppMsg {
|
|||
}
|
||||
|
||||
#[relm4::component(async, pub)]
|
||||
impl SimpleAsyncComponent for SandboxApp {
|
||||
impl SimpleAsyncComponent for SandboxPage {
|
||||
type Init = ();
|
||||
type Input = SandboxAppMsg;
|
||||
type Output = PreferencesAppMsg;
|
||||
type Input = SandboxPageMsg;
|
||||
type Output = EnhancementsAppMsg;
|
||||
|
||||
view! {
|
||||
adw::PreferencesPage {
|
||||
set_title: &tr("sandbox"),
|
||||
set_icon_name: Some("folder-symbolic"),
|
||||
|
||||
set_sensitive: is_available("bwrap"),
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("sandbox"),
|
||||
set_description: Some(&tr("sandbox-description")),
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr("enable-sandboxing"),
|
||||
set_subtitle: &tr("enable-sandboxing-description"),
|
||||
|
||||
add_suffix = >k::Switch {
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
set_state: CONFIG.sandbox.enabled,
|
||||
|
||||
connect_state_notify => |switch| {
|
||||
if is_ready() {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
config.sandbox.enabled = switch.state();
|
||||
|
||||
Config::update(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr("hide-home-directory"),
|
||||
set_subtitle: &tr("hide-home-directory-description"),
|
||||
|
||||
add_suffix = >k::Switch {
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
set_state: CONFIG.sandbox.isolate_home,
|
||||
|
||||
connect_state_notify => |switch| {
|
||||
if is_ready() {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
config.sandbox.isolate_home = switch.state();
|
||||
|
||||
Config::update(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
adw::EntryRow {
|
||||
set_title: &tr("hostname"),
|
||||
set_text: CONFIG.sandbox.hostname.as_ref().unwrap_or(&String::new()).trim(),
|
||||
|
||||
connect_changed => |entry| {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
let command = entry.text().trim().to_string();
|
||||
|
||||
config.sandbox.hostname = if command.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(command)
|
||||
};
|
||||
|
||||
Config::update(config);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
adw::EntryRow {
|
||||
set_title: &tr("additional-arguments"),
|
||||
set_text: CONFIG.sandbox.args.as_ref().unwrap_or(&String::new()).trim(),
|
||||
|
||||
connect_changed => |entry| {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
let command = entry.text().trim().to_string();
|
||||
|
||||
config.sandbox.args = if command.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(command)
|
||||
};
|
||||
|
||||
Config::update(config);
|
||||
}
|
||||
},
|
||||
|
||||
add_suffix = >k::Button {
|
||||
set_icon_name: "dialog-information-symbolic",
|
||||
add_css_class: "flat",
|
||||
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
connect_clicked[sender] => move |_| {
|
||||
if let Err(err) = open::that("https://man.archlinux.org/man/bwrap.1") {
|
||||
sender.output(PreferencesAppMsg::Toast {
|
||||
title: tr("documentation-url-open-failed"),
|
||||
description: Some(err.to_string())
|
||||
}).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("private-directories"),
|
||||
set_description: Some(&tr("private-directories-description")),
|
||||
|
||||
#[local_ref]
|
||||
private_path_entry -> adw::EntryRow {
|
||||
set_title: &tr("path"),
|
||||
|
||||
add_suffix = >k::Button {
|
||||
set_icon_name: "list-add-symbolic",
|
||||
add_css_class: "flat",
|
||||
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
connect_clicked => SandboxAppMsg::AddPrivate
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
add = private_paths -> adw::PreferencesGroup {},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("shared-directories"),
|
||||
set_description: Some(&tr("shared-directories-description")),
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
|
||||
adw::HeaderBar {
|
||||
#[wrap(Some)]
|
||||
set_header_suffix = >k::Button {
|
||||
add_css_class: "flat",
|
||||
set_title_widget = &adw::WindowTitle {
|
||||
set_title: &tr("sandbox")
|
||||
},
|
||||
|
||||
set_valign: gtk::Align::Center,
|
||||
pack_start = >k::Button {
|
||||
set_icon_name: "go-previous-symbolic",
|
||||
|
||||
adw::ButtonContent {
|
||||
set_icon_name: "list-add-symbolic",
|
||||
set_label: &tr("add")
|
||||
connect_clicked[sender] => move |_| {
|
||||
sender.output(EnhancementsAppMsg::OpenMainPage).unwrap();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
adw::PreferencesPage {
|
||||
set_title: &tr("sandbox"),
|
||||
set_icon_name: Some("folder-symbolic"),
|
||||
|
||||
set_sensitive: is_available("bwrap"),
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("sandbox"),
|
||||
set_description: Some(&tr("sandbox-description")),
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr("enable-sandboxing"),
|
||||
set_subtitle: &tr("enable-sandboxing-description"),
|
||||
|
||||
add_suffix = >k::Switch {
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
set_state: CONFIG.sandbox.enabled,
|
||||
|
||||
connect_state_notify => |switch| {
|
||||
if is_ready() {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
config.sandbox.enabled = switch.state();
|
||||
|
||||
Config::update(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
connect_clicked => SandboxAppMsg::AddShared
|
||||
adw::ActionRow {
|
||||
set_title: &tr("hide-home-directory"),
|
||||
set_subtitle: &tr("hide-home-directory-description"),
|
||||
|
||||
add_suffix = >k::Switch {
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
set_state: CONFIG.sandbox.isolate_home,
|
||||
|
||||
connect_state_notify => |switch| {
|
||||
if is_ready() {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
config.sandbox.isolate_home = switch.state();
|
||||
|
||||
Config::update(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
adw::EntryRow {
|
||||
set_title: &tr("hostname"),
|
||||
set_text: CONFIG.sandbox.hostname.as_ref().unwrap_or(&String::new()).trim(),
|
||||
|
||||
connect_changed => |entry| {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
let command = entry.text().trim().to_string();
|
||||
|
||||
config.sandbox.hostname = if command.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(command)
|
||||
};
|
||||
|
||||
Config::update(config);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
adw::EntryRow {
|
||||
set_title: &tr("additional-arguments"),
|
||||
set_text: CONFIG.sandbox.args.as_ref().unwrap_or(&String::new()).trim(),
|
||||
|
||||
connect_changed => |entry| {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
let command = entry.text().trim().to_string();
|
||||
|
||||
config.sandbox.args = if command.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(command)
|
||||
};
|
||||
|
||||
Config::update(config);
|
||||
}
|
||||
},
|
||||
|
||||
add_suffix = >k::Button {
|
||||
set_icon_name: "dialog-information-symbolic",
|
||||
add_css_class: "flat",
|
||||
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
connect_clicked[sender] => move |_| {
|
||||
if let Err(err) = open::that("https://man.archlinux.org/man/bwrap.1") {
|
||||
sender.output(EnhancementsAppMsg::Toast {
|
||||
title: tr("documentation-url-open-failed"),
|
||||
description: Some(err.to_string())
|
||||
}).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
shared_path_from_entry -> adw::EntryRow {
|
||||
set_title: &tr("original-path")
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
shared_path_to_entry -> adw::EntryRow {
|
||||
set_title: &tr("new-path")
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr("read-only"),
|
||||
set_subtitle: &tr("read-only-description"),
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("private-directories"),
|
||||
set_description: Some(&tr("private-directories-description")),
|
||||
|
||||
#[local_ref]
|
||||
add_suffix = read_only_switch -> gtk::Switch {
|
||||
set_valign: gtk::Align::Center
|
||||
private_path_entry -> adw::EntryRow {
|
||||
set_title: &tr("path"),
|
||||
|
||||
add_suffix = >k::Button {
|
||||
set_icon_name: "list-add-symbolic",
|
||||
add_css_class: "flat",
|
||||
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
connect_clicked => SandboxPageMsg::AddPrivate
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
add = shared_paths -> adw::PreferencesGroup {},
|
||||
#[local_ref]
|
||||
add = private_paths -> adw::PreferencesGroup {},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("symlinks"),
|
||||
set_description: Some(&tr("symlinks-description")),
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("shared-directories"),
|
||||
set_description: Some(&tr("shared-directories-description")),
|
||||
|
||||
#[wrap(Some)]
|
||||
set_header_suffix = >k::Button {
|
||||
add_css_class: "flat",
|
||||
#[wrap(Some)]
|
||||
set_header_suffix = >k::Button {
|
||||
add_css_class: "flat",
|
||||
|
||||
set_valign: gtk::Align::Center,
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
adw::ButtonContent {
|
||||
set_icon_name: "list-add-symbolic",
|
||||
set_label: &tr("add")
|
||||
adw::ButtonContent {
|
||||
set_icon_name: "list-add-symbolic",
|
||||
set_label: &tr("add")
|
||||
},
|
||||
|
||||
connect_clicked => SandboxPageMsg::AddShared
|
||||
},
|
||||
|
||||
connect_clicked => SandboxAppMsg::AddSymlink
|
||||
#[local_ref]
|
||||
shared_path_from_entry -> adw::EntryRow {
|
||||
set_title: &tr("original-path")
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
shared_path_to_entry -> adw::EntryRow {
|
||||
set_title: &tr("new-path")
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr("read-only"),
|
||||
set_subtitle: &tr("read-only-description"),
|
||||
|
||||
#[local_ref]
|
||||
add_suffix = read_only_switch -> gtk::Switch {
|
||||
set_valign: gtk::Align::Center
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
symlink_path_from_entry -> adw::EntryRow {
|
||||
set_title: &tr("original-path")
|
||||
add = shared_paths -> adw::PreferencesGroup {},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("symlinks"),
|
||||
set_description: Some(&tr("symlinks-description")),
|
||||
|
||||
#[wrap(Some)]
|
||||
set_header_suffix = >k::Button {
|
||||
add_css_class: "flat",
|
||||
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
adw::ButtonContent {
|
||||
set_icon_name: "list-add-symbolic",
|
||||
set_label: &tr("add")
|
||||
},
|
||||
|
||||
connect_clicked => SandboxPageMsg::AddSymlink
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
symlink_path_from_entry -> adw::EntryRow {
|
||||
set_title: &tr("original-path")
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
symlink_path_to_entry -> adw::EntryRow {
|
||||
set_title: &tr("new-path")
|
||||
}
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
symlink_path_to_entry -> adw::EntryRow {
|
||||
set_title: &tr("new-path")
|
||||
}
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
add = symlink_paths -> adw::PreferencesGroup {}
|
||||
add = symlink_paths -> adw::PreferencesGroup {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -376,7 +395,7 @@ impl SimpleAsyncComponent for SandboxApp {
|
|||
|
||||
async fn update(&mut self, msg: Self::Input, _sender: AsyncComponentSender<Self>) {
|
||||
match msg {
|
||||
SandboxAppMsg::AddPrivate => {
|
||||
SandboxPageMsg::AddPrivate => {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
let path = self.private_path_entry.text().trim().to_string();
|
||||
|
||||
|
@ -392,7 +411,7 @@ impl SimpleAsyncComponent for SandboxApp {
|
|||
}
|
||||
}
|
||||
|
||||
SandboxAppMsg::RemovePrivate(index) => {
|
||||
SandboxPageMsg::RemovePrivate(index) => {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
if let Some(var) = self.private_paths.guard().get(index.current_index()) {
|
||||
config.sandbox.private.retain(|item| item != &var.from);
|
||||
|
@ -404,7 +423,7 @@ impl SimpleAsyncComponent for SandboxApp {
|
|||
}
|
||||
},
|
||||
|
||||
SandboxAppMsg::AddShared => {
|
||||
SandboxPageMsg::AddShared => {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
let from = self.shared_path_from_entry.text().trim().to_string();
|
||||
let to = self.shared_path_to_entry.text().trim().to_string();
|
||||
|
@ -435,7 +454,7 @@ impl SimpleAsyncComponent for SandboxApp {
|
|||
}
|
||||
}
|
||||
|
||||
SandboxAppMsg::RemoveShared(index) => {
|
||||
SandboxPageMsg::RemoveShared(index) => {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
if let Some(var) = self.shared_paths.guard().get(index.current_index()) {
|
||||
config.sandbox.mounts.read_only.remove(&var.from);
|
||||
|
@ -448,7 +467,7 @@ impl SimpleAsyncComponent for SandboxApp {
|
|||
}
|
||||
},
|
||||
|
||||
SandboxAppMsg::AddSymlink => {
|
||||
SandboxPageMsg::AddSymlink => {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
let from = self.symlink_path_from_entry.text().trim().to_string();
|
||||
let to = self.symlink_path_to_entry.text().trim().to_string();
|
||||
|
@ -466,7 +485,7 @@ impl SimpleAsyncComponent for SandboxApp {
|
|||
}
|
||||
}
|
||||
|
||||
SandboxAppMsg::RemoveSymlink(index) => {
|
||||
SandboxPageMsg::RemoveSymlink(index) => {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
if let Some(var) = self.symlink_paths.guard().get(index.current_index()) {
|
||||
config.sandbox.mounts.symlinks.remove(&var.from);
|
|
@ -9,11 +9,11 @@ use anime_launcher_sdk::wincompatlib::prelude::*;
|
|||
use anime_launcher_sdk::components::*;
|
||||
use anime_launcher_sdk::components::wine::WincompatlibWine;
|
||||
|
||||
use super::GeneralAppMsg;
|
||||
|
||||
use crate::ui::components;
|
||||
use crate::ui::components::*;
|
||||
|
||||
use super::GeneralAppMsg;
|
||||
|
||||
use crate::i18n::*;
|
||||
use crate::*;
|
||||
|
||||
|
@ -58,6 +58,11 @@ impl SimpleAsyncComponent for ComponentsPage {
|
|||
set_orientation: gtk::Orientation::Vertical,
|
||||
|
||||
adw::HeaderBar {
|
||||
#[wrap(Some)]
|
||||
set_title_widget = &adw::WindowTitle {
|
||||
set_title: "Components"
|
||||
},
|
||||
|
||||
pack_start = >k::Button {
|
||||
set_icon_name: "go-previous-symbolic",
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
|
||||
view! {
|
||||
#[root]
|
||||
main_page = adw::PreferencesPage {
|
||||
adw::PreferencesPage {
|
||||
set_title: &tr("general"),
|
||||
set_icon_name: Some("applications-system-symbolic"),
|
||||
|
||||
|
|
|
@ -15,18 +15,12 @@ use crate::i18n::tr;
|
|||
|
||||
use super::general::*;
|
||||
use super::enhancements::*;
|
||||
use super::game::*;
|
||||
use super::sandbox::*;
|
||||
use super::environment::*;
|
||||
|
||||
pub static mut PREFERENCES_WINDOW: Option<adw::PreferencesWindow> = None;
|
||||
|
||||
pub struct PreferencesApp {
|
||||
general: AsyncController<GeneralApp>,
|
||||
enhancements: AsyncController<EnhancementsApp>,
|
||||
game: AsyncController<GameApp>,
|
||||
sandbox: AsyncController<SandboxApp>,
|
||||
environment: AsyncController<EnvironmentApp>
|
||||
enhancements: AsyncController<EnhancementsApp>
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -71,9 +65,6 @@ impl SimpleAsyncComponent for PreferencesApp {
|
|||
|
||||
add = model.general.widget(),
|
||||
add = model.enhancements.widget(),
|
||||
add = model.game.widget(),
|
||||
add = model.sandbox.widget(),
|
||||
add = model.environment.widget(),
|
||||
|
||||
connect_close_request[sender] => move |_| {
|
||||
if let Err(err) = Config::flush() {
|
||||
|
@ -102,19 +93,7 @@ impl SimpleAsyncComponent for PreferencesApp {
|
|||
|
||||
enhancements: EnhancementsApp::builder()
|
||||
.launch(())
|
||||
.detach(),
|
||||
|
||||
game: GameApp::builder()
|
||||
.launch(())
|
||||
.detach(),
|
||||
|
||||
sandbox: SandboxApp::builder()
|
||||
.launch(())
|
||||
.forward(sender.input_sender(), std::convert::identity),
|
||||
|
||||
environment: EnvironmentApp::builder()
|
||||
.launch(())
|
||||
.detach()
|
||||
.forward(sender.input_sender(), std::convert::identity)
|
||||
};
|
||||
|
||||
let widgets = view_output!();
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
pub mod main;
|
||||
pub mod general;
|
||||
pub mod enhancements;
|
||||
pub mod game;
|
||||
pub mod sandbox;
|
||||
pub mod environment;
|
||||
pub mod gamescope;
|
||||
|
|
Loading…
Reference in a new issue