mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
refactor(windows): handle tray menu events in the main loop (#3446)
Closes #2983
This commit is contained in:
@@ -222,58 +222,20 @@ async fn accept_deep_links(mut server: deep_link::Server, ctlr_tx: CtlrTx) -> Re
|
||||
}
|
||||
|
||||
fn handle_system_tray_event(app: &tauri::AppHandle, event: TrayMenuEvent) -> Result<()> {
|
||||
let ctlr_tx = &app
|
||||
.try_state::<Managed>()
|
||||
.ok_or_else(|| anyhow!("can't get Managed struct from Tauri"))?
|
||||
.ctlr_tx;
|
||||
|
||||
// TODO: Just handle these in Controller directly: <https://github.com/firezone/firezone/issues/2983>
|
||||
match event {
|
||||
TrayMenuEvent::About => {
|
||||
let win = app
|
||||
.get_window("about")
|
||||
.ok_or_else(|| anyhow!("getting handle to About window"))?;
|
||||
|
||||
if win.is_visible()? {
|
||||
win.hide()?;
|
||||
} else {
|
||||
win.show()?;
|
||||
}
|
||||
}
|
||||
TrayMenuEvent::CancelSignIn => ctlr_tx.blocking_send(ControllerRequest::CancelSignIn)?,
|
||||
TrayMenuEvent::Resource { id } => {
|
||||
ctlr_tx.blocking_send(ControllerRequest::CopyResource(id))?
|
||||
}
|
||||
TrayMenuEvent::Settings => {
|
||||
let win = app
|
||||
.get_window("settings")
|
||||
.ok_or_else(|| anyhow!("getting handle to Settings window"))?;
|
||||
|
||||
if win.is_visible()? {
|
||||
// If we close the window here, we can't re-open it, we'd have to fully re-create it. Not needed for MVP - We agreed 100 MB is fine for the GUI client.
|
||||
win.hide()?;
|
||||
} else {
|
||||
win.show()?;
|
||||
}
|
||||
}
|
||||
TrayMenuEvent::SignIn => ctlr_tx.blocking_send(ControllerRequest::SignIn)?,
|
||||
TrayMenuEvent::SignOut => ctlr_tx.blocking_send(ControllerRequest::SignOut)?,
|
||||
TrayMenuEvent::Quit => ctlr_tx.blocking_send(ControllerRequest::Quit)?,
|
||||
}
|
||||
app.try_state::<Managed>()
|
||||
.context("can't get Managed struct from Tauri")?
|
||||
.ctlr_tx
|
||||
.blocking_send(ControllerRequest::SystemTrayMenu(event))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) enum ControllerRequest {
|
||||
CancelSignIn,
|
||||
CopyResource(String),
|
||||
Disconnected,
|
||||
DisconnectedTokenExpired,
|
||||
ExportLogs { path: PathBuf, stem: PathBuf },
|
||||
GetAdvancedSettings(oneshot::Sender<AdvancedSettings>),
|
||||
Quit,
|
||||
SchemeRequest(url::Url),
|
||||
SignIn,
|
||||
SignOut,
|
||||
SystemTrayMenu(TrayMenuEvent),
|
||||
TunnelReady,
|
||||
}
|
||||
|
||||
@@ -509,6 +471,26 @@ impl Controller {
|
||||
self.refresh_system_tray_menu()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn toggle_window(&self, window: system_tray_menu::Window) -> Result<()> {
|
||||
let id = match window {
|
||||
system_tray_menu::Window::About => "about",
|
||||
system_tray_menu::Window::Settings => "settings",
|
||||
};
|
||||
|
||||
let win = self
|
||||
.app
|
||||
.get_window(id)
|
||||
.ok_or_else(|| anyhow!("getting handle to `{id}` window"))?;
|
||||
|
||||
if win.is_visible()? {
|
||||
// If we close the window here, we can't re-open it, we'd have to fully re-create it. Not needed for MVP - We agreed 100 MB is fine for the GUI client.
|
||||
win.hide()?;
|
||||
} else {
|
||||
win.show()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: After PR #2960 lands, move some of this into `impl Controller`
|
||||
@@ -553,9 +535,6 @@ async fn run_controller(
|
||||
break;
|
||||
};
|
||||
match req {
|
||||
Req::CopyResource(id) => if let Err(e) = controller.copy_resource(&id) {
|
||||
tracing::error!("couldn't copy resource to clipboard: {e:#?}");
|
||||
}
|
||||
Req::Disconnected => {
|
||||
tracing::debug!("connlib disconnected, tearing down Session");
|
||||
controller.tunnel_ready = false;
|
||||
@@ -566,10 +545,6 @@ async fn run_controller(
|
||||
}
|
||||
controller.refresh_system_tray_menu()?;
|
||||
}
|
||||
Req::CancelSignIn | Req::SignOut => {
|
||||
tracing::info!("User signed out or canceled sign-in");
|
||||
controller.sign_out()?;
|
||||
}
|
||||
Req::DisconnectedTokenExpired => {
|
||||
tracing::info!("Token expired");
|
||||
controller.sign_out()?;
|
||||
@@ -579,11 +554,18 @@ async fn run_controller(
|
||||
Req::GetAdvancedSettings(tx) => {
|
||||
tx.send(controller.advanced_settings.clone()).ok();
|
||||
}
|
||||
Req::Quit => break,
|
||||
Req::SchemeRequest(url) => if let Err(e) = controller.handle_deep_link(&url).await {
|
||||
tracing::error!("couldn't handle deep link: {e:#?}");
|
||||
}
|
||||
Req::SignIn => {
|
||||
Req::SystemTrayMenu(TrayMenuEvent::ToggleWindow(window)) => controller.toggle_window(window)?,
|
||||
Req::SystemTrayMenu(TrayMenuEvent::CancelSignIn | TrayMenuEvent::SignOut) => {
|
||||
tracing::info!("User signed out or canceled sign-in");
|
||||
controller.sign_out()?;
|
||||
}
|
||||
Req::SystemTrayMenu(TrayMenuEvent::Resource { id }) => if let Err(e) = controller.copy_resource(&id) {
|
||||
tracing::error!("couldn't copy resource to clipboard: {e:#?}");
|
||||
}
|
||||
Req::SystemTrayMenu(TrayMenuEvent::SignIn) => {
|
||||
if let Some(req) = controller.auth.start_sign_in()? {
|
||||
let url = req.to_url(&controller.advanced_settings.auth_base_url);
|
||||
controller.refresh_system_tray_menu()?;
|
||||
@@ -594,6 +576,7 @@ async fn run_controller(
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Req::SystemTrayMenu(TrayMenuEvent::Quit) => break,
|
||||
Req::TunnelReady => {
|
||||
controller.tunnel_ready = true;
|
||||
controller.refresh_system_tray_menu()?;
|
||||
|
||||
@@ -4,15 +4,20 @@ use tauri::{CustomMenuItem, SystemTrayMenu, SystemTrayMenuItem, SystemTraySubmen
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub(crate) enum Event {
|
||||
About,
|
||||
CancelSignIn,
|
||||
Resource { id: String },
|
||||
Settings,
|
||||
SignIn,
|
||||
SignOut,
|
||||
ToggleWindow(Window),
|
||||
Quit,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub(crate) enum Window {
|
||||
About,
|
||||
Settings,
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub(crate) enum Error {
|
||||
#[error("the system tray menu item ID is not valid")]
|
||||
@@ -24,9 +29,9 @@ impl FromStr for Event {
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Error> {
|
||||
Ok(match s {
|
||||
"/about" => Self::About,
|
||||
"/about" => Self::ToggleWindow(Window::About),
|
||||
"/cancel_sign_in" => Self::CancelSignIn,
|
||||
"/settings" => Self::Settings,
|
||||
"/settings" => Self::ToggleWindow(Window::Settings),
|
||||
"/sign_in" => Self::SignIn,
|
||||
"/sign_out" => Self::SignOut,
|
||||
"/quit" => Self::Quit,
|
||||
@@ -93,12 +98,15 @@ pub(crate) fn signed_out() -> SystemTrayMenu {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Event;
|
||||
use super::{Event, Window};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn systray_parse() {
|
||||
assert_eq!(Event::from_str("/about").unwrap(), Event::About);
|
||||
assert_eq!(
|
||||
Event::from_str("/about").unwrap(),
|
||||
Event::ToggleWindow(Window::About)
|
||||
);
|
||||
assert_eq!(
|
||||
Event::from_str("/resource/1234").unwrap(),
|
||||
Event::Resource {
|
||||
|
||||
Reference in New Issue
Block a user