@agent-native/core 0.82.0 → 0.83.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +6 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/CommandMenu.tsx +34 -12
- package/corpus/templates/analytics/actions/hubspot-deals.ts +64 -4
- package/corpus/templates/content/.env.local.example +6 -0
- package/corpus/templates/content/AGENTS.md +10 -1
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +14 -1
- package/corpus/templates/content/actions/_builder-cms-source-adapter.ts +43 -0
- package/corpus/templates/content/actions/_builder-cms-write-adapter.ts +79 -7
- package/corpus/templates/content/actions/_database-source-utils.ts +987 -22
- package/corpus/templates/content/actions/_database-utils.ts +41 -0
- package/corpus/templates/content/actions/_local-file-documents.ts +74 -1
- package/corpus/templates/content/actions/attach-content-database-source.ts +33 -8
- package/corpus/templates/content/actions/change-content-database-source-role.ts +14 -0
- package/corpus/templates/content/actions/disconnect-content-database-source.ts +3 -0
- package/corpus/templates/content/actions/execute-builder-source-execution.ts +71 -3
- package/corpus/templates/content/actions/list-content-databases.ts +41 -33
- package/corpus/templates/content/actions/process-builder-body-hydration.ts +47 -0
- package/corpus/templates/content/actions/update-document.ts +93 -0
- package/corpus/templates/content/app/blocks/SourceComponentBlock.tsx +277 -0
- package/corpus/templates/content/app/blocks/contentBlockRegistry.tsx +2 -0
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +45 -4
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +5 -1
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +92 -0
- package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +5 -3
- package/corpus/templates/content/app/components/editor/extensions/registryBlocks.ts +41 -0
- package/corpus/templates/content/app/components/editor/registrySlashItems.ts +4 -0
- package/corpus/templates/content/app/global.css +10 -3
- package/corpus/templates/content/app/hooks/use-content-database.ts +24 -0
- package/corpus/templates/content/app/i18n/zh-TW.ts +24 -0
- package/corpus/templates/content/app/i18n-data.ts +212 -0
- package/corpus/templates/content/app/lib/content-command-search.ts +64 -0
- package/corpus/templates/content/app/root.tsx +236 -8
- package/corpus/templates/content/changelog/2026-06-29-builder-cms-sources-now-sync-article-bodies-through-content.md +6 -0
- package/corpus/templates/content/changelog/2026-06-30-builder-article-media-now-render-as-images-and-embeds-when-r.md +6 -0
- package/corpus/templates/content/changelog/2026-06-30-builder-source-components-now-render-as-preserved-preview-bl.md +6 -0
- package/corpus/templates/content/changelog/2026-06-30-cmd-k-search-now-opens-from-the-editor-and-finds-real-content.md +6 -0
- package/corpus/templates/content/package.json +3 -1
- package/corpus/templates/content/scripts/check-native-deps.mjs +57 -0
- package/corpus/templates/content/scripts/dev-database.mjs +83 -0
- package/corpus/templates/content/scripts/seed-demo-user.mjs +107 -0
- package/corpus/templates/content/server/db/schema.ts +27 -0
- package/corpus/templates/content/server/plugins/db.ts +33 -0
- package/corpus/templates/content/shared/api.ts +45 -0
- package/corpus/templates/content/shared/builder-mdx.ts +905 -5
- package/corpus/templates/content/shared/nfm-registry.ts +2 -0
- package/corpus/templates/content/shared/source-component-block.ts +141 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +5 -1
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +229 -131
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +103 -6
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +6 -3
- package/corpus/templates/design/app/pages/DesignEditor.tsx +382 -72
- package/corpus/templates/design/changelog/2026-06-30-canvas-editing-now-keeps-undo-redo-and-cross-screen-layer-mo.md +6 -0
- package/dist/client/CommandMenu.d.ts +6 -2
- package/dist/client/CommandMenu.d.ts.map +1 -1
- package/dist/client/CommandMenu.js +25 -14
- package/dist/client/CommandMenu.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +8 -8
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/package.json +1 -1
|
@@ -497,12 +497,6 @@ export function removeUndoRedoOrderKind<T extends string>(
|
|
|
497
497
|
|
|
498
498
|
type UndoRedoOrderKind = "content" | "file-content" | "geometry";
|
|
499
499
|
|
|
500
|
-
function isContentUndoRedoOrderKind(
|
|
501
|
-
kind: UndoRedoOrderKind | undefined,
|
|
502
|
-
): kind is "content" | "file-content" {
|
|
503
|
-
return kind === "content" || kind === "file-content";
|
|
504
|
-
}
|
|
505
|
-
|
|
506
500
|
function resolveZoomUpdate(update: SetStateAction<number>, current: number) {
|
|
507
501
|
return typeof update === "function" ? update(current) : update;
|
|
508
502
|
}
|
|
@@ -882,6 +876,32 @@ interface GeometryHistoryEntry {
|
|
|
882
876
|
after: CanvasFrameGeometryById;
|
|
883
877
|
}
|
|
884
878
|
|
|
879
|
+
function geometryHistoryEntryTouchesFrameIds(
|
|
880
|
+
entry: GeometryHistoryEntry,
|
|
881
|
+
frameIds: Set<string>,
|
|
882
|
+
) {
|
|
883
|
+
for (const frameId of frameIds) {
|
|
884
|
+
if (entry.before[frameId] || entry.after[frameId]) return true;
|
|
885
|
+
}
|
|
886
|
+
return false;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
function removeRecentUndoRedoOrderKinds<T extends string>(
|
|
890
|
+
order: T[],
|
|
891
|
+
kind: T,
|
|
892
|
+
count: number,
|
|
893
|
+
): T[] {
|
|
894
|
+
if (count <= 0) return order;
|
|
895
|
+
const next = [...order];
|
|
896
|
+
let remaining = count;
|
|
897
|
+
for (let index = next.length - 1; index >= 0 && remaining > 0; index -= 1) {
|
|
898
|
+
if (next[index] !== kind) continue;
|
|
899
|
+
next.splice(index, 1);
|
|
900
|
+
remaining -= 1;
|
|
901
|
+
}
|
|
902
|
+
return next;
|
|
903
|
+
}
|
|
904
|
+
|
|
885
905
|
export interface ContentHistoryChange {
|
|
886
906
|
fileId: string;
|
|
887
907
|
before: string;
|
|
@@ -911,6 +931,17 @@ export function getAvailableContentHistoryChanges(
|
|
|
911
931
|
);
|
|
912
932
|
}
|
|
913
933
|
|
|
934
|
+
function findLastContentHistoryChangeIndex(
|
|
935
|
+
stack: ContentHistoryChange[],
|
|
936
|
+
fileId?: string | null,
|
|
937
|
+
) {
|
|
938
|
+
if (!fileId) return -1;
|
|
939
|
+
for (let index = stack.length - 1; index >= 0; index -= 1) {
|
|
940
|
+
if (stack[index]?.fileId === fileId) return index;
|
|
941
|
+
}
|
|
942
|
+
return -1;
|
|
943
|
+
}
|
|
944
|
+
|
|
914
945
|
type PatchProofStatus =
|
|
915
946
|
| "runtime"
|
|
916
947
|
| "queued"
|
|
@@ -1457,14 +1488,19 @@ function primitiveLayerName(primitive: CanvasPrimitiveInsert): string {
|
|
|
1457
1488
|
function appendCanvasPrimitiveToHtml(
|
|
1458
1489
|
content: string,
|
|
1459
1490
|
primitive: CanvasPrimitiveInsert,
|
|
1491
|
+
options?: { preserveNegativePosition?: boolean },
|
|
1460
1492
|
): string | null {
|
|
1461
1493
|
if (typeof window === "undefined") return null;
|
|
1462
1494
|
try {
|
|
1463
1495
|
const doc = new DOMParser().parseFromString(content, "text/html");
|
|
1464
1496
|
if (!doc.body) return null;
|
|
1465
1497
|
const geometry = primitive.geometry;
|
|
1466
|
-
const left =
|
|
1467
|
-
|
|
1498
|
+
const left = options?.preserveNegativePosition
|
|
1499
|
+
? Math.round(geometry.x)
|
|
1500
|
+
: Math.max(0, Math.round(geometry.x));
|
|
1501
|
+
const top = options?.preserveNegativePosition
|
|
1502
|
+
? Math.round(geometry.y)
|
|
1503
|
+
: Math.max(0, Math.round(geometry.y));
|
|
1468
1504
|
const width = Math.max(1, Math.round(geometry.width));
|
|
1469
1505
|
const height = Math.max(1, Math.round(geometry.height));
|
|
1470
1506
|
const nodeId = primitive.nodeId ?? uniqueLayerId(primitive.kind);
|
|
@@ -3973,22 +4009,50 @@ export default function DesignEditor() {
|
|
|
3973
4009
|
const undoManagerRef = useRef<Y.UndoManager | null>(null);
|
|
3974
4010
|
const contentUndoStackRef = useRef<ContentHistoryEntry[]>([]);
|
|
3975
4011
|
const contentRedoStackRef = useRef<ContentHistoryEntry[]>([]);
|
|
4012
|
+
const localContentUndoStackRef = useRef<ContentHistoryChange[]>([]);
|
|
4013
|
+
const localContentRedoStackRef = useRef<ContentHistoryChange[]>([]);
|
|
4014
|
+
const activeFileIdForUndoRef = useRef<string | null>(null);
|
|
3976
4015
|
const suppressContentHistoryRef = useRef(false);
|
|
3977
4016
|
const geometryUndoStackRef = useRef<GeometryHistoryEntry[]>([]);
|
|
3978
4017
|
const geometryRedoStackRef = useRef<GeometryHistoryEntry[]>([]);
|
|
3979
4018
|
const historyOrderRef = useRef<UndoRedoOrderKind[]>([]);
|
|
3980
4019
|
const redoOrderRef = useRef<UndoRedoOrderKind[]>([]);
|
|
4020
|
+
const clearRedoStacks = useCallback(() => {
|
|
4021
|
+
contentRedoStackRef.current = [];
|
|
4022
|
+
localContentRedoStackRef.current = [];
|
|
4023
|
+
geometryRedoStackRef.current = [];
|
|
4024
|
+
redoOrderRef.current = [];
|
|
4025
|
+
undoManagerRef.current?.clear(false, true);
|
|
4026
|
+
}, []);
|
|
3981
4027
|
const syncUndoRedoState = useCallback(() => {
|
|
3982
4028
|
const undoManager = undoManagerRef.current;
|
|
4029
|
+
const canUseOverviewHistory = viewModeRef.current === "overview";
|
|
4030
|
+
const activeHistoryFileId = activeFileIdForUndoRef.current;
|
|
4031
|
+
const hasLocalUndo =
|
|
4032
|
+
!canUseOverviewHistory &&
|
|
4033
|
+
findLastContentHistoryChangeIndex(
|
|
4034
|
+
localContentUndoStackRef.current,
|
|
4035
|
+
activeHistoryFileId,
|
|
4036
|
+
) !== -1;
|
|
4037
|
+
const hasLocalRedo =
|
|
4038
|
+
!canUseOverviewHistory &&
|
|
4039
|
+
findLastContentHistoryChangeIndex(
|
|
4040
|
+
localContentRedoStackRef.current,
|
|
4041
|
+
activeHistoryFileId,
|
|
4042
|
+
) !== -1;
|
|
3983
4043
|
setCanUndo(
|
|
3984
4044
|
Boolean(undoManager?.canUndo()) ||
|
|
3985
|
-
|
|
3986
|
-
|
|
4045
|
+
hasLocalUndo ||
|
|
4046
|
+
(canUseOverviewHistory &&
|
|
4047
|
+
(contentUndoStackRef.current.length > 0 ||
|
|
4048
|
+
geometryUndoStackRef.current.length > 0)),
|
|
3987
4049
|
);
|
|
3988
4050
|
setCanRedo(
|
|
3989
4051
|
Boolean(undoManager?.canRedo()) ||
|
|
3990
|
-
|
|
3991
|
-
|
|
4052
|
+
hasLocalRedo ||
|
|
4053
|
+
(canUseOverviewHistory &&
|
|
4054
|
+
(contentRedoStackRef.current.length > 0 ||
|
|
4055
|
+
geometryRedoStackRef.current.length > 0)),
|
|
3992
4056
|
);
|
|
3993
4057
|
}, []);
|
|
3994
4058
|
const recordContentHistoryEntry = useCallback(
|
|
@@ -3997,23 +4061,59 @@ export default function DesignEditor() {
|
|
|
3997
4061
|
(change) => change.before !== change.after,
|
|
3998
4062
|
);
|
|
3999
4063
|
if (changes.length === 0) return;
|
|
4064
|
+
const activeHistoryFileId = activeFileIdForUndoRef.current;
|
|
4065
|
+
if (
|
|
4066
|
+
activeHistoryFileId &&
|
|
4067
|
+
changes.some((change) => change.fileId === activeHistoryFileId)
|
|
4068
|
+
) {
|
|
4069
|
+
undoManagerRef.current?.clear(true, false);
|
|
4070
|
+
localContentUndoStackRef.current =
|
|
4071
|
+
localContentUndoStackRef.current.filter(
|
|
4072
|
+
(change) => change.fileId !== activeHistoryFileId,
|
|
4073
|
+
);
|
|
4074
|
+
localContentRedoStackRef.current =
|
|
4075
|
+
localContentRedoStackRef.current.filter(
|
|
4076
|
+
(change) => change.fileId !== activeHistoryFileId,
|
|
4077
|
+
);
|
|
4078
|
+
historyOrderRef.current = removeUndoRedoOrderKind(
|
|
4079
|
+
historyOrderRef.current,
|
|
4080
|
+
"content",
|
|
4081
|
+
);
|
|
4082
|
+
redoOrderRef.current = removeUndoRedoOrderKind(
|
|
4083
|
+
redoOrderRef.current,
|
|
4084
|
+
"content",
|
|
4085
|
+
);
|
|
4086
|
+
}
|
|
4000
4087
|
contentUndoStackRef.current = [
|
|
4001
4088
|
...contentUndoStackRef.current.slice(-(MAX_DESIGN_UNDO_STACK - 1)),
|
|
4002
4089
|
changes.length === 1 ? changes[0] : { changes },
|
|
4003
4090
|
];
|
|
4004
|
-
|
|
4091
|
+
clearRedoStacks();
|
|
4005
4092
|
historyOrderRef.current = [
|
|
4006
4093
|
...historyOrderRef.current.slice(-(MAX_DESIGN_UNDO_STACK - 1)),
|
|
4007
4094
|
"file-content",
|
|
4008
4095
|
];
|
|
4009
|
-
redoOrderRef.current = [];
|
|
4010
4096
|
syncUndoRedoState();
|
|
4011
4097
|
},
|
|
4012
|
-
[syncUndoRedoState],
|
|
4098
|
+
[clearRedoStacks, syncUndoRedoState],
|
|
4099
|
+
);
|
|
4100
|
+
const recordLocalContentHistoryEntry = useCallback(
|
|
4101
|
+
(change: ContentHistoryChange) => {
|
|
4102
|
+
if (change.before === change.after) return;
|
|
4103
|
+
localContentUndoStackRef.current = [
|
|
4104
|
+
...localContentUndoStackRef.current.slice(-(MAX_DESIGN_UNDO_STACK - 1)),
|
|
4105
|
+
change,
|
|
4106
|
+
];
|
|
4107
|
+
clearRedoStacks();
|
|
4108
|
+
syncUndoRedoState();
|
|
4109
|
+
},
|
|
4110
|
+
[clearRedoStacks, syncUndoRedoState],
|
|
4013
4111
|
);
|
|
4014
4112
|
const clearLocalUndoRedoStacks = useCallback(() => {
|
|
4015
4113
|
contentUndoStackRef.current = [];
|
|
4016
4114
|
contentRedoStackRef.current = [];
|
|
4115
|
+
localContentUndoStackRef.current = [];
|
|
4116
|
+
localContentRedoStackRef.current = [];
|
|
4017
4117
|
geometryUndoStackRef.current = [];
|
|
4018
4118
|
geometryRedoStackRef.current = [];
|
|
4019
4119
|
historyOrderRef.current = [];
|
|
@@ -5160,14 +5260,11 @@ export default function DesignEditor() {
|
|
|
5160
5260
|
after: afterSnapshot,
|
|
5161
5261
|
},
|
|
5162
5262
|
];
|
|
5163
|
-
|
|
5164
|
-
contentRedoStackRef.current = [];
|
|
5165
|
-
undoManagerRef.current?.clear(false, true);
|
|
5263
|
+
clearRedoStacks();
|
|
5166
5264
|
historyOrderRef.current = [
|
|
5167
5265
|
...historyOrderRef.current.slice(-(MAX_DESIGN_UNDO_STACK - 1)),
|
|
5168
5266
|
"geometry",
|
|
5169
5267
|
];
|
|
5170
|
-
redoOrderRef.current = [];
|
|
5171
5268
|
const resizedFrameIds = viewportChangedFrameIds(
|
|
5172
5269
|
beforeSnapshot,
|
|
5173
5270
|
afterSnapshot,
|
|
@@ -5180,7 +5277,7 @@ export default function DesignEditor() {
|
|
|
5180
5277
|
);
|
|
5181
5278
|
syncUndoRedoState();
|
|
5182
5279
|
},
|
|
5183
|
-
[syncUndoRedoState, writeFrameGeometrySnapshot],
|
|
5280
|
+
[clearRedoStacks, syncUndoRedoState, writeFrameGeometrySnapshot],
|
|
5184
5281
|
);
|
|
5185
5282
|
|
|
5186
5283
|
// §6.6 — "Make this a real app" handler.
|
|
@@ -5356,6 +5453,7 @@ export default function DesignEditor() {
|
|
|
5356
5453
|
}, [files, activeFileId]);
|
|
5357
5454
|
|
|
5358
5455
|
const activeFile = files.find((f) => f.id === activeFileId) ?? files[0];
|
|
5456
|
+
activeFileIdForUndoRef.current = activeFile?.id ?? null;
|
|
5359
5457
|
const motionTimelineQueryParams =
|
|
5360
5458
|
id && activeFile?.id
|
|
5361
5459
|
? { designId: id, sourceRef: activeFile.id }
|
|
@@ -5862,6 +5960,7 @@ export default function DesignEditor() {
|
|
|
5862
5960
|
const [collabContentFileId, setCollabContentFileId] = useState<string | null>(
|
|
5863
5961
|
null,
|
|
5864
5962
|
);
|
|
5963
|
+
const previousDesignIdForHistoryRef = useRef<string | null>(null);
|
|
5865
5964
|
const prevActiveFileIdRef = useRef<string | null>(null);
|
|
5866
5965
|
// `updatedAt` of the DB content this preview currently reflects. A poll that
|
|
5867
5966
|
// returns an older-or-equal value is a stale snapshot and is ignored; a newer
|
|
@@ -5907,7 +6006,16 @@ export default function DesignEditor() {
|
|
|
5907
6006
|
};
|
|
5908
6007
|
}, [awareness, ydoc]);
|
|
5909
6008
|
|
|
5910
|
-
|
|
6009
|
+
useEffect(() => {
|
|
6010
|
+
if (previousDesignIdForHistoryRef.current === id) return;
|
|
6011
|
+
previousDesignIdForHistoryRef.current = id ?? null;
|
|
6012
|
+
clearLocalUndoRedoStacks();
|
|
6013
|
+
syncUndoRedoState();
|
|
6014
|
+
}, [clearLocalUndoRedoStacks, id, syncUndoRedoState]);
|
|
6015
|
+
|
|
6016
|
+
// Reset per-file reconcile state when switching files.
|
|
6017
|
+
// Keep undo/redo content + geometry stacks intact: overview mode needs one
|
|
6018
|
+
// chronological history across all screens, board edits, and frame geometry.
|
|
5911
6019
|
useEffect(() => {
|
|
5912
6020
|
if (viewMode === "overview") {
|
|
5913
6021
|
prevActiveFileIdRef.current = activeFileId;
|
|
@@ -5916,9 +6024,7 @@ export default function DesignEditor() {
|
|
|
5916
6024
|
lastAppliedFileUpdatedAtRef.current = null;
|
|
5917
6025
|
lastLocalContentRef.current = null;
|
|
5918
6026
|
latestActiveContentRef.current = null;
|
|
5919
|
-
clearLocalUndoRedoStacks();
|
|
5920
6027
|
clearStaleAgentCollabRecovery();
|
|
5921
|
-
syncUndoRedoState();
|
|
5922
6028
|
return;
|
|
5923
6029
|
}
|
|
5924
6030
|
if (activeFileId !== prevActiveFileIdRef.current) {
|
|
@@ -5928,17 +6034,9 @@ export default function DesignEditor() {
|
|
|
5928
6034
|
lastAppliedFileUpdatedAtRef.current = null;
|
|
5929
6035
|
lastLocalContentRef.current = null;
|
|
5930
6036
|
latestActiveContentRef.current = null;
|
|
5931
|
-
clearLocalUndoRedoStacks();
|
|
5932
6037
|
clearStaleAgentCollabRecovery();
|
|
5933
|
-
syncUndoRedoState();
|
|
5934
6038
|
}
|
|
5935
|
-
}, [
|
|
5936
|
-
activeFileId,
|
|
5937
|
-
clearLocalUndoRedoStacks,
|
|
5938
|
-
clearStaleAgentCollabRecovery,
|
|
5939
|
-
syncUndoRedoState,
|
|
5940
|
-
viewMode,
|
|
5941
|
-
]);
|
|
6039
|
+
}, [activeFileId, clearStaleAgentCollabRecovery, viewMode]);
|
|
5942
6040
|
|
|
5943
6041
|
useEffect(() => {
|
|
5944
6042
|
return clearStaleAgentCollabRecovery;
|
|
@@ -6102,12 +6200,19 @@ export default function DesignEditor() {
|
|
|
6102
6200
|
});
|
|
6103
6201
|
|
|
6104
6202
|
const syncState = () => syncUndoRedoState();
|
|
6105
|
-
const handleStackItemAdded = (
|
|
6203
|
+
const handleStackItemAdded = (event: {
|
|
6204
|
+
origin?: unknown;
|
|
6205
|
+
type?: "undo" | "redo";
|
|
6206
|
+
}) => {
|
|
6207
|
+
if (event.origin !== LOCAL_EDIT_ORIGIN || event.type !== "undo") {
|
|
6208
|
+
syncUndoRedoState();
|
|
6209
|
+
return;
|
|
6210
|
+
}
|
|
6106
6211
|
historyOrderRef.current = [
|
|
6107
6212
|
...historyOrderRef.current.slice(-(MAX_DESIGN_UNDO_STACK - 1)),
|
|
6108
6213
|
"content",
|
|
6109
6214
|
];
|
|
6110
|
-
|
|
6215
|
+
clearRedoStacks();
|
|
6111
6216
|
syncUndoRedoState();
|
|
6112
6217
|
};
|
|
6113
6218
|
um.on("stack-item-added", handleStackItemAdded);
|
|
@@ -6135,7 +6240,7 @@ export default function DesignEditor() {
|
|
|
6135
6240
|
);
|
|
6136
6241
|
syncUndoRedoState();
|
|
6137
6242
|
};
|
|
6138
|
-
}, [ydoc, isSynced, syncUndoRedoState]);
|
|
6243
|
+
}, [clearRedoStacks, ydoc, isSynced, syncUndoRedoState]);
|
|
6139
6244
|
|
|
6140
6245
|
// Reconcile authoritative external DB content (agent edit / peer-via-SQL) into
|
|
6141
6246
|
// the live preview. This is the robustness fallback the Yjs observe path can't
|
|
@@ -6887,6 +6992,7 @@ export default function DesignEditor() {
|
|
|
6887
6992
|
immediateSave?: boolean;
|
|
6888
6993
|
persist?: boolean;
|
|
6889
6994
|
recordHistory?: boolean;
|
|
6995
|
+
historyBeforeContent?: string;
|
|
6890
6996
|
updatedAt?: string;
|
|
6891
6997
|
} = {},
|
|
6892
6998
|
) => {
|
|
@@ -6894,12 +7000,18 @@ export default function DesignEditor() {
|
|
|
6894
7000
|
const shouldRecordHistory =
|
|
6895
7001
|
options.recordHistory !== false && !options.updatedAt;
|
|
6896
7002
|
const previousContent =
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
7003
|
+
typeof options.historyBeforeContent === "string"
|
|
7004
|
+
? options.historyBeforeContent
|
|
7005
|
+
: collabContentFileIdRef.current === activeFile.id &&
|
|
7006
|
+
typeof collabContentRef.current === "string"
|
|
7007
|
+
? collabContentRef.current
|
|
7008
|
+
: (activeFile.content ?? "");
|
|
6901
7009
|
const yjsHistoryAvailable = Boolean(
|
|
6902
|
-
shouldRecordHistory &&
|
|
7010
|
+
shouldRecordHistory &&
|
|
7011
|
+
viewModeRef.current !== "overview" &&
|
|
7012
|
+
ydoc &&
|
|
7013
|
+
isSynced &&
|
|
7014
|
+
undoManagerRef.current,
|
|
6903
7015
|
);
|
|
6904
7016
|
if (
|
|
6905
7017
|
!suppressContentHistoryRef.current &&
|
|
@@ -6907,11 +7019,16 @@ export default function DesignEditor() {
|
|
|
6907
7019
|
!yjsHistoryAvailable &&
|
|
6908
7020
|
previousContent !== nextContent
|
|
6909
7021
|
) {
|
|
6910
|
-
|
|
7022
|
+
const change = {
|
|
6911
7023
|
fileId: activeFile.id,
|
|
6912
7024
|
before: previousContent,
|
|
6913
7025
|
after: nextContent,
|
|
6914
|
-
}
|
|
7026
|
+
};
|
|
7027
|
+
if (viewModeRef.current === "overview") {
|
|
7028
|
+
recordContentHistoryEntry(change);
|
|
7029
|
+
} else {
|
|
7030
|
+
recordLocalContentHistoryEntry(change);
|
|
7031
|
+
}
|
|
6915
7032
|
}
|
|
6916
7033
|
if (options.updatedAt) {
|
|
6917
7034
|
clearPendingLocalFileContent(activeFile.id);
|
|
@@ -6972,7 +7089,7 @@ export default function DesignEditor() {
|
|
|
6972
7089
|
ytext.delete(0, ytext.length);
|
|
6973
7090
|
ytext.insert(0, nextContent);
|
|
6974
7091
|
},
|
|
6975
|
-
|
|
7092
|
+
yjsHistoryAvailable ? LOCAL_EDIT_ORIGIN : TAB_ID,
|
|
6976
7093
|
);
|
|
6977
7094
|
}
|
|
6978
7095
|
}
|
|
@@ -6996,6 +7113,7 @@ export default function DesignEditor() {
|
|
|
6996
7113
|
queueFileContentSave,
|
|
6997
7114
|
replacePreviewContent,
|
|
6998
7115
|
recordContentHistoryEntry,
|
|
7116
|
+
recordLocalContentHistoryEntry,
|
|
6999
7117
|
syncUndoRedoState,
|
|
7000
7118
|
ydoc,
|
|
7001
7119
|
],
|
|
@@ -7273,7 +7391,9 @@ export default function DesignEditor() {
|
|
|
7273
7391
|
: storedContent;
|
|
7274
7392
|
})()
|
|
7275
7393
|
: storedContent);
|
|
7276
|
-
const nextContent = appendCanvasPrimitiveToHtml(baseContent, primitive
|
|
7394
|
+
const nextContent = appendCanvasPrimitiveToHtml(baseContent, primitive, {
|
|
7395
|
+
preserveNegativePosition: targetFile.id === boardFileId,
|
|
7396
|
+
});
|
|
7277
7397
|
if (!nextContent) {
|
|
7278
7398
|
toast.error(t("designEditor.toasts.primitiveInsertFailed"));
|
|
7279
7399
|
return false;
|
|
@@ -7287,7 +7407,10 @@ export default function DesignEditor() {
|
|
|
7287
7407
|
: null;
|
|
7288
7408
|
|
|
7289
7409
|
if (targetFile.id === activeFile?.id) {
|
|
7290
|
-
applyLocalContentUpdate(nextContent, {
|
|
7410
|
+
applyLocalContentUpdate(nextContent, {
|
|
7411
|
+
historyBeforeContent: baseContent,
|
|
7412
|
+
immediateSave: true,
|
|
7413
|
+
});
|
|
7291
7414
|
} else {
|
|
7292
7415
|
recordContentHistoryEntry({
|
|
7293
7416
|
fileId: targetFile.id,
|
|
@@ -7335,6 +7458,7 @@ export default function DesignEditor() {
|
|
|
7335
7458
|
activeContent,
|
|
7336
7459
|
activeFile?.id,
|
|
7337
7460
|
applyLocalContentUpdate,
|
|
7461
|
+
boardFileId,
|
|
7338
7462
|
canEditDesign,
|
|
7339
7463
|
files,
|
|
7340
7464
|
id,
|
|
@@ -8369,6 +8493,28 @@ export default function DesignEditor() {
|
|
|
8369
8493
|
);
|
|
8370
8494
|
})
|
|
8371
8495
|
: null;
|
|
8496
|
+
const yjsHistoryAvailable = Boolean(
|
|
8497
|
+
viewModeRef.current !== "overview" &&
|
|
8498
|
+
ydoc &&
|
|
8499
|
+
isSynced &&
|
|
8500
|
+
undoManagerRef.current,
|
|
8501
|
+
);
|
|
8502
|
+
if (
|
|
8503
|
+
!yjsHistoryAvailable &&
|
|
8504
|
+
!suppressContentHistoryRef.current &&
|
|
8505
|
+
baseContent !== resolvedNextContent
|
|
8506
|
+
) {
|
|
8507
|
+
const change = {
|
|
8508
|
+
fileId: activeFile.id,
|
|
8509
|
+
before: baseContent,
|
|
8510
|
+
after: resolvedNextContent,
|
|
8511
|
+
};
|
|
8512
|
+
if (viewModeRef.current === "overview") {
|
|
8513
|
+
recordContentHistoryEntry(change);
|
|
8514
|
+
} else {
|
|
8515
|
+
recordLocalContentHistoryEntry(change);
|
|
8516
|
+
}
|
|
8517
|
+
}
|
|
8372
8518
|
|
|
8373
8519
|
setCollabContent(resolvedNextContent);
|
|
8374
8520
|
setCollabContentFileId(activeFile.id);
|
|
@@ -8381,14 +8527,18 @@ export default function DesignEditor() {
|
|
|
8381
8527
|
latestActiveContentRef.current = resolvedNextContent;
|
|
8382
8528
|
// Write the edit into the shared Y.Doc so other open clients see it live
|
|
8383
8529
|
// through Yjs (not only via the slower update-file → applyText round-trip).
|
|
8384
|
-
//
|
|
8530
|
+
// Single-screen edits use the active-file UndoManager. Overview edits are
|
|
8531
|
+
// tracked in the global file-content stack so all screens share one order.
|
|
8385
8532
|
if (ydoc && isSynced) {
|
|
8386
8533
|
const ytext = ydoc.getText("content");
|
|
8387
8534
|
if (ytext.toString() !== resolvedNextContent) {
|
|
8388
|
-
ydoc.transact(
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8535
|
+
ydoc.transact(
|
|
8536
|
+
() => {
|
|
8537
|
+
ytext.delete(0, ytext.length);
|
|
8538
|
+
ytext.insert(0, resolvedNextContent);
|
|
8539
|
+
},
|
|
8540
|
+
yjsHistoryAvailable ? LOCAL_EDIT_ORIGIN : TAB_ID,
|
|
8541
|
+
);
|
|
8392
8542
|
}
|
|
8393
8543
|
}
|
|
8394
8544
|
queueFileContentSave(activeFile.id, resolvedNextContent, {
|
|
@@ -8427,6 +8577,8 @@ export default function DesignEditor() {
|
|
|
8427
8577
|
activeBreakpointWidthState,
|
|
8428
8578
|
canEditDesign,
|
|
8429
8579
|
queueFileContentSave,
|
|
8580
|
+
recordContentHistoryEntry,
|
|
8581
|
+
recordLocalContentHistoryEntry,
|
|
8430
8582
|
replacePreviewContent,
|
|
8431
8583
|
selectedElement,
|
|
8432
8584
|
t,
|
|
@@ -9966,14 +10118,24 @@ export default function DesignEditor() {
|
|
|
9966
10118
|
resolvedSourceNode?.dataAttributes["data-agent-native-node-id"] ??
|
|
9967
10119
|
sourceNodeId ??
|
|
9968
10120
|
sourceSelector;
|
|
10121
|
+
const destProjection = buildCodeLayerProjection(destContent);
|
|
10122
|
+
const resolvedTargetAnchor = targetAnchorNodeId
|
|
10123
|
+
? resolveCodeLayerNodeFromBridge(
|
|
10124
|
+
destProjection,
|
|
10125
|
+
undefined,
|
|
10126
|
+
targetAnchorNodeId,
|
|
10127
|
+
)
|
|
10128
|
+
: null;
|
|
10129
|
+
const targetAnchorAttrId =
|
|
10130
|
+
resolvedTargetAnchor?.dataAttributes["data-agent-native-node-id"];
|
|
9969
10131
|
|
|
9970
10132
|
// Use hit-test anchor when the canvas supplied one; fall back to
|
|
9971
10133
|
// top-level body append ("inside" with no anchor = existing behaviour).
|
|
9972
10134
|
const result = moveNodeBetweenDocuments(sourceContent, destContent, {
|
|
9973
10135
|
nodeId: nodeAttrId,
|
|
9974
|
-
...(
|
|
10136
|
+
...(targetAnchorAttrId
|
|
9975
10137
|
? {
|
|
9976
|
-
anchorNodeId:
|
|
10138
|
+
anchorNodeId: targetAnchorAttrId,
|
|
9977
10139
|
placement: targetAnchorPlacement ?? "inside",
|
|
9978
10140
|
}
|
|
9979
10141
|
: { placement: "inside" }),
|
|
@@ -10077,6 +10239,38 @@ export default function DesignEditor() {
|
|
|
10077
10239
|
delete nextGeometry[file.id];
|
|
10078
10240
|
});
|
|
10079
10241
|
|
|
10242
|
+
const nextGeometryUndoStack: GeometryHistoryEntry[] = [];
|
|
10243
|
+
let removedGeometryUndoEntries = 0;
|
|
10244
|
+
geometryUndoStackRef.current.forEach((entry) => {
|
|
10245
|
+
if (geometryHistoryEntryTouchesFrameIds(entry, deleteIds)) {
|
|
10246
|
+
removedGeometryUndoEntries += 1;
|
|
10247
|
+
return;
|
|
10248
|
+
}
|
|
10249
|
+
nextGeometryUndoStack.push(entry);
|
|
10250
|
+
});
|
|
10251
|
+
geometryUndoStackRef.current = nextGeometryUndoStack;
|
|
10252
|
+
historyOrderRef.current = removeRecentUndoRedoOrderKinds(
|
|
10253
|
+
historyOrderRef.current,
|
|
10254
|
+
"geometry",
|
|
10255
|
+
removedGeometryUndoEntries,
|
|
10256
|
+
);
|
|
10257
|
+
|
|
10258
|
+
const nextGeometryRedoStack: GeometryHistoryEntry[] = [];
|
|
10259
|
+
let removedGeometryRedoEntries = 0;
|
|
10260
|
+
geometryRedoStackRef.current.forEach((entry) => {
|
|
10261
|
+
if (geometryHistoryEntryTouchesFrameIds(entry, deleteIds)) {
|
|
10262
|
+
removedGeometryRedoEntries += 1;
|
|
10263
|
+
return;
|
|
10264
|
+
}
|
|
10265
|
+
nextGeometryRedoStack.push(entry);
|
|
10266
|
+
});
|
|
10267
|
+
geometryRedoStackRef.current = nextGeometryRedoStack;
|
|
10268
|
+
redoOrderRef.current = removeRecentUndoRedoOrderKinds(
|
|
10269
|
+
redoOrderRef.current,
|
|
10270
|
+
"geometry",
|
|
10271
|
+
removedGeometryRedoEntries,
|
|
10272
|
+
);
|
|
10273
|
+
|
|
10080
10274
|
writeFrameGeometrySnapshot(nextGeometry);
|
|
10081
10275
|
queryClient.setQueryData(["action", "get-design", { id }], (old: any) => {
|
|
10082
10276
|
if (!old || typeof old !== "object" || !Array.isArray(old.files)) {
|
|
@@ -10109,7 +10303,12 @@ export default function DesignEditor() {
|
|
|
10109
10303
|
});
|
|
10110
10304
|
});
|
|
10111
10305
|
|
|
10112
|
-
|
|
10306
|
+
// File-backed screen deletion is not a geometry-only edit. The screen rows
|
|
10307
|
+
// are hard-deleted, so suppress MultiScreenCanvas' local frame-history
|
|
10308
|
+
// entry; otherwise undo would restore geometry for files that no longer
|
|
10309
|
+
// exist.
|
|
10310
|
+
syncUndoRedoState();
|
|
10311
|
+
return false;
|
|
10113
10312
|
},
|
|
10114
10313
|
[
|
|
10115
10314
|
activeFile,
|
|
@@ -10119,6 +10318,7 @@ export default function DesignEditor() {
|
|
|
10119
10318
|
files,
|
|
10120
10319
|
id,
|
|
10121
10320
|
queryClient,
|
|
10321
|
+
syncUndoRedoState,
|
|
10122
10322
|
t,
|
|
10123
10323
|
writeFrameGeometrySnapshot,
|
|
10124
10324
|
],
|
|
@@ -10213,8 +10413,10 @@ export default function DesignEditor() {
|
|
|
10213
10413
|
const handleUndo = useCallback(() => {
|
|
10214
10414
|
if (!canEditDesign) return;
|
|
10215
10415
|
const um = undoManagerRef.current;
|
|
10216
|
-
const
|
|
10217
|
-
|
|
10416
|
+
const canUseOverviewHistory = viewModeRef.current === "overview";
|
|
10417
|
+
let prunedUndoHistory = false;
|
|
10418
|
+
const undoContent = (scope: "any" | "local" | "global" = "any") => {
|
|
10419
|
+
if (scope !== "global" && um?.canUndo()) {
|
|
10218
10420
|
um.undo();
|
|
10219
10421
|
if (ydoc && activeFile) {
|
|
10220
10422
|
const next = ydoc.getText("content").toString();
|
|
@@ -10247,6 +10449,43 @@ export default function DesignEditor() {
|
|
|
10247
10449
|
return true;
|
|
10248
10450
|
}
|
|
10249
10451
|
|
|
10452
|
+
if (!canUseOverviewHistory && scope !== "global" && activeFile?.id) {
|
|
10453
|
+
const localIndex = findLastContentHistoryChangeIndex(
|
|
10454
|
+
localContentUndoStackRef.current,
|
|
10455
|
+
activeFile.id,
|
|
10456
|
+
);
|
|
10457
|
+
if (localIndex !== -1) {
|
|
10458
|
+
const [entry] = localContentUndoStackRef.current.splice(
|
|
10459
|
+
localIndex,
|
|
10460
|
+
1,
|
|
10461
|
+
);
|
|
10462
|
+
if (entry) {
|
|
10463
|
+
localContentRedoStackRef.current = [
|
|
10464
|
+
...localContentRedoStackRef.current.slice(
|
|
10465
|
+
-(MAX_DESIGN_UNDO_STACK - 1),
|
|
10466
|
+
),
|
|
10467
|
+
entry,
|
|
10468
|
+
];
|
|
10469
|
+
applyLocalContentUpdate(entry.before, {
|
|
10470
|
+
refreshPreview: false,
|
|
10471
|
+
immediateSave: true,
|
|
10472
|
+
recordHistory: false,
|
|
10473
|
+
});
|
|
10474
|
+
setSelectedElement((prev) => {
|
|
10475
|
+
if (!prev) return prev;
|
|
10476
|
+
return refreshElementInfoFromContent(entry.before, prev);
|
|
10477
|
+
});
|
|
10478
|
+
setHoveredElement((prev) => {
|
|
10479
|
+
if (!prev) return prev;
|
|
10480
|
+
return refreshElementInfoFromContent(entry.before, prev);
|
|
10481
|
+
});
|
|
10482
|
+
return true;
|
|
10483
|
+
}
|
|
10484
|
+
}
|
|
10485
|
+
}
|
|
10486
|
+
|
|
10487
|
+
if (scope === "local") return false;
|
|
10488
|
+
if (!canUseOverviewHistory) return false;
|
|
10250
10489
|
const entry =
|
|
10251
10490
|
contentUndoStackRef.current[contentUndoStackRef.current.length - 1];
|
|
10252
10491
|
if (!entry) return false;
|
|
@@ -10255,7 +10494,11 @@ export default function DesignEditor() {
|
|
|
10255
10494
|
files.map((file) => file.id),
|
|
10256
10495
|
activeFile?.id,
|
|
10257
10496
|
);
|
|
10258
|
-
if (changes.length === 0)
|
|
10497
|
+
if (changes.length === 0) {
|
|
10498
|
+
contentUndoStackRef.current.pop();
|
|
10499
|
+
prunedUndoHistory = true;
|
|
10500
|
+
return false;
|
|
10501
|
+
}
|
|
10259
10502
|
contentUndoStackRef.current.pop();
|
|
10260
10503
|
contentRedoStackRef.current = [
|
|
10261
10504
|
...contentRedoStackRef.current.slice(-(MAX_DESIGN_UNDO_STACK - 1)),
|
|
@@ -10300,6 +10543,7 @@ export default function DesignEditor() {
|
|
|
10300
10543
|
return true;
|
|
10301
10544
|
};
|
|
10302
10545
|
const undoGeometry = () => {
|
|
10546
|
+
if (!canUseOverviewHistory) return false;
|
|
10303
10547
|
const entry = geometryUndoStackRef.current.pop();
|
|
10304
10548
|
if (!entry) return false;
|
|
10305
10549
|
geometryRedoStackRef.current = [
|
|
@@ -10319,14 +10563,25 @@ export default function DesignEditor() {
|
|
|
10319
10563
|
return true;
|
|
10320
10564
|
};
|
|
10321
10565
|
|
|
10322
|
-
const
|
|
10323
|
-
const didUndo =
|
|
10566
|
+
const undoByOrder = (preferred?: UndoRedoOrderKind) =>
|
|
10324
10567
|
preferred === "geometry"
|
|
10325
10568
|
? undoGeometry() || undoContent()
|
|
10326
|
-
:
|
|
10327
|
-
? undoContent() || undoGeometry()
|
|
10328
|
-
:
|
|
10329
|
-
|
|
10569
|
+
: preferred === "file-content"
|
|
10570
|
+
? undoContent("global") || undoGeometry()
|
|
10571
|
+
: preferred === "content"
|
|
10572
|
+
? undoContent("local") || undoContent("global") || undoGeometry()
|
|
10573
|
+
: undoContent() || undoGeometry();
|
|
10574
|
+
let didUndo = false;
|
|
10575
|
+
if (canUseOverviewHistory) {
|
|
10576
|
+
while (!didUndo) {
|
|
10577
|
+
const preferred = historyOrderRef.current.pop();
|
|
10578
|
+
didUndo = undoByOrder(preferred);
|
|
10579
|
+
if (didUndo || preferred === undefined) break;
|
|
10580
|
+
}
|
|
10581
|
+
} else {
|
|
10582
|
+
didUndo = undoContent("local");
|
|
10583
|
+
}
|
|
10584
|
+
if (didUndo || prunedUndoHistory) {
|
|
10330
10585
|
syncUndoRedoState();
|
|
10331
10586
|
}
|
|
10332
10587
|
}, [
|
|
@@ -10347,8 +10602,10 @@ export default function DesignEditor() {
|
|
|
10347
10602
|
const handleRedo = useCallback(() => {
|
|
10348
10603
|
if (!canEditDesign) return;
|
|
10349
10604
|
const um = undoManagerRef.current;
|
|
10350
|
-
const
|
|
10351
|
-
|
|
10605
|
+
const canUseOverviewHistory = viewModeRef.current === "overview";
|
|
10606
|
+
let prunedRedoHistory = false;
|
|
10607
|
+
const redoContent = (scope: "any" | "local" | "global" = "any") => {
|
|
10608
|
+
if (scope !== "global" && um?.canRedo()) {
|
|
10352
10609
|
um.redo();
|
|
10353
10610
|
if (ydoc && activeFile) {
|
|
10354
10611
|
const next = ydoc.getText("content").toString();
|
|
@@ -10381,6 +10638,43 @@ export default function DesignEditor() {
|
|
|
10381
10638
|
return true;
|
|
10382
10639
|
}
|
|
10383
10640
|
|
|
10641
|
+
if (!canUseOverviewHistory && scope !== "global" && activeFile?.id) {
|
|
10642
|
+
const localIndex = findLastContentHistoryChangeIndex(
|
|
10643
|
+
localContentRedoStackRef.current,
|
|
10644
|
+
activeFile.id,
|
|
10645
|
+
);
|
|
10646
|
+
if (localIndex !== -1) {
|
|
10647
|
+
const [entry] = localContentRedoStackRef.current.splice(
|
|
10648
|
+
localIndex,
|
|
10649
|
+
1,
|
|
10650
|
+
);
|
|
10651
|
+
if (entry) {
|
|
10652
|
+
localContentUndoStackRef.current = [
|
|
10653
|
+
...localContentUndoStackRef.current.slice(
|
|
10654
|
+
-(MAX_DESIGN_UNDO_STACK - 1),
|
|
10655
|
+
),
|
|
10656
|
+
entry,
|
|
10657
|
+
];
|
|
10658
|
+
applyLocalContentUpdate(entry.after, {
|
|
10659
|
+
refreshPreview: false,
|
|
10660
|
+
immediateSave: true,
|
|
10661
|
+
recordHistory: false,
|
|
10662
|
+
});
|
|
10663
|
+
setSelectedElement((prev) => {
|
|
10664
|
+
if (!prev) return prev;
|
|
10665
|
+
return refreshElementInfoFromContent(entry.after, prev);
|
|
10666
|
+
});
|
|
10667
|
+
setHoveredElement((prev) => {
|
|
10668
|
+
if (!prev) return prev;
|
|
10669
|
+
return refreshElementInfoFromContent(entry.after, prev);
|
|
10670
|
+
});
|
|
10671
|
+
return true;
|
|
10672
|
+
}
|
|
10673
|
+
}
|
|
10674
|
+
}
|
|
10675
|
+
|
|
10676
|
+
if (scope === "local") return false;
|
|
10677
|
+
if (!canUseOverviewHistory) return false;
|
|
10384
10678
|
const entry =
|
|
10385
10679
|
contentRedoStackRef.current[contentRedoStackRef.current.length - 1];
|
|
10386
10680
|
if (!entry) return false;
|
|
@@ -10389,7 +10683,11 @@ export default function DesignEditor() {
|
|
|
10389
10683
|
files.map((file) => file.id),
|
|
10390
10684
|
activeFile?.id,
|
|
10391
10685
|
);
|
|
10392
|
-
if (changes.length === 0)
|
|
10686
|
+
if (changes.length === 0) {
|
|
10687
|
+
contentRedoStackRef.current.pop();
|
|
10688
|
+
prunedRedoHistory = true;
|
|
10689
|
+
return false;
|
|
10690
|
+
}
|
|
10393
10691
|
contentRedoStackRef.current.pop();
|
|
10394
10692
|
contentUndoStackRef.current = [
|
|
10395
10693
|
...contentUndoStackRef.current.slice(-(MAX_DESIGN_UNDO_STACK - 1)),
|
|
@@ -10434,6 +10732,7 @@ export default function DesignEditor() {
|
|
|
10434
10732
|
return true;
|
|
10435
10733
|
};
|
|
10436
10734
|
const redoGeometry = () => {
|
|
10735
|
+
if (!canUseOverviewHistory) return false;
|
|
10437
10736
|
const entry = geometryRedoStackRef.current.pop();
|
|
10438
10737
|
if (!entry) return false;
|
|
10439
10738
|
geometryUndoStackRef.current = [
|
|
@@ -10453,14 +10752,25 @@ export default function DesignEditor() {
|
|
|
10453
10752
|
return true;
|
|
10454
10753
|
};
|
|
10455
10754
|
|
|
10456
|
-
const
|
|
10457
|
-
const didRedo =
|
|
10755
|
+
const redoByOrder = (preferred?: UndoRedoOrderKind) =>
|
|
10458
10756
|
preferred === "geometry"
|
|
10459
10757
|
? redoGeometry() || redoContent()
|
|
10460
|
-
:
|
|
10461
|
-
? redoContent() || redoGeometry()
|
|
10462
|
-
:
|
|
10463
|
-
|
|
10758
|
+
: preferred === "file-content"
|
|
10759
|
+
? redoContent("global") || redoGeometry()
|
|
10760
|
+
: preferred === "content"
|
|
10761
|
+
? redoContent("local") || redoContent("global") || redoGeometry()
|
|
10762
|
+
: redoContent() || redoGeometry();
|
|
10763
|
+
let didRedo = false;
|
|
10764
|
+
if (canUseOverviewHistory) {
|
|
10765
|
+
while (!didRedo) {
|
|
10766
|
+
const preferred = redoOrderRef.current.pop();
|
|
10767
|
+
didRedo = redoByOrder(preferred);
|
|
10768
|
+
if (didRedo || preferred === undefined) break;
|
|
10769
|
+
}
|
|
10770
|
+
} else {
|
|
10771
|
+
didRedo = redoContent("local");
|
|
10772
|
+
}
|
|
10773
|
+
if (didRedo || prunedRedoHistory) {
|
|
10464
10774
|
syncUndoRedoState();
|
|
10465
10775
|
}
|
|
10466
10776
|
}, [
|
|
@@ -11725,7 +12035,7 @@ ${serializedHtml}
|
|
|
11725
12035
|
},
|
|
11726
12036
|
});
|
|
11727
12037
|
if (!stamped.changed || stamped.content === activeContent) return;
|
|
11728
|
-
applyLocalContentUpdate(stamped.content);
|
|
12038
|
+
applyLocalContentUpdate(stamped.content, { recordHistory: false });
|
|
11729
12039
|
}, [activeContent, activeFile, applyLocalContentUpdate, id, viewMode]);
|
|
11730
12040
|
const activeCodeLayerTree = useMemo(
|
|
11731
12041
|
() => buildCodeLayerTree(activeCodeLayerProjection),
|