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