use futures_util::Stream;
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use zbus::zvariant::{
ObjectPath, Optional, Type,
as_value::{self, optional},
};
use crate::{Error, WindowIdentifier, proxy::Proxy};
#[derive(Serialize, Type, Debug, Default)]
#[zvariant(signature = "dict")]
pub struct UpdateOptions {}
#[derive(Deserialize, Type, Debug)]
#[zvariant(signature = "dict")]
#[serde(rename_all = "kebab-case")]
pub struct UpdateInfo {
#[serde(with = "as_value")]
running_commit: String,
#[serde(with = "as_value")]
local_commit: String,
#[serde(with = "as_value")]
remote_commit: String,
}
impl UpdateInfo {
pub fn running_commit(&self) -> &str {
&self.running_commit
}
pub fn local_commit(&self) -> &str {
&self.local_commit
}
pub fn remote_commit(&self) -> &str {
&self.remote_commit
}
}
#[cfg_attr(feature = "glib", derive(glib::Enum))]
#[cfg_attr(feature = "glib", enum_type(name = "AshpdUpdateStatus"))]
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Eq, Copy, Clone, Debug, Type)]
#[repr(u32)]
pub enum UpdateStatus {
#[doc(alias = "XDP_UPDATE_STATUS_RUNNING")]
Running = 0,
#[doc(alias = "XDP_UPDATE_STATUS_EMPTY")]
Empty = 1,
#[doc(alias = "XDP_UPDATE_STATUS_DONE")]
Done = 2,
#[doc(alias = "XDP_UPDATE_STATUS_FAILED")]
Failed = 3,
}
#[derive(Deserialize, Type, Debug)]
#[zvariant(signature = "dict")]
pub struct UpdateProgress {
#[serde(default, with = "optional")]
n_ops: Option<u32>,
#[serde(default, with = "optional")]
op: Option<u32>,
#[serde(default, with = "optional")]
progress: Option<u32>,
#[serde(default, with = "optional")]
status: Option<UpdateStatus>,
#[serde(default, with = "optional")]
error: Option<String>,
#[serde(default, with = "optional")]
error_message: Option<String>,
}
impl UpdateProgress {
pub fn error_message(&self) -> Option<&str> {
self.error_message.as_deref()
}
pub fn error(&self) -> Option<&str> {
self.error.as_deref()
}
pub fn status(&self) -> Option<UpdateStatus> {
self.status
}
pub fn progress(&self) -> Option<u32> {
self.progress
}
pub fn op(&self) -> Option<u32> {
self.op
}
pub fn n_ops(&self) -> Option<u32> {
self.n_ops
}
}
#[derive(Debug)]
#[doc(alias = "org.freedesktop.portal.Flatpak.UpdateMonitor")]
pub struct UpdateMonitor(Proxy<'static>);
impl UpdateMonitor {
pub(crate) async fn with_connection(
connection: zbus::Connection,
path: ObjectPath<'static>,
) -> Result<Self, Error> {
let proxy = Proxy::new_flatpak_with_path(
connection,
"org.freedesktop.portal.Flatpak.UpdateMonitor",
path,
)
.await?;
Ok(Self(proxy))
}
pub fn version(&self) -> u32 {
self.0.version()
}
#[doc(alias = "Progress")]
#[doc(alias = "XdpPortal::update-progress")]
pub async fn receive_progress(&self) -> Result<impl Stream<Item = UpdateProgress>, Error> {
self.0.signal("Progress").await
}
#[doc(alias = "UpdateAvailable")]
#[doc(alias = "XdpPortal::update-available")]
pub async fn receive_update_available(&self) -> Result<impl Stream<Item = UpdateInfo>, Error> {
self.0.signal("UpdateAvailable").await
}
#[doc(alias = "Update")]
#[doc(alias = "xdp_portal_update_install")]
pub async fn update(
&self,
identifier: Option<&WindowIdentifier>,
options: UpdateOptions,
) -> Result<(), Error> {
let identifier = Optional::from(identifier);
self.0.call("Update", &(identifier, options)).await
}
#[doc(alias = "Close")]
pub async fn close(&self) -> Result<(), Error> {
self.0.call("Close", &()).await
}
}
impl std::ops::Deref for UpdateMonitor {
type Target = zbus::Proxy<'static>;
fn deref(&self) -> &Self::Target {
&self.0
}
}