diff --git a/android/src/app.rs b/android/src/app.rs index 149a3e7..3a22cca 100644 --- a/android/src/app.rs +++ b/android/src/app.rs @@ -3147,6 +3147,9 @@ impl eframe::App for SleekApp { self.net.send(NetCmd::Quit); self.state.logout(); } + SettingsAction::SendRaw(line) => { + self.net.send(NetCmd::Raw(line)); + } } } } diff --git a/android/src/state.rs b/android/src/state.rs index ed28f00..12df2da 100644 --- a/android/src/state.rs +++ b/android/src/state.rs @@ -1243,6 +1243,8 @@ pub struct AppState { pub search: String, pub join_input: String, pub discover_input: String, + /// Raw IRC command typed in the settings server console. + pub console_input: String, /// Channel member list open (chat detail only). pub show_members: bool, /// Global message search overlay open (chat detail only). @@ -1419,6 +1421,7 @@ impl AppState { search: String::new(), join_input: String::new(), discover_input: String::new(), + console_input: String::new(), show_members: false, show_message_search: false, message_search: String::new(), diff --git a/android/src/ui/settings.rs b/android/src/ui/settings.rs index 71b98b6..0cfcdf8 100644 --- a/android/src/ui/settings.rs +++ b/android/src/ui/settings.rs @@ -13,6 +13,7 @@ pub enum SettingsAction { None, Disconnect, Logout, + SendRaw(String), } pub fn settings_tab( @@ -121,6 +122,51 @@ pub fn settings_tab( ui.add_space(sp.md); + // Server Console (only shown while connected) + if state.connection.is_live() { + card(ui, th, |ui| { + section_label(ui, th, "SERVER CONSOLE"); + ui.add_space(sp.md); + dim_label( + ui, + th, + "Send a raw IRC command to the server (e.g. PING, WHO, MODE).", + ); + ui.add_space(sp.sm); + ui.horizontal(|ui| { + let available = ui.available_width(); + let btn_w = 60.0; + let gap = sp.sm; + let field_w = (available - btn_w - gap).max(0.0); + let te = egui::TextEdit::singleline(&mut state.console_input) + .desired_width(field_w) + .hint_text("e.g. WHO #general") + .id(egui::Id::new("settings_console_input")); + let resp = ui.add_sized(egui::Vec2::new(field_w, 32.0), te); + let enter_pressed = resp.lost_focus() + && ui.input(|i| i.key_pressed(egui::Key::Enter)); + ui.add_space(gap); + let send_clicked = ui + .add_sized( + egui::Vec2::new(btn_w, 32.0), + egui::Button::new( + RichText::new("Send") + .size(th.type_scale.body) + .color(th.palette.accent_fg), + ) + .fill(th.palette.accent), + ) + .clicked(); + if (send_clicked || enter_pressed) && !state.console_input.trim().is_empty() { + let cmd = state.console_input.trim().to_string(); + state.console_input.clear(); + action = SettingsAction::SendRaw(cmd); + } + }); + }); + ui.add_space(sp.md); + } + // About card(ui, th, |ui| { section_label(ui, th, "ABOUT");