Add GitHub metadata enrichment for catalog apps

Enrich catalog apps with GitHub API data (stars, version, downloads,
release date) via two strategies: background drip for repo-level info
and on-demand fetch when opening a detail page.

- Add github_enrichment module with API calls, asset filtering, and
  architecture auto-detection for AppImage downloads
- DB migrations v14/v15 for GitHub metadata and release asset columns
- Extract github_owner/repo from feed links during catalog sync
- Display colored stat cards (stars, version, downloads, released) on
  detail pages with on-demand enrichment
- Show stars and version on browse tiles and featured carousel cards
- Replace install button with SplitButton dropdown when multiple arch
  assets available, preferring detected architecture
- Disable install button until enrichment completes to prevent stale
  AppImageHub URL downloads
- Keep enrichment banner visible on catalog page until truly complete,
  showing paused state when rate-limited
- Add GitHub token and auto-enrich toggle to preferences
This commit is contained in:
lashman
2026-02-28 16:49:13 +02:00
parent 92c51dc39e
commit f89aafca6a
15 changed files with 3027 additions and 224 deletions

View File

@@ -142,5 +142,15 @@
<summary>Watch removable media</summary>
<description>Scan removable drives for AppImages when mounted.</description>
</key>
<key name="github-token" type="s">
<default>''</default>
<summary>GitHub personal access token</summary>
<description>Optional GitHub token for higher API rate limits (5,000 vs 60 requests per hour).</description>
</key>
<key name="catalog-auto-enrich" type="b">
<default>true</default>
<summary>Auto-enrich catalog apps</summary>
<description>Automatically fetch GitHub metadata (stars, version, downloads) for catalog apps in the background.</description>
</key>
</schema>
</schemalist>

View File

@@ -175,6 +175,53 @@ button.flat:not(.pill):not(.suggested-action):not(.destructive-action) {
min-height: 24px;
}
/* ===== Catalog Tile Cards ===== */
.catalog-tile {
border: 1px solid alpha(@window_fg_color, 0.12);
border-radius: 12px;
}
.catalog-tile:hover {
border-color: alpha(@accent_bg_color, 0.5);
}
/* ===== Featured Banner Cards ===== */
.catalog-featured-card {
border-radius: 12px;
border: 1px solid alpha(@window_fg_color, 0.15);
padding: 0;
}
.catalog-featured-card:hover {
border-color: alpha(@accent_bg_color, 0.5);
}
/* Screenshot area inside featured card */
.catalog-featured-screenshot {
border-radius: 11px 11px 0 0;
border: none;
background: alpha(@window_fg_color, 0.04);
}
.catalog-featured-screenshot picture {
border-radius: 11px 11px 0 0;
}
/* ===== Destructive Context Menu Item ===== */
.destructive-context-item {
color: @error_fg_color;
background: alpha(@error_bg_color, 0.85);
border: none;
box-shadow: none;
padding: 6px 12px;
border-radius: 6px;
min-height: 28px;
}
.destructive-context-item:hover {
background: @error_bg_color;
}
/* ===== Screenshot Lightbox ===== */
window.lightbox {
background-color: rgba(0, 0, 0, 0.92);
@@ -193,3 +240,75 @@ window.lightbox .lightbox-nav {
min-width: 48px;
min-height: 48px;
}
/* ===== Catalog Tile Stats Row ===== */
.catalog-stats-row {
font-size: 0.8em;
color: alpha(@window_fg_color, 0.7);
}
.catalog-stats-row image {
opacity: 0.65;
}
/* ===== Detail Page Stat Cards ===== */
.stat-card {
background: alpha(@window_fg_color, 0.06);
border-radius: 12px;
padding: 14px 16px;
border: 1px solid alpha(@window_fg_color, 0.08);
}
.stat-card.stat-stars {
background: alpha(@warning_bg_color, 0.12);
border-color: alpha(@warning_bg_color, 0.2);
}
.stat-card.stat-stars image {
color: @warning_bg_color;
opacity: 0.85;
}
.stat-card.stat-version {
background: alpha(@accent_bg_color, 0.1);
border-color: alpha(@accent_bg_color, 0.18);
}
.stat-card.stat-version image {
color: @accent_bg_color;
opacity: 0.85;
}
.stat-card.stat-downloads {
background: alpha(@success_bg_color, 0.1);
border-color: alpha(@success_bg_color, 0.18);
}
.stat-card.stat-downloads image {
color: @success_bg_color;
opacity: 0.85;
}
.stat-card.stat-released {
background: alpha(@purple_3, 0.12);
border-color: alpha(@purple_3, 0.2);
}
.stat-card.stat-released image {
color: @purple_3;
opacity: 0.85;
}
.stat-card .stat-value {
font-weight: 700;
font-size: 1.15em;
}
.stat-card .stat-label {
font-size: 0.8em;
color: alpha(@window_fg_color, 0.6);
}
.stat-card image {
opacity: 0.55;
}