feat(library & studio): add EXIF info bar, portrait frame panning, and multi-photo selection with Panorama/HDR context menu
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from 'react';
|
||||
import { useI18n } from '../i18n/I18nProvider';
|
||||
import { MIN_CROP_FRAC, type CropRect, type GradientMask, type HealSpot, type MosaicSpot } from '../../shared/types';
|
||||
import { bitmapReader, samplePixel } from '../engine/imageOps';
|
||||
import { MIN_CROP_FRAC, type CropRect, type FrameId, type GradientMask, type HealSpot, type MosaicSpot } from '../../shared/types';
|
||||
import { bitmapReader, samplePixel, specsLine, type ShotSpecs } from '../engine/imageOps';
|
||||
import { RAW_ACCEPT } from '../engine/rawDevelop';
|
||||
// A phone's HEIC is offered beside the camera RAWs: it is the same offer to a
|
||||
// file the browser will not open by itself (see engine/heicDevelop.ts).
|
||||
@@ -286,6 +286,11 @@ export function ImageStage({
|
||||
onMaskCreate,
|
||||
onMaskEdit,
|
||||
dims = null,
|
||||
shotSpecs = null,
|
||||
place = null,
|
||||
frameId = 'none',
|
||||
framePanX = 0,
|
||||
onFramePanXChange,
|
||||
}: {
|
||||
previewUrl: string | null;
|
||||
originalUrl: string | null;
|
||||
@@ -377,6 +382,11 @@ export function ImageStage({
|
||||
// the quarter turn and cut by a committed crop, so the number in the row under
|
||||
// the photo is the resolution an export at the photo's own size renders.
|
||||
dims?: { w: number; h: number } | null;
|
||||
shotSpecs?: ShotSpecs | null;
|
||||
place?: string | null;
|
||||
frameId?: FrameId;
|
||||
framePanX?: number;
|
||||
onFramePanXChange?: (panX: number) => void;
|
||||
}) {
|
||||
const showStraighten = !!straightenRuler;
|
||||
// The curve graph is a fresh node on every parent render too, and the measure
|
||||
@@ -1987,14 +1997,13 @@ export function ImageStage({
|
||||
)}
|
||||
|
||||
{previewUrl ? (
|
||||
<div className="toolbar">
|
||||
{/* The row's own facts, left of its buttons: how big the photo under
|
||||
the stage is. The number is the render's, so a crop moves it. */}
|
||||
{dims ? (
|
||||
<span className="hint dims" data-key="photo-dims">
|
||||
{dims.w} × {dims.h}
|
||||
</span>
|
||||
<>
|
||||
{shotSpecs || place || dims ? (
|
||||
<div className="photo-meta-bar" data-key="photo-meta-bar">
|
||||
{specsLine(shotSpecs ?? null, place, dims)}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="toolbar">
|
||||
{onClear ? (
|
||||
<button type="button" className="btn" data-key="clear-photo" onClick={onClear}>
|
||||
{t('drop.clear')}
|
||||
@@ -2044,6 +2053,7 @@ export function ImageStage({
|
||||
</button>
|
||||
<span className="hint">{t('drop.peekHint')}</span>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
{busy ? <div className="busy">{busy}</div> : null}
|
||||
|
||||
Reference in New Issue
Block a user