fix(ui): polish demo-flow overlays
🔍 Lint / 🪄 Check lint (push) Has been cancelled
🔍 Lint / 🎨 Check format (push) Has been cancelled
🔍 Lint / 🔎 Typecheck (push) Has been cancelled
📊 Quality / 🔒 Security Audit (push) Has been cancelled
📊 Quality / 📋 Dependency Freshness (push) Has been cancelled
📊 Quality / 📦 Bundle Size (push) Has been cancelled
🔍 Lint / 🏗 Build (push) Has been cancelled
🔍 Lint / 🪄 Check lint (push) Has been cancelled
🔍 Lint / 🎨 Check format (push) Has been cancelled
🔍 Lint / 🔎 Typecheck (push) Has been cancelled
📊 Quality / 🔒 Security Audit (push) Has been cancelled
📊 Quality / 📋 Dependency Freshness (push) Has been cancelled
📊 Quality / 📦 Bundle Size (push) Has been cancelled
🔍 Lint / 🏗 Build (push) Has been cancelled
- OutroVideoOverlay: stagger reveal so 'Next step :' appears immediately and 'La ferme' fades in 500ms later, instead of both showing at once. - MissionNotification: enforce 589/211 aspect-ratio + objectFit cover on the <video> branch so webm assets (square 2000x2000) render at the same place as the legacy PNG notifications instead of shifting the layout. - HandTrackingTutorial: add a 5000ms fallback timeout that auto-dismisses the overlay if MediaPipe never reports a hand (camera blocked, mouse-only player), so the screen never stays stuck.
This commit is contained in:
@@ -6,6 +6,8 @@ const OUTRO_VIDEO_SRC = "/cinematics/outro.mp4";
|
||||
const TRANSITION_FADE_MS = 600;
|
||||
const TRANSITION_HOLD_MS = 2000;
|
||||
const TRANSITION_TEXT_FADE_MS = 500;
|
||||
// Delay between "Next step :" appearing and "La ferme" fading in.
|
||||
const TRANSITION_LAFERME_DELAY_MS = 500;
|
||||
|
||||
const MUTED_CATEGORIES: readonly AudioCategory[] = ["music", "sfx", "dialogue"];
|
||||
|
||||
@@ -28,6 +30,7 @@ type Stage =
|
||||
*/
|
||||
export function OutroVideoOverlay(): React.JSX.Element | null {
|
||||
const [stage, setStage] = useState<Stage>("hidden");
|
||||
const [lafermeVisible, setLafermeVisible] = useState(false);
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
const savedVolumesRef = useRef<Partial<Record<AudioCategory, number>>>({});
|
||||
|
||||
@@ -74,6 +77,24 @@ export function OutroVideoOverlay(): React.JSX.Element | null {
|
||||
return undefined;
|
||||
}, [stage]);
|
||||
|
||||
// Stagger the second word ("La ferme") so it fades in after "Next step :"
|
||||
// is already visible.
|
||||
useEffect(() => {
|
||||
if (stage === "showing-text") {
|
||||
const timer = window.setTimeout(
|
||||
() => setLafermeVisible(true),
|
||||
TRANSITION_LAFERME_DELAY_MS,
|
||||
);
|
||||
return () => window.clearTimeout(timer);
|
||||
}
|
||||
if (stage === "hidden" || stage === "fading-in") {
|
||||
// Reset the staged reveal so a re-triggered outro replays correctly.
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
setLafermeVisible(false);
|
||||
}
|
||||
return undefined;
|
||||
}, [stage]);
|
||||
|
||||
// Mute all game audio while the video is showing; restore on cleanup so
|
||||
// a re-mounted page doesn't stay silent.
|
||||
useEffect(() => {
|
||||
@@ -135,7 +156,15 @@ export function OutroVideoOverlay(): React.JSX.Element | null {
|
||||
transition: `opacity ${TRANSITION_TEXT_FADE_MS}ms ease-in`,
|
||||
}}
|
||||
>
|
||||
Next step : La ferme
|
||||
Next step :{" "}
|
||||
<span
|
||||
style={{
|
||||
opacity: lafermeVisible ? 1 : 0,
|
||||
transition: `opacity ${TRANSITION_TEXT_FADE_MS}ms ease-in`,
|
||||
}}
|
||||
>
|
||||
La ferme
|
||||
</span>
|
||||
</div>
|
||||
) : null}
|
||||
{stage === "video" ? (
|
||||
|
||||
Reference in New Issue
Block a user