feat: card design improvements
Some checks failed
CI / Rustfmt (push) Failing after 4m51s
CI / Flatpak (push) Failing after 6m36s

This commit is contained in:
Tine Jozelj 2024-01-11 21:36:44 +01:00
parent 6240c59e24
commit 2f09f3b093
Signed by: mentos1386
SSH key fingerprint: SHA256:MNtTsLbihYaWF8j1fkOHfkKNlnN1JQfxEU/rBU8nCGw
5 changed files with 82 additions and 25 deletions

View file

@ -11,13 +11,20 @@ template $Card: Box {
Box contents { Box contents {
orientation: vertical; orientation: vertical;
margin-start: 12;
margin-end: 12;
margin-top: 12;
margin-bottom: 12;
Label heading { Label heading {
styles ["heading"] styles ["heading"]
} }
Label body { Label body {
vexpand: true;
styles ["body"] styles ["body"]
} }
Box footer {}
} }
} }

View file

@ -37,24 +37,29 @@ template $GamesAndMods: Adw.Bin {
} }
} }
content: Adw.Clamp { content: Box {
orientation: vertical; orientation: vertical;
Label title { Label title {
label: "Mods"; label: "List of Mods";
styles ["title-1"] styles ["title-1"]
} }
Adw.Carousel { Label {
halign: start;
margin-bottom: 12;
label: "Latest mods";
styles ["title-2"]
} }
Adw.CarouselIndicatorDots {}
ScrolledWindow { ScrolledWindow {
vexpand: true; vexpand: true;
ListBox mods_list { hexpand: true;
} FlowBox mods_list {
row-spacing: 12;
column-spacing: 12;
homogeneous: true;
}
} }
}; };
} }
}; };

View file

@ -193,7 +193,22 @@ pub struct Logo {
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct Mod { pub struct Category {
pub id: i32,
// game_id: i32,
pub name: String,
pub slug: String,
// url: String,
// pub icon_url: String,
// date_modified: DateTime<Utc>,
// is_class: bool,
// class_id: i32,
// parent_category_id: i32,
// display_index: i32,
}
#[derive(Debug, Deserialize)]
pub struct GameMod {
pub name: String, pub name: String,
//pub modId: i32, //pub modId: i32,
//pub gameSlug: String, //pub gameSlug: String,
@ -212,6 +227,7 @@ pub struct Mod {
//pub gamePopularityRank: i32, //pub gamePopularityRank: i32,
//pub isAvailable: bool, //pub isAvailable: bool,
//pub thumbsUpCount: i32, //pub thumbsUpCount: i32,
pub categories: Vec<Category>,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -260,7 +276,7 @@ struct LatestEarlyAccessFileIndex {
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
struct GetModsResponse { struct GetModsResponse {
data: Vec<Mod>, data: Vec<GameMod>,
pagination: Pagination, pagination: Pagination,
} }
@ -272,7 +288,7 @@ struct Pagination {
totalCount: i32, totalCount: i32,
} }
pub fn get_mods(game_id: &i32) -> Vec<Mod> { pub fn get_mods(game_id: &i32) -> Vec<GameMod> {
let client = get_curse_forge_client().unwrap(); let client = get_curse_forge_client().unwrap();
let response = client let response = client

View file

@ -1,8 +1,10 @@
use adw::subclass::prelude::*; use adw::subclass::prelude::*;
use gtk::prelude::BoxExt;
use gtk::CompositeTemplate; use gtk::CompositeTemplate;
use gtk::{gio, glib}; use gtk::{gio, glib};
use crate::api::loaders::ImageLoader; use crate::api::loaders::ImageLoader;
use crate::api::GameMod;
use crate::dispatch::Worker; use crate::dispatch::Worker;
mod imp { mod imp {
@ -20,6 +22,9 @@ mod imp {
#[template_child] #[template_child]
pub image: TemplateChild<gtk::Image>, pub image: TemplateChild<gtk::Image>,
#[template_child]
pub footer: TemplateChild<gtk::Box>,
} }
#[glib::object_subclass] #[glib::object_subclass]
@ -53,21 +58,47 @@ impl Card {
glib::Object::builder().build() glib::Object::builder().build()
} }
pub fn bind(&self, worker: Worker, heading: &str, body: &str, image_url: &str) { fn set_heading(&self, heading: &str) {
let widget = self.imp(); let widget = self.imp();
widget.heading.set_text(heading); widget.heading.set_text(heading);
}
fn set_body(&self, body: &str) {
let widget = self.imp();
widget.body.set_text(body); widget.body.set_text(body);
}
println!("image_url: {}", image_url); fn set_image_from_url(&self, worker: Worker, url: String) {
let card = self.imp();
let image = card.image.clone();
let url = image_url.to_string();
let image = widget.image.clone();
worker.send_local_task(async move { worker.send_local_task(async move {
let loader = ImageLoader::new(); let loader = ImageLoader::new();
let pixbuf = loader.from_url(url).await; let pixbuf = loader.from_url(url).await;
image.set_from_pixbuf(pixbuf.as_ref()); image.set_from_pixbuf(pixbuf.as_ref());
}); });
} }
pub fn new_for_game_mod(worker: Worker, game_mod: &GameMod) -> Self {
let card = Self::new();
let widget = card.imp();
card.set_image_from_url(worker, game_mod.logo.url.to_string());
card.set_heading(&game_mod.name);
card.set_body(&game_mod.summary);
let categories = gtk::Box::new(gtk::Orientation::Horizontal, 0);
categories.append(&gtk::Label::new(Some("Categories: ")));
for category in &game_mod.categories {
let button = gtk::Button::builder()
.label(&category.name)
.css_classes(["pill", "flat"])
.build();
categories.append(&button);
}
widget.footer.append(&categories);
card
}
} }

View file

@ -47,7 +47,7 @@ mod imp {
pub games_list: TemplateChild<gtk::ListBox>, pub games_list: TemplateChild<gtk::ListBox>,
#[template_child] #[template_child]
pub mods_list: TemplateChild<gtk::ListBox>, pub mods_list: TemplateChild<gtk::FlowBox>,
} }
#[glib::object_subclass] #[glib::object_subclass]
@ -102,12 +102,10 @@ mod imp {
} }
})); }));
let mods = get_mods(&get_game_id(Game::TheSims4("".to_string()))) get_mods(&get_game_id(Game::TheSims4("".to_string())))
.iter() .iter()
.for_each(|mod_| { .for_each(|item| {
let card = Card::new(); let card = Card::new_for_game_mod(worker.clone(), item);
card.bind(worker.clone(), &mod_.name, &mod_.summary, &mod_.logo.url);
obj.imp().mods_list.append(&card); obj.imp().mods_list.append(&card);
}); });
} }