feat(appd): add version field to AppInfo; surface it in launcher tile tooltip

WappPackage and AppInfo both gain a version field. scan_installed_apps()
reads it from wapp.toml and includes it in InstalledApps responses.
system-ui.html shows it in the title tooltip as 'com.example.app v1.0.0'.
All roundtrip and integration tests updated.
This commit is contained in:
Marco Allegretti 2026-03-11 13:15:09 +01:00
parent 7a2014027a
commit 5d7c0bdf79
3 changed files with 9 additions and 1 deletions

View file

@ -21,6 +21,7 @@ pub struct SessionInfo {
pub struct AppInfo { pub struct AppInfo {
pub app_id: String, pub app_id: String,
pub name: String, pub name: String,
pub version: String,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@ -142,11 +143,13 @@ mod tests {
let info = super::AppInfo { let info = super::AppInfo {
app_id: "com.example.app".into(), app_id: "com.example.app".into(),
name: "Example App".into(), name: "Example App".into(),
version: "1.2.3".into(),
}; };
let bytes = rmp_serde::to_vec(&info).unwrap(); let bytes = rmp_serde::to_vec(&info).unwrap();
let decoded: super::AppInfo = rmp_serde::from_slice(&bytes).unwrap(); let decoded: super::AppInfo = rmp_serde::from_slice(&bytes).unwrap();
assert_eq!(decoded.app_id, "com.example.app"); assert_eq!(decoded.app_id, "com.example.app");
assert_eq!(decoded.name, "Example App"); assert_eq!(decoded.name, "Example App");
assert_eq!(decoded.version, "1.2.3");
} }
#[test] #[test]
@ -163,6 +166,7 @@ mod tests {
apps: vec![super::AppInfo { apps: vec![super::AppInfo {
app_id: "com.example.app".into(), app_id: "com.example.app".into(),
name: "Example App".into(), name: "Example App".into(),
version: "0.9.0".into(),
}], }],
}; };
let bytes = rmp_serde::to_vec(&resp).unwrap(); let bytes = rmp_serde::to_vec(&resp).unwrap();
@ -172,6 +176,7 @@ mod tests {
assert_eq!(apps.len(), 1); assert_eq!(apps.len(), 1);
assert_eq!(apps[0].app_id, "com.example.app"); assert_eq!(apps[0].app_id, "com.example.app");
assert_eq!(apps[0].name, "Example App"); assert_eq!(apps[0].name, "Example App");
assert_eq!(apps[0].version, "0.9.0");
} }
_ => panic!("wrong variant"), _ => panic!("wrong variant"),
} }

View file

@ -292,6 +292,7 @@ fn app_store_roots() -> Vec<std::path::PathBuf> {
struct WappPackage { struct WappPackage {
id: String, id: String,
name: String, name: String,
version: String,
} }
#[derive(serde::Deserialize)] #[derive(serde::Deserialize)]
@ -318,6 +319,7 @@ fn scan_installed_apps() -> Vec<AppInfo> {
apps.push(AppInfo { apps.push(AppInfo {
app_id: m.package.id, app_id: m.package.id,
name: m.package.name, name: m.package.name,
version: m.package.version,
}); });
} }
} }
@ -615,6 +617,7 @@ mod tests {
assert_eq!(apps.len(), 1); assert_eq!(apps.len(), 1);
assert_eq!(apps[0].app_id, "com.example.scanner"); assert_eq!(apps[0].app_id, "com.example.scanner");
assert_eq!(apps[0].name, "Scanner"); assert_eq!(apps[0].name, "Scanner");
assert_eq!(apps[0].version, "1.0.0");
unsafe { unsafe {
match prior { match prior {

View file

@ -319,7 +319,7 @@
apps.forEach(function (app) { apps.forEach(function (app) {
var icon = document.createElement('weft-app-icon'); var icon = document.createElement('weft-app-icon');
icon.dataset.appId = app.app_id; icon.dataset.appId = app.app_id;
icon.title = app.app_id; icon.title = app.app_id + (app.version ? ' v' + app.version : '');
icon.innerHTML = icon.innerHTML =
'<svg width="40" height="40" viewBox="0 0 40 40" fill="none"' + '<svg width="40" height="40" viewBox="0 0 40 40" fill="none"' +
' xmlns="http://www.w3.org/2000/svg" aria-hidden="true">' + ' xmlns="http://www.w3.org/2000/svg" aria-hidden="true">' +