Skip to main content

DevelopmentNodeEnvironment_MicrosoftVSCodeDependency_22NodeVersion_Bundle_Clean_Debug_ElectronProfile_EsbuildCompiler_Mountain/IPC/WindServiceHandlers/NativeHost/
ShowSaveDialog.rs

1#![allow(non_snake_case, unused_variables, dead_code, unused_imports)]
2
3//! Wire methods: `nativeHost:showSaveDialog`, `UserInterface.ShowSaveDialog`.
4//!
5//! Both surface a blocking save-file dialog via `tauri_plugin_dialog`. The
6//! difference is in the return shape:
7//!   - `nativeHost:showSaveDialog` → `{ canceled: bool, filePath?: string }`
8//!   - `UserInterface.ShowSaveDialog` → bare path string (or null) so Wind's
9//!     `typeof Result === "string"` guard finds a string value directly.
10
11use serde_json::{Value, json};
12use tauri::AppHandle;
13use tauri_plugin_dialog::DialogExt;
14
15/// `nativeHost:showSaveDialog` - returns `{ canceled, filePath }`.
16pub async fn NativeShowSaveDialog(ApplicationHandle:AppHandle, Arguments:Vec<Value>) -> Result<Value, String> {
17	let Options = Arguments.first().cloned().unwrap_or(Value::Null);
18	let Title = Options.get("title").and_then(Value::as_str).unwrap_or("Save").to_string();
19	let DefaultPath = Options.get("defaultPath").and_then(Value::as_str).map(str::to_string);
20	let Handle = ApplicationHandle.clone();
21	let Joined = tokio::task::spawn_blocking(move || -> Option<String> {
22		let mut Builder = Handle.dialog().file().set_title(&Title);
23		if let Some(Path) = DefaultPath.as_deref() {
24			Builder = Builder.set_directory(Path);
25		}
26		Builder.blocking_save_file().map(|P| P.to_string())
27	})
28	.await;
29	match Joined {
30		Ok(Some(Path)) => Ok(json!({ "canceled": false, "filePath": Path })),
31		Ok(None) => Ok(json!({ "canceled": true })),
32		Err(Error) => Err(format!("showSaveDialog join error: {}", Error)),
33	}
34}
35
36/// `UserInterface.ShowSaveDialog` - returns bare path string or null.
37/// Wind's `Files/Live.ts` calls this and checks `typeof Result === "string"`.
38pub async fn UserInterfaceShowSaveDialog(ApplicationHandle:AppHandle, Arguments:Vec<Value>) -> Result<Value, String> {
39	let Options = Arguments.first().cloned().unwrap_or(Value::Null);
40	let Title = Options.get("title").and_then(Value::as_str).unwrap_or("Save").to_string();
41	let DefaultPath = Options.get("defaultPath").and_then(Value::as_str).map(str::to_string);
42	let Handle = ApplicationHandle.clone();
43	let Joined = tokio::task::spawn_blocking(move || -> Option<String> {
44		let mut Builder = Handle.dialog().file().set_title(&Title);
45		if let Some(Path) = DefaultPath.as_deref() {
46			Builder = Builder.set_directory(Path);
47		}
48		Builder.blocking_save_file().map(|P| P.to_string())
49	})
50	.await;
51	match Joined {
52		Ok(Some(Path)) => Ok(json!(Path)),
53		Ok(None) => Ok(Value::Null),
54		Err(Error) => Err(format!("UserInterface.ShowSaveDialog join error: {}", Error)),
55	}
56}