soundboard/src/ui.rs

153 lines
4.8 KiB
Rust

use eframe::egui;
use raw_window_handle::{HasWindowHandle, RawWindowHandle};
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<Mutex<ServerSettings>>,
should_run: Arc<Mutex<bool>>,
tx: mpsc::Sender<ServerMessage>,
) {
// 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();
std::process::exit(0);
})
.unwrap();
let app = NativeApp {
settings,
should_run,
tx,
tray,
};
Box::new(app)
}),
)
.expect("Error running UI.");
}
struct NativeApp {
settings: Arc<Mutex<ServerSettings>>,
#[allow(dead_code)]
should_run: Arc<Mutex<bool>>,
tx: mpsc::Sender<ServerMessage>,
#[allow(dead_code)]
tray: TrayItem,
}
impl eframe::App for NativeApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
let mut settings = self.settings.lock().unwrap();
ui.heading("Server Settings");
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");
}
}
}