126 lines
3.5 KiB
Rust
126 lines
3.5 KiB
Rust
use bytes::Bytes;
|
|
use freya::prelude::*;
|
|
use oneclient_core::clusters::Cluster;
|
|
use oneclient_core::images::DEFAULT_IMAGE_EDGE;
|
|
use oneclient_common::domain::GameLoader;
|
|
use oneclient_common::{VersionKey, parse_mc_version};
|
|
|
|
use crate::AppAssets;
|
|
use crate::hooks::{loaded_image, use_cached_image, use_version_metadata};
|
|
use crate::layout::HOME_BACKGROUND_ASSET;
|
|
|
|
/// The size cluster cards request so it is usually already cached when anything else wants it
|
|
pub const ART_PREVIEW_EDGE: u32 = 512;
|
|
|
|
#[derive(PartialEq, Clone)]
|
|
pub struct DynamicArt {
|
|
major: Option<u32>,
|
|
key: Option<VersionKey>,
|
|
loader: Option<GameLoader>,
|
|
max_edge: u32,
|
|
preview_edge: Option<u32>,
|
|
}
|
|
|
|
impl DynamicArt {
|
|
pub fn for_version(major: u32, key: Option<VersionKey>, loader: Option<GameLoader>) -> Self {
|
|
Self {
|
|
major: Some(major),
|
|
key,
|
|
loader,
|
|
max_edge: DEFAULT_IMAGE_EDGE,
|
|
preview_edge: None,
|
|
}
|
|
}
|
|
|
|
pub fn for_cluster(cluster: &Cluster) -> Self {
|
|
let parsed = parse_mc_version(&cluster.mc_version);
|
|
Self {
|
|
major: parsed.as_ref().map(|p| p.major),
|
|
key: parsed.and_then(|p| p.key()),
|
|
loader: Some(cluster.mc_loader),
|
|
max_edge: DEFAULT_IMAGE_EDGE,
|
|
preview_edge: None,
|
|
}
|
|
}
|
|
|
|
pub fn fallback() -> Self {
|
|
Self {
|
|
major: None,
|
|
key: None,
|
|
loader: None,
|
|
max_edge: DEFAULT_IMAGE_EDGE,
|
|
preview_edge: None,
|
|
}
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn max_edge(mut self, max_edge: u32) -> Self {
|
|
self.max_edge = max_edge;
|
|
self
|
|
}
|
|
|
|
/// Stand in with a smaller cached variant until the full-size art downloads
|
|
#[must_use]
|
|
pub fn preview_edge(mut self, preview_edge: u32) -> Self {
|
|
self.preview_edge = Some(preview_edge);
|
|
self
|
|
}
|
|
|
|
pub fn use_bytes(&self) -> (String, Bytes) {
|
|
use_art_bytes(
|
|
self.major,
|
|
self.key,
|
|
self.loader,
|
|
self.max_edge,
|
|
self.preview_edge,
|
|
)
|
|
}
|
|
}
|
|
|
|
pub fn use_art_bytes(
|
|
major: Option<u32>,
|
|
key: Option<VersionKey>,
|
|
loader: Option<GameLoader>,
|
|
max_edge: u32,
|
|
preview_edge: Option<u32>,
|
|
) -> (String, Bytes) {
|
|
let fallback = use_memo(|| AppAssets::get_bytes(HOME_BACKGROUND_ASSET).unwrap_or_default());
|
|
|
|
let art_url = use_version_metadata(major, key, loader).and_then(|m| m.art_url);
|
|
|
|
let image_query = use_cached_image(art_url.clone(), max_edge);
|
|
|
|
let preview_edge = preview_edge.filter(|edge| *edge != max_edge);
|
|
let preview_query = match preview_edge {
|
|
Some(edge) => use_cached_image(art_url.clone(), edge),
|
|
None => use_cached_image(None, 0),
|
|
};
|
|
|
|
let full = loaded_image(art_url.as_deref(), &image_query)
|
|
.map(|(url, bytes)| (format!("{max_edge}|{url}"), bytes));
|
|
let preview = || {
|
|
let edge = preview_edge?;
|
|
loaded_image(art_url.as_deref(), &preview_query)
|
|
.map(|(url, bytes)| (format!("{edge}|{url}"), bytes))
|
|
};
|
|
|
|
full.or_else(preview).unwrap_or_else(|| {
|
|
(
|
|
format!("{max_edge}|{HOME_BACKGROUND_ASSET}"),
|
|
fallback.read().clone(),
|
|
)
|
|
})
|
|
}
|
|
|
|
impl Component for DynamicArt {
|
|
fn render(&self) -> impl IntoElement {
|
|
let (key, bytes) = self.use_bytes();
|
|
|
|
ImageViewer::new((key, bytes))
|
|
.width(Size::fill())
|
|
.height(Size::fill())
|
|
.aspect_ratio(AspectRatio::Max)
|
|
.image_cover(ImageCover::Center)
|
|
.into_element()
|
|
}
|
|
}
|