fix: preserve result thumbnail aspect ratios
This commit is contained in:
@@ -11,7 +11,9 @@ type PreviewState = {
|
||||
|
||||
function parseRatio(aspectRatio?: string) {
|
||||
if (!aspectRatio || aspectRatio === 'long') return aspectRatio === 'long' ? 1 / 3 : 1;
|
||||
const [w, h] = aspectRatio.split(':').map(Number);
|
||||
const [w, h] = aspectRatio.includes('/')
|
||||
? aspectRatio.split('/').map(part => Number(part.trim()))
|
||||
: aspectRatio.split(':').map(Number);
|
||||
return w && h ? w / h : 1;
|
||||
}
|
||||
|
||||
@@ -42,11 +44,13 @@ export function HoverImagePreview({
|
||||
alt,
|
||||
imageClassName,
|
||||
aspectRatio,
|
||||
onImageLoad,
|
||||
}: {
|
||||
src: string;
|
||||
alt: string;
|
||||
imageClassName?: string;
|
||||
aspectRatio?: string;
|
||||
onImageLoad?: (image: HTMLImageElement) => void;
|
||||
}) {
|
||||
const [preview, setPreview] = useState<PreviewState | null>(null);
|
||||
|
||||
@@ -61,6 +65,7 @@ export function HoverImagePreview({
|
||||
setPreview(nextPreviewState(event, aspectRatio));
|
||||
}}
|
||||
onPointerLeave={() => setPreview(null)}
|
||||
onLoad={event => onImageLoad?.(event.currentTarget)}
|
||||
/>
|
||||
{preview && (
|
||||
<div
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import type { GenImage } from '@/lib/types';
|
||||
import { HoverImagePreview } from './HoverImagePreview';
|
||||
|
||||
@@ -10,6 +10,8 @@ export type ResultGridProps = {
|
||||
};
|
||||
|
||||
export default function ResultGrid({ images, onAction }: ResultGridProps) {
|
||||
const [ratios, setRatios] = useState<Record<string, string>>({});
|
||||
|
||||
useEffect(() => {
|
||||
function handler(e: KeyboardEvent) {
|
||||
const target = e.target as HTMLElement;
|
||||
@@ -27,7 +29,7 @@ export default function ResultGrid({ images, onAction }: ResultGridProps) {
|
||||
return () => window.removeEventListener('keydown', handler);
|
||||
}, [images, onAction]);
|
||||
|
||||
const cols = images.length <= 4 ? 'grid-cols-2' : images.length <= 9 ? 'grid-cols-3' : 'grid-cols-4';
|
||||
const cols = images.length === 1 ? 'grid-cols-[minmax(220px,520px)]' : images.length <= 4 ? 'grid-cols-2' : images.length <= 9 ? 'grid-cols-3' : 'grid-cols-4';
|
||||
const selectedCount = images.filter(i => i.status === 'selected').length;
|
||||
|
||||
return (
|
||||
@@ -51,13 +53,24 @@ export default function ResultGrid({ images, onAction }: ResultGridProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={`grid ${cols} gap-3`}>
|
||||
<div className={`grid ${cols} items-start gap-3`}>
|
||||
{images.map((img, i) => (
|
||||
<div
|
||||
key={img.id}
|
||||
className={`tile group ${img.status === 'selected' ? 'tile-selected' : ''} ${img.status === 'rejected' ? 'tile-rejected' : ''}`}
|
||||
style={{ aspectRatio: ratios[img.id] ?? '1 / 1' }}
|
||||
>
|
||||
<HoverImagePreview src={img.url} alt={`gen ${i + 1}`} imageClassName="w-full h-full object-contain bg-white" />
|
||||
<HoverImagePreview
|
||||
src={img.url}
|
||||
alt={`gen ${i + 1}`}
|
||||
aspectRatio={ratios[img.id]}
|
||||
imageClassName="w-full h-full object-contain bg-white"
|
||||
onImageLoad={image => {
|
||||
if (!image.naturalWidth || !image.naturalHeight) return;
|
||||
const next = `${image.naturalWidth} / ${image.naturalHeight}`;
|
||||
setRatios(prev => prev[img.id] === next ? prev : { ...prev, [img.id]: next });
|
||||
}}
|
||||
/>
|
||||
<div className="tile-keynum">{i + 1}</div>
|
||||
|
||||
{img.status === 'selected' && (
|
||||
|
||||
Reference in New Issue
Block a user