Fix catalog refresh: handle null fields in AppImageHub feed JSON
The AppImageHub feed.json contains null values where arrays/strings are expected (296 items with null links, 6 items with null inside categories arrays). Changed AppImageHubItem deserialization to use Option types and flatten nulls. Also fixed refresh handler to dynamically look up the catalog source from DB instead of hardcoding id.
This commit is contained in:
@@ -152,17 +152,17 @@ fn fetch_appimage_hub() -> Result<Vec<CatalogApp>, CatalogError> {
|
|||||||
let apps: Vec<CatalogApp> = feed.items.into_iter().filter_map(|item| {
|
let apps: Vec<CatalogApp> = feed.items.into_iter().filter_map(|item| {
|
||||||
// AppImageHub items need at least a name and a link
|
// AppImageHub items need at least a name and a link
|
||||||
let name = item.name?;
|
let name = item.name?;
|
||||||
let download_url = item.links.into_iter()
|
let download_url = item.links.unwrap_or_default().into_iter()
|
||||||
.find(|l| l.r#type == "Download")
|
.find(|l| l.r#type == "Download")
|
||||||
.map(|l| l.url)?;
|
.map(|l| l.url)?;
|
||||||
|
|
||||||
Some(CatalogApp {
|
Some(CatalogApp {
|
||||||
name,
|
name,
|
||||||
description: item.description,
|
description: item.description,
|
||||||
categories: item.categories.unwrap_or_default(),
|
categories: item.categories.unwrap_or_default().into_iter().flatten().collect(),
|
||||||
latest_version: None,
|
latest_version: None,
|
||||||
download_url,
|
download_url,
|
||||||
icon_url: item.icons.and_then(|icons| icons.into_iter().next()),
|
icon_url: item.icons.and_then(|icons| icons.into_iter().flatten().next()),
|
||||||
homepage: item.authors.and_then(|a| {
|
homepage: item.authors.and_then(|a| {
|
||||||
let first = a.into_iter().next()?;
|
let first = a.into_iter().next()?;
|
||||||
if let Some(ref author_name) = first.name {
|
if let Some(ref author_name) = first.name {
|
||||||
@@ -237,10 +237,10 @@ struct AppImageHubFeed {
|
|||||||
struct AppImageHubItem {
|
struct AppImageHubItem {
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
categories: Option<Vec<String>>,
|
categories: Option<Vec<Option<String>>>,
|
||||||
authors: Option<Vec<AppImageHubAuthor>>,
|
authors: Option<Vec<AppImageHubAuthor>>,
|
||||||
links: Vec<AppImageHubLink>,
|
links: Option<Vec<AppImageHubLink>>,
|
||||||
icons: Option<Vec<String>>,
|
icons: Option<Vec<Option<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize)]
|
#[derive(Debug, serde::Deserialize)]
|
||||||
|
|||||||
@@ -175,15 +175,14 @@ pub fn build_catalog_page(db: &Rc<Database>) -> adw::NavigationPage {
|
|||||||
let db_bg = Database::open().ok();
|
let db_bg = Database::open().ok();
|
||||||
let result = gio::spawn_blocking(move || {
|
let result = gio::spawn_blocking(move || {
|
||||||
if let Some(ref db) = db_bg {
|
if let Some(ref db) = db_bg {
|
||||||
catalog::sync_catalog(db, &catalog::CatalogSource {
|
catalog::ensure_default_sources(db);
|
||||||
id: Some(1),
|
let sources = catalog::get_sources(db);
|
||||||
name: "AppImageHub".to_string(),
|
if let Some(source) = sources.first() {
|
||||||
url: "https://appimage.github.io/feed.json".to_string(),
|
catalog::sync_catalog(db, source)
|
||||||
source_type: catalog::CatalogType::AppImageHub,
|
.map_err(|e| e.to_string())
|
||||||
enabled: true,
|
} else {
|
||||||
last_synced: None,
|
Err("No catalog sources configured".to_string())
|
||||||
app_count: 0,
|
}
|
||||||
}).map_err(|e| e.to_string())
|
|
||||||
} else {
|
} else {
|
||||||
Err("Failed to open database".to_string())
|
Err("Failed to open database".to_string())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user