OneLauncher-Cracked/packages/oneclient_app/src/components/dynamic_art.rs

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()
}
}