Skip to content

Commit

Permalink
correctly shifting draggable post update
Browse files Browse the repository at this point in the history
  • Loading branch information
alexreardon committed Jun 14, 2018
1 parent e802a06 commit fdef7ae
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/state/create-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default ({

// > uncomment to use
// debugging logger
require('./debug-middleware/log-middleware').default,
// require('./debug-middleware/log-middleware').default,
// debugging timer
// require('./debug-middleware/action-timing-middleware').default,
// average action timer
Expand Down
11 changes: 11 additions & 0 deletions src/state/get-page-item-positions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// @flow
import type { Position } from 'css-box-model';
import type { ItemPositions } from '../types';
import { add } from './position';

export default (client: ItemPositions, windowScroll: Position): ItemPositions => ({
selection: add(client.selection, windowScroll),
borderBoxCenter: add(client.borderBoxCenter, windowScroll),
offset: add(client.offset, windowScroll),
});

12 changes: 8 additions & 4 deletions src/state/middleware/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,18 +147,22 @@ export default (getHooks: () => Hooks, announce: Announce) => {
const move = (critical: Critical, location: ?DraggableLocation) => {
invariant(isDragStartPublished && lastCritical, 'Cannot fire onDragMove when onDragStart has not been called');

// Our critical has changed - this can happen if the index of the draggable changes
// due to a draggable addition or removal
if (!isCriticalEqual(critical, lastCritical)) {
lastCritical = critical;
}

// No change to publish
if (isCriticalEqual(critical, lastCritical) &&
areLocationsEqual(lastLocation, location)) {
if (areLocationsEqual(lastLocation, location)) {
return;
}
lastLocation = location;

const data: DragUpdate = {
...getDragStart(critical),
destination: location,
};
lastLocation = location;
lastCritical = critical;

withTimings('onDragUpdate', () => execute(getHooks().onDragUpdate, data, messagePreset.onDragUpdate));
};
Expand Down
8 changes: 3 additions & 5 deletions src/state/publish/get-dimension-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,14 @@ const getRecord = (draggable: DraggableDimension, home: DroppableDimension) => {
return record;
};

const timingKey: string = 'Dynamic dimension change processing';
const timingKey: string = 'Dynamic dimension change processing (just math)';

export default ({
existing,
publish,
windowScroll,
}: Args): DimensionMap => {
timings.start(timingKey);
// TODO: everything
const partitioned: Partitioned = Object.keys(publish.additions.draggables)
.map((id: DraggableId): DraggableDimension => publish.additions.draggables[id])
.reduce((previous: Partitioned, draggable: DraggableDimension) => {
Expand Down Expand Up @@ -129,7 +128,6 @@ export default ({
});

// ## Adjust draggables based on changes

const shifted: DraggableDimensionMap = Object.keys(existing.draggables)
.map((id: DraggableId): DraggableDimension => {
const draggable: DraggableDimension = existing.draggables[id];
Expand Down Expand Up @@ -160,15 +158,15 @@ export default ({
const additionSize: number = getTotal(additions);
const removalSize: number = getTotal(removals);
const deltaShift: number = additionSize - removalSize;
console.log('DELTA SHIFT', deltaShift);
// console.log('DELTA SHIFT', deltaShift);

const change: Position = patch(droppable.axis.line, deltaShift);
const client: BoxModel = offset(draggable.client, change);
// TODO: should this be different?
const page: BoxModel = withScroll(client, windowScroll);

const indexChange: number = additions.length - removals.length;
console.log('INDEX SHIFT', indexChange);
// console.log('INDEX SHIFT', indexChange);
const index: number = startIndex + indexChange;

const moved: DraggableDimension = {
Expand Down
96 changes: 96 additions & 0 deletions src/state/publish/get-drag-positions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// @flow
import invariant from 'invariant';
import type { Position } from 'css-box-model';
import { isEqual, subtract, add, negate } from '../position';
import getPageItemPositions from '../get-page-item-positions';
import type {
DragPositions,
Viewport,
ItemPositions,
} from '../../types';

type Args = {|
initial: DragPositions,
current: DragPositions,
oldClientBorderBoxCenter: Position,
newClientBorderBoxCenter: Position,
viewport: Viewport,
|}

type Result = {|
initial: DragPositions,
current: DragPositions,
|}

const origin: Position = { x: 0, y: 0 };

export default ({
initial: oldInitial,
current: oldCurrent,
oldClientBorderBoxCenter,
newClientBorderBoxCenter,
viewport,
}: Args): Result => {
// Nothing needs to be changed
if (isEqual(oldClientBorderBoxCenter, newClientBorderBoxCenter)) {
return { initial: oldInitial, current: oldCurrent };
}

// how much the dragging item has shifted
const centerDiff: Position = subtract(newClientBorderBoxCenter, oldClientBorderBoxCenter);
// const displacement: Position = negate(centerDiff);

console.log('center offset', centerDiff);

const clientSelection: Position = add(
oldInitial.client.selection, centerDiff
);
console.log('old client selection', oldInitial.client.selection);
console.log('new client selection', clientSelection);

const initial: DragPositions = (() => {
const client: ItemPositions = {
selection: clientSelection,
borderBoxCenter: newClientBorderBoxCenter,
offset: origin,
};

return {
client,
page: getPageItemPositions(client, viewport.scroll.initial),
};
})();

const offset: Position = subtract(
// The offset before the update
oldCurrent.client.offset,
// The change caused by the update
centerDiff,
);

const current: DragPositions = (() => {
const client: ItemPositions = {
selection: add(initial.client.selection, offset),
// this should be the same as the previous client borderBox center
borderBoxCenter: add(initial.client.borderBoxCenter, offset),
offset,
};

invariant(
isEqual(oldCurrent.client.borderBoxCenter, client.borderBoxCenter),
`
Incorrect new client center position.
Expected ${JSON.stringify(oldCurrent.client.borderBoxCenter)}
to equal ${JSON.stringify(client.borderBoxCenter)}
`
);

return {
client,
page: getPageItemPositions(client, viewport.scroll.current),
};
})();

return { current, initial };
};

30 changes: 23 additions & 7 deletions src/state/publish/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import type {
CollectingState,
DropPendingState,
Publish,
Critical,
DraggableId,
DraggableDimension,
} from '../../types';
import getDragImpact from '../get-drag-impact';
import getHomeImpact from '../get-home-impact';
import getDimensionMap from './get-dimension-map';
import getDragPositions from './get-drag-positions';

type Args = {|
state: CollectingState | DropPendingState,
Expand Down Expand Up @@ -52,17 +54,26 @@ export default ({
windowScroll: state.viewport.scroll.initial,
});

// TODO: need to update initial and current positions to reflect any change in starting
const dragging: DraggableId = state.critical.draggable.id;
const original: DraggableDimension = state.dimensions.draggables[dragging];
const updated: DraggableDimension = dimensions.draggables[dragging];
const centerDiff: Position = subtract(
updated.client.borderBox.center,
original.client.borderBox.center
);

const critical: Critical = {
droppable: state.critical.droppable,
// draggable index can change during a drag
draggable: updated.descriptor,
};

const { initial, current } = getDragPositions({
initial: state.initial,
current: state.current,
oldClientBorderBoxCenter: original.client.borderBox.center,
newClientBorderBoxCenter: updated.client.borderBox.center,
viewport: state.viewport,
});

const impact: DragImpact = getDragImpact({
pageBorderBoxCenter: state.current.page.borderBoxCenter,
pageBorderBoxCenter: current.page.borderBoxCenter,
draggable: dimensions.draggables[state.critical.draggable.id],
draggables: dimensions.draggables,
droppables: dimensions.droppables,
Expand All @@ -75,9 +86,14 @@ export default ({
phase: 'DRAGGING',
...state,
// eslint-disable-next-line
phase: 'DRAGGING',
phase: 'DRAGGING',
critical,
current,
initial,
impact,
dimensions,
// not animating this movement
shouldAnimate: false,
};

if (state.phase === 'COLLECTING') {
Expand Down
8 changes: 3 additions & 5 deletions src/state/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import publish from './publish';
import { add, isEqual, subtract } from './position';
import scrollViewport from './scroll-viewport';
import getHomeImpact from './get-home-impact';
import getPageItemPositions from './get-page-item-positions';
import type {
Action,
State,
Expand Down Expand Up @@ -79,11 +80,8 @@ const moveWithPositionUpdates = ({
};
})();

const page: ItemPositions = {
selection: add(client.selection, currentWindowScroll),
borderBoxCenter: add(client.borderBoxCenter, currentWindowScroll),
offset: add(client.offset, currentWindowScroll),
};
const page: ItemPositions = getPageItemPositions(client, currentWindowScroll);

const current: DragPositions = {
client, page,
};
Expand Down
2 changes: 1 addition & 1 deletion stories/src/dynamic/with-controls.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export default class WithControls extends React.Component<*, State> {
}

onDragUpdate = (update: DragUpdate) => {
console.log('current index:', update.destination ? update.destination.index : null);
console.log('Update: current index =>', update.destination ? update.destination.index : null);
}

onDragEnd = (result: DropResult) => {
Expand Down

0 comments on commit fdef7ae

Please sign in to comment.