fix: use square cells in timeline grid
PhotoThumbnail computed cell height as size * min(aspectRatio, 1.5), so portrait photos overflowed their row. The TanStack Virtual row estimate is a single fixed value (thumbnailSize + gap), so any cell taller than that pushed into the row below — visible as overlapping thumbnails whenever a portrait shared a row with landscapes. Switching to square cells (Lightroom Library default) means every row is exactly the estimated height. The image still fills via object-cover, just cropped on the long axis. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react'
|
||||
import { Star, Check, X, RefreshCw } from 'lucide-react'
|
||||
import { Star, Check, Trash2, RefreshCw } from 'lucide-react'
|
||||
import clsx from 'clsx'
|
||||
import { photos as photosApi } from '../../services/api'
|
||||
import type { Photo } from '../../types/photo'
|
||||
@@ -28,9 +28,11 @@ export function PhotoThumbnail({ photo, size, isSelected, onClick, onDoubleClick
|
||||
const baseUrl = photosApi.getThumbnailUrl(photo.id, 'medium')
|
||||
const thumbnailUrl = retryCount > 0 ? `${baseUrl}?retry=${retryCount}` : baseUrl
|
||||
|
||||
// Calculate aspect ratio for proper sizing (default to 1:1 if dimensions unknown)
|
||||
const aspectRatio = (photo.height && photo.width) ? photo.height / photo.width : 1
|
||||
const displayHeight = size * Math.min(aspectRatio, 1.5) // Cap height at 1.5x width
|
||||
// Square cells (Lightroom-style grid). Variable-aspect cells previously
|
||||
// overflowed their row because TanStack Virtual estimates row height as a
|
||||
// single fixed value — portraits in a landscape row would overlap the row
|
||||
// below. With object-cover the image still fills the cell, just cropped.
|
||||
const displayHeight = size
|
||||
|
||||
const clearRetryTimer = () => {
|
||||
if (retryTimerRef.current !== null) {
|
||||
@@ -169,8 +171,8 @@ export function PhotoThumbnail({ photo, size, isSelected, onClick, onDoubleClick
|
||||
{photo.is_picked && (
|
||||
<Check className="h-4 w-4 text-pick" />
|
||||
)}
|
||||
{photo.is_rejected && (
|
||||
<X className="h-4 w-4 text-reject" />
|
||||
{photo.is_trashed && (
|
||||
<Trash2 className="h-4 w-4 text-reject" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user