diff --git a/Cargo.lock b/Cargo.lock index 8f2fdfe9..3508e5d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2272,10 +2272,15 @@ dependencies = [ "native-dialog", "once_cell", "poll-promise", + "serde_json", + "serde_yaml", "smol 2.0.0", + "smol-timeout", "smol_str", "smolscale", "tap", + "tracing", + "tracing-subscriber", ] [[package]] diff --git a/binaries/geph5-client-gui/Cargo.toml b/binaries/geph5-client-gui/Cargo.toml index c1e44e86..a17dc151 100644 --- a/binaries/geph5-client-gui/Cargo.toml +++ b/binaries/geph5-client-gui/Cargo.toml @@ -22,4 +22,9 @@ poll-promise = "0.3.0" smolscale = "0.4.4" futures-util = "0.3.30" smol = "2.0.0" -geph5-broker-protocol={path="../../libraries/geph5-broker-protocol"} \ No newline at end of file +geph5-broker-protocol={path="../../libraries/geph5-broker-protocol"} +serde_yaml = "0.9.34" +smol-timeout = "0.6.0" +tracing = "0.1.40" +tracing-subscriber = "0.3.18" +serde_json = "1.0.115" diff --git a/binaries/geph5-client-gui/src/dashboard.rs b/binaries/geph5-client-gui/src/dashboard.rs index 0b500a1f..d04b7561 100644 --- a/binaries/geph5-client-gui/src/dashboard.rs +++ b/binaries/geph5-client-gui/src/dashboard.rs @@ -1,9 +1,13 @@ +use std::time::Duration; + +use anyhow::Context as _; use futures_util::{future::Shared, FutureExt}; -use geph5_broker_protocol::ExitList; -use poll_promise::Promise; +use geph5_broker_protocol::{BrokerClient, ExitList}; + use smol::Task; +use smol_timeout::TimeoutExt as _; -use crate::l10n::l10n; +use crate::{l10n::l10n, settings::get_config}; pub struct Dashboard { selected_server: Option<(String, String)>, @@ -43,5 +47,35 @@ fn render_exit_selection(selection: &Option<(String, String)>) -> String { } async fn get_server_list() -> ExitList { - smol::future::pending().await + loop { + let fallible = async { + let broker_client = get_broker_client() + .await? + .context("no broker client available")?; + let exits = broker_client + .get_exits() + .timeout(Duration::from_secs(10)) + .await + .context("timeout")?? + .map_err(|e| anyhow::anyhow!(e))? + .inner; + anyhow::Ok(exits) + }; + match fallible.await { + Ok(res) => return res, + Err(err) => { + tracing::warn!(err = debug(err), "error getting server list"); + smol::Timer::after(Duration::from_secs(1)).await; + } + } + } +} + +async fn get_broker_client() -> anyhow::Result> { + let config = get_config()?; + if let Some(src) = config.broker { + Ok(Some(BrokerClient::from(src.rpc_transport()))) + } else { + Ok(None) + } } diff --git a/binaries/geph5-client-gui/src/main.rs b/binaries/geph5-client-gui/src/main.rs index 7802235f..eb96008c 100644 --- a/binaries/geph5-client-gui/src/main.rs +++ b/binaries/geph5-client-gui/src/main.rs @@ -1,6 +1,7 @@ mod dashboard; mod l10n; mod prefs; +mod settings; use std::time::Duration; use dashboard::Dashboard; @@ -9,9 +10,23 @@ use egui::{Color32, FontData, FontDefinitions, FontFamily, Visuals}; use l10n::l10n; use native_dialog::MessageType; use prefs::{pref_read, pref_write}; +use settings::render_settings; use tap::Tap as _; +use tracing_subscriber::{layer::SubscriberExt as _, util::SubscriberInitExt, EnvFilter}; fn main() { + tracing_subscriber::registry() + .with( + tracing_subscriber::fmt::layer() + .compact() + .with_writer(std::io::stderr), + ) + .with( + EnvFilter::builder() + .with_default_directive("geph5=debug".parse().unwrap()) + .from_env_lossy(), + ) + .init(); // default prefs for (key, value) in [("lang", "en")] { if pref_read(key).is_err() { @@ -98,7 +113,7 @@ impl eframe::App for App { let result = egui::CentralPanel::default().show(ctx, |ui| match self.selected_tab { TabName::Dashboard => self.dashboard.render(ui), TabName::Logs => Ok(()), - TabName::Settings => Ok(()), + TabName::Settings => render_settings(ui), }); if let Err(err) = result.inner { diff --git a/binaries/geph5-client-gui/src/settings.rs b/binaries/geph5-client-gui/src/settings.rs new file mode 100644 index 00000000..cb4817d5 --- /dev/null +++ b/binaries/geph5-client-gui/src/settings.rs @@ -0,0 +1,19 @@ +use geph5_client::Config; + +use crate::prefs::{pref_read, pref_write}; + +pub fn get_config() -> anyhow::Result { + let settings = pref_read("settings")?; + let yaml: serde_yaml::Value = serde_yaml::from_str(&settings)?; + let json: serde_json::Value = serde_json::to_value(&yaml)?; + Ok(serde_json::from_value(json)?) +} + +pub fn render_settings(ui: &mut egui::Ui) -> anyhow::Result<()> { + let mut settings_yaml = pref_read("settings").unwrap_or_default().to_string(); + ui.centered_and_justified(|ui| { + egui::ScrollArea::vertical().show(ui, |ui| ui.code_editor(&mut settings_yaml)) + }); + pref_write("settings", &settings_yaml)?; + Ok(()) +} diff --git a/binaries/geph5-client/src/lib.rs b/binaries/geph5-client/src/lib.rs index d83501ef..2f2b2e10 100644 --- a/binaries/geph5-client/src/lib.rs +++ b/binaries/geph5-client/src/lib.rs @@ -1,3 +1,4 @@ +pub use broker::broker_client; pub use client::Client; pub use client::Config;