Files
mule-image/frontend/src/components/timeline
dtoro 5e10b12b13 fix: arrow key navigation matches the visual grid
The Timeline arrow keys moved by currentIndex ± columns in the FLAT
photos array, but with date / tag grouping the rendered grid has
half-full last rows for each group, so flat-index nav routinely
landed in the wrong cell — and tag grouping (where one photo can
appear in multiple groups) made it incoherent.

Fix: navigate the actual visual grid the user sees.

- New photoRows = items.filter(type='row') in visual order. The
  buildItems pipeline already chunks photos into row items of
  [1..columns] cells per group; this is exactly the rendered layout.
- findActiveCell() walks photoRows looking for the activePhotoId
  and returns its (rowIndex, colIndex), or null if it isn't on
  screen. First-occurrence wins, which matches user intuition in
  the tag-grouped view.
- New move(dr, dc) helper:
    Left/Right: walk col, wrap across row boundaries (so going Right
    off the end of a half-full row jumps to the next group's first
    row). Clamps at the very first/last cell.
    Up/Down: change row, then clamp the column to the destination
    row's actual width — moving down into a 2-cell row from col 3
    lands on col 1, not nothing.
- The four arrow handlers all funnel through move(); shift-arrow
  still calls selectRange with the destination cell's globalIndex
  so range selection works the same as a shift-click on that cell.
- Headers are skipped automatically because they were never in
  photoRows. Edge cells, end-of-group, single-row groups, and
  tag-repeated photos all behave consistently.

Pulled activePhotoId out of usePhotoStore (was already in the store
but the Timeline component wasn't reading it). Effect deps updated
to invalidate the listener whenever the visible grid changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:25:16 +02:00
..