use arboard::Clipboard; use babylonia_terminal_sdk::game_config::GameConfig; use log::error; use relm4::{ gtk::{ prelude::{EditableExt, GtkWindowExt, OrientableExt, WidgetExt}, InputHints, }, prelude::{gtk, AsyncComponentParts, SimpleAsyncComponent}, }; use libadwaita::{ self as adw, prelude::{ EntryRowExt, MessageDialogExt, PreferencesGroupExt, PreferencesPageExt, PreferencesRowExt, }, }; use crate::ui::MAIN_WINDOW; #[derive(Debug)] pub enum SettingsPageMsg { UpdateLaunchOption(Option), ShowError(String), } pub struct SettingsPage { launch_option: String, } #[relm4::component(pub, async)] impl SimpleAsyncComponent for SettingsPage { type Input = SettingsPageMsg; type Output = (); type Init = (); view! { gtk::Box { set_orientation: gtk::Orientation::Vertical, adw::PreferencesPage { set_title: "General settings", add = &adw::PreferencesGroup { set_width_request: 500, set_title: "Launch option", set_description: Some("Pass launch options to tinker the behavior of the game"), adw::EntryRow { set_title: "%command%", set_text: &model.launch_option, connect_changed[sender] => move |entry| { let command = entry.text().trim().to_string(); if command.is_empty() { sender.input(SettingsPageMsg::UpdateLaunchOption(None)) } else { sender.input(SettingsPageMsg::UpdateLaunchOption(Some(command))) } } } } } } } async fn init( _: Self::Init, root: Self::Root, sender: relm4::AsyncComponentSender, ) -> relm4::prelude::AsyncComponentParts { let launch_option = match GameConfig::get_launch_options().await { Err(e) => String::new(), Ok(v) => match v { None => String::new(), Some(launch) => launch, }, }; let model = SettingsPage { launch_option }; let widgets = view_output!(); AsyncComponentParts { model, widgets } } async fn update(&mut self, message: Self::Input, sender: relm4::AsyncComponentSender) { match message { SettingsPageMsg::UpdateLaunchOption(new_launch_option) => { if let Err(e) = GameConfig::set_launch_options(new_launch_option).await { sender.input(SettingsPageMsg::ShowError(format!( "Something went wrong when updated the launch options : {}", e ))); } } SettingsPageMsg::ShowError(message) => { let dialog = unsafe { adw::MessageDialog::new( MAIN_WINDOW.as_ref(), Some("Something went wrong"), Some(&message), ) }; dialog.add_response("close", "Close"); dialog.add_response("copy", "Copy"); dialog.set_response_appearance("copy", adw::ResponseAppearance::Suggested); dialog.connect_response(Some("copy"), move |_, _| { if let Err(err) = Clipboard::new().unwrap().set_text(&message.clone()) { error!("Failed to copy the error to the clipboard : {}", err); } }); dialog.present(); } } } }