tauri_plugin_network_manager/
lib.rs1use 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 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
118pub 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 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 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
162pub 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}