feat: experiment with a diff shift locking behavior

This commit is contained in:
Ryan Di
2025-07-07 18:09:18 +10:00
parent a2cf15db9c
commit c79893608a
3 changed files with 52 additions and 11 deletions

View File

@ -124,6 +124,11 @@ export const getDefaultAppState = (): Omit<
searchMatches: null, searchMatches: null,
lockedMultiSelections: {}, lockedMultiSelections: {},
activeLockedId: null, activeLockedId: null,
cropPositionMovement: {
enabled: false,
croppingElementId: undefined,
directionLock: null,
},
}; };
}; };
@ -249,6 +254,7 @@ const APP_STATE_STORAGE_CONF = (<
searchMatches: { browser: false, export: false, server: false }, searchMatches: { browser: false, export: false, server: false },
lockedMultiSelections: { browser: true, export: true, server: true }, lockedMultiSelections: { browser: true, export: true, server: true },
activeLockedId: { browser: false, export: false, server: false }, activeLockedId: { browser: false, export: false, server: false },
cropPositionMovement: { browser: false, export: false, server: false },
}); });
const _clearAppStateForStorage = < const _clearAppStateForStorage = <

View File

@ -6994,6 +6994,8 @@ class App extends React.Component<AppProps, AppState> {
}, },
cropPositionMovement: { cropPositionMovement: {
enabled: false, enabled: false,
croppingElementId: undefined,
directionLock: null,
}, },
}; };
} }
@ -8134,20 +8136,47 @@ class App extends React.Component<AppProps, AppState> {
}; };
// apply shift key constraint for directional movement // apply shift key constraint for directional movement
const threshold = 20;
let snappingToOrigin = false;
if (event.shiftKey) { if (event.shiftKey) {
const distanceX = Math.abs(totalDragOffset.x); if (!pointerDownState.cropPositionMovement.directionLock) {
const distanceY = Math.abs(totalDragOffset.y); if (
Math.abs(totalDragOffset.x) > threshold ||
const lockX = distanceX < distanceY; Math.abs(totalDragOffset.y) > threshold
const lockY = distanceX > distanceY; ) {
pointerDownState.cropPositionMovement.directionLock =
if (lockX) { Math.abs(totalDragOffset.x) > Math.abs(totalDragOffset.y)
totalDragOffset.x = 0; ? "x"
: "y";
} else {
// if within threshold and not locked, always snap to origin
snappingToOrigin = true;
}
} else {
// if user moves back within threshold, unlock and snap back
if (
Math.abs(totalDragOffset.x) < threshold &&
Math.abs(totalDragOffset.y) < threshold
) {
pointerDownState.cropPositionMovement.directionLock = null;
snappingToOrigin = true;
}
} }
} else {
pointerDownState.cropPositionMovement.directionLock = null;
}
if (lockY) { if (snappingToOrigin) {
totalDragOffset.y = 0; totalDragOffset.x = 0;
} totalDragOffset.y = 0;
}
if (pointerDownState.cropPositionMovement.directionLock === "x") {
totalDragOffset.y = 0;
} else if (
pointerDownState.cropPositionMovement.directionLock === "y"
) {
totalDragOffset.x = 0;
} }
// scale the drag offset // scale the drag offset

View File

@ -444,6 +444,11 @@ export interface AppState {
// as elements are unlocked, we remove the groupId from the elements // as elements are unlocked, we remove the groupId from the elements
// and also remove groupId from this map // and also remove groupId from this map
lockedMultiSelections: { [groupId: string]: true }; lockedMultiSelections: { [groupId: string]: true };
cropPositionMovement: {
croppingElementId?: string;
enabled: boolean;
directionLock: "x" | "y" | null;
};
} }
export type SearchMatch = { export type SearchMatch = {
@ -800,6 +805,7 @@ export type PointerDownState = Readonly<{
cropPositionMovement: { cropPositionMovement: {
croppingElementId?: string; croppingElementId?: string;
enabled: boolean; enabled: boolean;
directionLock: "x" | "y" | null;
}; };
}>; }>;