feat(frame): give ROTATE quarter turns plus a fine straighten
This commit is contained in:
@@ -32,6 +32,7 @@ type GroupKey =
|
||||
| 'gpsName'
|
||||
| 'gpsTime'
|
||||
| 'crop'
|
||||
| 'rotate'
|
||||
// Not a strip: the WATERMARK row REPLACES the frame chips (sub-panel).
|
||||
| 'wm';
|
||||
|
||||
@@ -81,10 +82,13 @@ interface AdjustmentPanelProps {
|
||||
onToggleFavorite: (id: string) => void;
|
||||
onUpdateAdjustments: (adjustments: Partial<ColorAdjustments>) => void;
|
||||
onUpdateFrame: (frameId: FrameId) => void;
|
||||
// FRAME tab: turn the inserted library photo 90deg (landscape <-> portrait)
|
||||
// so it fits the chosen frame better.
|
||||
photoRotation: 0 | 90;
|
||||
onToggleRotation: () => void;
|
||||
// FRAME tab: turn the inserted library photo by a quarter turn (0/90/180/
|
||||
// 270deg clockwise) so it fits the chosen frame better, plus a fine
|
||||
// STRAIGHTEN offset (-45..45deg) applied on top of that turn.
|
||||
photoRotation: 0 | 90 | 180 | 270;
|
||||
photoStraighten: number;
|
||||
onPickRotation: (deg: 0 | 90 | 180 | 270) => void;
|
||||
onStraighten: (deg: number) => void;
|
||||
// FRAME tab (WALL FRAME only): hang the artwork landscape instead of the
|
||||
// default portrait rotation.
|
||||
wallLandscape: boolean;
|
||||
@@ -213,6 +217,9 @@ export default function AdjustmentPanel({
|
||||
onUpdateAdjustments,
|
||||
onUpdateFrame,
|
||||
photoRotation,
|
||||
photoStraighten,
|
||||
onPickRotation,
|
||||
onStraighten,
|
||||
wallLandscape,
|
||||
onToggleWallLandscape,
|
||||
onToggleGeotag,
|
||||
@@ -224,7 +231,6 @@ export default function AdjustmentPanel({
|
||||
onAcceptCustomWm,
|
||||
onCancelCustomWm,
|
||||
wmEditNonce,
|
||||
onToggleRotation,
|
||||
wmRotation,
|
||||
onRotateWm,
|
||||
onWmPanelChange,
|
||||
@@ -421,7 +427,21 @@ export default function AdjustmentPanel({
|
||||
: p
|
||||
),
|
||||
filters: toRows(PARAM_DEFS.filters),
|
||||
frame: [],
|
||||
// FRAME carries one slider row: the fine STRAIGHTEN angle. The ROTATE
|
||||
// strip's STRAIGHTEN option opens it, exactly like COLOR TEMP's.
|
||||
frame: [
|
||||
{
|
||||
key: 'straighten',
|
||||
label: 'STRAIGHTEN',
|
||||
value: photoStraighten,
|
||||
default: 0,
|
||||
min: -45,
|
||||
max: 45,
|
||||
step: 0.5,
|
||||
display: (v: number) => `${v > 0 ? '+' : ''}${v}°`,
|
||||
onChange: (v: number) => onStraighten(v),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// TEMP chip's value: the remembered preset while the engine pair still
|
||||
@@ -546,6 +566,31 @@ export default function AdjustmentPanel({
|
||||
],
|
||||
onPick: (v) => onUpdateCropRatio(v as CropRatio),
|
||||
},
|
||||
// ROTATE: the quarter turns plus the fine STRAIGHTEN slider in one strip.
|
||||
// Its RESET undoes this parameter only (quarter turn + fine angle).
|
||||
rotate: {
|
||||
label: 'ROTATE', off: '0',
|
||||
// 'straighten' while its slider row is open, so that chip highlights.
|
||||
value: openParam === 'straighten' ? 'straighten' : String(photoRotation),
|
||||
options: [
|
||||
{ v: 'reset', d: 'RESET' },
|
||||
{ v: '0', d: '0' },
|
||||
{ v: '90', d: '90' },
|
||||
{ v: '180', d: '180' },
|
||||
{ v: '270', d: '270' },
|
||||
{ v: 'straighten', d: 'STRAIGHTEN (±45°)' },
|
||||
],
|
||||
onPick: (v) => {
|
||||
if (v === 'reset') {
|
||||
onPickRotation(0);
|
||||
onStraighten(0);
|
||||
} else if (v === 'straighten') {
|
||||
toggleParam('straighten');
|
||||
} else {
|
||||
onPickRotation(Number(v) as 0 | 90 | 180 | 270);
|
||||
}
|
||||
},
|
||||
},
|
||||
// PHOTO STYLE: the eight film simulations, collapsed into one strip chip.
|
||||
// Its value is the applied sim's id — or '' when a saved recipe is active
|
||||
// (then the chip reads as "not the startup sim" and glows amber). The label
|
||||
@@ -591,6 +636,19 @@ export default function AdjustmentPanel({
|
||||
label: wbTempLabel(),
|
||||
});
|
||||
|
||||
// ROTATE's chip names the applied turn — and the fine angle once it is set
|
||||
// (the strip holds the options; nothing else names the angle).
|
||||
const rotateChip = (): ChipDef => {
|
||||
const label = `ROTATE ${photoRotation}`;
|
||||
return {
|
||||
...groupChip('rotate'),
|
||||
label: photoStraighten
|
||||
? `${label} · ${photoStraighten > 0 ? '+' : ''}${photoStraighten}°`
|
||||
: label,
|
||||
amberValue: openGroup !== 'rotate' && (photoRotation !== 0 || photoStraighten !== 0),
|
||||
};
|
||||
};
|
||||
|
||||
// WATERMARK is a sub-panel of FRAME now (the rail tab is gone): its chip swaps
|
||||
// the frame chips for the watermark controls, behind a breadcrumb back.
|
||||
const wmOn = useGeotag || customWm.enabled;
|
||||
@@ -777,12 +835,7 @@ export default function AdjustmentPanel({
|
||||
(val) => onUpdateFrame(val as FrameId)
|
||||
)}
|
||||
{cropEnabled && renderChip(groupChip('crop'))}
|
||||
{renderChip({
|
||||
key: 'rotate',
|
||||
label: photoRotation === 0 ? 'ROTATE 90' : 'ROTATE 0',
|
||||
active: photoRotation !== 0,
|
||||
onPress: onToggleRotation,
|
||||
})}
|
||||
{renderChip(rotateChip())}
|
||||
{selectedFrame === 'wallframe' &&
|
||||
renderChip({
|
||||
key: 'wall-orient',
|
||||
|
||||
Reference in New Issue
Block a user