// Shared placeholder primitives for the onboarding tour. Everything here is // deliberately fake — rights-clean demo stills (generated, owned), looping // demo progress — so new users see the real UI's shapes before their own // library exists. import sunset from "../../assets/onboarding/sunset.webp"; import sunsetcoast from "../../assets/onboarding/sunsetcoast.webp"; import sunsetlake from "../../assets/onboarding/sunsetlake.webp"; import beach from "../../assets/onboarding/beach.webp"; import landscape1 from "../../assets/onboarding/landscape1.webp"; import landscape2 from "../../assets/onboarding/landscape2.webp"; import forest from "../../assets/onboarding/forest.webp"; import citynight from "../../assets/onboarding/citynight.webp"; import flower from "../../assets/onboarding/flower.webp"; import alpinelake from "../../assets/onboarding/alpinelake.webp"; import dunes from "../../assets/onboarding/dunes.webp"; import cozy from "../../assets/onboarding/cozy.webp"; import cat from "../../assets/onboarding/cat.webp"; import balloon from "../../assets/onboarding/balloon.webp"; import architecture from "../../assets/onboarding/architecture.webp"; // Ordered for grid variety: adjacent indices are visually distinct. const FAKE_IMAGES = [ sunset, cozy, landscape1, citynight, flower, dunes, alpinelake, cat, forest, balloon, landscape2, beach, architecture, ]; export function fakeImage(index: number): string { return FAKE_IMAGES[index % FAKE_IMAGES.length]; } // Result sets matched to what each query would genuinely return. // - filename: one exact file (a filename search hits a specific name) // - semantic "golden sunset over water": only the ocean-sunset stills // - tags "landscape": mountain valleys + the alpine lake (all landscapes) export const SEARCH_RESULTS = { filename: [beach], semantic: [sunsetcoast, sunset, sunsetlake], tags: [landscape1, landscape2, alpinelake], } as const; // Abstract gradient blobs/ticks for the Explore & Timeline mini-previews, // where small non-photographic shapes read more clearly than tiny stills. const TILE_GRADIENTS = [ "from-sky-900/70 via-slate-800 to-slate-900", "from-amber-900/60 via-stone-800 to-stone-900", "from-emerald-900/60 via-slate-800 to-gray-900", "from-rose-900/50 via-slate-800 to-slate-900", "from-indigo-900/60 via-slate-800 to-gray-900", "from-cyan-900/60 via-slate-800 to-slate-900", "from-fuchsia-900/40 via-slate-800 to-gray-900", "from-orange-900/50 via-stone-800 to-stone-900", ]; export function tileGradient(index: number): string { return TILE_GRADIENTS[index % TILE_GRADIENTS.length]; } export function FakeTile({ index, loaded = true, favorite = false, rating = 0, duration, className = "", }: { index: number; loaded?: boolean; favorite?: boolean; rating?: number; duration?: string; className?: string; }) { return (
{loaded ? ( ) : (
)} {loaded && favorite ? (
) : null} {loaded && rating > 0 ? (
{Array.from({ length: rating }).map((_, i) => ( ))}
) : null} {loaded && duration ? (
{duration}
) : null}
); } export function FakeStageTag({ label, state }: { label: string; state: "active" | "done" | "waiting" }) { const className = state === "active" ? "bg-white/5 text-gray-300" : state === "done" ? "bg-emerald-500/10 text-emerald-400" : "bg-white/4 text-gray-600"; return {label}; } export function FakeProgressBar({ fraction, className = "" }: { fraction: number | null; className?: string }) { return (
{fraction === null ? (
) : (
)}
); } export function ReplayButton({ onClick, label = "Replay" }: { onClick: () => void; label?: string }) { return ( ); } export function formatBytes(bytes: number): string { if (bytes >= 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`; if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(0)} MB`; if (bytes >= 1024) return `${(bytes / 1024).toFixed(0)} KB`; return `${bytes} B`; }