- Expanded start screen card and drop zone visuals for better accessibility.
- Implemented a global #global-drag-overlay that appears on drag over the entire window.
- Attached drag-and-drop listeners to document.body for universal file loading.
- Refined dragCounter logic to prevent overlay flickering during child element transit.
IMPROVEMENTS:
- **utils.js**: Enhanced [extractTimestampInfo](cci//file:///d:/Work/Repo/refactor/steps/src/utils.js:36:0-70:1) with a robust, prefix-agnostic regular expression. It now identifies `YYYYMMDD_HHMMSS` and `DDMMYYYY_HHMMSS` patterns anywhere in a filename, enabling support for generic camera names like `cam_20260312_163310` or raw recordings.
- **dom.js**: Decoupled persistent overlays and debug diagnostics from mandatory video date-time metadata. The dashboard now remains fully functional even when loading generic video files (e.g., `output.mp4`).
- **Standardized Epoch Fallback**: Implemented a unified time-anchoring logic. If a filename lacks date-time information, the system now defaults to **January 1, 1970 (Unix Epoch)**, ensuring the absolute time clocks and sync diagnostics proceed without error or disappearance.
- **Bug Fixes**: Corrected syntax errors and structural scoping issues in the [updateDebugOverlay](cci:1://file:///d:/Work/Repo/refactor/steps/src/dom.js:200:0-291:1) function that were causing diagnostics to display inconsistently.
This commit refactors the initialization phase of the Visualizer to act as a Single Page Application (SPA). A persistent workspace shell is now initially hidden behind a "Data Synchronizer" Start Screen, which handles file ingestion before seamlessly revealing the canvas.
Part 1: Implement SPA Start Screen Modal and Data Routing
* steps/index.html: Added the full-screen `start-screen-modal` overlay to intercept the user on load. Removed text placeholders inside the video and canvas containers since the workspace is now exclusively visible when populated.
* steps/src/dom.js: Exported references for the new modal, drop zone, and primary load buttons.
* steps/src/main.js: Routed standard drag-and-drop and click events to target the new Start Screen elements rather than the legacy footer buttons, initiating the existing file pipeline.
Part 2: Integrate Loading Progress Natively
* steps/index.html: Added a hidden `start-progress-container` directly inside the Start Screen card to prevent overlapping popups.
* steps/src/dom.js: Exported references to the native progress bar and text elements.
* steps/src/modal.js: Refactored `showLoadingModal`, `updateLoadingModal`, and `hideModal` to dynamically route progress updates. If the Start Screen is active, it renders the inline progress bar and disables background buttons rather than spawning the generic popup modal.
* steps/src/fileLoader.js: Updated `processFilePipeline` to fully dismiss the `start-screen-modal` upon successful data ingestion and precomputation, seamlessly transitioning the user.
Part 3: Replicate Accessibility and Theme Controls
* steps/index.html: Duplicated the Quick Start Guide, Codebase Overview, What's New, and Theme Toggle buttons, positioning them in the top-right corner of the Start Screen. Also fixed a `-webkit-appearance` CSS warning on the range slider.
* steps/src/dom.js: Exported references for the new accessibility buttons and theme toggle SVGs.
* steps/src/ui.js: Attached existing `toggleGuideModal`, `toggleCodebaseModal`, and `toggleChangelogModal` event listeners to the new replicated buttons, granting users access to documentation before data load.
* steps/src/theme.js: Updated `initializeTheme()` so switching the theme from either the workspace or the Start Screen bidirectionally syncs the Light/Dark SVGs on both buttons simultaneously.
Refactors animation and interpolation logic to ensure consistent behavior
across different monitor refresh rates (e.g., 60Hz vs 144Hz).
Changes:
- Implement time-delta adjusted smoothing for FPS counter and mouse tracking.
- Update IFT graph scaling in 'dom.js' to use performance-based delta time.
- Remove hardcoded 60FPS limit in zoom sketch to allow native refresh rates.
- Fix vertical tooltip jitter in 'drawUtils.js' by using smoothed mouse coordinates.
- Add 'lastOverlayUpdateTime' to global state for cross-module time tracking.
- Implemented smooth dynamic scaling for the Inter-Frame Timing (IFT) graph that remains active even when playback is paused.
- Added a conditional `requestAnimationFrame` loop to ensure the graph scale converges smoothly to the target value during scrubbing or pause states.
- Tuned animation speeds: fast convergence (0.1 smoothing) during playback, slower (0.033) when paused for a more polished visual transition.
- Fixed a layout thrashing (forced reflow) performance issue in `updatePersistentOverlays` by reading `clientWidth` before writing text updates to the DOM.
- Implement robust fallback and safety logic to prevent division-by-zero or invalid state crashes.
- Update scale calculations and drawing utilities to use dynamic boundaries from appState.
- Refine radar-info-overlay to match plot width and center text content for better alignment.
- Add double-click reset functionality to the range slider to revert to default constants.
- Fix hover detection bug in God Mode during scroll-zoom interactions.
- Ensure Regions of Interest (ROI) scale proportionally with the dynamic plot range.
Vehicle Dimensions:
- Added "Show Dimensions" toggle to the display settings.
- Implemented `drawObjectDimensions` in `drawUtils.js` to render object extents as oriented rectangles based on `objectExtentRadii` and `objectExtentAngle`.
- Updated `radarSketch.js` to draw dimensions when enabled.
- Ensured dimensions and covariance ellipses are drawn at the `correctedPosition` for accurate alignment with track markers.
Track Visualization:
- Updated `drawTrajectories` to prioritize the `risk` property on track logs for coloring (0=Low/Blue, 1=Medium/Orange, 2=High/Red).
- Added fallback to `ttcCategoryTimeline` for backward compatibility.
- Fixed off-by-one error in trajectory history filtering to prevent drawing future points.
Frame Synchronization & UI:
- Refactored frame number display logic across Overlays, Data Explorer, and Timeline.
- UI now displays the actual `frameIdx` from the data source instead of the internal array index, resolving discrepancies between the Data Explorer and the main view.
This commit introduces several improvements to the radar visualization, focusing on responsiveness, error handling, and clearer data representation.
**Key Changes:**
* **Responsive Radar Overlay:** The persistent radar information overlay (`ift-dot-matrix` canvas) in `dom.js` is no longer a fixed size. It now dynamically adjusts its width to match the radar plot's size, ensuring a consistent visual experience across different screen resolutions and resize events. The internal drawing logic has been updated to dynamically calculate column counts based on the canvas's current dimensions.
* **Improved Error Handling in Drawing Utilities:** Comprehensive `try...catch` blocks have been added to all major drawing functions within `drawUtils.js`. This significantly enhances the application's robustness by gracefully handling potential errors during rendering, preventing crashes and providing better debugging insights.
* **TTC Category Fallback:** In `drawUtils.js`, the trajectory drawing logic for Time-to-Collision (TTC) now includes a fallback mechanism. If a track's `ttcCategory` is undefined or invalid, it will default to a neutral gray color, ensuring that trajectories are always rendered with a clear visual state.
Create `shortcuts.html` as a standalone reference page.
Implement `#shortcuts-modal` in `index.html` to display key bindings.
Implement `#guide-modal` with an iframe to embed `User_Manual.html` directly in the app.
Refactor header navigation into color-coded buttons (Green/Blue/Amber-Indigo).
Update `src/dom.js` and `src/ui.js` to handle modal visibili and interactions (ESC key, 'k' key, click-to-close).
Improve visual consistency of header button heights and moda styling.
Improves the time offset feature by making manual offsets persistent and enhancing the user workflow.
- **Persistent Manual Offsets**: Manual offsets are now saved to IndexedDB, keyed by filename. They are automatically applied when the same file is loaded in a future session.
- **Click to Revert & Forget**: The "Manual" status indicator is now clickable. Clicking it reverts to the auto-calculated offset and, crucially, deletes the saved manual offset from the database. This ensures future sessions will correctly default to the automatic calculation.
- **Consistent UI**: The "Manual" indicator now appears instantly with a consistent gray style, whether set manually or loaded from cache, removing UI ambiguity.
- **Refactored Sync Logic**: The `revertToAutoOffset` function has been refactored to reuse the core `forceResyncWithOffset` logic. This reduces code duplication and centralizes the synchronization process, making it more robust and easier to maintain.
Resolve infinite p5.js auto-draw loop during file processing by ensuring comprehensive UI cleanup and correct p5 instance lifecycle management (`redraw` instead of `lo`).
Introduce conditional video retention in `resetUIForNewLoad`, allowing the loaded video to persist when only new JSON data is supplied.
The new loop iterates through the data and draws rectangles directly to the canvas. It changes ctx.fillStyle more often (once per column), but this cost is negligible to the cost of allocating and collecting memory 60 times a second. This should resolve the heap memory issue you observed.
- Refactor(main.js): The manual offset input listener contained duplicated logic for pausing and re-syncing. This has been removed and replaced with `forceResyncWithOffset` imported from `sync.js`.
- Fix(dom.js): The drift calculation in `updateDebugOverlay` and `updatePersistentOverlays` was using static `timestampMs` combined with the dynamic offset, leading to incorrect values after a manual adjustment. Updated to use `currentRadarFrame.videoSyncedTime` for accurate, architecture-aligned drift reporting.
This commit introduces a major improvement to the file loading pipeline, resolving a critical race condition that occurred during fresh loads and drag-and-drop actions. Previously, the application would attempt to initialize data-dependent components (like the speed graph) and manage the loading modal simultaneously, leading to timing issues.
The core of this fix is a new, robust processFilePipeline function in main.js that implements a two-stage video loading process. This decouples data initialization from UI updates, ensuring each occurs at the correct point in the browser's file loading lifecycle.
Key Changes & Bug Fixes:
main.js: Refactored processFilePipeline
Two-Stage Video Loading: The video loading process now uses two distinct event listeners:
loadedmetadata: Fires as soon as the video's duration is known. This event now immediately triggers finalizeSetup(), ensuring that the speedGraphSketch is created with the correct time axis, fixing the blank graph bug.
canplaythrough: Fires only after the video has buffered enough for smooth playback. The resolution of the main videoReadyPromise is tied to this event, guaranteeing the loading modal is hidden at the appropriate time and resolving the "stuck modal" bug.
Explicit Data Synchronization: A final, crucial fix was added to finalizeSetup() to re-synchronize all radar frame timestamps against the video's confirmed start time. This eliminates data mismatches that previously caused NaN errors on fresh loads.
speedGraphSketch.js: Enhanced Robustness
The sketch's draw() and drawTimeIndicator() functions have been made more defensive. They now check that both videoDuration and appState.currentFrame are valid before attempting to render, preventing crashes and NaN errors if the sketch is asked to draw before all data is ready.
modal.js: Improved Loading Modal
The modal logic was updated to support a dedicated loading state with a progress bar, providing better user feedback during the file parsing and video buffering stages.
Adds a new zoom panel that provides a magnified, real-time view of the area under the cursor when "Close-Up Mode" is active. This feature enhances the tool's precision for detailed data analysis.
Key features and fixes include:
- Renders a high-fidelity, vector-based redraw of the scene, not a pixelated image.
- Implemented dynamic zoom control via the mouse wheel when hovering over the main radar canvas.
- The zoom sketch is fully decoupled from the main radar sketch to ensure stability and prevent UI freezes.
- Includes a self-contained tooltip within the zoom window that correctly scales its size and text to match the zoom level.
- The tooltip's position is now smart, dynamically moving to the least cluttered quadrant to avoid obstructing data points.
- Connector lines and item highlighting are now fully functional and styled to match the main view's tooltip.
Motion state added in the persistent overlays
This commit introduces a major feature release, adding powerful new tools for data analysis and significantly enhancing the user experience and application robustness.
### ✨ Advanced Visualization & Analysis
* **Custom TTC Coloring Scheme**: Implemented a new UI panel allowing users to switch between the default TTC coloring and a fully customizable scheme. Users can now define their own time thresholds and colors for Critical, High, Medium, and Low risk TTC categories on the fly, with the visualization updating in real-time. [cite: steps/src/drawUtils.js, steps/index.html]
* **Persistent Info Overlays**: Added new, always-on overlays to the top-left of both the radar and video views. These display critical diagnostic information, including frame numbers, absolute UTC time, and real-time synchronization drift. [cite: steps/src/dom.js]
### 🚀 Workflow & UX Enhancements
* **Session Management**: Added "Save Session" and "Load Session" functionality. Users can now save their complete setup (loaded filenames, time offset, toggle states) to a JSON file and restore it later, which reloads the application with the exact same configuration. [cite: steps/src/main.js]
* **Advanced Timeline Navigation**:
* **Scroll-to-Seek**: The timeline slider now supports seeking via the mouse scroll wheel, with a dynamic acceleration feature for faster navigation through long recordings. [cite: steps/src/main.js]
* **Scrub Preview**: A tooltip now appears when hovering over the timeline, showing the precise frame and timestamp under the cursor for more accurate seeking. [cite: steps/src/main.js]
### 🐛 Bug Fixes & Robustness
* **Malformed Data Handling**: The application is now resilient to malformed `track` objects in the JSON data. The drawing functions in `drawUtils.js` now include robust safeguards that detect tracks missing a `historyLog`, print a detailed warning to the console, and safely skip them instead of crashing. [cite: steps/src/drawUtils.js]
* **File Load Order**: Fixed a critical bug where the speed graph would fail to load if the video file was loaded before the JSON file. The logic now correctly creates the graph regardless of the file loading sequence. [cite: steps/src/main.js]
* **UI Initialization**: Resolved a `ReferenceError` caused by event listeners running before the DOM was fully loaded. The custom TTC control logic is now correctly initialized after the `DOMContentLoaded` event, ensuring stability.
Main:
This major update refactors the entire application from a single monolithic HTML file into a modern, modular JavaScript architecture for improved maintainability, performance, and future extensibility.
Alongside the refactoring, this commit introduces a completely overhauled synchronization engine and several quality-of-life improvements.
Key changes and new features include:
- **Modular Architecture**: The application is now split into distinct, decoupled modules for state management (`state.js`), DOM manipulation (`dom.js`), synchronization (`sync.js`), file parsing (`fileParsers.js`), and UI components (`p5/radarSketch.js`, `modal.js`, etc.).
- **Robust Synchronization Engine**:
- The core playback loop in `sync.js` now correctly applies the manual time offset, ensuring accurate synchronization between the video and radar data during playback.
- Fixed a bug where fast scrubbing with the timeline slider could leave a persistent drift while paused. The fix uses the video's `seeked` event for a reliable, event-driven UI update.
- **Enhanced User Experience**:
- Added a new feature allowing users to press 'Enter' in the offset input box to instantly resync the video to the current radar frame, which significantly streamlines the manual calibration process.
- **Improved Debugging Tools**:
- The advanced debug overlay's drift calculation is now "offset-aware," providing an accurate representation of the true synchronization status during both playback and seeking.
Body:
This commit introduces a new advanced debugging overlay to help diagnose synchronization issues and fixes three core timing bugs that caused data streams to be misaligned.
Advanced Debug Overlay:
A new "Show Advanced Debug" toggle has been added to the UI. When enabled, it displays critical synchronization diagnostics in real-time, including:
Video vs. Target Radar timestamps
The calculated "Drift" in milliseconds between the two
Absolute start times for video and radar recordings
The currently applied offset
This provides a precise tool for manually calibrating the offset and verifying sync accuracy.
Synchronization Fixes:
The previous implementation suffered from several race conditions and logical errors in its time management:
Speed Graph Misalignment: The ego speed line on the graph was plotted using raw radar timestamps, ignoring the video offset. This has been corrected to use the offset-adjusted timestampMs, aligning it with the CAN data.
Playback Drift: The main animation loop was incorrectly applying the time offset a second time during playback, causing the radar visualization to lead or lag the video. The redundant offset calculation has been removed from the animationLoop.
Seeking Inaccuracy: When scrubbing the timeline, the UI would update the CAN speed using a stale videoPlayer.currentTime value due to the asynchronous nature of video seeking. The logic in updateFrame now uses the precise, calculated target time for the update, ensuring the EGO and CAN speed indicators match perfectly during seeks.
These changes result in a significantly more robust and verifiable synchronization between the video and radar data feeds.