euv-example 0.5.41

An example application demonstrating the euv UI framework with reactive signals, custom components, and WebAssembly.
Documentation
use crate::*;

/// Creates native bridge state signals wrapped in a `UseNativeBridge` struct.
///
/// Initializes all signals with default values and sets `available` to `false`.
/// The actual data is loaded asynchronously via `load_native_bridge_data`.
///
/// # Returns
///
/// - `UseNativeBridge` - The native bridge state.
pub(crate) fn use_native_bridge() -> UseNativeBridge {
    UseNativeBridge::new(
        use_signal(|| false),
        use_signal(|| true),
        use_signal(String::new),
    )
}

/// Checks whether the Tauri native bridge is available on the current platform.
///
/// Looks up `window.__TAURI__.core` via `Reflect` to determine if the
/// Tauri runtime is present. Returns `false` if the property chain does not exist
/// or if any reflection error occurs.
///
/// # Returns
///
/// - `bool` - `true` if the Tauri core module is available.
pub(crate) fn is_tauri_available() -> bool {
    let window_value: Window = window().expect("no global window exists");
    let tauri_key: JsValue = JsValue::from_str("__TAURI__");
    let tauri_obj: JsValue = match Reflect::get(&window_value, &tauri_key) {
        Ok(value) => value,
        Err(_) => return false,
    };
    if tauri_obj.is_undefined() || tauri_obj.is_null() {
        return false;
    }
    let core_key: JsValue = JsValue::from_str("core");
    let core_obj: JsValue = match Reflect::get(&tauri_obj, &core_key) {
        Ok(value) => value,
        Err(_) => return false,
    };
    !core_obj.is_undefined() && !core_obj.is_null()
}

/// Invokes a Tauri core command by name via `window.__TAURI__.core.invoke`.
///
/// Resolves the `__TAURI__` → `core` → `invoke` property chain on the global
/// `window` object, then calls `invoke` with the given command name and
/// optional arguments object. Returns the resulting `Promise`, or an
/// error string if any step in the reflection chain fails.
///
/// # Arguments
///
/// - `&str` - The Tauri command name to invoke.
/// - `Option<&JsValue>` - Optional arguments object to pass to the command.
///
/// # Returns
///
/// - `Result<Promise, String>` - The promise returned by the invoke call, or an error message.
pub(crate) fn tauri_invoke(command: &str, args: Option<&JsValue>) -> Result<Promise, String> {
    let window_value: Window = window().expect("no global window exists");
    let tauri_key: JsValue = JsValue::from_str("__TAURI__");
    let tauri_obj: JsValue =
        Reflect::get(&window_value, &tauri_key).map_err(|error: JsValue| format!("{error:?}"))?;
    let core_key: JsValue = JsValue::from_str("core");
    let core_obj: JsValue =
        Reflect::get(&tauri_obj, &core_key).map_err(|error: JsValue| format!("{error:?}"))?;
    let invoke_key: JsValue = JsValue::from_str("invoke");
    let invoke_fn: JsValue =
        Reflect::get(&core_obj, &invoke_key).map_err(|error: JsValue| format!("{error:?}"))?;
    let invoke_function: Function = invoke_fn
        .dyn_into::<Function>()
        .map_err(|error: JsValue| format!("{error:?}"))?;
    let command_value: JsValue = JsValue::from_str(command);
    let result: JsValue = match args {
        Some(arguments) => invoke_function
            .call2(&core_obj, &command_value, arguments)
            .map_err(|error: JsValue| format!("{error:?}"))?,
        None => invoke_function
            .call1(&core_obj, &command_value)
            .map_err(|error: JsValue| format!("{error:?}"))?,
    };
    result
        .dyn_into::<Promise>()
        .map_err(|error: JsValue| format!("{error:?}"))
}

/// Asynchronously loads native bridge data and updates the provided state signals.
///
/// First checks platform availability via `is_tauri_available`. If unavailable,
/// sets `available` to `false` and returns. Otherwise, invokes the
/// `resolve_bridge_group_permissions` command, then populates the corresponding
/// signal from the result. If the invoke fails, sets `available` to `false`
/// so the card is hidden.
///
/// # Arguments
///
/// - `UseNativeBridge` - The native bridge state to populate.
pub(crate) fn load_native_bridge_data(state: UseNativeBridge) {
    if !is_tauri_available() {
        state.get_available().set(false);
        state.get_loading().set(false);
        return;
    }
    let permissions_state: UseNativeBridge = state;
    spawn_local(async move {
        let args_obj: Object = Object::new();
        Reflect::set(
            &args_obj,
            &JsValue::from_str("group"),
            &JsValue::from_str(TAURI_BRIDGE_GROUP_ALL),
        )
        .unwrap_or(false);
        let permissions_result: Result<JsValue, String> = match tauri_invoke(
            TAURI_INVOKE_RESOLVE_BRIDGE_GROUP_PERMISSIONS,
            Some(&args_obj),
        ) {
            Ok(promise) => {
                let future: JsFuture = JsFuture::from(promise);
                match future.await {
                    Ok(value) => Ok(value),
                    Err(error) => Err(format!("{error:?}")),
                }
            }
            Err(error) => Err(error),
        };
        match permissions_result {
            Ok(value) => {
                let permissions_array: Vec<String> = value
                    .dyn_into::<Array>()
                    .map(|array: Array| {
                        array
                            .iter()
                            .filter_map(|item: JsValue| item.as_string())
                            .collect::<Vec<String>>()
                    })
                    .unwrap_or_default();
                permissions_state
                    .get_permissions()
                    .set(permissions_array.join(", "));
                permissions_state.get_available().set(true);
            }
            Err(_) => {
                permissions_state.get_available().set(false);
            }
        }
        permissions_state.get_loading().set(false);
    });
}