Add comprehensive AppImage metadata extraction, display, and bug fixes

- Add AppStream XML parser (quick-xml) to extract rich metadata from bundled
  metainfo/appdata files: description, developer, license, URLs, keywords,
  categories, content rating, release history, and MIME types
- Database migration v9: 16 new columns for extended metadata storage
- Extended inspector to parse AppStream XML, desktop entry extended fields,
  and detect binary signatures without executing AppImages
- Redesigned detail view overview tab with 8 conditional groups: About,
  Description, Links, Release History, Usage, Capabilities, File Info
- Fix crash on exit caused by stale GLib SourceId removal in debounce timers
- Fix wayland.rs executing AppImages directly to detect squashfs offset,
  replaced with safe binary scan via find_squashfs_offset_for()
- Fix scan skipping re-analysis of apps missing new metadata fields
This commit is contained in:
lashman
2026-02-27 18:31:07 +02:00
parent 39b773fed5
commit 1bb7a3bdc0
13 changed files with 1239 additions and 24 deletions

View File

@@ -61,7 +61,7 @@ pub fn run_background_analysis(id: i64, path: PathBuf, appimage_type: AppImageTy
log::warn!("Failed to set analysis status to 'analyzing' for id {}: {}", id, e);
}
// Inspect metadata (app name, version, icon, desktop entry, etc.)
// Inspect metadata (app name, version, icon, desktop entry, AppStream, etc.)
if let Ok(meta) = inspector::inspect_appimage(&path, &appimage_type) {
let categories = if meta.categories.is_empty() {
None
@@ -84,6 +84,61 @@ pub fn run_background_analysis(id: i64, path: PathBuf, appimage_type: AppImageTy
) {
log::warn!("Failed to update metadata for id {}: {}", id, e);
}
// Store extended metadata from AppStream XML and desktop entry
let keywords = if meta.keywords.is_empty() {
None
} else {
Some(meta.keywords.join(","))
};
let mime_types = if meta.mime_types.is_empty() {
None
} else {
Some(meta.mime_types.join(";"))
};
let release_json = if meta.releases.is_empty() {
None
} else {
let releases: Vec<serde_json::Value> = meta
.releases
.iter()
.map(|r| {
serde_json::json!({
"version": r.version,
"date": r.date,
"description": r.description,
})
})
.collect();
Some(serde_json::to_string(&releases).unwrap_or_default())
};
let actions_json = if meta.desktop_actions.is_empty() {
None
} else {
Some(serde_json::to_string(&meta.desktop_actions).unwrap_or_default())
};
if let Err(e) = db.update_appstream_metadata(
id,
meta.appstream_id.as_deref(),
meta.appstream_description.as_deref(),
meta.generic_name.as_deref(),
meta.license.as_deref(),
meta.homepage_url.as_deref(),
meta.bugtracker_url.as_deref(),
meta.donation_url.as_deref(),
meta.help_url.as_deref(),
meta.vcs_url.as_deref(),
keywords.as_deref(),
mime_types.as_deref(),
meta.content_rating.as_deref(),
meta.project_group.as_deref(),
release_json.as_deref(),
actions_json.as_deref(),
meta.has_signature,
) {
log::warn!("Failed to update appstream metadata for id {}: {}", id, e);
}
}
// FUSE status