perf: enforce journey budgets and reference traces
This commit is contained in:
@@ -20,6 +20,9 @@ import type { PortfolioContent, SectionId } from '@/content/types';
|
||||
import type { SceneHostState } from '@/composables/useSceneController';
|
||||
import type { MotionPolicy, QualityTier } from '@/journey/motion-policy';
|
||||
|
||||
declare const __PORTFOLIO_TEST_BUILD__: boolean;
|
||||
const TEST_BUILD = typeof __PORTFOLIO_TEST_BUILD__ !== 'undefined' && __PORTFOLIO_TEST_BUILD__;
|
||||
|
||||
const props = defineProps<{ content: Readonly<PortfolioContent> }>();
|
||||
|
||||
const canonicalSectionIds = [
|
||||
@@ -57,7 +60,13 @@ const adaptive = useAdaptiveQuality({
|
||||
sceneState,
|
||||
pageLifecycle,
|
||||
});
|
||||
const actualQuality = computed(() => adaptive.snapshot.value.actual);
|
||||
const requestedPerformanceTier = TEST_BUILD
|
||||
? new URL(window.location.href).searchParams.get('__portfolio_tier')
|
||||
: null;
|
||||
const pinnedPerformanceTier = requestedPerformanceTier === 'high' || requestedPerformanceTier === 'low'
|
||||
? requestedPerformanceTier
|
||||
: null;
|
||||
const actualQuality = computed(() => pinnedPerformanceTier ?? adaptive.snapshot.value.actual);
|
||||
const activeSectionLabel = computed(() => sectionLabel(journey.value.activeSectionId));
|
||||
const serverDefaultPolicy: MotionPolicy = {
|
||||
allowSceneRequest: false,
|
||||
@@ -70,6 +79,16 @@ const displayedQuality = computed<QualityTier>(() => controlsReady.value ? actua
|
||||
const displayedSceneState = computed(() => controlsReady.value ? sceneState.value : 'running');
|
||||
let removePageListeners = (): void => {};
|
||||
|
||||
const sampleSceneFrame = (start: number, end: number): void => {
|
||||
if (pinnedPerformanceTier === null) adaptive.sampleFrame(start, end);
|
||||
if (TEST_BUILD) window.__PORTFOLIO_PERFORMANCE__?.recordSceneFrame(start, end);
|
||||
};
|
||||
|
||||
const updateSceneState = (state: SceneHostState): void => {
|
||||
sceneState.value = state;
|
||||
if (TEST_BUILD) window.__PORTFOLIO_PERFORMANCE__?.recordSceneState(state);
|
||||
};
|
||||
|
||||
watch(
|
||||
() => journey.value.activeSectionId,
|
||||
(id) => navigation.notePassiveSection(id),
|
||||
@@ -100,6 +119,28 @@ const enableMotion = (): void => {
|
||||
const resumeMotion = (): void => {
|
||||
motion.setPaused(false);
|
||||
adaptive.setMaximum(motion.policy.value.maximumTier, 'manual');
|
||||
if (TEST_BUILD) window.__PORTFOLIO_PERFORMANCE__?.recordActionMutation('resume');
|
||||
};
|
||||
|
||||
const pauseMotion = (): void => {
|
||||
motion.setPaused(true);
|
||||
if (TEST_BUILD) window.__PORTFOLIO_PERFORMANCE__?.recordActionMutation('pause');
|
||||
};
|
||||
|
||||
const startDrive = (): void => {
|
||||
audio.startFromGesture();
|
||||
if (TEST_BUILD) window.__PORTFOLIO_PERFORMANCE__?.recordActionMutation('start');
|
||||
};
|
||||
|
||||
const toggleAudioMuted = (): void => {
|
||||
const action = audio.muted.value ? 'unmute' : 'mute';
|
||||
audio.toggleMuted();
|
||||
if (TEST_BUILD) window.__PORTFOLIO_PERFORMANCE__?.recordActionMutation(action);
|
||||
};
|
||||
|
||||
const updateAudioVolume = (value: number): void => {
|
||||
audio.setVolume(value);
|
||||
if (TEST_BUILD && value === 0.35) window.__PORTFOLIO_PERFORMANCE__?.recordActionMutation('volume');
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
@@ -126,8 +167,8 @@ onUnmounted(() => removePageListeners());
|
||||
:policy="motion.policy.value"
|
||||
:quality="actualQuality"
|
||||
:scene-description="content.sceneDescription"
|
||||
:sample-frame="adaptive.sampleFrame"
|
||||
@state-change="sceneState = $event"
|
||||
:sample-frame="sampleSceneFrame"
|
||||
@state-change="updateSceneState"
|
||||
/>
|
||||
<JourneyHud
|
||||
:journey="journey"
|
||||
@@ -203,13 +244,13 @@ onUnmounted(() => removePageListeners());
|
||||
:audio-state="audio.state.value"
|
||||
:audio-muted="audio.muted.value"
|
||||
:audio-volume="controlsReady ? motion.volume.value : 0.4"
|
||||
@pause="motion.setPaused(true)"
|
||||
@pause="pauseMotion"
|
||||
@resume="resumeMotion"
|
||||
@enable="enableMotion"
|
||||
@quality-change="setQuality"
|
||||
@audio-start="audio.startFromGesture"
|
||||
@audio-start="startDrive"
|
||||
@audio-resume="audio.resumeFromGesture"
|
||||
@audio-mute-toggle="audio.toggleMuted"
|
||||
@audio-volume-change="audio.setVolume"
|
||||
@audio-mute-toggle="toggleAudioMuted"
|
||||
@audio-volume-change="updateAudioVolume"
|
||||
/>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user