From 43aeb315fad5b464c51f52b00f30348561e4d553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Tue, 12 Aug 2025 15:24:22 +0200 Subject: [PATCH 1/4] Handle system tray icon double-click --- src-tauri/src/tray.rs | 46 +++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/src-tauri/src/tray.rs b/src-tauri/src/tray.rs index 39aee101..d63bbb81 100644 --- a/src-tauri/src/tray.rs +++ b/src-tauri/src/tray.rs @@ -2,7 +2,7 @@ use tauri::{ image::Image, menu::{MenuBuilder, MenuEvent, MenuItem, SubmenuBuilder}, path::BaseDirectory, - tray::{TrayIcon, TrayIconBuilder}, + tray::{TrayIcon, TrayIconBuilder, TrayIconEvent}, AppHandle, Emitter, Manager, }; @@ -19,6 +19,8 @@ const SUBSCRIBE_UPDATES_LINK: &str = "https://defguard.net/newsletter"; const JOIN_COMMUNITY_LINK: &str = "https://matrix.to/#/#defguard:teonite.com"; const FOLLOW_US_LINK: &str = "https://floss.social/@defguard"; +const MAIN_WINDOW_ID: &str = "main"; + const TRAY_ICON_ID: &str = "tray"; const TRAY_EVENT_QUIT: &str = "quit"; @@ -104,8 +106,13 @@ pub async fn generate_tray_menu(app: &AppHandle) -> Result { let tray = TrayIconBuilder::with_id(TRAY_ICON_ID) .menu(&tray_menu) - .show_menu_on_left_click(true) - .on_menu_event(handle_tray_event) + .show_menu_on_left_click(false) + .on_tray_icon_event(|icon, event| { + if let TrayIconEvent::DoubleClick { .. } = event { + show_main_window(icon.app_handle()) + } + }) + .on_menu_event(handle_tray_menu_event) .build(app)?; debug!("Tray menu successfully generated"); @@ -119,23 +126,30 @@ pub async fn reload_tray_menu(app_handle: &AppHandle) { } } +fn hide_main_window(app: &AppHandle) { + if let Some(main_window) = app.get_webview_window(MAIN_WINDOW_ID) { + if let Err(err) = main_window.hide() { + warn!("Failed to hide main window: {err}"); + } + } +} + fn show_main_window(app: &AppHandle) { - if let Some(main_window) = app.get_webview_window("main") { - // If this fails, Tauri has a problem. - let minimized = main_window.is_minimizable().unwrap_or_default(); - let visible = main_window.is_visible().unwrap_or_default(); - if minimized { - let _ = main_window.hide(); + if let Some(main_window) = app.get_webview_window(MAIN_WINDOW_ID) { + if main_window.is_minimized().unwrap_or_default() { + if let Err(err) = main_window.unminimize() { + warn!("Failed to unminimize main window: {err}"); + } } - if !visible { - let _ = main_window.show(); + if let Err(err) = main_window.show() { + warn!("Failed to show main window: {err}"); } let _ = main_window.set_focus(); } } /// Handle tray actions. -pub fn handle_tray_event(app: &AppHandle, event: MenuEvent) { +pub fn handle_tray_menu_event(app: &AppHandle, event: MenuEvent) { let handle = app.clone(); match event.id.as_ref() { TRAY_EVENT_QUIT => { @@ -143,13 +157,7 @@ pub fn handle_tray_event(app: &AppHandle, event: MenuEvent) { handle.exit(0); } TRAY_EVENT_SHOW => show_main_window(app), - TRAY_EVENT_HIDE => { - if let Some(main_window) = app.get_webview_window("main") { - if main_window.is_visible().unwrap_or_default() { - let _ = main_window.hide(); - } - } - } + TRAY_EVENT_HIDE => hide_main_window(app), TRAY_EVENT_UPDATES => { let _ = webbrowser::open(SUBSCRIBE_UPDATES_LINK); } From 6278f976d03cdb05a3039be310217e0d217fb43a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Tue, 12 Aug 2025 15:34:48 +0200 Subject: [PATCH 2/4] Fix system tray behaviour on macOS --- src-tauri/src/tray.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/tray.rs b/src-tauri/src/tray.rs index d63bbb81..0b634f76 100644 --- a/src-tauri/src/tray.rs +++ b/src-tauri/src/tray.rs @@ -2,7 +2,7 @@ use tauri::{ image::Image, menu::{MenuBuilder, MenuEvent, MenuItem, SubmenuBuilder}, path::BaseDirectory, - tray::{TrayIcon, TrayIconBuilder, TrayIconEvent}, + tray::{TrayIcon, TrayIconBuilder}, AppHandle, Emitter, Manager, }; @@ -104,11 +104,21 @@ pub async fn generate_tray_menu(app: &AppHandle) -> Result { .item(&quit) .build()?; + // On macOS, always show menu under system tray icon. + #[cfg(target_os = "macos")] + let tray = TrayIconBuilder::with_id(TRAY_ICON_ID) + .menu(&tray_menu) + .show_menu_on_left_click(true) + .on_menu_event(handle_tray_menu_event) + .build(app)?; + // On other systems (especially Windows), system tray menu is on right-click, + // and double-click shows the main window. + #[cfg(not(target_os = "macos"))] let tray = TrayIconBuilder::with_id(TRAY_ICON_ID) .menu(&tray_menu) .show_menu_on_left_click(false) .on_tray_icon_event(|icon, event| { - if let TrayIconEvent::DoubleClick { .. } = event { + if let tauri::tray::TrayIconEvent::DoubleClick { .. } = event { show_main_window(icon.app_handle()) } }) From 636e19a12156a22b74546b87a8d2c6504cc7f811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Tue, 12 Aug 2025 16:42:58 +0200 Subject: [PATCH 3/4] Move active connections into LazyLock --- src-tauri/src/active_connections.rs | 97 +++++++++++++++++ src-tauri/src/appstate.rs | 101 ++---------------- src-tauri/src/bin/defguard-client.rs | 28 +++-- src-tauri/src/commands.rs | 26 ++--- src-tauri/src/enterprise/periodic/config.rs | 8 +- src-tauri/src/lib.rs | 1 + .../src/log_watcher/global_log_watcher.rs | 19 ++-- .../src/log_watcher/service_log_watcher.rs | 5 +- src-tauri/src/periodic/connection.rs | 3 +- src-tauri/src/tray.rs | 13 +-- src-tauri/tauri.conf.json | 2 +- tsconfig.json | 2 +- 12 files changed, 152 insertions(+), 153 deletions(-) create mode 100644 src-tauri/src/active_connections.rs diff --git a/src-tauri/src/active_connections.rs b/src-tauri/src/active_connections.rs new file mode 100644 index 00000000..c58b6299 --- /dev/null +++ b/src-tauri/src/active_connections.rs @@ -0,0 +1,97 @@ +use std::{collections::HashSet, sync::LazyLock}; + +use tokio::sync::Mutex; + +use crate::{ + database::{ + models::{connection::ActiveConnection, instance::Instance, location::Location, Id}, + DB_POOL, + }, + error::Error, + utils::disconnect_interface, + ConnectionType, +}; + +pub(crate) static ACTIVE_CONNECTIONS: LazyLock>> = + LazyLock::new(|| Mutex::new(Vec::new())); + +pub(crate) async fn get_connection_id_by_type(connection_type: ConnectionType) -> Vec { + let active_connections = ACTIVE_CONNECTIONS.lock().await; + + let connection_ids = active_connections + .iter() + .filter_map(|con| { + if con.connection_type == connection_type { + Some(con.location_id) + } else { + None + } + }) + .collect(); + + connection_ids +} + +pub async fn close_all_connections() -> Result<(), Error> { + debug!("Closing all active connections"); + let active_connections = ACTIVE_CONNECTIONS.lock().await; + let active_connections_count = active_connections.len(); + debug!("Found {active_connections_count} active connections"); + for connection in active_connections.iter() { + debug!( + "Found active connection with location {}", + connection.location_id + ); + trace!("Connection: {connection:#?}"); + debug!("Removing interface {}", connection.interface_name); + disconnect_interface(connection).await?; + } + if active_connections_count > 0 { + info!("All active connections ({active_connections_count}) have been closed."); + } else { + debug!("There were no active connections to close, nothing to do."); + } + Ok(()) +} + +pub(crate) async fn find_connection( + id: Id, + connection_type: ConnectionType, +) -> Option { + let connections = ACTIVE_CONNECTIONS.lock().await; + trace!( + "Checking for active connection with ID {id}, type {connection_type} in active connections." + ); + + if let Some(connection) = connections + .iter() + .find(|conn| conn.location_id == id && conn.connection_type == connection_type) + { + // 'connection' now contains the first element with the specified id and connection_type + trace!("Found connection: {connection:?}"); + Some(connection.to_owned()) + } else { + debug!( + "Couldn't find connection with ID {id}, type: {connection_type} in active connections." + ); + None + } +} + +/// Returns active connections for a given instance. +pub(crate) async fn active_connections( + instance: &Instance, +) -> Result, Error> { + let locations: HashSet = Location::find_by_instance_id(&*DB_POOL, instance.id) + .await? + .iter() + .map(|location| location.id) + .collect(); + Ok(ACTIVE_CONNECTIONS + .lock() + .await + .iter() + .filter(|connection| locations.contains(&connection.location_id)) + .cloned() + .collect()) +} diff --git a/src-tauri/src/appstate.rs b/src-tauri/src/appstate.rs index 3b3cedd7..16d6e118 100644 --- a/src-tauri/src/appstate.rs +++ b/src-tauri/src/appstate.rs @@ -1,22 +1,21 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; -use tauri::async_runtime::{spawn, JoinHandle, Mutex}; +use tauri::async_runtime::{spawn, JoinHandle}; use tokio_util::sync::CancellationToken; use crate::{ + active_connections::ACTIVE_CONNECTIONS, app_config::AppConfig, database::{ - models::{connection::ActiveConnection, instance::Instance, location::Location, Id}, + models::{connection::ActiveConnection, Id}, DB_POOL, }, - error::Error, service::utils::DAEMON_CLIENT, - utils::{disconnect_interface, stats_handler}, + utils::stats_handler, ConnectionType, }; pub struct AppState { - pub active_connections: Mutex>, pub log_watchers: std::sync::Mutex>, pub app_config: std::sync::Mutex, stat_threads: std::sync::Mutex>>, // location ID is the key @@ -26,7 +25,6 @@ impl AppState { #[must_use] pub fn new(config: AppConfig) -> Self { AppState { - active_connections: Mutex::new(Vec::new()), log_watchers: std::sync::Mutex::new(HashMap::new()), app_config: std::sync::Mutex::new(config), stat_threads: std::sync::Mutex::new(HashMap::new()), @@ -42,7 +40,7 @@ impl AppState { let ifname = interface_name.into(); let connection = ActiveConnection::new(location_id, ifname.clone(), connection_type); debug!("Adding active connection for location ID: {location_id}"); - let mut connections = self.active_connections.lock().await; + let mut connections = ACTIVE_CONNECTIONS.lock().await; connections.push(connection); trace!("Current active connections: {connections:?}"); drop(connections); @@ -92,7 +90,7 @@ impl AppState { } } - let mut connections = self.active_connections.lock().await; + let mut connections = ACTIVE_CONNECTIONS.lock().await; if let Some(index) = connections.iter().position(|conn| { conn.location_id == location_id && conn.connection_type == connection_type }) { @@ -105,89 +103,4 @@ impl AppState { None } } - - pub(crate) async fn get_connection_id_by_type( - &self, - connection_type: ConnectionType, - ) -> Vec { - let active_connections = self.active_connections.lock().await; - - let connection_ids = active_connections - .iter() - .filter_map(|con| { - if con.connection_type == connection_type { - Some(con.location_id) - } else { - None - } - }) - .collect(); - - connection_ids - } - - pub async fn close_all_connections(&self) -> Result<(), crate::error::Error> { - debug!("Closing all active connections"); - let active_connections = self.active_connections.lock().await; - let active_connections_count = active_connections.len(); - debug!("Found {active_connections_count} active connections"); - for connection in active_connections.iter() { - debug!( - "Found active connection with location {}", - connection.location_id - ); - trace!("Connection: {connection:#?}"); - debug!("Removing interface {}", connection.interface_name); - disconnect_interface(connection).await?; - } - if active_connections_count > 0 { - info!("All active connections ({active_connections_count}) have been closed."); - } else { - debug!("There were no active connections to close, nothing to do."); - } - Ok(()) - } - - pub(crate) async fn find_connection( - &self, - id: Id, - connection_type: ConnectionType, - ) -> Option { - let connections = self.active_connections.lock().await; - trace!( - "Checking for active connection with ID {id}, type {connection_type} in active connections." - ); - - if let Some(connection) = connections - .iter() - .find(|conn| conn.location_id == id && conn.connection_type == connection_type) - { - // 'connection' now contains the first element with the specified id and connection_type - trace!("Found connection: {connection:?}"); - Some(connection.to_owned()) - } else { - debug!("Couldn't find connection with ID {id}, type: {connection_type} in active connections."); - None - } - } - - /// Returns active connections for a given instance. - pub(crate) async fn active_connections( - &self, - instance: &Instance, - ) -> Result, Error> { - let locations: HashSet = Location::find_by_instance_id(&*DB_POOL, instance.id) - .await? - .iter() - .map(|location| location.id) - .collect(); - Ok(self - .active_connections - .lock() - .await - .iter() - .filter(|connection| locations.contains(&connection.location_id)) - .cloned() - .collect()) - } } diff --git a/src-tauri/src/bin/defguard-client.rs b/src-tauri/src/bin/defguard-client.rs index 72db24bd..67a57d79 100644 --- a/src-tauri/src/bin/defguard-client.rs +++ b/src-tauri/src/bin/defguard-client.rs @@ -8,6 +8,7 @@ use std::{env, str::FromStr, sync::LazyLock}; #[cfg(target_os = "windows")] use defguard_client::utils::sync_connections; use defguard_client::{ + active_connections::close_all_connections, app_config::AppConfig, appstate::AppState, commands::*, @@ -25,7 +26,7 @@ use defguard_client::{ use log::{Level, LevelFilter}; #[cfg(target_os = "macos")] use tauri::{process, Env}; -use tauri::{AppHandle, Builder, Emitter, Manager, RunEvent, State, WindowEvent}; +use tauri::{AppHandle, Builder, Emitter, Manager, RunEvent, WindowEvent}; use tauri_plugin_log::{Target, TargetKind}; #[derive(Clone, serde::Serialize)] @@ -129,7 +130,7 @@ fn main() { "PATH", format!("{current_path}:{}", current_bin_dir.to_str().unwrap()), ); - debug!("Added binary dir {current_bin_dir:?} to PATH"); + debug!("Added binary dir {} to PATH", current_bin_dir.display()); } let app = Builder::default() @@ -277,18 +278,18 @@ fn main() { // Startup tasks RunEvent::Ready => { info!( - "Application data (database file) will be stored in: {:?} and application logs in: {:?}. \ + "Application data (database file) will be stored in: {} and application logs in: {}. \ Logs of the background Defguard service responsible for managing VPN connections at the \ network level will be stored in: {}.", // display the path to the app data directory, convert option to option<&str> app_handle .path() .app_data_dir() - .unwrap_or_else(|_| "UNDEFINED DATA DIRECTORY".into()), + .unwrap_or_else(|_| "UNDEFINED DATA DIRECTORY".into()).display(), app_handle .path() .app_log_dir() - .unwrap_or_else(|_| "UNDEFINED LOG DIRECTORY".into()), + .unwrap_or_else(|_| "UNDEFINED LOG DIRECTORY".into()).display(), service::config::DEFAULT_LOG_DIR ); tauri::async_runtime::block_on(startup(app_handle)); @@ -305,22 +306,17 @@ fn main() { }); debug!("Ctrl-C handler has been set up successfully"); } - // Prevent shutdown on window close. - RunEvent::ExitRequested { code, api, .. } => { + RunEvent::ExitRequested { api, .. } => { debug!("Received exit request"); - // `None` when the exit is requested by user interaction. - if code.is_none() { - api.prevent_exit(); - } else { - let app_state = app_handle.state::>(); - tauri::async_runtime::block_on(async { - let _ = app_state.close_all_connections().await; - }); - } + // Prevent shutdown on window close. + api.prevent_exit(); } // Handle shutdown. RunEvent::Exit => { debug!("Exiting the application's main event loop."); + tauri::async_runtime::block_on(async { + let _ = close_all_connections().await; + }); } _ => { trace!("Received event: {event:?}"); diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 8f92fa19..c5a151a8 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -14,6 +14,7 @@ use tauri::{AppHandle, Emitter, Manager, State}; const UPDATE_URL: &str = "https://pkgs.defguard.net/api/update/check"; use crate::{ + active_connections::{find_connection, get_connection_id_by_type}, app_config::{AppConfig, AppConfigPatch}, appstate::AppState, database::{ @@ -293,7 +294,7 @@ pub async fn save_device_config( } #[tauri::command(async)] -pub async fn all_instances(app_state: State<'_, AppState>) -> Result>, Error> { +pub async fn all_instances() -> Result>, Error> { debug!("Getting information about all instances."); let instances = Instance::all(&*DB_POOL).await?; trace!( @@ -302,9 +303,7 @@ pub async fn all_instances(app_state: State<'_, AppState>) -> Result = locations.iter().map(|location| location.id).collect(); @@ -357,10 +356,7 @@ impl fmt::Display for LocationInfo { } #[tauri::command(async)] -pub async fn all_locations( - instance_id: Id, - app_state: State<'_, AppState>, -) -> Result, Error> { +pub async fn all_locations(instance_id: Id) -> Result, Error> { let Some(instance) = Instance::find_by_id(&*DB_POOL, instance_id).await? else { error!( "Tried to get all locations for the instance with ID {instance_id}, but the \ @@ -377,9 +373,7 @@ pub async fn all_locations( "Found {} locations for instance {instance} to return information about.", locations.len() ); - let active_locations_ids = app_state - .get_connection_id_by_type(ConnectionType::Location) - .await; + let active_locations_ids = get_connection_id_by_type(ConnectionType::Location).await; let mut location_info = Vec::new(); for location in locations { let info = LocationInfo { @@ -687,12 +681,10 @@ pub async fn all_tunnel_connections(location_id: Id) -> Result Result, Error> { - let state = handle.state::(); let name = get_tunnel_or_location_name(location_id, connection_type).await; debug!("Checking if there is an active connection for location {name}(ID: {location_id})"); - let connection = state.find_connection(location_id, connection_type).await; + let connection = find_connection(location_id, connection_type).await; if connection.is_some() { debug!("Found active connection for location {name}(ID: {location_id})"); } @@ -913,16 +905,14 @@ pub struct TunnelInfo { } #[tauri::command(async)] -pub async fn all_tunnels(app_state: State<'_, AppState>) -> Result>, Error> { +pub async fn all_tunnels() -> Result>, Error> { trace!("Getting information about all tunnels"); let tunnels = Tunnel::all(&*DB_POOL).await?; trace!("Found ({}) tunnels to get information about", tunnels.len()); trace!("Tunnels found: {tunnels:#?}"); let mut tunnel_info = Vec::new(); - let active_tunnel_ids = app_state - .get_connection_id_by_type(ConnectionType::Tunnel) - .await; + let active_tunnel_ids = get_connection_id_by_type(ConnectionType::Tunnel).await; for tunnel in tunnels { tunnel_info.push(TunnelInfo { diff --git a/src-tauri/src/enterprise/periodic/config.rs b/src-tauri/src/enterprise/periodic/config.rs index 91bb6598..ce78ccb6 100644 --- a/src-tauri/src/enterprise/periodic/config.rs +++ b/src-tauri/src/enterprise/periodic/config.rs @@ -2,11 +2,11 @@ use std::{str::FromStr, time::Duration}; use reqwest::{Client, StatusCode}; use sqlx::{Sqlite, Transaction}; -use tauri::{AppHandle, Emitter, Manager, State, Url}; +use tauri::{AppHandle, Emitter, Url}; use tokio::time::sleep; use crate::{ - appstate::AppState, + active_connections::active_connections, commands::{do_update_instance, locations_changed}, database::{ models::{instance::Instance, Id}, @@ -201,8 +201,8 @@ pub async fn poll_instance( // Config changed. If there are no active connections for this instance, update the database. // Otherwise just display a message to reconnect. - let state: State<'_, AppState> = handle.state(); - if state.active_connections(instance).await?.is_empty() { + // + if active_connections(instance).await?.is_empty() { debug!( "Updating instance {}({}) configuration: {device_config:?}", instance.name, instance.id, diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 7f41ca1f..469e2cc5 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize}; use self::database::models::{Id, NoId}; +pub mod active_connections; pub mod app_config; pub mod appstate; pub mod commands; diff --git a/src-tauri/src/log_watcher/global_log_watcher.rs b/src-tauri/src/log_watcher/global_log_watcher.rs index 60408145..38ca7b41 100644 --- a/src-tauri/src/log_watcher/global_log_watcher.rs +++ b/src-tauri/src/log_watcher/global_log_watcher.rs @@ -45,7 +45,7 @@ impl LogDirs { })?; debug!( "Log directories of service and client have been identified by the global log watcher: \ - {service_log_dir:?} and {client_log_dir:?}" + {} and {}", service_log_dir.display(), client_log_dir.display() ); Ok(Self { @@ -61,8 +61,8 @@ impl LogDirs { /// with the last 10 characters specifying a date (e.g. `2023-12-15`). fn get_latest_log_file(&self) -> Result, LogWatcherError> { trace!( - "Getting latest log file from directory: {:?}", - self.service_log_dir + "Getting latest log file from directory: {}", + self.service_log_dir.display() ); let entries = read_dir(&self.service_log_dir)?; @@ -107,15 +107,15 @@ impl LogDirs { fn get_client_file(&self) -> Result { trace!( - "Opening the log file for the client, using directory: {:?}", - self.client_log_dir + "Opening the log file for the client, using directory: {}", + self.client_log_dir.display() ); let dir_str = self .client_log_dir .to_str() .ok_or(LogWatcherError::LogPathError(format!( - "Couldn't convert the client log directory path ({:?}) to a string slice", - self.client_log_dir + "Couldn't convert the client log directory path ({}) to a string slice", + self.client_log_dir.display() )))?; let path = format!("{dir_str}/defguard-client.log"); trace!("Constructed client log file path: {path}"); @@ -185,8 +185,9 @@ impl GlobalLogWatcher { trace!("Checking if log files are available"); if service_reader.is_none() && client_reader.is_none() { warn!( - "Couldn't read files at {:?} and {:?}, there will be no logs reported in the client.", - self.log_dirs.current_service_log_file, self.log_dirs.client_log_dir + "Couldn't read files at {:?} and {}, there will be no logs reported in the client.", + self.log_dirs.current_service_log_file, + self.log_dirs.client_log_dir.display() ); // Wait for logs to appear. sleep(DELAY); diff --git a/src-tauri/src/log_watcher/service_log_watcher.rs b/src-tauri/src/log_watcher/service_log_watcher.rs index 7db9b0a9..94bd9a57 100644 --- a/src-tauri/src/log_watcher/service_log_watcher.rs +++ b/src-tauri/src/log_watcher/service_log_watcher.rs @@ -181,7 +181,10 @@ impl<'a> ServiceLogWatcher<'a> { /// Log files are rotated daily and have a knows naming format, /// with the last 10 characters specifying a date (e.g. `2023-12-15`). fn get_latest_log_file(&self) -> Result, LogWatcherError> { - trace!("Getting latest log file from directory: {:?}", self.log_dir); + trace!( + "Getting latest log file from directory: {}", + self.log_dir.display() + ); let entries = read_dir(self.log_dir)?; let mut latest_log = None; diff --git a/src-tauri/src/periodic/connection.rs b/src-tauri/src/periodic/connection.rs index 88cc0a21..fd20254c 100644 --- a/src-tauri/src/periodic/connection.rs +++ b/src-tauri/src/periodic/connection.rs @@ -5,6 +5,7 @@ use tauri::{AppHandle, Manager}; use tokio::time::interval; use crate::{ + active_connections::ACTIVE_CONNECTIONS, appstate::AppState, commands::{connect, disconnect}, database::{ @@ -111,7 +112,7 @@ pub async fn verify_active_connections(app_handle: AppHandle) { loop { interval.tick().await; - let connections = app_state.active_connections.lock().await; + let connections = ACTIVE_CONNECTIONS.lock().await; let connection_count = connections.len(); if connection_count == 0 { debug!( diff --git a/src-tauri/src/tray.rs b/src-tauri/src/tray.rs index 0b634f76..ea4c2d18 100644 --- a/src-tauri/src/tray.rs +++ b/src-tauri/src/tray.rs @@ -7,8 +7,8 @@ use tauri::{ }; use crate::{ + active_connections::get_connection_id_by_type, app_config::AppTrayTheme, - appstate::AppState, commands::{all_instances, all_locations, connect, disconnect}, database::{models::location::Location, DB_POOL}, error::Error, @@ -31,7 +31,6 @@ const TRAY_EVENT_COMMINITY: &str = "community"; const TRAY_EVENT_FOLLOW: &str = "follow"; pub async fn generate_tray_menu(app: &AppHandle) -> Result { - let app_state = app.state::(); debug!("Generating tray menu."); let quit = MenuItem::with_id(app, TRAY_EVENT_QUIT, "Quit", true, None::<&str>)?; let show = MenuItem::with_id(app, TRAY_EVENT_SHOW, "Show", true, None::<&str>)?; @@ -55,12 +54,12 @@ pub async fn generate_tray_menu(app: &AppHandle) -> Result { // INSTANCE SECTION let mut instance_menu = SubmenuBuilder::new(app, "Instances"); debug!("Getting all instances information for the tray menu"); - match all_instances(app_state.clone()).await { + match all_instances().await { Ok(instances) => { let instance_count = instances.len(); debug!("Got {instance_count} instances to display in the tray menu"); for instance in instances { - let all_locations = all_locations(instance.id, app_state.clone()).await.unwrap(); + let all_locations = all_locations(instance.id).await.unwrap(); debug!( "Found {} locations for the {} instance to display in the tray menu", all_locations.len(), @@ -214,10 +213,8 @@ async fn handle_location_tray_menu(id: String, handle: &AppHandle) { Ok(location_id) => { match Location::find_by_id(&*DB_POOL, location_id).await { Ok(Some(location)) => { - let active_locations_ids = handle - .state::() - .get_connection_id_by_type(ConnectionType::Location) - .await; + let active_locations_ids = + get_connection_id_by_type(ConnectionType::Location).await; if active_locations_ids.contains(&location_id) { info!("Disconnect location with ID {id}"); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 8d35070a..652fc895 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ "bundle": { "active": true, "category": "Utility", - "copyright": "teonite", + "copyright": "Defguard", "targets": [ "deb", "app" diff --git a/tsconfig.json b/tsconfig.json index 71027951..e14af76c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -45,4 +45,4 @@ "path": "./tsconfig.node.json" } ] -} \ No newline at end of file +} From 4ffcc473edad0fe7b9c9a7e74915e2bfee2f8807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Tue, 12 Aug 2025 17:58:04 +0200 Subject: [PATCH 4/4] Cleanup --- src-tauri/src/appstate.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src-tauri/src/appstate.rs b/src-tauri/src/appstate.rs index 16d6e118..87d6496b 100644 --- a/src-tauri/src/appstate.rs +++ b/src-tauri/src/appstate.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, sync::Mutex}; use tauri::async_runtime::{spawn, JoinHandle}; use tokio_util::sync::CancellationToken; @@ -16,18 +16,18 @@ use crate::{ }; pub struct AppState { - pub log_watchers: std::sync::Mutex>, - pub app_config: std::sync::Mutex, - stat_threads: std::sync::Mutex>>, // location ID is the key + pub log_watchers: Mutex>, + pub app_config: Mutex, + stat_threads: Mutex>>, // location ID is the key } impl AppState { #[must_use] pub fn new(config: AppConfig) -> Self { AppState { - log_watchers: std::sync::Mutex::new(HashMap::new()), - app_config: std::sync::Mutex::new(config), - stat_threads: std::sync::Mutex::new(HashMap::new()), + log_watchers: Mutex::new(HashMap::new()), + app_config: Mutex::new(config), + stat_threads: Mutex::new(HashMap::new()), } }