Placeholder cover arts
[skip ci]
This commit is contained in:
BIN
dash-frontend/assets/dashboard/placeholder_cover.png
Normal file
BIN
dash-frontend/assets/dashboard/placeholder_cover.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
@@ -12,10 +12,13 @@ use wgui::{
|
|||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, WidgetID, WidgetPair},
|
layout::{Layout, WidgetID, WidgetPair},
|
||||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||||
renderer_vk::text::custom_glyph::{CustomGlyphContent, CustomGlyphData},
|
renderer_vk::text::{
|
||||||
|
FontWeight, HorizontalAlign, TextShadow, TextStyle,
|
||||||
|
custom_glyph::{CustomGlyphContent, CustomGlyphData},
|
||||||
|
},
|
||||||
taffy::{
|
taffy::{
|
||||||
self,
|
self, AlignItems, AlignSelf, JustifyContent, JustifySelf,
|
||||||
prelude::{length, percent},
|
prelude::{auto, length, percent},
|
||||||
},
|
},
|
||||||
task::Tasks,
|
task::Tasks,
|
||||||
widget::{
|
widget::{
|
||||||
@@ -33,7 +36,7 @@ use crate::{
|
|||||||
util::{
|
util::{
|
||||||
cover_art_fetcher::{self, CoverArt},
|
cover_art_fetcher::{self, CoverArt},
|
||||||
popup_manager::MountPopupParams,
|
popup_manager::MountPopupParams,
|
||||||
steam_utils::{self, AppID, SteamUtils},
|
steam_utils::{self, AppID, AppManifest, SteamUtils},
|
||||||
various::AsyncExecutor,
|
various::AsyncExecutor,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -54,6 +57,7 @@ pub struct Params<'a> {
|
|||||||
|
|
||||||
struct Cell {
|
struct Cell {
|
||||||
image_parent: WidgetID,
|
image_parent: WidgetID,
|
||||||
|
manifest: AppManifest,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct View {
|
pub struct View {
|
||||||
@@ -66,6 +70,7 @@ pub struct View {
|
|||||||
steam_utils: steam_utils::SteamUtils,
|
steam_utils: steam_utils::SteamUtils,
|
||||||
|
|
||||||
cells: HashMap<AppID, Cell>,
|
cells: HashMap<AppID, Cell>,
|
||||||
|
img_placeholder: Option<CustomGlyphData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View {
|
impl View {
|
||||||
@@ -93,6 +98,7 @@ impl View {
|
|||||||
id_list_parent: list_parent.id,
|
id_list_parent: list_parent.id,
|
||||||
steam_utils,
|
steam_utils,
|
||||||
cells: HashMap::new(),
|
cells: HashMap::new(),
|
||||||
|
img_placeholder: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,6 +186,8 @@ fn construct_game_cover(
|
|||||||
height: percent(1.0),
|
height: percent(1.0),
|
||||||
},
|
},
|
||||||
padding: taffy::Rect::length(2.0),
|
padding: taffy::Rect::length(2.0),
|
||||||
|
align_items: Some(AlignItems::Center),
|
||||||
|
justify_content: Some(JustifyContent::Center),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
@@ -257,6 +265,7 @@ fn construct_game_cover(
|
|||||||
button,
|
button,
|
||||||
Cell {
|
Cell {
|
||||||
image_parent: image_parent.id,
|
image_parent: image_parent.id,
|
||||||
|
manifest: manifest.clone(),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -353,36 +362,22 @@ impl View {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_set_cover_art(
|
fn get_placeholder_image(&mut self) -> anyhow::Result<&CustomGlyphData> {
|
||||||
&mut self,
|
if self.img_placeholder.is_none() {
|
||||||
layout: &mut Layout,
|
let c = CustomGlyphData::new(CustomGlyphContent::from_assets(
|
||||||
app_id: &AppID,
|
&self.globals,
|
||||||
cover_art: Rc<CoverArt>,
|
AssetPath::BuiltIn("dashboard/placeholder_cover.png"),
|
||||||
) -> anyhow::Result<()> {
|
)?);
|
||||||
if cover_art.compressed_image_data.is_empty() {
|
self.img_placeholder = Some(c);
|
||||||
return Ok(()); // do nothing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(cell) = self.cells.get(app_id) else {
|
Ok(self.img_placeholder.as_ref().unwrap()) // safe
|
||||||
debug_assert!(false); // this shouldn't happen
|
}
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
|
|
||||||
let glyph_content = match CustomGlyphContent::from_bin_raster(&cover_art.compressed_image_data) {
|
|
||||||
Ok(c) => c,
|
|
||||||
Err(e) => {
|
|
||||||
log::warn!(
|
|
||||||
"failed to decode cover art image for AppID {} ({:?}), skipping",
|
|
||||||
app_id,
|
|
||||||
e
|
|
||||||
);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
fn mount_image(layout: &mut Layout, cell: &Cell, glyph: &CustomGlyphData) -> anyhow::Result<()> {
|
||||||
let image = WidgetImage::create(WidgetImageParams {
|
let image = WidgetImage::create(WidgetImageParams {
|
||||||
round: WLength::Units(12.0),
|
round: WLength::Units(12.0),
|
||||||
glyph_data: Some(CustomGlyphData::new(glyph_content)),
|
glyph_data: Some(glyph.clone()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -401,4 +396,90 @@ impl View {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mount_placeholder_text(
|
||||||
|
globals: &WguiGlobals,
|
||||||
|
layout: &mut Layout,
|
||||||
|
parent: WidgetID,
|
||||||
|
text: &str,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let label = WidgetLabel::create(
|
||||||
|
&mut globals.get(),
|
||||||
|
WidgetLabelParams {
|
||||||
|
content: Translation::from_raw_text(text),
|
||||||
|
style: TextStyle {
|
||||||
|
weight: Some(FontWeight::Bold),
|
||||||
|
wrap: true,
|
||||||
|
size: Some(16.0),
|
||||||
|
align: Some(HorizontalAlign::Center),
|
||||||
|
shadow: Some(TextShadow {
|
||||||
|
color: drawing::Color::new(0.0, 0.0, 0.0, 0.5),
|
||||||
|
x: 2.0,
|
||||||
|
y: 2.0,
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
layout.add_child(
|
||||||
|
parent,
|
||||||
|
label,
|
||||||
|
taffy::Style {
|
||||||
|
position: taffy::Position::Absolute,
|
||||||
|
align_self: Some(AlignSelf::Baseline),
|
||||||
|
justify_self: Some(JustifySelf::Center),
|
||||||
|
margin: taffy::Rect {
|
||||||
|
top: length(32.0),
|
||||||
|
bottom: auto(),
|
||||||
|
left: auto(),
|
||||||
|
right: auto(),
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn action_set_cover_art(
|
||||||
|
&mut self,
|
||||||
|
layout: &mut Layout,
|
||||||
|
app_id: &AppID,
|
||||||
|
cover_art: Rc<CoverArt>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
if cover_art.compressed_image_data.is_empty() {
|
||||||
|
// mount placeholder
|
||||||
|
let img = self.get_placeholder_image()?.clone();
|
||||||
|
|
||||||
|
let Some(cell) = self.cells.get(app_id) else {
|
||||||
|
debug_assert!(false); // this shouldn't happen
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
View::mount_image(layout, cell, &img)?;
|
||||||
|
View::mount_placeholder_text(&self.globals, layout, cell.image_parent, &cell.manifest.name)?;
|
||||||
|
} else {
|
||||||
|
// mount image
|
||||||
|
|
||||||
|
let Some(cell) = self.cells.get(app_id) else {
|
||||||
|
debug_assert!(false); // this shouldn't happen
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
let glyph = match CustomGlyphContent::from_bin_raster(&cover_art.compressed_image_data) {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!(
|
||||||
|
"failed to decode cover art image for AppID {} ({:?}), skipping",
|
||||||
|
app_id,
|
||||||
|
e
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
View::mount_image(layout, cell, &CustomGlyphData::new(glyph))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user