use lingxia_service::update::{
AppUpdateApply, AppUpdateEvent, AppUpdateStage, HostAppUpdateService, UpdatePackageInfo,
UpdateUiMode, configure_update, update_config,
};
use std::fmt;
use std::path::Path;
pub use lingxia_service::update::HostAppInstall;
pub fn use_custom_host_app_update() {
let mut config = update_config();
config.ui_mode = UpdateUiMode::Custom;
config.auto_check_app = false;
configure_update(config);
}
pub fn set_host_app_installer(
installer: impl Fn(&Path) -> crate::Result<HostAppInstall> + Send + Sync + 'static,
) {
lingxia_service::update::set_host_app_installer(move |path| {
installer(path).map_err(|error| lingxia_update::UpdateError::runtime(error.to_string()))
});
}
pub struct HostAppUpdate {
info: UpdatePackageInfo,
service: HostAppUpdateService,
}
impl HostAppUpdate {
fn new(info: UpdatePackageInfo, service: HostAppUpdateService) -> Self {
Self { info, service }
}
pub fn info(&self) -> HostAppUpdateInfo<'_> {
HostAppUpdateInfo { inner: &self.info }
}
pub fn apply(self) -> HostAppUpdateApply {
HostAppUpdateApply {
inner: self.service.apply(self.info),
}
}
}
#[derive(Clone, Copy)]
pub struct HostAppUpdateInfo<'a> {
inner: &'a UpdatePackageInfo,
}
impl HostAppUpdateInfo<'_> {
pub fn version(&self) -> &str {
&self.inner.version
}
pub fn package_size_bytes(&self) -> Option<u64> {
self.inner.size
}
pub fn release_notes(&self) -> Option<&[String]> {
self.inner.release_notes.as_deref()
}
pub fn is_force_update(&self) -> bool {
self.inner.is_force_update
}
}
impl fmt::Debug for HostAppUpdateInfo<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("HostAppUpdateInfo")
.field("version", &self.version())
.field("package_size_bytes", &self.package_size_bytes())
.field("release_notes", &self.release_notes())
.field("is_force_update", &self.is_force_update())
.finish()
}
}
pub struct HostAppUpdateApply {
inner: AppUpdateApply,
}
impl HostAppUpdateApply {
pub async fn next(&mut self) -> Option<HostAppUpdateEvent> {
while let Some(event) = self.inner.next().await {
if let Some(event) = HostAppUpdateEvent::from_service_event(event) {
return Some(event);
}
}
None
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum HostAppUpdateEvent {
Downloading {
downloaded_bytes: u64,
progress: Option<u8>,
},
Downloaded,
InstallRequested,
Failed {
stage: HostAppUpdateStage,
error: String,
},
}
impl HostAppUpdateEvent {
fn from_service_event(event: AppUpdateEvent) -> Option<Self> {
match event {
AppUpdateEvent::Available(_) => None,
AppUpdateEvent::DownloadStarted { .. } => Some(Self::Downloading {
downloaded_bytes: 0,
progress: None,
}),
AppUpdateEvent::DownloadProgress {
downloaded_bytes,
progress,
..
} => Some(Self::Downloading {
downloaded_bytes,
progress,
}),
AppUpdateEvent::Downloaded { .. } => Some(Self::Downloaded),
AppUpdateEvent::InstallRequested { .. } => Some(Self::InstallRequested),
AppUpdateEvent::Failed { stage, error } => Some(Self::Failed {
stage: stage.into(),
error,
}),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HostAppUpdateStage {
Check,
Prompt,
Download,
Install,
}
impl From<AppUpdateStage> for HostAppUpdateStage {
fn from(stage: AppUpdateStage) -> Self {
match stage {
AppUpdateStage::Check => Self::Check,
AppUpdateStage::Prompt => Self::Prompt,
AppUpdateStage::Download => Self::Download,
AppUpdateStage::Install => Self::Install,
}
}
}
pub async fn check_host_app_update() -> crate::Result<Option<HostAppUpdate>> {
let service = host_update_service()?;
let Some(info) = service.check().await? else {
return Ok(None);
};
Ok(Some(HostAppUpdate::new(info, service)))
}
pub(crate) fn spawn_host_app_update_flow(runtime: std::sync::Arc<lingxia_platform::Platform>) {
host_update_service_from(runtime).spawn_builtin_flow();
}
fn host_update_service() -> crate::Result<HostAppUpdateService> {
let runtime = lxapp::get_platform()
.ok_or_else(|| crate::Error::internal("platform is not initialized"))?;
Ok(host_update_service_from(runtime))
}
fn host_update_service_from(
runtime: std::sync::Arc<lingxia_platform::Platform>,
) -> HostAppUpdateService {
HostAppUpdateService::new(runtime, lxapp::provider::update_provider())
}