From 77895c01ffb45746e8a9206ee21f93c10097c6e6 Mon Sep 17 00:00:00 2001 From: LucaP Date: Wed, 2 Sep 2026 06:04:20 +0300 Subject: [PATCH] fix: close phase 2 journey blockers --- src/components/AppShell.vue | 17 ++++-- src/components/SceneCanvas.vue | 17 ++++-- src/composables/useAdaptiveQuality.ts | 3 +- src/composables/useJourneySections.ts | 12 +++- src/composables/useSceneController.ts | 18 +++++- src/composables/useScrollDrive.ts | 1 + src/journey/scroll-drive-controller.ts | 4 ++ src/scene/create-scene-controller.ts | 13 ++++- src/scene/types.ts | 1 + src/scene/world/car.ts | 45 ++++++++++++++- src/scene/world/environment.ts | 11 +++- src/styles/world.css | 2 + tests/browser/bfcache-lifecycle.spec.ts | 2 +- tests/browser/scene-controls.spec.ts | 41 ++++++++++++- tests/unit/SceneCanvas.test.ts | 67 +++++++++++++++++++++- tests/unit/adaptive-quality.test.ts | 21 +++++++ tests/unit/scene-lifecycle.test.ts | 55 +++++++++++++++++- tests/unit/scene-resources.test.ts | 47 +++++++++++++++ tests/unit/scroll-drive-controller.test.ts | 27 +++++++++ 19 files changed, 378 insertions(+), 26 deletions(-) diff --git a/src/components/AppShell.vue b/src/components/AppShell.vue index f2ccd6a..487e4b0 100644 --- a/src/components/AppShell.vue +++ b/src/components/AppShell.vue @@ -78,20 +78,28 @@ watch( watch( () => motion.policy.value.maximumTier, (tier, previous) => { - if (tier !== previous) adaptive.setMaximum(tier, 'manual'); + if (tier !== previous) { + adaptive.setMaximum(tier, controlsReady.value ? 'resize' : 'manual'); + } }, + { flush: 'sync' }, ); const setQuality = (tier: import('@/journey/motion-policy').QualityTier): void => { motion.setMaximumQuality(tier); - adaptive.setMaximum(tier, 'manual'); + adaptive.setMaximum(motion.policy.value.maximumTier, 'manual'); }; const enableMotion = (): void => { const tier = motion.maximumQuality.value === 'static' ? 'high' : motion.maximumQuality.value; motion.setMaximumQuality(tier); motion.setPaused(false); - adaptive.setMaximum(tier, 'manual'); + adaptive.setMaximum(motion.policy.value.maximumTier, 'manual'); +}; + +const resumeMotion = (): void => { + motion.setPaused(false); + adaptive.setMaximum(motion.policy.value.maximumTier, 'manual'); }; onMounted(() => { @@ -118,6 +126,7 @@ onUnmounted(() => removePageListeners()); :policy="motion.policy.value" :quality="actualQuality" :scene-description="content.sceneDescription" + :sample-frame="adaptive.sampleFrame" @state-change="sceneState = $event" /> removePageListeners()); :audio-muted="audio.muted.value" :audio-volume="controlsReady ? motion.volume.value : 0.4" @pause="motion.setPaused(true)" - @resume="motion.setPaused(false)" + @resume="resumeMotion" @enable="enableMotion" @quality-change="setQuality" @audio-start="audio.startFromGesture" diff --git a/src/components/SceneCanvas.vue b/src/components/SceneCanvas.vue index db5133f..82a95e2 100644 --- a/src/components/SceneCanvas.vue +++ b/src/components/SceneCanvas.vue @@ -9,6 +9,7 @@ const props = defineProps<{ policy: MotionPolicy; quality: QualityTier; sceneDescription: string; + sampleFrame?: (start: number, end: number) => unknown; }>(); const emit = defineEmits<{ @@ -20,13 +21,16 @@ const clientReady = ref(false); const journey = toRef(props, 'journey'); const policy = toRef(props, 'policy'); const quality = toRef(props, 'quality'); -const scene = useSceneController({ canvas, journey, policy, quality }); +const scene = useSceneController({ canvas, journey, policy, quality, sampleFrame: props.sampleFrame }); const sceneState = computed(() => scene.state.value); +const sceneGeneration = computed(() => scene.snapshot.value?.currentGeneration ?? null); const showCanvas = computed(() => ( clientReady.value - && policy.value.allowSceneRequest - && quality.value !== 'static' && !scene.error.value + && ( + (policy.value.allowSceneRequest && quality.value !== 'static') + || (policy.value.reason === 'visitor-pause' && sceneGeneration.value !== null) + ) )); watch(scene.state, (state) => emit('stateChange', state), { immediate: true }); @@ -35,7 +39,12 @@ onMounted(() => { clientReady.value = true; });