use eframe::egui; use raw_window_handle::{HasWindowHandle, RawWindowHandle}; use std::borrow::BorrowMut; use std::sync::Mutex; use std::sync::{ atomic::{AtomicBool, Ordering}, Arc, }; use tokio::sync::mpsc; use tray_item::TrayItem; use crate::server::{ServerMessage, ServerSettings}; pub enum UIMessage { ServerHasQuit, } pub fn run_ui( settings: Arc>, should_run: Arc>, tx: mpsc::Sender, rx: mpsc::Receiver, ) { // Initialize visibility as AtomicBool let visible = Arc::new(AtomicBool::new(true)); let icon = crate::icon::load_app_icon("icon-soundboard"); let native_options = eframe::NativeOptions { viewport: egui::ViewportBuilder::default().with_icon(icon), ..Default::default() }; let visible_for_tray = Arc::clone(&visible); eframe::run_native( "App", native_options, Box::new(|cc| { let window_handle = cc.window_handle().unwrap(); let window_handle = window_handle.as_raw(); let mut tray = TrayItem::new( "Soundboard", tray_item::IconSource::Resource("icon-soundboard"), ) .unwrap(); if let RawWindowHandle::Win32(handle) = window_handle { #[cfg(windows)] { use windows::Win32::Foundation::HWND; use windows::Win32::UI::WindowsAndMessaging::{ ShowWindow, SW_HIDE, SW_RESTORE, }; tray.add_label("Server Control").unwrap(); let window_handle = HWND(handle.hwnd.into()); tray.add_menu_item("Show/Hide", { //let visible_for_tray = Arc::clone(&visible_for_tray); move || { let is_visible = visible_for_tray.load(Ordering::SeqCst); if is_visible { unsafe { _ = ShowWindow(window_handle, SW_HIDE); } visible_for_tray.store(false, Ordering::SeqCst); } else { unsafe { _ = ShowWindow(window_handle, SW_RESTORE); } visible_for_tray.store(true, Ordering::SeqCst); } } }) .unwrap(); } } else { println!("Unsupported platform for tray icon."); } let my_tx = tx.clone(); tray.add_menu_item("Quit", move || { my_tx.try_send(ServerMessage::Shutdown).unwrap_or_else(|_| { eprintln!("Failed to send Shutdown message"); }); //std::process::exit(0); }) .unwrap(); let app = NativeApp { settings, should_run, tx, rx, tray, }; Box::new(app) }), ) .expect("Error running UI."); } struct NativeApp { settings: Arc>, #[allow(dead_code)] should_run: Arc>, tx: mpsc::Sender, rx: mpsc::Receiver, #[allow(dead_code)] tray: TrayItem, } impl eframe::App for NativeApp { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { if let Ok(message) = self.rx.try_recv() { match message { UIMessage::ServerHasQuit => { eprintln!("Server has quit!!!?"); } _ => {} } } egui::CentralPanel::default().show(ctx, |ui| { egui::TopBottomPanel::top("top_panel") .resizable(true) .min_height(32.0) .show_inside(ui, |ui| { egui::ScrollArea::vertical().show(ui, |ui| { ui.vertical_centered(|ui| { ui.heading("Soundboard"); }); }); }); egui::SidePanel::left("left_panel") .resizable(true) .default_width(180.0) .width_range(80.0..=220.0) .show_inside(ui, |ui| { ui.vertical_centered(|ui| { ui.vertical(|ui| { ui.heading("Menu"); if ui.button("Status").clicked() {} if ui.button("Devices").clicked() {} if ui.button("Pages").clicked() {} if ui.button("Server Settings").clicked() {} if ui.button("Sound Settings").clicked() {} }); }); egui::ScrollArea::vertical().show(ui, |ui| {}); }); let mut settings = self.settings.lock().unwrap(); ui.heading("Server Settings"); egui::Frame { inner_margin: 12.0.into(), outer_margin: 24.0.into(), rounding: 14.0.into(), shadow: egui::epaint::Shadow::NONE, fill: egui::Color32::from_rgba_unmultiplied(97, 0, 255, 128), stroke: egui::Stroke::new(1.0, egui::Color32::GRAY), } .show(ui, |ui| { ui.label(egui::RichText::new("3311").color(egui::Color32::WHITE)); }); ui.horizontal(|ui| { ui.label("Port:"); if ui.text_edit_singleline(&mut settings.port).changed() {} }); if ui.button("Apply").clicked() { if self .tx .try_send(ServerMessage::UpdateSettings(settings.clone())) .is_err() { eprintln!("Failed to send settings update"); } } if ui.button("Interact").clicked() { if self.tx.try_send(ServerMessage::Interact).is_err() { eprintln!("Failed to send interaction message"); } } if ui.button("Shutdown Server").clicked() { if self.tx.try_send(ServerMessage::Shutdown).is_err() { eprintln!("Failed to send shutdown message"); } } drop(settings); }); } fn on_exit(&mut self, _gl: Option<&eframe::glow::Context>) { if self.tx.try_send(ServerMessage::Shutdown).is_err() { eprintln!("Failed to send shutdown message"); } } }