ashpd/flatpak/update_monitor.rs
1//! # Examples
2//!
3//! How to monitor if there's a new update and install it.
4//! Only available for Flatpak applications.
5//!
6//! ```rust,no_run
7//! use ashpd::flatpak::Flatpak;
8//! use futures_util::StreamExt;
9//!
10//! async fn run() -> ashpd::Result<()> {
11//! let proxy = Flatpak::new().await?;
12//!
13//! let monitor = proxy.create_update_monitor().await?;
14//! let info = monitor.receive_update_available().await?;
15//!
16//! monitor.update(None).await?;
17//! let progress = monitor
18//! .receive_progress()
19//! .await?
20//! .next()
21//! .await
22//! .expect("Stream exhausted");
23//! println!("{:#?}", progress);
24//!
25//! Ok(())
26//! }
27//! ```
28
29use futures_util::Stream;
30use serde_repr::{Deserialize_repr, Serialize_repr};
31use zbus::zvariant::{DeserializeDict, ObjectPath, SerializeDict, Type};
32
33use crate::{proxy::Proxy, Error, WindowIdentifier};
34
35#[derive(SerializeDict, Type, Debug, Default)]
36/// Specified options for a [`UpdateMonitor::update`] request.
37///
38/// Currently there are no possible options yet.
39#[zvariant(signature = "dict")]
40struct UpdateOptions {}
41
42#[derive(DeserializeDict, Type, Debug)]
43/// A response containing the update information when an update is available.
44#[zvariant(signature = "dict")]
45pub struct UpdateInfo {
46 #[zvariant(rename = "running-commit")]
47 running_commit: String,
48 #[zvariant(rename = "local-commit")]
49 local_commit: String,
50 #[zvariant(rename = "remote-commit")]
51 remote_commit: String,
52}
53
54impl UpdateInfo {
55 /// The currently running OSTree commit.
56 pub fn running_commit(&self) -> &str {
57 &self.running_commit
58 }
59
60 /// The locally installed OSTree commit.
61 pub fn local_commit(&self) -> &str {
62 &self.local_commit
63 }
64
65 /// The available commit to install.
66 pub fn remote_commit(&self) -> &str {
67 &self.remote_commit
68 }
69}
70
71#[cfg_attr(feature = "glib", derive(glib::Enum))]
72#[cfg_attr(feature = "glib", enum_type(name = "AshpdUpdateStatus"))]
73#[derive(Serialize_repr, Deserialize_repr, PartialEq, Eq, Copy, Clone, Debug, Type)]
74#[repr(u32)]
75/// The update status.
76pub enum UpdateStatus {
77 #[doc(alias = "XDP_UPDATE_STATUS_RUNNING")]
78 /// Running.
79 Running = 0,
80 #[doc(alias = "XDP_UPDATE_STATUS_EMPTY")]
81 /// No update to install.
82 Empty = 1,
83 #[doc(alias = "XDP_UPDATE_STATUS_DONE")]
84 /// Done.
85 Done = 2,
86 #[doc(alias = "XDP_UPDATE_STATUS_FAILED")]
87 /// Failed.
88 Failed = 3,
89}
90
91#[derive(DeserializeDict, Type, Debug)]
92/// A response of the update progress signal.
93#[zvariant(signature = "dict")]
94pub struct UpdateProgress {
95 /// The number of operations that the update consists of.
96 pub n_ops: Option<u32>,
97 /// The position of the currently active operation.
98 pub op: Option<u32>,
99 /// The progress of the currently active operation, as a number between 0
100 /// and 100.
101 pub progress: Option<u32>,
102 /// The overall status of the update.
103 pub status: Option<UpdateStatus>,
104 /// The error name, sent when status is `UpdateStatus::Failed`.
105 pub error: Option<String>,
106 /// The error message, sent when status is `UpdateStatus::Failed`.
107 pub error_message: Option<String>,
108}
109
110/// The interface exposes some interactions with Flatpak on the host to the
111/// sandbox. For example, it allows you to restart the applications or start a
112/// more sandboxed instance.
113///
114/// Wrapper of the DBus interface: [`org.freedesktop.portal.Flatpak.UpdateMonitor`](https://docs.flatpak.org/en/latest/portal-api-reference.html#gdbus-org.freedesktop.portal.Flatpak.UpdateMonitor).
115#[derive(Debug)]
116#[doc(alias = "org.freedesktop.portal.Flatpak.UpdateMonitor")]
117pub struct UpdateMonitor<'a>(Proxy<'a>);
118
119impl<'a> UpdateMonitor<'a> {
120 /// Create a new instance of [`UpdateMonitor`].
121 ///
122 /// **Note** A [`UpdateMonitor`] is not supposed to be created
123 /// manually.
124 pub(crate) async fn new(path: ObjectPath<'a>) -> Result<UpdateMonitor<'a>, Error> {
125 let proxy =
126 Proxy::new_flatpak_with_path("org.freedesktop.portal.Flatpak.UpdateMonitor", path)
127 .await?;
128 Ok(Self(proxy))
129 }
130
131 /// A signal received when there's progress during the application update.
132 ///
133 /// # Specifications
134 ///
135 /// See also [`Progress`](https://docs.flatpak.org/en/latest/portal-api-reference.html#gdbus-signal-org-freedesktop-portal-Flatpak-UpdateMonitor.Progress).
136 #[doc(alias = "Progress")]
137 #[doc(alias = "XdpPortal::update-progress")]
138 pub async fn receive_progress(&self) -> Result<impl Stream<Item = UpdateProgress>, Error> {
139 self.0.signal("Progress").await
140 }
141
142 /// A signal received when there's an application update.
143 ///
144 /// # Specifications
145 ///
146 /// See also [`UpdateAvailable`](https://docs.flatpak.org/en/latest/portal-api-reference.html#gdbus-signal-org-freedesktop-portal-Flatpak-UpdateMonitor.UpdateAvailable).
147 #[doc(alias = "UpdateAvailable")]
148 #[doc(alias = "XdpPortal::update-available")]
149 pub async fn receive_update_available(&self) -> Result<impl Stream<Item = UpdateInfo>, Error> {
150 self.0.signal("UpdateAvailable").await
151 }
152
153 /// Asks to install an update of the calling app.
154 ///
155 /// **Note** updates are only allowed if the new version has the same
156 /// permissions (or less) than the currently installed version.
157 ///
158 /// # Specifications
159 ///
160 /// See also [`Update`](https://docs.flatpak.org/en/latest/portal-api-reference.html#gdbus-method-org-freedesktop-portal-Flatpak-UpdateMonitor.Update).
161 #[doc(alias = "Update")]
162 #[doc(alias = "xdp_portal_update_install")]
163 pub async fn update(&self, identifier: Option<&WindowIdentifier>) -> Result<(), Error> {
164 let options = UpdateOptions::default();
165 let identifier = identifier.map(|i| i.to_string()).unwrap_or_default();
166
167 self.0.call("Update", &(&identifier, options)).await
168 }
169
170 /// Ends the update monitoring and cancels any ongoing installation.
171 ///
172 /// # Specifications
173 ///
174 /// See also [`Close`](https://docs.flatpak.org/en/latest/portal-api-reference.html#gdbus-method-org-freedesktop-portal-Flatpak-UpdateMonitor.Close).
175 #[doc(alias = "Close")]
176 pub async fn close(&self) -> Result<(), Error> {
177 self.0.call("Close", &()).await
178 }
179}
180
181impl<'a> std::ops::Deref for UpdateMonitor<'a> {
182 type Target = zbus::Proxy<'a>;
183
184 fn deref(&self) -> &Self::Target {
185 &self.0
186 }
187}