tauri_plugin_network_manager/
lib.rs

1use commands::{
2    connect_to_wifi, delete_wifi_connection, disconnect_from_wifi, get_network_state,
3    get_saved_wifi_networks, list_wifi_networks, toggle_network_state,
4};
5pub use models::{NetworkInfo, WiFiConnectionConfig, WiFiSecurityType};
6use serde::{Deserialize, Serialize};
7use std::result::Result;
8use std::sync::{Arc, RwLock};
9use tauri::{
10    plugin::{Builder, TauriPlugin},
11    AppHandle,
12    Runtime,
13    Manager,
14    Emitter
15};
16
17#[cfg(desktop)]
18pub mod desktop;
19
20mod commands;
21pub mod error;
22pub mod models;
23
24pub use crate::error::{NetworkError, Result as NetworkResult};
25
26#[derive(Default)]
27pub struct NetworkManagerState<R: Runtime> {
28    pub manager: Arc<RwLock<Option<crate::models::VSKNetworkManager<'static, R>>>>,
29}
30
31pub fn spawn_network_change_emitter<R: tauri::Runtime>(
32    app: AppHandle<R>,
33    network_manager: crate::models::VSKNetworkManager<'static, R>,
34) {
35    println!("Iniciando escucha de cambios de red");
36    let rx = match network_manager.listen_network_changes() {
37        Ok(rx) => rx,
38        Err(e) => {
39            eprintln!("No se pudo escuchar cambios de red: {:?}", e);
40            return;
41        }
42    };
43
44    std::thread::spawn(move || {
45        println!("Escuchando cambios de red");
46        for network_info in rx {
47            // Emitir evento a Tauri
48            println!("Cambio de red detectado: {:?}", network_info);
49            let _ = app.emit("network-changed", &network_info);
50        }
51    });
52}
53
54impl<R: Runtime> NetworkManagerState<R> {
55    pub fn new(manager: Option<crate::models::VSKNetworkManager<'static, R>>) -> Self {
56        Self {
57            manager: Arc::new(RwLock::new(manager)),
58        }
59    }
60
61    pub fn list_wifi_networks(&self) -> Result<Vec<NetworkInfo>, NetworkError> {
62        let manager = self.manager.read().map_err(|_| NetworkError::LockError)?;
63        match manager.as_ref() {
64            Some(manager) => manager.list_wifi_networks(),
65            _none => Err(NetworkError::NotInitialized),
66        }
67    }
68
69    pub async fn connect_to_wifi(&self, config: WiFiConnectionConfig) -> Result<(), NetworkError> {
70        let manager = self.manager.read().map_err(|_| NetworkError::LockError)?;
71        match manager.as_ref() {
72            Some(manager) => manager.connect_to_wifi(config).await,
73            _none => Err(NetworkError::NotInitialized),
74        }
75    }
76
77    pub async fn disconnect_from_wifi(&self) -> Result<(), NetworkError> {
78        let manager = self.manager.read().map_err(|_| NetworkError::LockError)?;
79        match manager.as_ref() {
80            Some(manager) => manager.disconnect_from_wifi().await,
81            _none => Err(NetworkError::NotInitialized),
82        }
83    }
84
85    pub fn get_saved_wifi_networks(&self) -> Result<Vec<NetworkInfo>, NetworkError> {
86        let manager = self.manager.read().map_err(|_| NetworkError::LockError)?;
87        match manager.as_ref() {
88            Some(manager) => manager.get_saved_wifi_networks(),
89            _none => Err(NetworkError::NotInitialized),
90        }
91    }
92
93    pub fn delete_wifi_connection(&self, ssid: &str) -> Result<bool, NetworkError> {
94        let manager = self.manager.read().map_err(|_| NetworkError::LockError)?;
95        match manager.as_ref() {
96            Some(manager) => manager.delete_wifi_connection(ssid),
97            _none => Err(NetworkError::NotInitialized),
98        }
99    }
100
101    pub fn toggle_network_state(&self, enabled: bool) -> Result<bool, NetworkError> {
102        let manager = self.manager.read().map_err(|_| NetworkError::LockError)?;
103        match manager.as_ref() {
104            Some(manager) => manager.toggle_network_state(enabled),
105            _none => Err(NetworkError::NotInitialized),
106        }
107    }
108}
109
110#[derive(Serialize, Deserialize)]
111struct NetworkRequest {
112    ssid: String,
113    password: Option<String>,
114    security_type: WiFiSecurityType,
115    username: Option<String>,
116}
117
118/// Initializes the plugin.
119pub fn init() -> TauriPlugin<tauri::Wry> {
120    Builder::new("network-manager")
121        .invoke_handler(tauri::generate_handler![
122            get_network_state,
123            list_wifi_networks,
124            connect_to_wifi,
125            disconnect_from_wifi,
126            get_saved_wifi_networks,
127            delete_wifi_connection,
128            toggle_network_state,
129        ])
130        .setup(|app, _api| -> Result<(), Box<dyn std::error::Error>> {
131            #[cfg(desktop)]
132            // Removed tokio runtime initialization
133            let rt = tokio::runtime::Builder::new_multi_thread()
134                .enable_all()
135                .build()?;
136            let network_manager = rt.block_on(async { crate::desktop::init(&app, _api).await })?;
137
138            app.manage(NetworkManagerState::<tauri::Wry>::new(Some(
139                network_manager,
140            )));
141
142            app.state::<NetworkManagerState<tauri::Wry>>()
143                .manager
144                .read()
145                .map_err(|_| NetworkError::LockError)?
146                .as_ref()
147                .map(|manager| {
148                    // Clone the manager with a 'static lifetime
149                    let manager_static: crate::models::VSKNetworkManager<'static, tauri::Wry> = crate::models::VSKNetworkManager {
150                        connection: manager.connection.clone(),
151                        proxy: manager.proxy.clone(),
152                        app: app.clone(),
153                    };
154                    spawn_network_change_emitter(app.clone(), manager_static);
155                });
156
157            Ok(())
158        })
159        .build()
160}
161
162/// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the network-manager APIs.
163pub trait NetworkManagerExt<R: Runtime> {
164    fn network_manager(&self) -> Option<crate::models::VSKNetworkManager<'static, R>>;
165}
166
167impl<R: Runtime + Clone, T: Manager<R>> NetworkManagerExt<R> for T {
168    fn network_manager(&self) -> Option<crate::models::VSKNetworkManager<'static, R>> {
169        self.try_state::<NetworkManagerState<R>>()
170            .and_then(|state| {
171                state.manager.read().ok().and_then(|m| {
172                    m.as_ref().map(|x| crate::models::VSKNetworkManager {
173                        connection: x.connection.clone(),
174                        proxy: x.proxy.clone(),
175                        app: self.app_handle().clone(),
176                    })
177                })
178            })
179    }
180}