feat: some initial work on adding "game" settings section

Is not yet even started, just had to commit changed to checkout to the main branch
This commit is contained in:
Observer KRypt0n_ 2023-05-03 21:06:24 +02:00
parent 7c4ea25b59
commit c765448e43
6 changed files with 223 additions and 13 deletions

View file

@ -51,10 +51,12 @@ impl SimpleComponent for AboutDialog {
]),
add_credit_section: (Some("An Anime Team"), &[
"Nikita Podvirnyy https://github.com/krypt0nn",
"@Marie https://github.com/Mar0xy",
"@lane https://github.com/laurinneff",
"@jiro-too https://github.com/jiro-too",
"@cybik https://github.com/cybik"
"@cybik https://github.com/cybik",
"@mkrsym1 https://github.com/mkrsym1"
]),
set_artists: &[

View file

@ -717,10 +717,8 @@ impl SimpleComponent for App {
description: if changes.is_empty() {
None
} else {
let max_len = changes.iter().map(|line| line.len()).max().unwrap_or(80);
Some(changes.into_iter()
.map(|line| format!("- {line}{}", " ".repeat(max_len - line.len())))
.map(|line| format!("- {line}"))
.collect::<Vec<_>>()
.join("\n"))
}

View file

@ -16,10 +16,10 @@ struct Variable {
#[relm4::factory(async)]
impl AsyncFactoryComponent for Variable {
type Init = (String, String);
type Input = EnvironmentMsg;
type Output = EnvironmentMsg;
type Input = EnvironmentAppMsg;
type Output = EnvironmentAppMsg;
type CommandOutput = ();
type ParentInput = EnvironmentMsg;
type ParentInput = EnvironmentAppMsg;
type ParentWidget = adw::PreferencesGroup;
view! {
@ -33,7 +33,7 @@ impl AsyncFactoryComponent for Variable {
set_valign: gtk::Align::Center,
connect_clicked[sender, index] => move |_| {
sender.input(EnvironmentMsg::Remove(index.clone()));
sender.input(EnvironmentAppMsg::Remove(index.clone()));
}
}
}
@ -67,7 +67,7 @@ pub struct EnvironmentApp {
}
#[derive(Debug, Clone)]
pub enum EnvironmentMsg {
pub enum EnvironmentAppMsg {
Add,
Remove(DynamicIndex)
}
@ -75,7 +75,7 @@ pub enum EnvironmentMsg {
#[relm4::component(async, pub)]
impl SimpleAsyncComponent for EnvironmentApp {
type Init = ();
type Input = EnvironmentMsg;
type Input = EnvironmentAppMsg;
type Output = ();
view! {
@ -127,7 +127,7 @@ impl SimpleAsyncComponent for EnvironmentApp {
set_margin_top: 8,
set_halign: gtk::Align::Start,
connect_clicked => EnvironmentMsg::Add
connect_clicked => EnvironmentAppMsg::Add
}
},
@ -166,7 +166,7 @@ impl SimpleAsyncComponent for EnvironmentApp {
async fn update(&mut self, msg: Self::Input, _sender: AsyncComponentSender<Self>) {
match msg {
EnvironmentMsg::Add => {
EnvironmentAppMsg::Add => {
if let Ok(mut config) = Config::get() {
let name = self.name_entry.text().trim().to_string();
let value = self.value_entry.text().trim().to_string();
@ -184,7 +184,7 @@ impl SimpleAsyncComponent for EnvironmentApp {
}
}
EnvironmentMsg::Remove(index) => {
EnvironmentAppMsg::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);

202
src/ui/preferences/game.rs Normal file
View file

@ -0,0 +1,202 @@
use relm4::prelude::*;
use relm4::component::*;
use relm4::factory::*;
use adw::prelude::*;
use crate::i18n::tr;
use crate::*;
#[derive(Debug)]
struct GameSession {
title: String,
description: Option<String>,
id: usize
}
#[relm4::factory(async)]
impl AsyncFactoryComponent for GameSession {
type Init = GameSession;
type Input = GameAppMsg;
type Output = GameAppMsg;
type CommandOutput = ();
type ParentInput = GameAppMsg;
type ParentWidget = adw::PreferencesGroup;
view! {
root = adw::ActionRow {
set_title: &self.title,
set_subtitle: match &self.description {
Some(description) => description.as_str(),
None => ""
},
add_suffix = &gtk::Button {
set_icon_name: "user-trash-symbolic",
add_css_class: "flat",
set_valign: gtk::Align::Center,
connect_clicked[sender, index] => move |_| {
sender.input(GameAppMsg::Remove(index.clone()));
}
}
}
}
fn output_to_parent_input(output: Self::Output) -> Option<Self::ParentInput> {
Some(output)
}
async fn init_model(
init: Self::Init,
_index: &DynamicIndex,
_sender: AsyncFactorySender<Self>,
) -> Self {
init
}
async fn update(&mut self, msg: Self::Input, sender: AsyncFactorySender<Self>) {
sender.output(msg);
}
}
pub struct GameApp {
variables: AsyncFactoryVecDeque<GameSession>,
name_entry: adw::EntryRow,
value_entry: adw::EntryRow
}
#[derive(Debug, Clone)]
pub enum GameAppMsg {
Add,
Remove(DynamicIndex)
}
#[relm4::component(async, pub)]
impl SimpleAsyncComponent for GameApp {
type Init = ();
type Input = GameAppMsg;
type Output = ();
view! {
adw::PreferencesPage {
set_title: &tr("environment"),
set_icon_name: Some("document-properties-symbolic"),
add = &adw::PreferencesGroup {
set_title: &tr("game-command"),
set_description: Some(&tr("game-command-description")),
adw::EntryRow {
set_title: "%command%",
set_text: CONFIG.game.command.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.game.command = if command.is_empty() {
None
} else {
Some(command)
};
Config::update(config);
}
}
}
},
add = &adw::PreferencesGroup {
set_title: &tr("new-variable"),
#[local_ref]
name_entry -> adw::EntryRow {
set_title: &tr("name")
},
#[local_ref]
value_entry -> adw::EntryRow {
set_title: &tr("value")
},
gtk::Button {
set_label: &tr("add"),
add_css_class: "pill",
set_margin_top: 8,
set_halign: gtk::Align::Start,
connect_clicked => GameAppMsg::Add
}
},
#[local_ref]
add = variables -> adw::PreferencesGroup {}
}
}
async fn init(
_init: Self::Init,
root: Self::Root,
sender: AsyncComponentSender<Self>,
) -> AsyncComponentParts<Self> {
tracing::info!("Initializing environment settings");
let mut model = Self {
variables: AsyncFactoryVecDeque::new(adw::PreferencesGroup::new(), sender.input_sender()),
name_entry: adw::EntryRow::new(),
value_entry: adw::EntryRow::new()
};
/*for (name, value) in &CONFIG.game.environment {
model.variables.guard().push_back();
}*/
let variables = model.variables.widget();
let name_entry = &model.name_entry;
let value_entry = &model.value_entry;
let widgets = view_output!();
AsyncComponentParts { model, widgets }
}
async fn update(&mut self, msg: Self::Input, _sender: AsyncComponentSender<Self>) {
match msg {
GameAppMsg::Add => {
if let Ok(mut config) = Config::get() {
let name = self.name_entry.text().trim().to_string();
let value = self.value_entry.text().trim().to_string();
if !name.is_empty() && !value.is_empty() {
self.name_entry.set_text("");
self.value_entry.set_text("");
config.game.environment.insert(name.clone(), value.clone());
Config::update(config);
// self.variables.guard().push_back((name, value));
}
}
}
GameAppMsg::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);
Config::update(config);
}
self.variables.guard().remove(index.current_index());
}
}
}
}
}

View file

@ -15,6 +15,7 @@ use crate::i18n::tr;
use super::general::*;
use super::enhancements::*;
use super::game::*;
use super::sandbox::*;
use super::environment::*;
@ -23,6 +24,7 @@ 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>
}
@ -69,6 +71,7 @@ impl SimpleAsyncComponent for PreferencesApp {
add = model.general.widget(),
add = model.enhancements.widget(),
add = model.game.widget(),
add = model.sandbox.widget(),
add = model.environment.widget(),
@ -101,6 +104,10 @@ impl SimpleAsyncComponent for PreferencesApp {
.launch(())
.detach(),
game: GameApp::builder()
.launch(())
.detach(),
sandbox: SandboxApp::builder()
.launch(())
.forward(sender.input_sender(), std::convert::identity),

View file

@ -1,6 +1,7 @@
pub mod main;
pub mod general;
pub mod enhancements;
pub mod game;
pub mod sandbox;
pub mod environment;
pub mod gamescope;