fix: cancel Nepal media preloads and respect drawing ownership

Retain active-flight preloading while canceling hidden frames and pending Facebook sessions on stop, disable, and replacement. Add lifecycle and pointer-ownership regression coverage. Apply the runtime formatting adopted on main and keep the existing source-shape check insensitive to that formatting.
This commit is contained in:
Sameh Khamis committed 2026-09-15 08:29:01 -07:00
1 parent 1a936ebac1
commit a9482f0a5b
15 files changed
+3584 -1803

No files matched your search

+701 -287
View File
File diff suppressed because it is too large. Load diff
+109 -83
View File
@@ -13,7 +13,7 @@ const ADDITIONAL_SHOTS = [
alt: 10145,
heading: 224,
pitch: -38,
hold: 11
hold: 11,
},
{
id: 'dhunche',
@@ -23,7 +23,7 @@ const ADDITIONAL_SHOTS = [
alt: 6212,
heading: 208,
pitch: -39,
hold: 16
hold: 16,
},
{
id: 'mailung-upper-trishuli',
@@ -33,7 +33,7 @@ const ADDITIONAL_SHOTS = [
alt: 6353,
heading: 211,
pitch: -40,
hold: 13
hold: 13,
},
{
id: 'mailung-bazzar',
@@ -43,7 +43,7 @@ const ADDITIONAL_SHOTS = [
alt: 6331,
heading: 212,
pitch: -40,
hold: 15
hold: 15,
},
{
id: 'dandagaun',
@@ -53,7 +53,7 @@ const ADDITIONAL_SHOTS = [
alt: 6311,
heading: 214,
pitch: -40,
hold: 15
hold: 15,
},
{
id: 'dandagaun-viewpoint',
@@ -63,7 +63,7 @@ const ADDITIONAL_SHOTS = [
alt: 6740,
heading: 215,
pitch: -41,
hold: 13
hold: 13,
},
{
id: 'betrawati-bazaar',
@@ -73,7 +73,7 @@ const ADDITIONAL_SHOTS = [
alt: 7034,
heading: 216,
pitch: -41,
hold: 12
hold: 12,
},
{
id: 'bhainse',
@@ -83,7 +83,7 @@ const ADDITIONAL_SHOTS = [
alt: 8051,
heading: 219,
pitch: -41,
hold: 13
hold: 13,
},
{
id: 'devighat-taadi-khola-bridge',
@@ -93,7 +93,7 @@ const ADDITIONAL_SHOTS = [
alt: 9056,
heading: 224,
pitch: -42,
hold: 13
hold: 13,
},
{
id: 'charaudi',
@@ -103,7 +103,7 @@ const ADDITIONAL_SHOTS = [
alt: 10347,
heading: 232,
pitch: -42,
hold: 11
hold: 11,
},
{
id: 'final-view',
@@ -116,8 +116,8 @@ const ADDITIONAL_SHOTS = [
roll: 174,
duration: 4,
hold: 11,
locatorPresentation: 'bhote-koshi-incident-places'
}
locatorPresentation: 'bhote-koshi-incident-places',
},
];
const EVIDENCE_ORDER = [
'immediate-collapse-viewpoint',
@@ -136,7 +136,7 @@ const EVIDENCE_ORDER = [
'bidur-trishuli-bridge',
'devighat-taadi-khola-bridge',
'charaudi',
'final-view'
'final-view',
];
// Per-reach motion timing keeps the schematic front ahead of the fixed 4.2s
@@ -147,60 +147,66 @@ const PATH_DURATION_BY_BEAT = Object.freeze({
'second-landslide': 6.5,
'timure-cluster': 2.1,
'syabru-besi': 2.8,
'dhunche': 2.5,
dhunche: 2.5,
'mailung-upper-trishuli': 2.9,
'mailung-bazzar': 2.1,
'dandagaun': 1.2,
dandagaun: 1.2,
'dandagaun-viewpoint': 2.5,
'betrawati-bazaar': 2.9,
'bhainse': 1.5,
bhainse: 1.5,
'bidur-trishuli-bridge': 2.6,
});
/** Extend the six-beat Nepal pack without replacing existing authored shots. */
export function expandNepalEvidencePack(base) {
const layerId = base.requiredSourcePackLayerId;
const extraShots = ADDITIONAL_SHOTS.map(({
id,
hold,
duration = 4.2,
locatorPresentation,
...camera
}) => ({
...camera,
roll: Number.isFinite(Number(camera.roll)) ? Number(camera.roll) : 0,
duration,
hold,
mapStack: 'photoreal',
layers: {
[layerId]: { enabled: true, params: {
presentation: 'scene-beat',
beatId: id,
beatReveal: 0.36,
split: 0.5,
} },
...(locatorPresentation ? {
'bhote-koshi-locator': {
const extraShots = ADDITIONAL_SHOTS.map(
({ id, hold, duration = 4.2, locatorPresentation, ...camera }) => ({
...camera,
roll: Number.isFinite(Number(camera.roll)) ? Number(camera.roll) : 0,
duration,
hold,
mapStack: 'photoreal',
layers: {
[layerId]: {
enabled: true,
params: { presentation: locatorPresentation },
params: {
presentation: 'scene-beat',
beatId: id,
beatReveal: 0.36,
split: 0.5,
},
},
} : {}),
},
}));
const byBeat = new Map([...base.cameraPath, ...extraShots].map((shot) => [
shot.layers[layerId].params.beatId, shot,
]));
...(locatorPresentation
? {
'bhote-koshi-locator': {
enabled: true,
params: { presentation: locatorPresentation },
},
}
: {}),
},
}),
);
const byBeat = new Map(
[...base.cameraPath, ...extraShots].map((shot) => [
shot.layers[layerId].params.beatId,
shot,
]),
);
const cameraPath = EVIDENCE_ORDER.map((id) => byBeat.get(id));
const runtimeControlsByBeat = { ...base.runtimeControlsByBeat };
const cameraLedPathBeats = new Set([
'timure-cluster', 'syabru-besi', ...SOURCE_PATH_BEAT_IDS.slice(2),
]);
const mediaLedPathBeats = new Set([
'debris-dammed-lake', 'second-landslide',
'timure-cluster',
'syabru-besi',
...SOURCE_PATH_BEAT_IDS.slice(2),
]);
const mediaLedPathBeats = new Set(['debris-dammed-lake', 'second-landslide']);
const finalSourcedPathBeatId = SOURCE_PATH_BEAT_IDS.at(-1);
const postSourceHistoryBeats = new Set([
'devighat-taadi-khola-bridge', 'charaudi', 'final-view',
'devighat-taadi-khola-bridge',
'charaudi',
'final-view',
]);
for (const shot of cameraPath) {
const id = shot.layers[layerId].params.beatId;
@@ -209,33 +215,43 @@ export function expandNepalEvidencePack(base) {
runtimeControlsByBeat[id] = {
...runtimeControlsByBeat[id],
evidenceMediaAutoplay: !isFinalView,
...(isFinalView ? {} : {
mediaPlaybackHoldSec: id === 'mailung-bazzar' ? 7 : 6,
mediaExitDurationSec: 0.65,
}),
...(isFinalView
? {}
: {
mediaPlaybackHoldSec: id === 'mailung-bazzar' ? 7 : 6,
mediaExitDurationSec: 0.65,
}),
deferEvidenceUntilCameraSettled: !isFinalView,
evidenceRevealDurationSec: 0.9,
evidencePath: SOURCE_PATH_BEAT_IDS.includes(id) ? 'source'
: ['gyirong-border-gate', 'timure-cluster', 'syabru-besi'].includes(id) ? 'comparison' : 'none',
...(cameraLedPathBeats.has(id) ? {
evidencePathDuringCamera: true,
evidencePathPersistent: true,
...(authoredPathDurationSec
? { evidencePathTravelDurationSec: authoredPathDurationSec }
: {}),
} : {}),
...(mediaLedPathBeats.has(id) ? {
evidencePathDuringMedia: true,
evidencePathPersistent: true,
evidencePathStartDelaySec: 0,
} : {}),
evidencePath: SOURCE_PATH_BEAT_IDS.includes(id)
? 'source'
: ['gyirong-border-gate', 'timure-cluster', 'syabru-besi'].includes(id)
? 'comparison'
: 'none',
...(cameraLedPathBeats.has(id)
? {
evidencePathDuringCamera: true,
evidencePathPersistent: true,
...(authoredPathDurationSec
? { evidencePathTravelDurationSec: authoredPathDurationSec }
: {}),
}
: {}),
...(mediaLedPathBeats.has(id)
? {
evidencePathDuringMedia: true,
evidencePathPersistent: true,
evidencePathStartDelaySec: 0,
}
: {}),
};
if (SOURCE_PATH_BEAT_IDS.includes(id)) {
runtimeControlsByBeat[id] = {
...runtimeControlsByBeat[id],
evidenceHoldCard: true,
evidencePathHistory: true,
evidencePathDurationSec: authoredPathDurationSec || Math.max(4, shot.hold),
evidencePathDurationSec:
authoredPathDurationSec || Math.max(4, shot.hold),
minimumHoldSec: Math.max(4, shot.hold),
};
}
@@ -256,33 +272,40 @@ export function expandNepalEvidencePack(base) {
evidencePathElevation: 'source',
};
}
const pathDurationSec = Number(runtimeControlsByBeat[id].evidencePathDurationSec)
|| (!cameraLedPathBeats.has(id) && runtimeControlsByBeat[id].evidenceSequence === true
const pathDurationSec =
Number(runtimeControlsByBeat[id].evidencePathDurationSec) ||
(!cameraLedPathBeats.has(id) &&
runtimeControlsByBeat[id].evidenceSequence === true
? Number(runtimeControlsByBeat[id].evidenceSequenceDurationSec) || 0
: 0);
const mediaPresentationSec = isFinalView
? 0
: (id === 'mailung-bazzar' ? 7 : 6) + 0.65;
const mediaAndPathHoldSec = pathDurationSec > 0
&& !cameraLedPathBeats.has(id)
? mediaLedPathBeats.has(id)
? Math.max(mediaPresentationSec, pathDurationSec)
: mediaPresentationSec + pathDurationSec
: mediaPresentationSec;
const mediaAndPathHoldSec =
pathDurationSec > 0 && !cameraLedPathBeats.has(id)
? mediaLedPathBeats.has(id)
? Math.max(mediaPresentationSec, pathDurationSec)
: mediaPresentationSec + pathDurationSec
: mediaPresentationSec;
runtimeControlsByBeat[id] = {
...runtimeControlsByBeat[id],
minimumHoldSec: id === 'mailung-bazzar' ? mediaAndPathHoldSec : Math.max(
Number(runtimeControlsByBeat[id].minimumHoldSec) || 0,
mediaAndPathHoldSec,
),
minimumHoldSec:
id === 'mailung-bazzar'
? mediaAndPathHoldSec
: Math.max(
Number(runtimeControlsByBeat[id].minimumHoldSec) || 0,
mediaAndPathHoldSec,
),
};
}
// Keep the downstream sequence on its sourced river profile. Coarse Google
// mesh samples can contain cliff-height spikes that reverse apparent motion.
// Preserve each authored readable hold after the media-first timing floor.
for (const [id, seconds, sequenceSeconds = seconds] of [
['immediate-collapse-viewpoint', 10], ['gyirong-border-gate', 8, 2.5],
['timure-cluster', 12], ['syabru-besi', 11],
['immediate-collapse-viewpoint', 10],
['gyirong-border-gate', 8, 2.5],
['timure-cluster', 12],
['syabru-besi', 11],
]) {
runtimeControlsByBeat[id] = {
...runtimeControlsByBeat[id],
@@ -296,7 +319,10 @@ export function expandNepalEvidencePack(base) {
}
const finalView = byBeat.get('final-view');
return Object.freeze({
...base, version: 18, cameraPath, runtimeControlsByBeat,
...base,
version: 18,
cameraPath,
runtimeControlsByBeat,
// Clip trims must also replace older saved holds, not just lower a floor.
runtimeHoldSecByBeat: { 'mailung-bazzar': 7 + 0.65 },
expansionFromVersion: 17,
+492 -492
View File
File diff suppressed because it is too large. Load diff