From a636f3a36e6bca52e871b31b6cf93120479c2af5 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Tue, 11 Aug 2026 15:06:55 +0200 Subject: [PATCH] UI only needs concrete client/source info --- deltachat-jsonrpc/src/api.rs | 18 +++++++--- .../src/api/types/appversions.rs | 36 +++++-------------- src/appversions.rs | 36 +++++++++++-------- 3 files changed, 42 insertions(+), 48 deletions(-) diff --git a/deltachat-jsonrpc/src/api.rs b/deltachat-jsonrpc/src/api.rs index 869791880..1f187c852 100644 --- a/deltachat-jsonrpc/src/api.rs +++ b/deltachat-jsonrpc/src/api.rs @@ -64,7 +64,7 @@ use self::types::{ JsonrpcMessageListItem, MessageNotificationInfo, MessageSearchResult, MessageViewtype, }, }; -use crate::api::types::appversions::JsonrpcAppVersionInfo; +use crate::api::types::appversions::JsonrpcAppSource; use crate::api::types::chat_list::{ChatListItemFetchResult, get_chat_list_item_by_id}; use crate::api::types::login_param::TransportListEntry; use crate::api::types::qr::{QrObject, SecurejoinSource, SecurejoinUiPath}; @@ -2791,11 +2791,19 @@ impl CommandApi { } } - /// Get version information of clients. - async fn get_app_versions(&self, account_id: u32) -> Result { + /// Get version information of a specific client and source. + async fn get_app_version( + &self, + account_id: u32, + client_id: String, + source_id: String, + ) -> Result> { let ctx = self.get_context(account_id).await?; - let info = deltachat::appversions::get_app_versions(&ctx).await?; - JsonrpcAppVersionInfo::from_core_type(info) + Ok( + deltachat::appversions::get_app_version(&ctx, &client_id, &source_id) + .await? + .map(|s| JsonrpcAppSource::from_core_type(s)), + ) } } diff --git a/deltachat-jsonrpc/src/api/types/appversions.rs b/deltachat-jsonrpc/src/api/types/appversions.rs index 18aa892c9..8ab45418c 100644 --- a/deltachat-jsonrpc/src/api/types/appversions.rs +++ b/deltachat-jsonrpc/src/api/types/appversions.rs @@ -1,34 +1,11 @@ -use anyhow::Result; -use deltachat::appversions::AppVersionInfo; +use deltachat::appversions::AppSource; use serde::{Deserialize, Serialize}; use typescript_type_def::TypeDef; -/// Version information of clients. -#[derive(Serialize, Deserialize, TypeDef, schemars::JsonSchema)] -#[serde(rename = "AppVersionInfo", rename_all = "camelCase")] -pub struct JsonrpcAppVersionInfo { - /// Array of clients with version information. - pub clients: Vec, -} - -/// Version information of a single client, eg. "deltachat" or "ubuntutouch". -#[derive(Serialize, Deserialize, TypeDef, schemars::JsonSchema)] -#[serde(rename = "AppClient", rename_all = "camelCase")] -pub struct JsonrpcAppClient { - /// ID how the client identifies itself, eg. "deltachat" or "ubuntutouch". - pub client_id: String, - - /// Array of sources for that client. - pub sources: Vec, -} - /// Version information of a single source of a client, eg. "gplay" or "fdroid". #[derive(Serialize, Deserialize, TypeDef, schemars::JsonSchema)] #[serde(rename = "AppSource", rename_all = "camelCase")] pub struct JsonrpcAppSource { - /// ID how the client identifies a source, eg. "gplay" or "fdroid". - pub app_id: String, - /// Always increasing version number. pub version_integer: u32, @@ -39,9 +16,12 @@ pub struct JsonrpcAppSource { pub download_url: String, } -impl JsonrpcAppVersionInfo { - pub fn from_core_type(info: AppVersionInfo) -> Result { - let value = serde_json::to_value(info)?; - Ok(serde_json::from_value(value)?) +impl JsonrpcAppSource { + pub fn from_core_type(source: AppSource) -> Self { + JsonrpcAppSource { + version_integer: source.version_integer, + version_string: source.version_string, + download_url: source.download_url, + } } } diff --git a/src/appversions.rs b/src/appversions.rs index eaa1bec06..32f40e01d 100644 --- a/src/appversions.rs +++ b/src/appversions.rs @@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize}; /// Version information of clients as used on the wire. #[derive(Debug, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase", default)] -pub struct AppVersionInfo { +struct AppVersionInfo { /// Array clients with version information. clients: Vec, } @@ -18,7 +18,7 @@ pub struct AppVersionInfo { /// Version infomation of a single client, eg. "deltachat" or "ubuntutouch". #[derive(Debug, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase", default)] -pub struct AppClient { +struct AppClient { /// ID how the client identifies itself, eg. "deltachat" or "ubuntutouch" client_id: String, @@ -34,29 +34,35 @@ pub struct AppSource { app_id: String, /// Always increasing version number. - version_integer: u32, + pub version_integer: u32, /// Any version string. - version_string: String, + pub version_string: String, /// Where to download that version. - download_url: String, + pub download_url: String, } -/// Get version information of clients. +/// Get version information of a specific client and source. /// -/// If no version information are available, `clients` is set to an empty array. -/// -/// The information is coming from the relay via IMAP METADATA and is not cached. -/// A call to `get_app_versions()` is cheap and does not involve network or database calls. -pub async fn get_app_versions(context: &Context) -> Result { +/// If no matching version information are available, `None` is returned. +pub async fn get_app_version( + context: &Context, + client_id: &str, + source_id: &str, +) -> Result> { if let Some(metadata) = context.metadata.read().await.values().next() && let Some(json) = &metadata.app_versions { let app_versions: AppVersionInfo = serde_json::from_str(json)?; - return Ok(app_versions); + let app_version = app_versions + .clients + .into_iter() + .find(|c| c.client_id == client_id) + .and_then(|c| c.sources.into_iter().find(|s| s.app_id == source_id)); + return Ok(app_version); } - Ok(AppVersionInfo::default()) + Ok(None) } #[cfg(test)] @@ -126,8 +132,8 @@ mod tests { let mut tcm = TestContextManager::new(); let alice = &tcm.alice().await; - let versions = get_app_versions(alice).await?; - assert!(versions.clients.is_empty()); + let version = get_app_version(alice, "deltachat", "gplay").await?; + assert!(version.is_none()); Ok(()) }