pre-warm cluster art
This commit is contained in:
parent
50bf2c07ee
commit
4995276c51
7 changed files with 113 additions and 15 deletions
|
|
@ -50,7 +50,7 @@ pub use queries::{
|
|||
mutation_error, mutation_is_pending, mutation_is_running, mutation_ok,
|
||||
onboarding_bundles_items, package_meta_batch, package_updates, pick_version_metadata,
|
||||
project_detail, provider_versions, query_error, query_is_busy, query_is_loading,
|
||||
refresh_version_art_gallery, reset_login_code_dedup, resolve_art_url, search_items,
|
||||
cluster_art_url, refresh_version_art_gallery, reset_login_code_dedup, resolve_art_url, search_items,
|
||||
search_pending, search_total, settled_or_loading, stale_hashes, terms_document, terms_error,
|
||||
terms_is_loading, try_account, try_accounts, try_cluster_analytics, try_cluster_logs,
|
||||
try_cluster_screenshots, try_default_account, try_game_profile, try_global_analytics,
|
||||
|
|
|
|||
|
|
@ -104,8 +104,8 @@ pub use storage::{
|
|||
};
|
||||
pub use tos::{TermsQuery, terms_document, terms_error, terms_is_loading, use_terms};
|
||||
pub use version_metadata::{
|
||||
pick_version_metadata, refresh_version_art_gallery, resolve_art_url, use_version_art,
|
||||
use_version_art_gallery, use_version_metadata,
|
||||
cluster_art_url, pick_version_metadata, refresh_version_art_gallery, resolve_art_url,
|
||||
use_version_art, use_version_art_gallery, use_version_metadata,
|
||||
};
|
||||
pub use versions::{
|
||||
GameVersion, JavaMajorsQuery, game_versions, java_majors,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
use oneclient_common::VersionKey;
|
||||
use oneclient_common::domain::GameLoader;
|
||||
use oneclient_common::{VersionKey, parse_mc_version};
|
||||
use oneclient_core::VersionMetadata;
|
||||
use oneclient_core::clusters::Cluster;
|
||||
use oneclient_core::versions::VersionArts;
|
||||
|
||||
use freya::query::QueriesStorage;
|
||||
|
||||
|
|
@ -107,6 +109,23 @@ pub fn resolve_art_url(
|
|||
.or_else(|| candidates.fallback.clone())
|
||||
}
|
||||
|
||||
pub fn cluster_art_url(
|
||||
cluster: &Cluster,
|
||||
list: &[VersionMetadata],
|
||||
arts: &VersionArts,
|
||||
) -> Option<String> {
|
||||
let parsed = parse_mc_version(&cluster.mc_version);
|
||||
let major = parsed.as_ref().map(|p| p.major);
|
||||
let key = parsed.and_then(|p| p.key());
|
||||
let curated =
|
||||
major.and_then(|major| pick_version_metadata(list, major, key, Some(cluster.mc_loader)));
|
||||
let candidates = VersionArtCandidates {
|
||||
minor: arts.specific_art_url(major, key),
|
||||
fallback: arts.fallback_art_url(major),
|
||||
};
|
||||
resolve_art_url(curated.as_ref(), &candidates)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ use crate::hooks::{
|
|||
use_provide_browser_state, use_provide_browser_type, use_provide_datapack_world, use_splash,
|
||||
};
|
||||
use crate::theme::colors;
|
||||
use crate::utils::home_cluster;
|
||||
use oneclient_events::LaunchStage;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
|
|
@ -271,12 +272,6 @@ pub(crate) fn appshell_overlay(alpha: f32) -> Rect {
|
|||
|
||||
pub const HOME_BACKGROUND_ASSET: &str = "backgrounds/CavesAndCliffs.jpg";
|
||||
|
||||
fn home_cluster(clusters: &[Cluster], active: Option<ClusterId>) -> Option<&Cluster> {
|
||||
active
|
||||
.and_then(|id| clusters.iter().find(|c| c.id == id))
|
||||
.or_else(|| clusters.first())
|
||||
}
|
||||
|
||||
fn home_art(cluster: Option<&Cluster>) -> DynamicArt {
|
||||
cluster
|
||||
.map_or_else(DynamicArt::fallback, DynamicArt::for_cluster)
|
||||
|
|
|
|||
|
|
@ -335,9 +335,14 @@ pub fn bundle_display_name(archive: &BundleArchive) -> String {
|
|||
}
|
||||
|
||||
pub fn default_cluster(clusters: Vec<Cluster>, active: Option<i64>) -> Option<Cluster> {
|
||||
home_cluster(&clusters, active).cloned()
|
||||
}
|
||||
|
||||
pub fn home_cluster(clusters: &[Cluster], active: Option<i64>) -> Option<&Cluster> {
|
||||
active
|
||||
.and_then(|id| clusters.iter().find(|cluster| cluster.id == id).cloned())
|
||||
.or_else(|| sort_clusters_for_home(clusters).into_iter().next())
|
||||
.and_then(|id| clusters.iter().find(|cluster| cluster.id == id))
|
||||
// `min_by` keeps the first of equals, matching the stable sort in `sort_clusters_for_home`
|
||||
.or_else(|| clusters.iter().min_by(|a, b| compare_recent_activity(a, b)))
|
||||
}
|
||||
|
||||
pub fn sort_clusters_for_home(mut clusters: Vec<Cluster>) -> Vec<Cluster> {
|
||||
|
|
@ -444,6 +449,22 @@ mod tests {
|
|||
assert_eq!(order, vec![2, 1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn home_background_matches_the_first_recents_card() {
|
||||
let clusters = vec![
|
||||
versioned(1, "1.8.9"),
|
||||
versioned(2, "26.2"),
|
||||
versioned(3, "1.21.1"),
|
||||
];
|
||||
|
||||
let first_card = sort_clusters_for_home(clusters.clone())[0].id;
|
||||
assert_eq!(
|
||||
home_cluster(&clusters, None).map(|c| c.id),
|
||||
Some(first_card)
|
||||
);
|
||||
assert_eq!(home_cluster(&clusters, Some(3)).map(|c| c.id), Some(3));
|
||||
}
|
||||
|
||||
fn line(major: u32, minor: Option<u32>) -> ReleaseLine {
|
||||
ReleaseLine { major, minor }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,18 @@
|
|||
use freya::prelude::*;
|
||||
use freya::router::RouterContext;
|
||||
use oneclient_core::clusters::Cluster;
|
||||
use oneclient_core::images::BACKGROUND_IMAGE_EDGE;
|
||||
use oneclient_core::{BundleArchive, BundleFile, ImportTarget, MigrationSource, SentryExclusion};
|
||||
use oneclient_db::models::OverrideType;
|
||||
|
||||
use crate::components::ART_PREVIEW_EDGE;
|
||||
use crate::hooks::{
|
||||
Actions, ClusterBundles, invalidate_cluster_queries, migration_detection,
|
||||
Actions, ClusterBundles, cluster_art_url, invalidate_cluster_queries, migration_detection,
|
||||
onboarding_bundles_items, try_default_account, use_current_account, use_dispatch,
|
||||
use_migration, use_onboarding_bundles, use_onboarding_selection, use_settings_snapshot,
|
||||
};
|
||||
use crate::routes::Route;
|
||||
use crate::utils::{home_cluster, sort_clusters_for_home};
|
||||
use crate::view::onboarding::{matching_new_cluster_id, pkg_key};
|
||||
|
||||
mod view;
|
||||
|
|
@ -302,6 +306,8 @@ fn finish_setup(
|
|||
|
||||
invalidate_cluster_queries().await;
|
||||
|
||||
let _ = tokio::time::timeout(std::time::Duration::from_secs(30), warm_home_art()).await;
|
||||
|
||||
for version in versions {
|
||||
dispatch.record_seen_version(version);
|
||||
}
|
||||
|
|
@ -311,6 +317,59 @@ fn finish_setup(
|
|||
});
|
||||
}
|
||||
|
||||
const HOME_ART_CLUSTERS: usize = 3;
|
||||
|
||||
async fn warm_home_art() {
|
||||
let Ok(state) = crate::launcher::state() else {
|
||||
return;
|
||||
};
|
||||
let clusters = match state.clusters.list().await {
|
||||
Ok(clusters) => clusters,
|
||||
Err(err) => {
|
||||
tracing::debug!("could not list clusters to warm home art: {err}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let meta_url_base = &state.services.requester.config().meta_url_base;
|
||||
let (list, arts) = tokio::join!(
|
||||
state.versions.metadata(meta_url_base),
|
||||
state.versions.arts(meta_url_base),
|
||||
);
|
||||
let art_url = |cluster: &Cluster| {
|
||||
cluster
|
||||
.cover_file()
|
||||
.is_none()
|
||||
.then(|| cluster_art_url(cluster, &list, &arts))
|
||||
.flatten()
|
||||
};
|
||||
|
||||
let background = home_cluster(&clusters, None).and_then(art_url);
|
||||
let mut warms: Vec<(String, &[u32])> = sort_clusters_for_home(clusters.clone())
|
||||
.iter()
|
||||
.take(HOME_ART_CLUSTERS)
|
||||
.filter_map(art_url)
|
||||
.filter(|url| Some(url) != background.as_ref())
|
||||
.map(|url| (url, &[ART_PREVIEW_EDGE][..]))
|
||||
.collect();
|
||||
warms.sort();
|
||||
warms.dedup();
|
||||
warms.extend(background.map(|url| (url, &[ART_PREVIEW_EDGE, BACKGROUND_IMAGE_EDGE][..])));
|
||||
|
||||
let net = &state.services.requester;
|
||||
let results = futures_util::future::join_all(
|
||||
warms
|
||||
.iter()
|
||||
.map(|(url, edges)| state.images.prefetch(net, url, edges)),
|
||||
)
|
||||
.await;
|
||||
for ((url, _), result) in warms.iter().zip(results) {
|
||||
if let Err(err) = result {
|
||||
tracing::debug!("home art warm failed for {url}: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn apply_overrides(plan: &ClusterPlan) -> oneclient_core::LauncherResult<()> {
|
||||
let state = crate::launcher::state()?;
|
||||
oneclient_core::set_bundle_package_overrides(
|
||||
|
|
|
|||
|
|
@ -2,12 +2,16 @@ use std::collections::BTreeSet;
|
|||
|
||||
use futures_util::StreamExt;
|
||||
|
||||
use crate::images::{DEFAULT_IMAGE_EDGE, PREVIEW_IMAGE_EDGE};
|
||||
use crate::images::{BACKGROUND_IMAGE_EDGE, DEFAULT_IMAGE_EDGE, PREVIEW_IMAGE_EDGE};
|
||||
use crate::state::LauncherState;
|
||||
|
||||
const PREFETCH_CONCURRENCY: usize = 4;
|
||||
|
||||
const PREFETCH_EDGES: [u32; 2] = [PREVIEW_IMAGE_EDGE, DEFAULT_IMAGE_EDGE];
|
||||
const PREFETCH_EDGES: [u32; 3] = [
|
||||
PREVIEW_IMAGE_EDGE,
|
||||
DEFAULT_IMAGE_EDGE,
|
||||
BACKGROUND_IMAGE_EDGE,
|
||||
];
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(state))]
|
||||
pub async fn prefetch_version_art(state: &LauncherState) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue