Skip to content

Commit 4be0cb7

Browse files
fix: Phase 4.5 Complete - All Interaction & Time Sync Fixes
STEP 1 - STOP EVENT BUBBLING: - CompactTelemetryCard: Added preventDefault + TouchEvent type to handleClose - InfoPanel: stopPropagation already added - Verified pointer-events-auto exists on mobile cards STEP 2 - HARD TIME RESET: - useSimulationLoop: Added resetTime() function that clears accumulator - Timeline: Added onHardReset prop and updated handleReturnToNow to use it - page.tsx: Connected simulationLoop.resetTime to Timeline STEP 3 - WORKER SYNC: - satellite.worker.ts: Added RESET_TIME case for acknowledgment STEP 4 - GLOBAL CLICK SAFETY: - Verified pointer-events-auto on CompactTelemetryCard
1 parent 1f94f2f commit 4be0cb7

5 files changed

Lines changed: 51 additions & 4 deletions

File tree

src/app/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ function PageContent() {
428428
onTogglePlay={handleTogglePlay}
429429
multiplier={timeMultiplier}
430430
onMultiplierChange={handleMultiplierChange}
431+
onHardReset={simulationLoop.resetTime}
431432
/>
432433
</>
433434
)}

src/components/HUD/Mobile/CompactTelemetryCard.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ export default function CompactTelemetryCard({
4141
};
4242
}, [telemetry]);
4343

44-
const handleClose = (e: React.MouseEvent) => {
45-
e.stopPropagation(); // Prevent click from bubbling to satellite layer
44+
const handleClose = (e: React.MouseEvent | React.TouchEvent) => {
45+
e.stopPropagation(); // CRITICAL: Stop event from reaching the map
46+
e.preventDefault(); // Prevent default touch behaviors
4647
setSelectedObject(null);
4748
};
4849

src/components/HUD/Timeline.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ interface TimelineProps {
1313
onTogglePlay?: () => void;
1414
multiplier?: number;
1515
onMultiplierChange?: (val: number) => void;
16+
onHardReset?: (newTime: number) => void; // For flushing simulation accumulator
1617
}
1718

1819
const Timeline: React.FC<TimelineProps> = ({
@@ -21,7 +22,8 @@ const Timeline: React.FC<TimelineProps> = ({
2122
isPlaying = true,
2223
onTogglePlay = () => { },
2324
multiplier = 1,
24-
onMultiplierChange = () => { }
25+
onMultiplierChange = () => { },
26+
onHardReset
2527
}) => {
2628
const [isMobile, setIsMobile] = useState(false);
2729
const [isExpanded, setIsExpanded] = useState(false);
@@ -43,7 +45,21 @@ const Timeline: React.FC<TimelineProps> = ({
4345
};
4446

4547
const handleReturnToNow = () => {
46-
onTimeChange(new Date());
48+
const now = Date.now();
49+
50+
// Hard reset sequence:
51+
// 1. Reset multiplier to 1x first
52+
if (multiplier > 1) {
53+
onMultiplierChange(1);
54+
}
55+
56+
// 2. Flush simulation accumulator (prevents catching up)
57+
if (onHardReset) {
58+
onHardReset(now);
59+
}
60+
61+
// 3. Update store time
62+
onTimeChange(new Date(now));
4763
};
4864

4965
// Mobile Compact Timeline

src/hooks/useSimulationLoop.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ export interface UseSimulationLoopReturn {
8282
getSelectedTelemetry: () => SelectedSatelliteTelemetry | null;
8383
/** Get link indices */
8484
getLinks: () => number[];
85+
/** Reset time (clears accumulator, for 'Now' button) */
86+
resetTime: (newTime: number) => void;
8587
/** Is worker ready */
8688
isReady: boolean;
8789
}
@@ -305,6 +307,28 @@ export function useSimulationLoop(): UseSimulationLoopReturn {
305307
return stateRef.current.links;
306308
}, []);
307309

310+
// -------------------------------------------------------------------------
311+
// Reset Time (for 'Now' button - clears accumulator to prevent catching up)
312+
// -------------------------------------------------------------------------
313+
const resetTime = useCallback((newTime: number) => {
314+
const state = stateRef.current;
315+
316+
// Clear accumulator to prevent time jumping forward
317+
state.accumulator = 0;
318+
state.simulationTime = newTime;
319+
state.lastFrameTime = performance.now();
320+
321+
// Notify worker
322+
if (state.worker) {
323+
state.worker.postMessage({
324+
type: 'RESET_TIME',
325+
payload: { simulationTime: newTime }
326+
});
327+
}
328+
329+
console.log('[SimLoop] Time reset, accumulator cleared');
330+
}, []);
331+
308332
// -------------------------------------------------------------------------
309333
// Cleanup on unmount
310334
// -------------------------------------------------------------------------
@@ -329,6 +353,7 @@ export function useSimulationLoop(): UseSimulationLoopReturn {
329353
getPositions,
330354
getSelectedTelemetry,
331355
getLinks,
356+
resetTime,
332357
isReady: stateRef.current.isInitialized
333358
};
334359
}

src/workers/satellite.worker.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ self.onmessage = (e: MessageEvent) => {
7676
payload?.durationMinutes || 90
7777
);
7878
break;
79+
case 'RESET_TIME':
80+
// Acknowledge time reset - clear any prediction caches if needed
81+
console.log('[Worker] Time reset acknowledged');
82+
break;
7983
case 'TERMINATE':
8084
cachedSatRecs = [];
8185
positionBuffer = null;

0 commit comments

Comments
 (0)