mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 21:27:20 +00:00
114 lines
3.2 KiB
TypeScript
114 lines
3.2 KiB
TypeScript
import { Vec } from '@tldraw/vec';
|
|
import { TLDR } from '@toeverything/components/board-state';
|
|
import type {
|
|
TldrawCommand,
|
|
PagePartial,
|
|
} from '@toeverything/components/board-types';
|
|
import type { TldrawApp } from '@toeverything/components/board-state';
|
|
|
|
export function translateShapes(
|
|
app: TldrawApp,
|
|
ids: string[],
|
|
delta: number[]
|
|
): TldrawCommand {
|
|
const { currentPageId, selectedIds } = app;
|
|
|
|
// Clear session cache
|
|
app.rotationInfo.selectedIds = [...selectedIds];
|
|
|
|
const before: PagePartial = {
|
|
shapes: {},
|
|
bindings: {},
|
|
};
|
|
|
|
const after: PagePartial = {
|
|
shapes: {},
|
|
bindings: {},
|
|
};
|
|
|
|
const idsToMutate = ids
|
|
.flatMap(id => {
|
|
const shape = app.getShape(id);
|
|
return shape.children ? shape.children : shape.id;
|
|
})
|
|
.filter(id => !app.getShape(id).isLocked);
|
|
|
|
const change = TLDR.mutate_shapes(
|
|
app.state,
|
|
idsToMutate,
|
|
shape => ({
|
|
point: Vec.toFixed(Vec.add(shape.point, delta)),
|
|
}),
|
|
currentPageId
|
|
);
|
|
|
|
before.shapes = change.before;
|
|
after.shapes = change.after;
|
|
|
|
// Delete bindings from nudged shapes, unless both bound and bound-to shapes are selected
|
|
const bindingsToDelete = TLDR.get_bindings(app.state, currentPageId).filter(
|
|
binding => ids.includes(binding.fromId) && !ids.includes(binding.toId)
|
|
);
|
|
|
|
bindingsToDelete.forEach(binding => {
|
|
before.bindings[binding.id] = binding;
|
|
after.bindings[binding.id] = undefined;
|
|
|
|
for (const id of [binding.toId, binding.fromId]) {
|
|
// Let's also look at the bound shape...
|
|
const shape = app.getShape(id);
|
|
|
|
if (!shape.handles) continue;
|
|
|
|
// If the bound shape has a handle that references the deleted binding, delete that reference
|
|
|
|
Object.values(shape.handles)
|
|
.filter(handle => handle.bindingId === binding.id)
|
|
.forEach(handle => {
|
|
before.shapes[id] = {
|
|
...before.shapes[id],
|
|
handles: {
|
|
...before.shapes[id]?.handles,
|
|
[handle.id]: { bindingId: binding.id },
|
|
},
|
|
};
|
|
after.shapes[id] = {
|
|
...after.shapes[id],
|
|
handles: {
|
|
...after.shapes[id]?.handles,
|
|
[handle.id]: { bindingId: undefined },
|
|
},
|
|
};
|
|
});
|
|
}
|
|
});
|
|
|
|
return {
|
|
id: 'translate',
|
|
before: {
|
|
document: {
|
|
pages: {
|
|
[currentPageId]: before,
|
|
},
|
|
pageStates: {
|
|
[currentPageId]: {
|
|
selectedIds: ids,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
after: {
|
|
document: {
|
|
pages: {
|
|
[currentPageId]: after,
|
|
},
|
|
pageStates: {
|
|
[currentPageId]: {
|
|
selectedIds: ids,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
}
|