Add similar app recommendations from shared categories

This commit is contained in:
lashman
2026-02-28 00:17:55 +02:00
parent 2108b0f3d8
commit 2704ebb316
2 changed files with 77 additions and 0 deletions

View File

@@ -1869,6 +1869,51 @@ impl Database {
)
}
// --- Similar apps ---
/// Find AppImages from the user's library that share categories with the given app.
pub fn find_similar_apps(
&self,
categories: &str,
exclude_id: i64,
limit: i32,
) -> SqlResult<Vec<(i64, String, Option<String>)>> {
// Split categories and match any overlap
let cats: Vec<&str> = categories.split(';').filter(|s| !s.is_empty()).collect();
if cats.is_empty() {
return Ok(Vec::new());
}
// Build LIKE conditions for each category
let conditions: Vec<String> = cats.iter()
.map(|c| format!("categories LIKE '%{}%'", c.replace('\'', "''")))
.collect();
let where_clause = conditions.join(" OR ");
let sql = format!(
"SELECT id, COALESCE(app_name, filename) AS name, icon_path
FROM appimages
WHERE id != ?1 AND ({})
LIMIT ?2",
where_clause
);
let mut stmt = self.conn.prepare(&sql)?;
let rows = stmt.query_map(params![exclude_id, limit], |row| {
Ok((
row.get::<_, i64>(0)?,
row.get::<_, String>(1)?,
row.get::<_, Option<String>>(2)?,
))
})?;
let mut results = Vec::new();
for row in rows {
results.push(row?);
}
Ok(results)
}
// --- System modification tracking ---
pub fn register_modification(

View File

@@ -868,6 +868,38 @@ fn build_overview_tab(record: &AppImageRecord, db: &Rc<Database>) -> gtk::Box {
}
inner.append(&info_group);
// "You might also like" - similar apps from the user's library
if let Some(ref cats) = record.categories {
if let Ok(similar) = db.find_similar_apps(cats, record.id, 4) {
if !similar.is_empty() {
let similar_group = adw::PreferencesGroup::builder()
.title("You might also like")
.build();
for (id, name, icon_path) in &similar {
let row = adw::ActionRow::builder()
.title(name.as_str())
.activatable(true)
.build();
let icon = widgets::app_icon(
icon_path.as_deref(),
name,
32,
);
row.add_prefix(&icon);
// Store the record ID in the widget name for navigation
row.set_widget_name(&format!("similar-{}", id));
similar_group.add(&row);
}
inner.append(&similar_group);
}
}
}
clamp.set_child(Some(&inner));
tab.append(&clamp);
tab