@agent-native/core 0.163.4 → 0.164.3
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/templates/analytics/app/components/agents/FeatureFlagsFleetPanel.tsx +78 -19
- package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +29 -0
- package/corpus/templates/analytics/app/lib/use-auto-focus-select.ts +4 -4
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +6 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -2
- package/corpus/templates/analytics/app/routes/_index.tsx +3 -2
- package/corpus/templates/analytics/app/routes/adhoc.$id.tsx +7 -2
- package/corpus/templates/analytics/app/routes/dashboard.tsx +3 -2
- package/corpus/templates/analytics/app/routes/overview.tsx +3 -2
- package/corpus/templates/analytics/app/routes/traffic.tsx +3 -2
- package/corpus/templates/analytics/changelog/2026-08-18-verify-cross-app-feature-flag-changes.md +6 -0
- package/corpus/templates/analytics/netlify.toml +2 -0
- package/corpus/templates/analytics/server/lib/workspace-feature-flags.ts +196 -48
- package/corpus/templates/analytics/server/plugins/feature-flags.ts +5 -0
- package/corpus/templates/analytics/shared/feature-flags.ts +10 -0
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +5 -1
- package/corpus/templates/assets/app/routes/brand-kits._index.tsx +4 -1
- package/corpus/templates/assets/app/routes/libraries.tsx +4 -1
- package/corpus/templates/assets/app/routes/picker.tsx +4 -1
- package/corpus/templates/assets/netlify.toml +2 -0
- package/corpus/templates/brain/netlify.toml +2 -0
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +2 -1
- package/corpus/templates/calendar/changelog/2026-08-19-calendar-page-loads-stay-fast-after-idle-periods.md +6 -0
- package/corpus/templates/calendar/netlify.toml +2 -0
- package/corpus/templates/chat/netlify.toml +2 -0
- package/corpus/templates/clips/app/components/player/player-controls.tsx +3 -3
- package/corpus/templates/clips/app/components/player/reaction-emojis.ts +12 -0
- package/corpus/templates/clips/app/components/player/reactions-tray.tsx +90 -9
- package/corpus/templates/clips/app/components/player/scrubber.tsx +43 -10
- package/corpus/templates/clips/app/components/player/video-player.tsx +105 -15
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +1 -2
- package/corpus/templates/clips/app/routes/_app.wispr.tsx +2 -1
- package/corpus/templates/clips/app/routes/_index.tsx +7 -3
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +13 -8
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +15 -8
- package/corpus/templates/clips/netlify.toml +2 -0
- package/corpus/templates/clips/server/routes/[...page].head.ts +5 -0
- package/corpus/templates/content/netlify.toml +2 -0
- package/corpus/templates/design/.agents/skills/design-editor-architecture/SKILL.md +103 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +2 -1
- package/corpus/templates/design/AGENTS.md +3 -1
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +3 -2
- package/corpus/templates/design/app/components/design/editor/AgentNativeMenuMark.tsx +25 -0
- package/corpus/templates/design/app/components/design/editor/DesignBottomToolbar.tsx +411 -0
- package/corpus/templates/design/app/components/design/editor/DesignCollaborators.tsx +153 -0
- package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +231 -0
- package/corpus/templates/design/app/components/design/editor/MakeRealDialog.tsx +223 -0
- package/corpus/templates/design/app/components/design/editor/PendingScreenDeletionDialog.tsx +58 -0
- package/corpus/templates/design/app/components/design/editor/PendingVisualStyleWarningDialog.tsx +56 -0
- package/corpus/templates/design/app/components/design/editor/ReadOnlyEditorPanel.tsx +23 -0
- package/corpus/templates/design/app/components/design/editor/SaveTemplateDialog.tsx +161 -0
- package/corpus/templates/design/app/components/design/editor/toolbar-controls.tsx +185 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +20913 -0
- package/corpus/templates/design/app/pages/design-editor/command-types.ts +120 -0
- package/corpus/templates/design/app/pages/design-editor/commands/README.md +193 -0
- package/corpus/templates/design/app/pages/design-editor/commands/add-auto-layout.ts +416 -0
- package/corpus/templates/design/app/pages/design-editor/commands/add-screen.ts +112 -0
- package/corpus/templates/design/app/pages/design-editor/commands/align-selection.ts +183 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +243 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +236 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +304 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-pending-visual-styles-with-agent.ts +376 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-to-source.ts +132 -0
- package/corpus/templates/design/app/pages/design-editor/commands/can-move-layer.ts +117 -0
- package/corpus/templates/design/app/pages/design-editor/commands/change-selected-z-index.ts +212 -0
- package/corpus/templates/design/app/pages/design-editor/commands/commit-relative-style-delta-to-selected-layers.ts +176 -0
- package/corpus/templates/design/app/pages/design-editor/commands/commit-styles-to-selected-layers.ts +175 -0
- package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +710 -0
- package/corpus/templates/design/app/pages/design-editor/commands/confirm-make-real.ts +99 -0
- package/corpus/templates/design/app/pages/design-editor/commands/copy-as-figma-svg.ts +95 -0
- package/corpus/templates/design/app/pages/design-editor/commands/copy-selection.ts +156 -0
- package/corpus/templates/design/app/pages/design-editor/commands/create-primitive.ts +291 -0
- package/corpus/templates/design/app/pages/design-editor/commands/create-screen-frame.ts +131 -0
- package/corpus/templates/design/app/pages/design-editor/commands/cross-screen-element-drop.ts +577 -0
- package/corpus/templates/design/app/pages/design-editor/commands/delete-files.ts +364 -0
- package/corpus/templates/design/app/pages/design-editor/commands/delete-selection.ts +521 -0
- package/corpus/templates/design/app/pages/design-editor/commands/detach-instance-menu-action.ts +88 -0
- package/corpus/templates/design/app/pages/design-editor/commands/distribute-selection.ts +114 -0
- package/corpus/templates/design/app/pages/design-editor/commands/download-all-screens-pdf.ts +116 -0
- package/corpus/templates/design/app/pages/design-editor/commands/download-pdf.ts +103 -0
- package/corpus/templates/design/app/pages/design-editor/commands/download-svg.ts +159 -0
- package/corpus/templates/design/app/pages/design-editor/commands/duplicate-screen.ts +201 -0
- package/corpus/templates/design/app/pages/design-editor/commands/duplicate-selection.ts +279 -0
- package/corpus/templates/design/app/pages/design-editor/commands/editor-paste.ts +81 -0
- package/corpus/templates/design/app/pages/design-editor/commands/enter-hotkey.ts +155 -0
- package/corpus/templates/design/app/pages/design-editor/commands/enter-single-screen.ts +168 -0
- package/corpus/templates/design/app/pages/design-editor/commands/escape-hotkey.ts +212 -0
- package/corpus/templates/design/app/pages/design-editor/commands/frame-selection.ts +119 -0
- package/corpus/templates/design/app/pages/design-editor/commands/geometry-commit.ts +169 -0
- package/corpus/templates/design/app/pages/design-editor/commands/get-selected-layer-snapshots.ts +177 -0
- package/corpus/templates/design/app/pages/design-editor/commands/group-selection.ts +127 -0
- package/corpus/templates/design/app/pages/design-editor/commands/iframe-context-menu.ts +121 -0
- package/corpus/templates/design/app/pages/design-editor/commands/import-figma-clipboard-into-design.ts +119 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts +163 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-move-to-screen.ts +331 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-move.ts +517 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-rename.ts +247 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +161 -0
- package/corpus/templates/design/app/pages/design-editor/commands/mode-change.ts +122 -0
- package/corpus/templates/design/app/pages/design-editor/commands/nudge-selection.ts +213 -0
- package/corpus/templates/design/app/pages/design-editor/commands/overview-primitive-reparent.ts +318 -0
- package/corpus/templates/design/app/pages/design-editor/commands/paste-copied-screens.ts +114 -0
- package/corpus/templates/design/app/pages/design-editor/commands/paste-over-selection.ts +70 -0
- package/corpus/templates/design/app/pages/design-editor/commands/paste-selection.ts +436 -0
- package/corpus/templates/design/app/pages/design-editor/commands/paste-to-replace.ts +135 -0
- package/corpus/templates/design/app/pages/design-editor/commands/pasted-image-files.ts +209 -0
- package/corpus/templates/design/app/pages/design-editor/commands/persist-frame-geometry-save.ts +113 -0
- package/corpus/templates/design/app/pages/design-editor/commands/persist-tweak-save.ts +160 -0
- package/corpus/templates/design/app/pages/design-editor/commands/primitive-created.ts +168 -0
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-live-layer-state-edit.ts +149 -0
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-live-structure-edit.ts +200 -0
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-live-text-edit.ts +152 -0
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-visual-style-edit.ts +247 -0
- package/corpus/templates/design/app/pages/design-editor/commands/redo.ts +1086 -0
- package/corpus/templates/design/app/pages/design-editor/commands/render-png-blob.ts +200 -0
- package/corpus/templates/design/app/pages/design-editor/commands/save-file-content.ts +207 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-element-select.ts +262 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-text-content-change.ts +216 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-duplicate-change.ts +108 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-structure-change.ts +280 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts +151 -0
- package/corpus/templates/design/app/pages/design-editor/commands/send-overview-annotations.ts +88 -0
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-move-semantic-handoff.ts +122 -0
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-semantic-handoff.ts +143 -0
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-state-semantic-handoff.ts +115 -0
- package/corpus/templates/design/app/pages/design-editor/commands/start-retry-generation.ts +152 -0
- package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +99 -0
- package/corpus/templates/design/app/pages/design-editor/commands/style-change.ts +152 -0
- package/corpus/templates/design/app/pages/design-editor/commands/styles-change.ts +155 -0
- package/corpus/templates/design/app/pages/design-editor/commands/suggest-auto-layout.ts +125 -0
- package/corpus/templates/design/app/pages/design-editor/commands/text-content-change.ts +201 -0
- package/corpus/templates/design/app/pages/design-editor/commands/tidy-up.ts +123 -0
- package/corpus/templates/design/app/pages/design-editor/commands/toggle-layer-hidden.ts +167 -0
- package/corpus/templates/design/app/pages/design-editor/commands/toggle-layer-locked.ts +175 -0
- package/corpus/templates/design/app/pages/design-editor/commands/toggle-motion-keyframe.ts +99 -0
- package/corpus/templates/design/app/pages/design-editor/commands/tweak-prompt-submit.ts +84 -0
- package/corpus/templates/design/app/pages/design-editor/commands/undo.ts +906 -0
- package/corpus/templates/design/app/pages/design-editor/commands/ungroup-selection.ts +170 -0
- package/corpus/templates/design/app/pages/design-editor/commands/visual-duplicate-change.ts +119 -0
- package/corpus/templates/design/app/pages/design-editor/commands/visual-structure-change.ts +274 -0
- package/corpus/templates/design/app/pages/design-editor/commands/write-frame-geometry-snapshot.ts +99 -0
- package/corpus/templates/design/app/pages/design-editor/derive/design-breakpoints.ts +56 -0
- package/corpus/templates/design/app/pages/design-editor/derive/overview-screens.ts +146 -0
- package/corpus/templates/design/app/pages/design-editor/domains/use-tweaks.ts +326 -0
- package/corpus/templates/design/app/pages/design-editor/editor-constants.ts +54 -0
- package/corpus/templates/design/app/pages/design-editor/editor-helpers.ts +183 -0
- package/corpus/templates/design/app/pages/design-editor/effects/adopt-db-file-content.ts +270 -0
- package/corpus/templates/design/app/pages/design-editor/effects/mirror-selection-to-agent-chat.ts +134 -0
- package/corpus/templates/design/app/pages/design-editor/effects/motion-autosave.ts +335 -0
- package/corpus/templates/design/app/pages/design-editor/effects/observe-collab-text.ts +183 -0
- package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +252 -0
- package/corpus/templates/design/app/pages/design-editor/effects/resume-pending-generation.ts +178 -0
- package/corpus/templates/design/app/pages/design-editor/effects/seed-collab-content.ts +157 -0
- package/corpus/templates/design/app/pages/design-editor/preview-html.ts +19 -0
- package/corpus/templates/design/app/routes/examples.tsx +2 -1
- package/corpus/templates/design/netlify.toml +2 -0
- package/corpus/templates/design/shared/board-file.ts +2 -1
- package/corpus/templates/dispatch/netlify.toml +2 -0
- package/corpus/templates/forms/app/routes/_index.tsx +3 -2
- package/corpus/templates/forms/netlify.toml +2 -0
- package/corpus/templates/mail/app/routes/_index.tsx +3 -2
- package/corpus/templates/mail/netlify.toml +2 -0
- package/corpus/templates/plan/netlify.toml +2 -0
- package/corpus/templates/slides/netlify.toml +2 -0
- package/corpus/templates/tasks/app/routes/_index.tsx +2 -1
- package/dist/agent/engine/builder-engine.d.ts +6 -4
- package/dist/agent/engine/builder-engine.js +91 -26
- package/dist/agent/engine/registry.js +16 -0
- package/dist/cli/code-agent-agent-tools.d.ts +2 -0
- package/dist/cli/code-agent-agent-tools.js +188 -0
- package/dist/cli/code-agent-collaboration.d.ts +34 -0
- package/dist/cli/code-agent-collaboration.js +104 -0
- package/dist/cli/code-agent-executor.js +6 -0
- package/dist/cli/code-agent-schedules.d.ts +54 -0
- package/dist/cli/code-agent-schedules.js +198 -0
- package/dist/client/AgentPanel.js +1 -1
- package/dist/client/ConnectBuilderCard.js +5 -2
- package/dist/client/EnvironmentBadge.js +6 -5
- package/dist/client/chat/run-recovery.js +3 -2
- package/dist/client/chat/tool-call-display.js +2 -3
- package/dist/client/components/CodeRequiredDialog.js +4 -2
- package/dist/client/i18n.js +5 -4
- package/dist/client/settings/SettingsPanel.js +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.js +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +6 -1
- package/dist/client/settings/useBuilderStatus.js +22 -33
- package/dist/client/transcription/BuilderTranscriptionCta.js +1 -1
- package/dist/code-agents/index.d.ts +2 -0
- package/dist/code-agents/index.js +2 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/deploy/build.js +10 -4
- package/dist/localization/shared.d.ts +2 -0
- package/dist/localization/shared.js +5 -0
- package/dist/mcp-client/oauth-client.d.ts +1 -0
- package/dist/mcp-client/oauth-client.js +50 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +1 -1
- package/dist/provider-api/actions/provider-api.d.ts +2 -2
- package/dist/server/auth-marketing-locales.d.ts +7 -0
- package/dist/server/auth-marketing-locales.js +1322 -0
- package/dist/server/auth-marketing.d.ts +1 -0
- package/dist/server/auth-marketing.js +35 -6
- package/dist/server/auth.js +4 -17
- package/dist/server/builder-browser.d.ts +22 -0
- package/dist/server/builder-browser.js +77 -1
- package/dist/server/builder-oauth.d.ts +50 -0
- package/dist/server/builder-oauth.js +263 -0
- package/dist/server/core-routes-plugin.d.ts +11 -0
- package/dist/server/core-routes-plugin.js +291 -415
- package/dist/server/credential-provider.d.ts +1 -1
- package/dist/server/credential-provider.js +1 -1
- package/dist/server/csrf.js +2 -2
- package/dist/server/onboarding-html.js +52 -120
- package/dist/server/ssr-handler.js +13 -4
- package/dist/settings/store.d.ts +9 -0
- package/dist/settings/store.js +19 -0
- package/dist/shared/cache-control.d.ts +22 -0
- package/dist/shared/cache-control.js +25 -0
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.js +1 -0
- package/dist/templates/chat/netlify.toml +2 -0
- package/docs/content/deployment.mdx +2 -0
- package/docs/content/multi-app-workspace.mdx +1 -1
- package/package.json +2 -2
- package/src/templates/chat/netlify.toml +2 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
import { computeReparentedChildPosition } from "@shared/board-file";
|
|
2
|
+
import type { CodeLayerNode, CodeLayerTreeNode } from "@shared/code-layer";
|
|
3
|
+
import {
|
|
4
|
+
applyVisualEdit,
|
|
5
|
+
buildCodeLayerProjection,
|
|
6
|
+
buildCodeLayerTree,
|
|
7
|
+
moveNodeBetweenDocuments,
|
|
8
|
+
} from "@shared/code-layer";
|
|
9
|
+
import type { Dispatch, RefObject, SetStateAction } from "react";
|
|
10
|
+
import { toast } from "sonner";
|
|
11
|
+
|
|
12
|
+
import type { LayersPanelMoveIntent } from "@/components/design/LayersPanel";
|
|
13
|
+
import type {
|
|
14
|
+
ElementInfo,
|
|
15
|
+
RuntimeStructureMoveRequest,
|
|
16
|
+
} from "@/components/design/types";
|
|
17
|
+
import type { ClipboardContentMutationPublication } from "@/lib/clipboard-content-lineage";
|
|
18
|
+
import type { EffectiveCodeLayerState } from "@/pages/design-editor/code-layer-state";
|
|
19
|
+
import {
|
|
20
|
+
bridgeSourceIdForCodeLayerNode,
|
|
21
|
+
codeLayerPatchMessage,
|
|
22
|
+
collectCodeLayerAncestors,
|
|
23
|
+
elementInfoFromCodeLayerNode,
|
|
24
|
+
findMovedCodeLayerNodeInProjection,
|
|
25
|
+
removeEmptyGeneratedGroupWrappers,
|
|
26
|
+
} from "@/pages/design-editor/code-layer-state";
|
|
27
|
+
import {
|
|
28
|
+
getLayerMoveIterationOrder,
|
|
29
|
+
getLayerMoveSourceContent,
|
|
30
|
+
} from "@/pages/design-editor/editor-state";
|
|
31
|
+
import type {
|
|
32
|
+
ContentHistoryChange,
|
|
33
|
+
ContentHistoryEntry,
|
|
34
|
+
} from "@/pages/design-editor/history";
|
|
35
|
+
import {
|
|
36
|
+
getAbsolutePositioningForNodeInHtml,
|
|
37
|
+
setAbsolutePositioningForNodeInHtml,
|
|
38
|
+
} from "@/pages/design-editor/html-layer-positioning";
|
|
39
|
+
import { resolveRuntimeStructureMoveExecutionMode } from "@/pages/design-editor/react-semantic-handoff";
|
|
40
|
+
import type { DesignFile } from "@/pages/design-editor/types";
|
|
41
|
+
|
|
42
|
+
export interface LayerMoveArgs {
|
|
43
|
+
activeFile: DesignFile;
|
|
44
|
+
applyFileContentUpdate: (
|
|
45
|
+
fileId: string,
|
|
46
|
+
nextContent: string,
|
|
47
|
+
options?: {
|
|
48
|
+
refreshPreview?: boolean;
|
|
49
|
+
skipPreview?: boolean;
|
|
50
|
+
forcePreviewFullDocument?: boolean;
|
|
51
|
+
persist?: boolean;
|
|
52
|
+
recordHistory?: boolean;
|
|
53
|
+
updatedAt?: string;
|
|
54
|
+
clipboardMutation?: ClipboardContentMutationPublication;
|
|
55
|
+
},
|
|
56
|
+
) => void;
|
|
57
|
+
canEditDesign: boolean;
|
|
58
|
+
canMoveLayer: (intent: LayersPanelMoveIntent) => boolean;
|
|
59
|
+
codeLayerOwnerByNodeId: Map<
|
|
60
|
+
string,
|
|
61
|
+
{
|
|
62
|
+
fileId: string;
|
|
63
|
+
node: CodeLayerNode;
|
|
64
|
+
tree: CodeLayerTreeNode[];
|
|
65
|
+
runtimeOnly: boolean;
|
|
66
|
+
}
|
|
67
|
+
>;
|
|
68
|
+
effectiveCodeLayerState: EffectiveCodeLayerState;
|
|
69
|
+
files: DesignFile[];
|
|
70
|
+
getFreshActiveContent: () => string;
|
|
71
|
+
handleLayerMoveToScreen: (
|
|
72
|
+
intent: LayersPanelMoveIntent,
|
|
73
|
+
targetFileId: string,
|
|
74
|
+
) => void;
|
|
75
|
+
handleScreenLayerMove: (intent: LayersPanelMoveIntent) => void;
|
|
76
|
+
recordContentHistoryEntry: (entry: ContentHistoryEntry) => void;
|
|
77
|
+
recordLocalContentHistoryEntry: (change: ContentHistoryChange) => void;
|
|
78
|
+
runtimeStructureMoveRevisionRef: RefObject<number>;
|
|
79
|
+
sendRuntimeLayerMoveSemanticHandoff: (
|
|
80
|
+
subjectLayerId: string,
|
|
81
|
+
targetLayerId: string,
|
|
82
|
+
placement: "before" | "after" | "inside",
|
|
83
|
+
) => boolean;
|
|
84
|
+
setExpandedLayerIds: Dispatch<SetStateAction<string[]>>;
|
|
85
|
+
setRuntimeStructureMoveRequest: Dispatch<
|
|
86
|
+
SetStateAction<(RuntimeStructureMoveRequest & { screenId: string }) | null>
|
|
87
|
+
>;
|
|
88
|
+
setSelectedElement: Dispatch<SetStateAction<ElementInfo | null>>;
|
|
89
|
+
setSelectedLayerIdsState: Dispatch<SetStateAction<string[]>>;
|
|
90
|
+
t: (key: string, options?: Record<string, unknown>) => string;
|
|
91
|
+
viewModeRef: RefObject<"single" | "overview">;
|
|
92
|
+
visualScreenFileIds: Set<string>;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function runLayerMove(
|
|
96
|
+
{
|
|
97
|
+
activeFile,
|
|
98
|
+
applyFileContentUpdate,
|
|
99
|
+
canEditDesign,
|
|
100
|
+
canMoveLayer,
|
|
101
|
+
codeLayerOwnerByNodeId,
|
|
102
|
+
effectiveCodeLayerState,
|
|
103
|
+
files,
|
|
104
|
+
getFreshActiveContent,
|
|
105
|
+
handleLayerMoveToScreen,
|
|
106
|
+
handleScreenLayerMove,
|
|
107
|
+
recordContentHistoryEntry,
|
|
108
|
+
recordLocalContentHistoryEntry,
|
|
109
|
+
runtimeStructureMoveRevisionRef,
|
|
110
|
+
sendRuntimeLayerMoveSemanticHandoff,
|
|
111
|
+
setExpandedLayerIds,
|
|
112
|
+
setRuntimeStructureMoveRequest,
|
|
113
|
+
setSelectedElement,
|
|
114
|
+
setSelectedLayerIdsState,
|
|
115
|
+
t,
|
|
116
|
+
viewModeRef,
|
|
117
|
+
visualScreenFileIds,
|
|
118
|
+
}: LayerMoveArgs,
|
|
119
|
+
intent: LayersPanelMoveIntent,
|
|
120
|
+
) {
|
|
121
|
+
if (!canEditDesign) return;
|
|
122
|
+
if (!canMoveLayer(intent)) return;
|
|
123
|
+
if (
|
|
124
|
+
intent.draggedIds.length > 0 &&
|
|
125
|
+
intent.draggedIds.every((draggedId) => visualScreenFileIds.has(draggedId))
|
|
126
|
+
) {
|
|
127
|
+
handleScreenLayerMove(intent);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const targetOwner = codeLayerOwnerByNodeId.get(intent.targetId);
|
|
131
|
+
if (!targetOwner) {
|
|
132
|
+
const targetFile = files.find((file) => file.id === intent.targetId);
|
|
133
|
+
if (targetFile) {
|
|
134
|
+
handleLayerMoveToScreen(intent, targetFile.id);
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const runtimeDraggedOwner =
|
|
139
|
+
intent.draggedIds.length === 1
|
|
140
|
+
? codeLayerOwnerByNodeId.get(intent.draggedIds[0]!)
|
|
141
|
+
: undefined;
|
|
142
|
+
if (targetOwner.runtimeOnly || runtimeDraggedOwner?.runtimeOnly) {
|
|
143
|
+
if (!runtimeDraggedOwner) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const executionMode = resolveRuntimeStructureMoveExecutionMode({
|
|
147
|
+
subjectRuntimeOnly: runtimeDraggedOwner.runtimeOnly,
|
|
148
|
+
targetRuntimeOnly: targetOwner.runtimeOnly,
|
|
149
|
+
sourceScreenId: runtimeDraggedOwner.fileId,
|
|
150
|
+
targetScreenId: targetOwner.fileId,
|
|
151
|
+
});
|
|
152
|
+
if (executionMode === "screen-bridge") {
|
|
153
|
+
// Keep the existing fast, optimistic in-iframe path when one
|
|
154
|
+
// screen-scoped bridge owns both runtime endpoints. Cross-screen or
|
|
155
|
+
// mixed runtime/source ownership cannot be represented by that
|
|
156
|
+
// one-screen StructureMove message and must go through the semantic
|
|
157
|
+
// coding-agent handoff below.
|
|
158
|
+
runtimeStructureMoveRevisionRef.current += 1;
|
|
159
|
+
setRuntimeStructureMoveRequest({
|
|
160
|
+
requestId: runtimeStructureMoveRevisionRef.current,
|
|
161
|
+
screenId: targetOwner.fileId,
|
|
162
|
+
subject: {
|
|
163
|
+
selector: runtimeDraggedOwner.node.selector,
|
|
164
|
+
sourceId: bridgeSourceIdForCodeLayerNode(runtimeDraggedOwner.node),
|
|
165
|
+
},
|
|
166
|
+
anchor: {
|
|
167
|
+
selector: targetOwner.node.selector,
|
|
168
|
+
sourceId: bridgeSourceIdForCodeLayerNode(targetOwner.node),
|
|
169
|
+
},
|
|
170
|
+
placement: intent.placement,
|
|
171
|
+
});
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
sendRuntimeLayerMoveSemanticHandoff(
|
|
175
|
+
intent.draggedIds[0]!,
|
|
176
|
+
intent.targetId,
|
|
177
|
+
intent.placement,
|
|
178
|
+
);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
// L8: locked/hidden is no longer a blocker for using this row as a drop
|
|
182
|
+
// anchor (see canMoveLayer) — only dragging a LOCKED row is blocked,
|
|
183
|
+
// checked per-draggedId below. Hidden rows are draggable.
|
|
184
|
+
const freshActiveContent = getFreshActiveContent();
|
|
185
|
+
const destFile = files.find((file) => file.id === targetOwner.fileId);
|
|
186
|
+
const destContent =
|
|
187
|
+
targetOwner.fileId === activeFile?.id
|
|
188
|
+
? freshActiveContent
|
|
189
|
+
: (destFile?.content ?? "");
|
|
190
|
+
if (!destContent) return;
|
|
191
|
+
|
|
192
|
+
// L17: a single ordered insert pipeline for a MIXED same-file/cross-file
|
|
193
|
+
// multi-drag. Previously same-file drags were all applied as one batch
|
|
194
|
+
// (each inserted at the shared anchor), THEN cross-file drags were
|
|
195
|
+
// applied as a second batch — so a selection like [same-file A,
|
|
196
|
+
// cross-file B, same-file C] (in panel-visual order) would always end
|
|
197
|
+
// up as A,C,B relative to the anchor instead of preserving A,B,C,
|
|
198
|
+
// because the two source kinds never interleaved against one another.
|
|
199
|
+
// Fix: classify each dragged id but keep ONE combined list in the
|
|
200
|
+
// original intent.draggedIds order (already translated from panel order
|
|
201
|
+
// into DOM order at the LayersPanel callback boundary), then iterate
|
|
202
|
+
// that single list once, dispatching each item through the same-file or
|
|
203
|
+
// cross-file primitive against the shared running nextDestContent /
|
|
204
|
+
// sourceContentMap state so mixed sequences interleave in the intended
|
|
205
|
+
// order.
|
|
206
|
+
const movedNodeSnapshots = new Map<string, CodeLayerNode>();
|
|
207
|
+
type ClassifiedDrag =
|
|
208
|
+
| { draggedId: string; kind: "same-file" }
|
|
209
|
+
| { draggedId: string; kind: "cross-file"; sourceFileId: string };
|
|
210
|
+
const classifiedDrags: ClassifiedDrag[] = [];
|
|
211
|
+
for (const draggedId of intent.draggedIds) {
|
|
212
|
+
const draggedOwner = codeLayerOwnerByNodeId.get(draggedId);
|
|
213
|
+
if (
|
|
214
|
+
draggedId === intent.targetId ||
|
|
215
|
+
!draggedOwner ||
|
|
216
|
+
// L8: only LOCKED dragged rows are blocked; hidden rows may be
|
|
217
|
+
// dragged/reordered like any other layer.
|
|
218
|
+
effectiveCodeLayerState.lockedIds.has(draggedId)
|
|
219
|
+
) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
// L15: mirror canMoveLayer's per-drag ancestor-of-target guard here.
|
|
223
|
+
// canMoveLayer only gates the whole intent (true if ANY dragged id is
|
|
224
|
+
// valid), so a mixed multi-drag where one id is an ancestor of the
|
|
225
|
+
// drop target would otherwise reach applyVisualEdit/moveNode for that
|
|
226
|
+
// id, which always reports "conflict" (the anchor is inside the
|
|
227
|
+
// dragged element) — a spurious per-id failure toast for a case we
|
|
228
|
+
// can just silently skip, exactly like the other guards above.
|
|
229
|
+
if (
|
|
230
|
+
draggedOwner.fileId === targetOwner.fileId &&
|
|
231
|
+
collectCodeLayerAncestors(targetOwner.tree, intent.targetId).includes(
|
|
232
|
+
draggedId,
|
|
233
|
+
)
|
|
234
|
+
) {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
movedNodeSnapshots.set(draggedId, draggedOwner.node);
|
|
238
|
+
if (draggedOwner.fileId === targetOwner.fileId) {
|
|
239
|
+
classifiedDrags.push({ draggedId, kind: "same-file" });
|
|
240
|
+
} else {
|
|
241
|
+
classifiedDrags.push({
|
|
242
|
+
draggedId,
|
|
243
|
+
kind: "cross-file",
|
|
244
|
+
sourceFileId: draggedOwner.fileId,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const movedIdOrder = classifiedDrags.map((drag) => drag.draggedId);
|
|
250
|
+
|
|
251
|
+
// L25: track each dragged node's former parent (by fileId + stable
|
|
252
|
+
// data-agent-native-node-id), so that once every move in this intent
|
|
253
|
+
// is applied we can sweep each touched file for now-empty generated
|
|
254
|
+
// "Group" wrappers left behind by the move.
|
|
255
|
+
const formerParentAttrIdsByFileId = new Map<string, Set<string>>();
|
|
256
|
+
for (const drag of classifiedDrags) {
|
|
257
|
+
const draggedOwner = codeLayerOwnerByNodeId.get(drag.draggedId);
|
|
258
|
+
const parentId = draggedOwner?.node.parentId;
|
|
259
|
+
if (!parentId) continue;
|
|
260
|
+
const parentAttrId =
|
|
261
|
+
codeLayerOwnerByNodeId.get(parentId)?.node.dataAttributes[
|
|
262
|
+
"data-agent-native-node-id"
|
|
263
|
+
];
|
|
264
|
+
if (!parentAttrId) continue;
|
|
265
|
+
const fileId = draggedOwner.fileId;
|
|
266
|
+
const set = formerParentAttrIdsByFileId.get(fileId) ?? new Set<string>();
|
|
267
|
+
set.add(parentAttrId);
|
|
268
|
+
formerParentAttrIdsByFileId.set(fileId, set);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
let nextDestContent = destContent;
|
|
272
|
+
let moved = false;
|
|
273
|
+
const sourceContentMap = new Map<string, string>();
|
|
274
|
+
const sourceOriginalContentMap = new Map<string, string>();
|
|
275
|
+
const movedNodeIdByDraggedId = new Map<string, string>();
|
|
276
|
+
|
|
277
|
+
for (const drag of getLayerMoveIterationOrder(
|
|
278
|
+
classifiedDrags,
|
|
279
|
+
intent.placement,
|
|
280
|
+
)) {
|
|
281
|
+
const { draggedId } = drag;
|
|
282
|
+
if (drag.kind === "same-file") {
|
|
283
|
+
const draggedOwner = codeLayerOwnerByNodeId.get(draggedId);
|
|
284
|
+
// L2: a panel drop can reparent the node onto a different container
|
|
285
|
+
// (not just reorder among the same siblings) — e.g. dropping
|
|
286
|
+
// "inside" a different frame, or "before"/"after" an anchor that
|
|
287
|
+
// lives under a different parent than the dragged node's current
|
|
288
|
+
// one. The overview canvas reparent path
|
|
289
|
+
// (handleOverviewPrimitiveReparent) already rebases absolute
|
|
290
|
+
// left/top in that case so the element keeps its visual position
|
|
291
|
+
// instead of teleporting to (0,0)-relative-to-new-parent; mirror
|
|
292
|
+
// that here for the panel/tree move path.
|
|
293
|
+
const targetOwnerNode = codeLayerOwnerByNodeId.get(intent.targetId);
|
|
294
|
+
const newParentAttrId =
|
|
295
|
+
intent.placement === "inside"
|
|
296
|
+
? intent.targetId
|
|
297
|
+
: (targetOwnerNode?.node.parentId ?? null);
|
|
298
|
+
const isCrossParent = Boolean(
|
|
299
|
+
draggedOwner &&
|
|
300
|
+
newParentAttrId &&
|
|
301
|
+
draggedOwner.node.parentId !== newParentAttrId,
|
|
302
|
+
);
|
|
303
|
+
const prevContentForRebase = nextDestContent;
|
|
304
|
+
const patch = applyVisualEdit(nextDestContent, {
|
|
305
|
+
kind: "moveNode",
|
|
306
|
+
target: { nodeId: draggedId },
|
|
307
|
+
anchor: { nodeId: intent.targetId },
|
|
308
|
+
placement: intent.placement,
|
|
309
|
+
});
|
|
310
|
+
if (patch.result.status !== "applied") {
|
|
311
|
+
toast.error(
|
|
312
|
+
codeLayerPatchMessage(
|
|
313
|
+
patch.result.message,
|
|
314
|
+
t("designEditor.toasts.layerMoveFailed"),
|
|
315
|
+
),
|
|
316
|
+
{ duration: 4000 },
|
|
317
|
+
);
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
nextDestContent = patch.content;
|
|
321
|
+
if (isCrossParent && newParentAttrId) {
|
|
322
|
+
const movedNodeAttrId =
|
|
323
|
+
patch.projection.nodes.find(
|
|
324
|
+
(n) =>
|
|
325
|
+
n.dataAttributes["data-agent-native-node-id"] === draggedId ||
|
|
326
|
+
n.id === draggedId,
|
|
327
|
+
)?.dataAttributes["data-agent-native-node-id"] ?? draggedId;
|
|
328
|
+
const sourcePosition = getAbsolutePositioningForNodeInHtml(
|
|
329
|
+
prevContentForRebase,
|
|
330
|
+
draggedId,
|
|
331
|
+
);
|
|
332
|
+
const targetPosition = getAbsolutePositioningForNodeInHtml(
|
|
333
|
+
prevContentForRebase,
|
|
334
|
+
newParentAttrId,
|
|
335
|
+
);
|
|
336
|
+
if (sourcePosition && targetPosition) {
|
|
337
|
+
// Same parent-relative rebase as the canvas reparent path —
|
|
338
|
+
// computeReparentedChildPosition also strips the historic
|
|
339
|
+
// board-surface offset poison (65536-multiples) from either
|
|
340
|
+
// side so a panel move of a poisoned nested board child heals
|
|
341
|
+
// its coordinates instead of preserving them.
|
|
342
|
+
nextDestContent = setAbsolutePositioningForNodeInHtml(
|
|
343
|
+
nextDestContent,
|
|
344
|
+
movedNodeAttrId,
|
|
345
|
+
computeReparentedChildPosition(sourcePosition, targetPosition),
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
moved = true;
|
|
350
|
+
} else {
|
|
351
|
+
const { sourceFileId } = drag;
|
|
352
|
+
const srcFile = files.find((f) => f.id === sourceFileId);
|
|
353
|
+
if (!srcFile) continue;
|
|
354
|
+
const currentSourceContent = getLayerMoveSourceContent({
|
|
355
|
+
sourceFileId,
|
|
356
|
+
activeFileId: activeFile?.id,
|
|
357
|
+
activeContent: freshActiveContent,
|
|
358
|
+
sourceFileContent: srcFile.content,
|
|
359
|
+
sourceContentMap,
|
|
360
|
+
});
|
|
361
|
+
if (!sourceOriginalContentMap.has(sourceFileId)) {
|
|
362
|
+
sourceOriginalContentMap.set(sourceFileId, currentSourceContent);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// The dragged node's data-agent-native-node-id is the node id
|
|
366
|
+
// tracked by code-layer. Look up the actual attribute value from
|
|
367
|
+
// the owner.
|
|
368
|
+
const draggedOwner = codeLayerOwnerByNodeId.get(draggedId);
|
|
369
|
+
const nodeAttrId =
|
|
370
|
+
draggedOwner?.node.dataAttributes["data-agent-native-node-id"] ??
|
|
371
|
+
draggedId;
|
|
372
|
+
const anchorAttrId =
|
|
373
|
+
codeLayerOwnerByNodeId.get(intent.targetId)?.node.dataAttributes[
|
|
374
|
+
"data-agent-native-node-id"
|
|
375
|
+
] ?? intent.targetId;
|
|
376
|
+
|
|
377
|
+
const result = moveNodeBetweenDocuments(
|
|
378
|
+
currentSourceContent,
|
|
379
|
+
nextDestContent,
|
|
380
|
+
{
|
|
381
|
+
nodeId: nodeAttrId,
|
|
382
|
+
anchorNodeId: anchorAttrId,
|
|
383
|
+
placement: intent.placement,
|
|
384
|
+
},
|
|
385
|
+
);
|
|
386
|
+
if (result.status !== "applied") {
|
|
387
|
+
toast.error(
|
|
388
|
+
codeLayerPatchMessage(
|
|
389
|
+
result.message,
|
|
390
|
+
t("designEditor.toasts.layerMoveFailed"),
|
|
391
|
+
),
|
|
392
|
+
{ duration: 4000 },
|
|
393
|
+
);
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
sourceContentMap.set(sourceFileId, result.sourceHtml);
|
|
397
|
+
nextDestContent = result.destHtml;
|
|
398
|
+
movedNodeIdByDraggedId.set(draggedId, result.movedNodeId ?? nodeAttrId);
|
|
399
|
+
moved = true;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (!moved) return;
|
|
404
|
+
|
|
405
|
+
// L25: sweep every touched file for now-empty generated "Group"
|
|
406
|
+
// wrappers left behind once their last child moved away, and remove
|
|
407
|
+
// them. Applied per-file against whichever content variable currently
|
|
408
|
+
// holds that file's post-move state.
|
|
409
|
+
for (const [fileId, parentAttrIds] of formerParentAttrIdsByFileId) {
|
|
410
|
+
if (fileId === targetOwner.fileId) {
|
|
411
|
+
nextDestContent = removeEmptyGeneratedGroupWrappers(
|
|
412
|
+
nextDestContent,
|
|
413
|
+
parentAttrIds,
|
|
414
|
+
);
|
|
415
|
+
} else if (sourceContentMap.has(fileId)) {
|
|
416
|
+
sourceContentMap.set(
|
|
417
|
+
fileId,
|
|
418
|
+
removeEmptyGeneratedGroupWrappers(
|
|
419
|
+
sourceContentMap.get(fileId)!,
|
|
420
|
+
parentAttrIds,
|
|
421
|
+
),
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
const finalDestProjection =
|
|
427
|
+
nextDestContent !== destContent
|
|
428
|
+
? buildCodeLayerProjection(nextDestContent)
|
|
429
|
+
: null;
|
|
430
|
+
const finalDestTree = finalDestProjection
|
|
431
|
+
? buildCodeLayerTree(finalDestProjection)
|
|
432
|
+
: [];
|
|
433
|
+
const movedNodesAfterMove = movedIdOrder
|
|
434
|
+
.map((draggedId) => {
|
|
435
|
+
const node = movedNodeSnapshots.get(draggedId);
|
|
436
|
+
return node && finalDestProjection
|
|
437
|
+
? findMovedCodeLayerNodeInProjection(
|
|
438
|
+
finalDestProjection,
|
|
439
|
+
node,
|
|
440
|
+
movedNodeIdByDraggedId.get(draggedId),
|
|
441
|
+
)
|
|
442
|
+
: null;
|
|
443
|
+
})
|
|
444
|
+
.filter((node): node is CodeLayerNode => Boolean(node));
|
|
445
|
+
|
|
446
|
+
if (movedNodesAfterMove.length > 0) {
|
|
447
|
+
setSelectedLayerIdsState(movedNodesAfterMove.map((node) => node.id));
|
|
448
|
+
const lastMovedNode = movedNodesAfterMove[movedNodesAfterMove.length - 1];
|
|
449
|
+
if (lastMovedNode && targetOwner.fileId === activeFile?.id) {
|
|
450
|
+
setSelectedElement(elementInfoFromCodeLayerNode(lastMovedNode));
|
|
451
|
+
}
|
|
452
|
+
const movedAncestorIds = movedNodesAfterMove.flatMap((node) =>
|
|
453
|
+
collectCodeLayerAncestors(finalDestTree, node.id),
|
|
454
|
+
);
|
|
455
|
+
setExpandedLayerIds((current) => {
|
|
456
|
+
const next = new Set(current);
|
|
457
|
+
next.add(targetOwner.fileId);
|
|
458
|
+
movedAncestorIds.forEach((ancestorId) => next.add(ancestorId));
|
|
459
|
+
return next.size === current.length ? current : Array.from(next);
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const hasCrossFileMoves = sourceContentMap.size > 0;
|
|
464
|
+
if (hasCrossFileMoves) {
|
|
465
|
+
const crossFileChanges = [
|
|
466
|
+
...Array.from(sourceContentMap.entries()).map(
|
|
467
|
+
([sourceFileId, newSourceContent]) => ({
|
|
468
|
+
fileId: sourceFileId,
|
|
469
|
+
before:
|
|
470
|
+
sourceOriginalContentMap.get(sourceFileId) ??
|
|
471
|
+
files.find((file) => file.id === sourceFileId)?.content ??
|
|
472
|
+
"",
|
|
473
|
+
after: newSourceContent,
|
|
474
|
+
}),
|
|
475
|
+
),
|
|
476
|
+
...(nextDestContent !== destContent
|
|
477
|
+
? [
|
|
478
|
+
{
|
|
479
|
+
fileId: targetOwner.fileId,
|
|
480
|
+
before: destContent,
|
|
481
|
+
after: nextDestContent,
|
|
482
|
+
},
|
|
483
|
+
]
|
|
484
|
+
: []),
|
|
485
|
+
];
|
|
486
|
+
// recordContentHistoryEntry writes to the overview-only global stack
|
|
487
|
+
// and (when the change touches the active file) clears the live
|
|
488
|
+
// single-mode Yjs undo stack as a side effect. Outside overview mode
|
|
489
|
+
// that stack is never consulted by handleUndo, so a cross-file move
|
|
490
|
+
// made while a single screen is focused would both go unrecorded and
|
|
491
|
+
// wipe that screen's undo history (see U5). Record into the local
|
|
492
|
+
// per-file stack instead so single-mode Cmd+Z can reach it.
|
|
493
|
+
if (viewModeRef.current === "overview") {
|
|
494
|
+
recordContentHistoryEntry({ changes: crossFileChanges });
|
|
495
|
+
} else {
|
|
496
|
+
crossFileChanges.forEach((change) =>
|
|
497
|
+
recordLocalContentHistoryEntry(change),
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Persist source files that changed.
|
|
503
|
+
for (const [sourceFileId, newSourceContent] of sourceContentMap) {
|
|
504
|
+
applyFileContentUpdate(sourceFileId, newSourceContent, {
|
|
505
|
+
recordHistory: !hasCrossFileMoves,
|
|
506
|
+
refreshPreview: false,
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Persist dest file (which may also be the active file).
|
|
511
|
+
if (nextDestContent !== destContent) {
|
|
512
|
+
applyFileContentUpdate(targetOwner.fileId, nextDestContent, {
|
|
513
|
+
recordHistory: !hasCrossFileMoves,
|
|
514
|
+
refreshPreview: false,
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
}
|