Mountain/IPC/WindServiceHandler/
NativeHost.rs1#![allow(non_snake_case)]
2
3use serde_json::{Value, json};
9use tauri::{AppHandle, Manager};
10
11use crate::dev_log;
12
13pub async fn handle_native_pick_folder(AppHandle:AppHandle, _Args:Vec<Value>) -> Result<Value, String> {
15 use tauri_plugin_dialog::DialogExt;
16 use tauri::WebviewWindow;
17
18 dev_log!("folder", "pickFolderAndOpen requested");
19
20 dev_log!("folder", "pickFolderAndOpen requested");
21
22 let Handle = AppHandle.clone();
23 tokio::task::spawn_blocking(move || {
24 let FolderPath = Handle.dialog().file().blocking_pick_folder();
25
26 if let Some(Path) = FolderPath {
27 let PathStr = Path.to_string();
28 dev_log!("folder", "picked: {}", PathStr);
29
30 if let Some(Window) = Handle.get_webview_window("main") {
31 if let Ok(CurrentUrl) = Window.url() {
32 let Origin = CurrentUrl.origin().unicode_serialization();
33 let EncodedPath = url::form_urlencoded::Serializer::new(String::new())
34 .append_pair("folder", &PathStr)
35 .finish();
36 let NewUrl = format!("{}/?{}", Origin, EncodedPath);
37 dev_log!("folder", "navigating: {}", NewUrl);
38 let _ = Window.navigate(NewUrl.parse().unwrap());
39 }
40 }
41 }
42 });
43
44 Ok(Value::Null)
45}
46
47pub async fn handle_native_show_open_dialog(AppHandle:AppHandle, Args:Vec<Value>) -> Result<Value, String> {
49 dev_log!("folder", "showOpenDialog: {:?}", Args);
50 Ok(json!({ "canceled": true, "filePaths": [] }))
51}
52
53pub async fn handle_native_os_properties() -> Result<Value, String> {
55 use sysinfo::System;
56
57 let OsType = match std::env::consts::OS {
58 "macos" => "Darwin",
59 "windows" => "Windows_NT",
60 "linux" => "Linux",
61 _ => std::env::consts::OS,
62 };
63
64 let Release = {
65 #[cfg(target_os = "macos")]
66 {
67 std::process::Command::new("sw_vers")
68 .arg("-productVersion")
69 .output()
70 .ok()
71 .map(|O| String::from_utf8_lossy(&O.stdout).trim().to_string())
72 .unwrap_or_else(|| "14.0".to_string())
73 }
74 #[cfg(target_os = "windows")]
75 {
76 std::process::Command::new("cmd")
77 .args(["/c", "ver"])
78 .output()
79 .ok()
80 .map(|O| {
81 let Output = String::from_utf8_lossy(&O.stdout);
82 Output
83 .split('[')
84 .nth(1)
85 .and_then(|S| S.split(']').next())
86 .and_then(|S| S.strip_prefix("Version "))
87 .unwrap_or("10.0.0")
88 .to_string()
89 })
90 .unwrap_or_else(|| "10.0.0".to_string())
91 }
92 #[cfg(target_os = "linux")]
93 {
94 std::process::Command::new("uname")
95 .arg("-r")
96 .output()
97 .ok()
98 .map(|O| String::from_utf8_lossy(&O.stdout).trim().to_string())
99 .unwrap_or_else(|| "6.1.0".to_string())
100 }
101 #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))]
102 {
103 "0.0.0".to_string()
104 }
105 };
106
107 let mut Sys = System::new();
108 Sys.refresh_cpu_all();
109 let Cpus:Vec<Value> = Sys
110 .cpus()
111 .iter()
112 .map(|Cpu| {
113 json!({
114 "model": Cpu.brand(),
115 "speed": Cpu.frequency()
116 })
117 })
118 .collect();
119
120 Ok(json!({
121 "type": OsType,
122 "release": Release,
123 "arch": std::env::consts::ARCH,
124 "platform": std::env::consts::OS,
125 "cpus": Cpus
126 }))
127}
128
129pub async fn handle_native_os_statistics() -> Result<Value, String> {
131 use sysinfo::System;
132
133 let mut Sys = System::new();
134 Sys.refresh_memory();
135
136 let TotalMem = Sys.total_memory();
137 let FreeMem = Sys.available_memory();
138
139 let LoadAvg = {
140 #[cfg(unix)]
141 {
142 let Load = System::load_average();
143 vec![Load.one, Load.five, Load.fifteen]
144 }
145 #[cfg(not(unix))]
146 {
147 vec![0.0, 0.0, 0.0]
148 }
149 };
150
151 Ok(json!({
152 "totalmem": TotalMem,
153 "freemem": FreeMem,
154 "loadavg": LoadAvg
155 }))
156}
157
158pub async fn handle_native_is_fullscreen(AppHandle:AppHandle) -> Result<Value, String> {
160 use tauri::Manager;
161 let Window = AppHandle.get_webview_window("main");
162 if let Some(W) = Window {
163 Ok(json!(W.is_fullscreen().unwrap_or(false)))
164 } else {
165 Ok(json!(false))
166 }
167}
168
169pub async fn handle_native_is_maximized(AppHandle:AppHandle) -> Result<Value, String> {
171 use tauri::Manager;
172 let Window = AppHandle.get_webview_window("main");
173 if let Some(W) = Window {
174 Ok(json!(W.is_maximized().unwrap_or(false)))
175 } else {
176 Ok(json!(false))
177 }
178}
179
180pub async fn handle_native_find_free_port(Args:Vec<Value>) -> Result<Value, String> {
182 let StartPort = Args.get(0).and_then(|V| V.as_u64()).unwrap_or(9000) as u16;
183
184 for Port in StartPort..StartPort + 100 {
185 if std::net::TcpListener::bind(("127.0.0.1", Port)).is_ok() {
186 return Ok(json!(Port));
187 }
188 }
189 Ok(json!(0))
190}
191
192pub async fn handle_native_get_color_scheme() -> Result<Value, String> {
194 let Dark = detect_dark_mode();
195 let HighContrast = {
196 #[cfg(target_os = "windows")]
197 {
198 std::process::Command::new("reg")
199 .args(["query", "HKCU\\Control Panel\\Accessibility\\HighContrast", "/v", "Flags"])
200 .output()
201 .ok()
202 .map(|O| {
203 let Output = String::from_utf8_lossy(&O.stdout);
204 Output.contains("0x1") || Output.contains("REG_DWORD 1")
205 })
206 .unwrap_or(false)
207 }
208 #[cfg(not(target_os = "windows"))]
209 {
210 #[cfg(target_os = "linux")]
211 {
212 std::process::Command::new("gsettings")
213 .args(["get", "org.gnome.desktop.a11y.interface", "high-contrast"])
214 .output()
215 .ok()
216 .map(|O| String::from_utf8_lossy(&O.stdout).trim() == "true")
217 .unwrap_or(false)
218 }
219 #[cfg(not(target_os = "linux"))]
220 {
221 false
222 }
223 }
224 };
225
226 Ok(json!({ "dark": Dark, "highContrast": HighContrast }))
227}
228
229fn detect_dark_mode() -> bool {
231 #[cfg(target_os = "macos")]
232 {
233 std::process::Command::new("defaults")
234 .args(["read", "-g", "AppleInterfaceStyle"])
235 .output()
236 .ok()
237 .map(|O| String::from_utf8_lossy(&O.stdout).trim().to_lowercase().contains("dark"))
238 .unwrap_or(false)
239 }
240
241 #[cfg(target_os = "windows")]
242 {
243 std::process::Command::new("reg")
244 .args([
245 "query",
246 "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
247 "/v",
248 "AppsUseLightTheme",
249 ])
250 .output()
251 .ok()
252 .map(|O| {
253 let Output = String::from_utf8_lossy(&O.stdout);
254 Output.contains("0x0") || Output.contains("REG_DWORD 0")
255 })
256 .unwrap_or(false)
257 }
258
259 #[cfg(target_os = "linux")]
260 {
261 let GtkDark = std::process::Command::new("gsettings")
262 .args(["get", "org.gnome.desktop.interface", "color-scheme"])
263 .output()
264 .ok()
265 .map(|O| String::from_utf8_lossy(&O.stdout).contains("dark"))
266 .unwrap_or(false);
267
268 if GtkDark {
269 return true;
270 }
271
272 let GtkTheme = std::process::Command::new("gsettings")
273 .args(["get", "org.gnome.desktop.interface", "gtk-theme"])
274 .output()
275 .ok()
276 .map(|O| String::from_utf8_lossy(&O.stdout).to_lowercase().contains("dark"))
277 .unwrap_or(false);
278
279 if GtkTheme {
280 return true;
281 }
282
283 let KdeDark = std::env::var("KDE_COLOR_SCHEME")
284 .ok()
285 .map(|V| V.to_lowercase().contains("dark"))
286 .unwrap_or(false);
287
288 if KdeDark {
289 return true;
290 }
291
292 let XfceDark = std::process::Command::new("xfconf-query")
293 .args(["-c", "xsettings", "-p", "/Net/ThemeName"])
294 .output()
295 .ok()
296 .map(|O| String::from_utf8_lossy(&O.stdout).to_lowercase().contains("dark"))
297 .unwrap_or(false);
298
299 XfceDark
300 }
301
302 #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))]
303 {
304 false
305 }
306}