feat(canvas): enhance edge insertion animations and update reflow duration
- Added a new CSS animation for edge insertion to improve visual feedback during node creation. - Updated the edge insertion reflow duration from 997ms to 1297ms for smoother transitions. - Refactored related components to support the new animation and ensure consistent behavior across the canvas. - Enhanced tests to validate the new edge insertion features and animations.
This commit is contained in:
@@ -746,8 +746,6 @@ export function useCanvasSyncEngine({
|
||||
]);
|
||||
});
|
||||
|
||||
const createNodeWithEdgeSplitMut = useMutation(api.nodes.createWithEdgeSplit);
|
||||
|
||||
const createEdge = useMutation(api.edges.create).withOptimisticUpdate(
|
||||
(localStore, args) => {
|
||||
const edgeList = localStore.getQuery(api.edges.list, {
|
||||
@@ -849,7 +847,10 @@ export function useCanvasSyncEngine({
|
||||
|
||||
const addOptimisticNodeLocally = useCallback(
|
||||
(
|
||||
args: Parameters<typeof createNode>[0] & { clientRequestId: string },
|
||||
args: Parameters<typeof createNode>[0] & {
|
||||
clientRequestId: string;
|
||||
className?: string;
|
||||
},
|
||||
): Id<"nodes"> => {
|
||||
const optimisticNodeId = `${OPTIMISTIC_NODE_PREFIX}${args.clientRequestId}`;
|
||||
setNodes((current) => {
|
||||
@@ -866,6 +867,7 @@ export function useCanvasSyncEngine({
|
||||
style: { width: args.width, height: args.height },
|
||||
parentId: args.parentId as string | undefined,
|
||||
zIndex: args.zIndex,
|
||||
className: args.className,
|
||||
selected: false,
|
||||
},
|
||||
];
|
||||
@@ -1390,15 +1392,24 @@ export function useCanvasSyncEngine({
|
||||
);
|
||||
|
||||
const runCreateNodeWithEdgeSplitOnlineOnly = useCallback(
|
||||
async (args: Parameters<typeof createNodeWithEdgeSplitMut>[0]) => {
|
||||
async (args: Parameters<typeof createNodeWithEdgeSplitRaw>[0]) => {
|
||||
const clientRequestId = args.clientRequestId ?? crypto.randomUUID();
|
||||
const payload = { ...args, clientRequestId };
|
||||
const splitEdgeId = payload.splitEdgeId as string;
|
||||
|
||||
if (isSyncOnline) {
|
||||
return await createNodeWithEdgeSplitMut(payload);
|
||||
}
|
||||
controller.pendingConnectionCreatesRef.current.add(clientRequestId);
|
||||
|
||||
const optimisticNodeId = addOptimisticNodeLocally(payload);
|
||||
const originalSplitEdge = edgesRef.current.find(
|
||||
(edge) =>
|
||||
edge.id === splitEdgeId &&
|
||||
edge.className !== "temp" &&
|
||||
!isOptimisticEdgeId(edge.id),
|
||||
);
|
||||
|
||||
const optimisticNodeId = addOptimisticNodeLocally({
|
||||
...payload,
|
||||
className: "canvas-edge-insert-enter",
|
||||
});
|
||||
const splitApplied = applyEdgeSplitLocally({
|
||||
clientRequestId,
|
||||
splitEdgeId: payload.splitEdgeId,
|
||||
@@ -1411,6 +1422,34 @@ export function useCanvasSyncEngine({
|
||||
positionY: payload.positionY,
|
||||
});
|
||||
|
||||
if (isSyncOnline) {
|
||||
try {
|
||||
const realId = await trackPendingNodeCreate(
|
||||
clientRequestId,
|
||||
createNodeWithEdgeSplitRaw({ ...payload }),
|
||||
);
|
||||
await remapOptimisticNodeLocally(clientRequestId, realId);
|
||||
return realId;
|
||||
} catch (error) {
|
||||
removeOptimisticCreateLocally({
|
||||
clientRequestId,
|
||||
removeNode: true,
|
||||
removeEdge: true,
|
||||
});
|
||||
|
||||
if (splitApplied && originalSplitEdge) {
|
||||
setEdges((current) => {
|
||||
if (current.some((edge) => edge.id === originalSplitEdge.id)) {
|
||||
return current;
|
||||
}
|
||||
return [...current, originalSplitEdge];
|
||||
});
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
if (splitApplied) {
|
||||
await enqueueSyncMutation("createNodeWithEdgeSplit", payload);
|
||||
} else {
|
||||
@@ -1430,7 +1469,19 @@ export function useCanvasSyncEngine({
|
||||
|
||||
return optimisticNodeId;
|
||||
},
|
||||
[addOptimisticNodeLocally, applyEdgeSplitLocally, createNodeWithEdgeSplitMut, enqueueSyncMutation, isSyncOnline],
|
||||
[
|
||||
addOptimisticNodeLocally,
|
||||
applyEdgeSplitLocally,
|
||||
controller.pendingConnectionCreatesRef,
|
||||
createNodeWithEdgeSplitRaw,
|
||||
edgesRef,
|
||||
enqueueSyncMutation,
|
||||
isSyncOnline,
|
||||
remapOptimisticNodeLocally,
|
||||
removeOptimisticCreateLocally,
|
||||
setEdges,
|
||||
trackPendingNodeCreate,
|
||||
],
|
||||
);
|
||||
|
||||
const runBatchRemoveNodesMutation = useCallback<RunBatchRemoveNodesMutation>(
|
||||
|
||||
Reference in New Issue
Block a user