lingxia-lxapp 0.5.0

LxApp (lightweight application) container and runtime for LingXia framework
use super::{await_or_cancel, parse_release_type};
use crate::LxApp;
use crate::lxapp::ReleaseType;
use crate::startup::LxAppStartupOptions;
use crate::{LxAppError, UpdateManager};
use serde::Deserialize;
use std::sync::Arc;

#[derive(Deserialize)]
struct NavigateToLxAppOptions {
    #[serde(rename = "appId")]
    appid: String,
    path: Option<String>,
    #[serde(rename = "envVersion")]
    env_version: Option<String>,
    #[serde(rename = "targetVersion")]
    target_version: Option<String>,
}

fn build_startup_options(options: &NavigateToLxAppOptions) -> (LxAppStartupOptions, ReleaseType) {
    let path = options.path.as_deref().unwrap_or("");
    let mut startup_options = LxAppStartupOptions::new(path);

    let release_type = parse_release_type(options.env_version.as_deref());

    if options.env_version.is_some() {
        startup_options = startup_options.set_release_type(release_type);
    }

    (startup_options, release_type)
}

fn should_navigate_to_lxapp(
    lxapp: &LxApp,
    options: &NavigateToLxAppOptions,
) -> Result<bool, LxAppError> {
    if options.appid.is_empty() {
        return Err(LxAppError::InvalidParameter(
            "navigateToLxApp requires appId".to_string(),
        ));
    }

    if lxapp.appid == options.appid {
        return Ok(false);
    }

    Ok(true)
}

async fn do_navigate_to_lxapp(
    lxapp: Arc<LxApp>,
    options: NavigateToLxAppOptions,
    cancel: &mut super::HostCancel,
) -> Result<(), LxAppError> {
    let (startup_options, release_type) = build_startup_options(&options);
    let target_appid = options.appid.clone();
    let target_version = options
        .target_version
        .as_deref()
        .map(str::trim)
        .filter(|v| !v.is_empty());

    if let Some(target_version) = target_version {
        await_or_cancel(
            cancel,
            crate::update::ensure_target_version_ready(
                &lxapp,
                &target_appid,
                release_type,
                target_version,
            ),
        )
        .await?;
    } else {
        await_or_cancel(
            cancel,
            crate::update::ensure_first_install(&lxapp, &target_appid, release_type),
        )
        .await?;
        await_or_cancel(
            cancel,
            crate::update::ensure_force_update_for_installed(&lxapp, &target_appid, release_type),
        )
        .await?;
    }

    lxapp.navigate_to(target_appid.clone(), startup_options)?;

    UpdateManager::spawn_release_lxapp_update_check(target_appid);
    Ok(())
}

host_api_async!(
    NavigateToLxApp,
    NavigateToLxAppOptions,
    (),
    |lxapp, options, cancel| async {
        if !should_navigate_to_lxapp(&lxapp, &options)? {
            return Ok(());
        }
        do_navigate_to_lxapp(lxapp, options, &mut cancel).await?;
        Ok(())
    }
);

host_api!(NavigateBackLxApp, (), |lxapp| {
    lxapp.navigate_back()?;
    Ok(())
});

pub(crate) fn register_all() {
    register_host_module!("navigator", {
        "navigateToLxApp" => Arc::new(NavigateToLxApp),
        "navigateBackLxApp" => Arc::new(NavigateBackLxApp)
    });
}