Preload images, video, and artifact thumbnails on mount.
This commit is contained in:
@@ -0,0 +1,53 @@
|
|||||||
|
import type { MediaConfig } from './mediaConfig';
|
||||||
|
import { preloadAudioAssets } from './mediaSounds';
|
||||||
|
import { ARTIFACTS_BASE_URL } from './puzzle2Config';
|
||||||
|
|
||||||
|
const preloadedUrls = new Set<string>();
|
||||||
|
|
||||||
|
function preloadOnce(url: string, load: () => void): void {
|
||||||
|
if (preloadedUrls.has(url)) return;
|
||||||
|
preloadedUrls.add(url);
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function preloadImage(url: string): void {
|
||||||
|
preloadOnce(url, () => {
|
||||||
|
const img = new Image();
|
||||||
|
img.src = url;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function preloadVideo(url: string): void {
|
||||||
|
preloadOnce(url, () => {
|
||||||
|
const video = document.createElement('video');
|
||||||
|
video.preload = 'auto';
|
||||||
|
video.src = url;
|
||||||
|
video.load();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Warm cache for config-driven audio, images, and video. */
|
||||||
|
export function preloadMediaAssets(config: MediaConfig): void {
|
||||||
|
preloadAudioAssets(config);
|
||||||
|
preloadImage(config.mapImageUrl);
|
||||||
|
preloadImage(config.tedCelebrateImageUrl);
|
||||||
|
preloadVideo(config.unlockVideoUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function preloadArtifactImages(entries: readonly { file: string }[]): void {
|
||||||
|
for (const entry of entries) {
|
||||||
|
preloadImage(`${ARTIFACTS_BASE_URL}/${encodeURIComponent(entry.file)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fetch artifact manifest and preload all puzzle-2 thumbnails. */
|
||||||
|
export async function preloadArtifactManifest(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${ARTIFACTS_BASE_URL}/manifest.json`);
|
||||||
|
if (!res.ok) return;
|
||||||
|
const data = (await res.json()) as { file: string }[];
|
||||||
|
preloadArtifactImages(data);
|
||||||
|
} catch {
|
||||||
|
/* manifest unavailable until setup script runs */
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
import { preloadArtifactImages } from './mediaPreload';
|
||||||
import { ARTIFACTS_BASE_URL } from './puzzle2Config';
|
import { ARTIFACTS_BASE_URL } from './puzzle2Config';
|
||||||
|
|
||||||
export interface ArtifactEntry {
|
export interface ArtifactEntry {
|
||||||
@@ -19,6 +20,7 @@ export function useArtifactManifest(): ArtifactEntry[] | null {
|
|||||||
.then((res) => (res.ok ? res.json() : null))
|
.then((res) => (res.ok ? res.json() : null))
|
||||||
.then((data: ArtifactEntry[] | null) => {
|
.then((data: ArtifactEntry[] | null) => {
|
||||||
if (cancelled || !data) return;
|
if (cancelled || !data) return;
|
||||||
|
preloadArtifactImages(data);
|
||||||
setManifest(data);
|
setManifest(data);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { DEFAULT_MEDIA_CONFIG, mergeMediaConfig, type MediaConfig } from './mediaConfig';
|
import { DEFAULT_MEDIA_CONFIG, mergeMediaConfig, type MediaConfig } from './mediaConfig';
|
||||||
import { preloadAudioAssets } from './mediaSounds';
|
import { preloadArtifactManifest, preloadMediaAssets } from './mediaPreload';
|
||||||
|
|
||||||
export function useMediaConfig(): MediaConfig {
|
export function useMediaConfig(): MediaConfig {
|
||||||
const [config, setConfig] = useState<MediaConfig>(DEFAULT_MEDIA_CONFIG);
|
const [config, setConfig] = useState<MediaConfig>(DEFAULT_MEDIA_CONFIG);
|
||||||
@@ -24,7 +24,8 @@ export function useMediaConfig(): MediaConfig {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
preloadAudioAssets(config);
|
preloadMediaAssets(config);
|
||||||
|
void preloadArtifactManifest();
|
||||||
}, [config]);
|
}, [config]);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
|
|||||||
Reference in New Issue
Block a user