app_ui/settings_ipc.rs
1//! JS-bridge bindings for the M-SAVE.0 recorder settings — the
2//! persisted output directory + the native folder picker.
3//!
4//! Mirror of [`crate::recording_ipc`]. The `__screenPickOutputDir` /
5//! `__screenGetOutputDir` / `__screenSetOutputDir` helpers in
6//! `index.html` wrap `window.__TAURI__.core.invoke(...)`. Consumed by
7//! the post-record Save panel (M-SAVE.3) and the "Recording folder"
8//! settings row (M-SAVE.4).
9//!
10//! The `extern "C"` block is intentionally **not** `cfg`-gated to
11//! wasm32: `#[wasm_bindgen]` externs compile on native targets too
12//! (they just can't be invoked there), which keeps
13//! `cargo check --workspace` green on the host triple. The wrapper
14//! functions are only ever called from the browser.
15
16use wasm_bindgen::JsValue;
17use wasm_bindgen::prelude::*;
18
19#[wasm_bindgen]
20extern "C" {
21 /// `__screenPickOutputDir()` — opens the native folder dialog.
22 /// `Promise<string | null>` (null on cancel).
23 #[wasm_bindgen(js_name = __screenPickOutputDir, catch)]
24 async fn pick_output_dir_js() -> Result<JsValue, JsValue>;
25
26 /// `__screenGetOutputDir()` — `Promise<string>` returning the
27 /// configured output directory (persisted override or per-OS
28 /// default; never empty).
29 #[wasm_bindgen(js_name = __screenGetOutputDir, catch)]
30 async fn get_output_dir_js() -> Result<JsValue, JsValue>;
31
32 /// `__screenSetOutputDir(dir)` — `Promise<void>`. Persists `dir`
33 /// as the default; empty string clears the override.
34 #[wasm_bindgen(js_name = __screenSetOutputDir, catch)]
35 async fn set_output_dir_js(dir: String) -> Result<JsValue, JsValue>;
36}
37
38/// Open the native folder picker. Returns the chosen absolute path, or
39/// `None` when the user cancelled (or on IPC failure — the caller
40/// treats both the same: keep the current directory).
41pub async fn pick_output_dir() -> Option<String> {
42 match pick_output_dir_js().await {
43 Ok(value) => value.as_string().filter(|s| !s.is_empty()),
44 Err(_) => None,
45 }
46}
47
48/// Read the currently-configured output directory. Returns an empty
49/// string on IPC failure (caller falls back to a placeholder label).
50pub async fn get_output_dir() -> String {
51 match get_output_dir_js().await {
52 Ok(value) => value.as_string().unwrap_or_default(),
53 Err(_) => String::new(),
54 }
55}
56
57/// Persist `dir` as the default output directory. Empty string clears
58/// the override (reverts to the per-OS default).
59///
60/// # Errors
61///
62/// Returns the IPC error string when the persist fails.
63pub async fn set_output_dir(dir: &str) -> Result<(), String> {
64 set_output_dir_js(dir.to_owned())
65 .await
66 .map(|_| ())
67 .map_err(|err| err.as_string().unwrap_or_else(|| format!("{err:?}")))
68}