* resize n reflow rough cut * removing warnings * relatively stable changes * minor bug fix * reflow relative collision * working dp cut * fix for reflow of widgets closer next to each other * disabling scroll * Drag with reflow * reflow fix * overlap and retracing fix * On Drop updates. * bug when no displacement but resize update. * temp fix for new widget addition. * reflow bug fixes * new widget addition bug. * stop reflow on leave. * fix corner case overlap * update bottom row when reflowed widgets go beyond bottom boundary. * capture mouse positions on enter * enable container jumps with faster mouse movements. * reflow only for snap changes. * restructured reflow Algorithm * collision check and bug fixes * undo redo fix for new widget drop * resizable fix snapRows fix * directional stability * self collision fix * first round of perf fixes * update bottom row while resizing and resize-reflowing * performance fix and overlapping fix * Remove eslint warning * remove eslint warning * eslint warning * can reflowed Drop Indication Stability * container jumps and force direction on entering canvas * fixing scroll on resize jitters. * reflow when jumping into container. * reflow ux fixes while leaving container * resizing fixes. * fixes for edge move. * restrict container jumps into reflowed containers. * container jump direction reflow * checkbox dimensions fix. * Excess bottom rows not lost post dragging or resizing widgets. * fixing the after drop css glitch. * double first move trigger bug fix. * stop reflow only if reflowing * stabilize container exit directions * using acceleration and speed instead of movement covered to restrict reflow. * fixing modal drops. * remove warnings. * reflow resize styles * moving acceleration and movement logic to a monitoring effect. * adding beta flag for reflow. * fixing jest tests * Adding analytics to beta flag toggle. * Adding placeholder for reflow beta screens. * fixing initial load's screen * few more crashes. * force close onboarding for the session. * fixing bugs in reset canvas. * Beta flag bug fixes. * fixing bugs. * restrict reflow screens during onboarding. * disabling reflow screens in tests. * code review comments. * fixing store based specs. * fixing cypress failures. * fixing specs. * code cleanup * reverting yarn lock changes * removing onboarding screens. * more cleanup and function descriptors * keeping reflow under the hood. Co-authored-by: rahulramesha <rahul@appsmith.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com>
139 lines
3.9 KiB
TypeScript
139 lines
3.9 KiB
TypeScript
import { reflowMoveAction, stopReflowAction } from "actions/reflowActions";
|
|
import { OccupiedSpace, WidgetSpace } from "constants/CanvasEditorConstants";
|
|
import { isEmpty, throttle } from "lodash";
|
|
import { useRef } from "react";
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
import { getWidgetSpacesSelectorForContainer } from "selectors/editorSelectors";
|
|
import { reflow } from "reflow";
|
|
import {
|
|
CollidingSpace,
|
|
GridProps,
|
|
ReflowDirection,
|
|
ReflowedSpaceMap,
|
|
} from "reflow/reflowTypes";
|
|
import { getLimitedMovementMap } from "reflow/reflowUtils";
|
|
import { getBottomRowAfterReflow } from "utils/reflowHookUtils";
|
|
import { checkIsDropTarget } from "components/designSystems/appsmith/PositionedContainer";
|
|
|
|
type WidgetCollidingSpace = CollidingSpace & {
|
|
type: string;
|
|
};
|
|
|
|
type WidgetCollidingSpaceMap = {
|
|
[key: string]: WidgetCollidingSpace;
|
|
};
|
|
|
|
export interface ReflowInterface {
|
|
(
|
|
newPositions: OccupiedSpace,
|
|
OGPositions: OccupiedSpace,
|
|
direction: ReflowDirection,
|
|
stopMoveAfterLimit?: boolean,
|
|
shouldSkipContainerReflow?: boolean,
|
|
forceDirection?: boolean,
|
|
immediateExitContainer?: string,
|
|
): {
|
|
canHorizontalMove: boolean;
|
|
canVerticalMove: boolean;
|
|
movementMap: ReflowedSpaceMap;
|
|
bottomMostRow: number;
|
|
};
|
|
}
|
|
|
|
export const useReflow = (
|
|
widgetId: string,
|
|
parentId: string,
|
|
gridProps: GridProps,
|
|
): ReflowInterface => {
|
|
const dispatch = useDispatch();
|
|
|
|
const throttledDispatch = throttle(dispatch, 50);
|
|
|
|
const isReflowing = useRef<boolean>(false);
|
|
|
|
const reflowSpacesSelector = getWidgetSpacesSelectorForContainer(parentId);
|
|
const widgetSpaces: WidgetSpace[] = useSelector(reflowSpacesSelector) || [];
|
|
|
|
const originalSpacePosition = widgetSpaces?.find(
|
|
(space) => space.id === widgetId,
|
|
);
|
|
|
|
const prevPositions = useRef<OccupiedSpace | undefined>(
|
|
originalSpacePosition,
|
|
);
|
|
const prevCollidingSpaces = useRef<WidgetCollidingSpaceMap>();
|
|
const prevMovementMap = useRef<ReflowedSpaceMap>({});
|
|
// will become a state if we decide that resize should be a "toggle on-demand" feature
|
|
const shouldResize = true;
|
|
return function reflowSpaces(
|
|
newPositions: OccupiedSpace,
|
|
OGPositions: OccupiedSpace,
|
|
direction: ReflowDirection,
|
|
stopMoveAfterLimit = false,
|
|
shouldSkipContainerReflow = false,
|
|
forceDirection = false,
|
|
immediateExitContainer?: string,
|
|
) {
|
|
const { collidingSpaceMap, movementLimit, movementMap } = reflow(
|
|
newPositions,
|
|
OGPositions,
|
|
widgetSpaces,
|
|
direction,
|
|
gridProps,
|
|
forceDirection,
|
|
shouldResize,
|
|
immediateExitContainer,
|
|
prevPositions.current,
|
|
prevCollidingSpaces.current,
|
|
);
|
|
|
|
prevPositions.current = newPositions;
|
|
prevCollidingSpaces.current = collidingSpaceMap as WidgetCollidingSpaceMap;
|
|
|
|
let correctedMovementMap = movementMap || {};
|
|
|
|
if (stopMoveAfterLimit)
|
|
correctedMovementMap = getLimitedMovementMap(
|
|
movementMap,
|
|
prevMovementMap.current,
|
|
movementLimit,
|
|
);
|
|
|
|
if (shouldSkipContainerReflow) {
|
|
const collidingSpaces = Object.values(
|
|
(collidingSpaceMap as WidgetCollidingSpaceMap) || {},
|
|
);
|
|
for (const collidingSpace of collidingSpaces) {
|
|
if (checkIsDropTarget(collidingSpace.type)) {
|
|
correctedMovementMap = {};
|
|
}
|
|
}
|
|
}
|
|
|
|
prevMovementMap.current = correctedMovementMap;
|
|
|
|
if (!isEmpty(correctedMovementMap)) {
|
|
isReflowing.current = true;
|
|
if (forceDirection) dispatch(reflowMoveAction(correctedMovementMap));
|
|
else throttledDispatch(reflowMoveAction(correctedMovementMap));
|
|
} else if (isReflowing.current) {
|
|
isReflowing.current = false;
|
|
throttledDispatch.cancel();
|
|
dispatch(stopReflowAction());
|
|
}
|
|
|
|
const bottomMostRow = getBottomRowAfterReflow(
|
|
movementMap,
|
|
newPositions.bottom,
|
|
widgetSpaces,
|
|
gridProps,
|
|
);
|
|
|
|
return {
|
|
...movementLimit,
|
|
movementMap: correctedMovementMap,
|
|
bottomMostRow,
|
|
};
|
|
};
|
|
};
|