@mindexec/cli 0.2.445 → 0.2.447

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.
Files changed (34) hide show
  1. package/README.md +2 -2
  2. package/package.json +6 -3
  3. package/remote-fast/osx-arm64/mindexec-remote-fast.dll +0 -0
  4. package/remote-fast/osx-x64/mindexec-remote-fast.dll +0 -0
  5. package/remote-fast/win-x64/mindexec-remote-fast.dll +0 -0
  6. package/remote-hub.js +171 -6
  7. package/scripts/remote-fast-live-rate-smoke.mjs +1 -0
  8. package/scripts/remote-fleet-render-smoke.mjs +74 -36
  9. package/scripts/remote-hub-smoke.mjs +7 -0
  10. package/server.js +2 -2
  11. package/wwwroot/_content/MindExecution.Shared/js/background-themes.js +1 -3
  12. package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +199 -100
  13. package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-hotpath.js +902 -0
  14. package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +186 -360
  15. package/wwwroot/_content/MindExecution.Shared/js/mind-map-interactions.js +124 -179
  16. package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-renderer.js +167 -24
  17. package/wwwroot/_content/MindExecution.Shared/js/mind-map-nodes.js +96 -74
  18. package/wwwroot/_content/MindExecution.Shared/js/mind-map-pipeline.js +66 -30
  19. package/wwwroot/_content/MindExecution.Shared/js/mind-map-remote-codecs.js +6 -3
  20. package/wwwroot/_content/MindExecution.Shared/js/renderers/CSS3DRenderer.js +35 -2
  21. package/wwwroot/_framework/{MindExecution.Core.4moacskf64.dll → MindExecution.Core.mswl4wlkm9.dll} +0 -0
  22. package/wwwroot/_framework/{MindExecution.Kernel.pa251cfsz4.dll → MindExecution.Kernel.zupeldfptg.dll} +0 -0
  23. package/wwwroot/_framework/{MindExecution.Plugins.Admin.dxyuwmxv1s.dll → MindExecution.Plugins.Admin.hq0vyqnqtn.dll} +0 -0
  24. package/wwwroot/_framework/{MindExecution.Plugins.Business.7uj5erqhhn.dll → MindExecution.Plugins.Business.pucw3o7rno.dll} +0 -0
  25. package/wwwroot/_framework/{MindExecution.Plugins.Concept.108rmsxc96.dll → MindExecution.Plugins.Concept.557tzzkrrx.dll} +0 -0
  26. package/wwwroot/_framework/{MindExecution.Plugins.Directory.ccsy3g0fe5.dll → MindExecution.Plugins.Directory.zh1ddg1fn6.dll} +0 -0
  27. package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.1vjpuoe9ff.dll → MindExecution.Plugins.PlanMaster.0z9pzynpu9.dll} +0 -0
  28. package/wwwroot/_framework/{MindExecution.Plugins.YouTube.q8ml98phj9.dll → MindExecution.Plugins.YouTube.y8g77r54fa.dll} +0 -0
  29. package/wwwroot/_framework/{MindExecution.Shared.2pywq19zjy.dll → MindExecution.Shared.1ymsdbwid2.dll} +0 -0
  30. package/wwwroot/_framework/{MindExecution.Web.qucbls1wfr.dll → MindExecution.Web.bb1txupuv0.dll} +0 -0
  31. package/wwwroot/_framework/blazor.boot.json +21 -21
  32. package/wwwroot/index.html +2 -1
  33. package/wwwroot/service-worker-assets.js +36 -32
  34. package/wwwroot/service-worker.js +1 -1
@@ -826,6 +826,32 @@
826
826
  cursor: grab;
827
827
  }
828
828
 
829
+ .css3d-resolution-wrapper:not(.is-text-selection-owner) .node-response,
830
+ .css3d-resolution-wrapper:not(.is-text-selection-owner) .code-body,
831
+ .css3d-resolution-wrapper:not(.is-text-selection-owner) .text-content,
832
+ .css3d-resolution-wrapper:not(.is-text-selection-owner) .markdown-body,
833
+ .css3d-resolution-wrapper:not(.is-text-selection-owner) .csv-table-scroll,
834
+ .css3d-resolution-wrapper:not(.is-text-selection-owner) textarea,
835
+ .css3d-resolution-wrapper:not(.is-text-selection-owner) .map-node-memo__title,
836
+ .css3d-resolution-wrapper:not(.is-text-selection-owner) .map-node-memo__body,
837
+ .css3d-resolution-wrapper:not(.is-text-selection-owner) .map-node-memo__body-view {
838
+ user-select: none !important;
839
+ -webkit-user-select: none !important;
840
+ }
841
+
842
+ .css3d-resolution-wrapper.is-text-selection-owner .node-response,
843
+ .css3d-resolution-wrapper.is-text-selection-owner .code-body,
844
+ .css3d-resolution-wrapper.is-text-selection-owner .text-content,
845
+ .css3d-resolution-wrapper.is-text-selection-owner .markdown-body,
846
+ .css3d-resolution-wrapper.is-text-selection-owner .csv-table-scroll,
847
+ .css3d-resolution-wrapper.is-text-selection-owner textarea,
848
+ .css3d-resolution-wrapper.is-text-selection-owner .map-node-memo__title,
849
+ .css3d-resolution-wrapper.is-text-selection-owner .map-node-memo__body,
850
+ .css3d-resolution-wrapper.is-text-selection-owner .map-node-memo__body-view {
851
+ user-select: text !important;
852
+ -webkit-user-select: text !important;
853
+ }
854
+
829
855
  .css3d-resolution-wrapper.node-type-image,
830
856
  .css3d-resolution-wrapper.node-type-video,
831
857
  .css3d-resolution-wrapper.node-type-embed,
@@ -4689,9 +4715,6 @@
4689
4715
  const TEXT_OVERLAY_MAX_CANDIDATES = 6;
4690
4716
  const TEXT_OVERLAY_MAX_VISIBLE = 2;
4691
4717
  const TEXT_OVERLAY_OVERLAP_PADDING = 10;
4692
- const TEXT_OVERLAY_SOURCE_SUSPENDED_CLASS = 'mind-map-text-overlay-source-suspended';
4693
- const TEXT_OVERLAY_SOURCE_SUSPENDED_ATTR = 'data-text-overlay-source-suspended';
4694
- const TEXT_OVERLAY_SOURCE_STYLE_STATE = new WeakMap();
4695
4718
  const EDIT_OVERLAY_SUPPORTED_TYPES = new Set(['memo', 'note']);
4696
4719
 
4697
4720
  function hexToRgb(hexColor) {
@@ -5005,354 +5028,45 @@
5005
5028
  || getTextOverlayHostElement(nodeEntry);
5006
5029
  }
5007
5030
 
5008
- function getTextOverlaySourceTargets(nodeEntry) {
5009
- if (!nodeEntry?.cssObject?.element || !supportsTextOverlay(nodeEntry.model)) {
5010
- return [];
5011
- }
5012
-
5013
- if (getTextOverlayRenderMode(nodeEntry) === 'memo') {
5014
- const host = getTextOverlayHostElement(nodeEntry);
5015
- if (!host) {
5016
- return [];
5017
- }
5018
-
5019
- return [
5020
- host.querySelector('.map-node-memo__title'),
5021
- host.querySelector('.map-node-memo__body-view')
5022
- ].filter(element =>
5023
- !!element && (element.style.display !== 'none' || element.offsetWidth > 0 || element.offsetHeight > 0));
5024
- }
5025
-
5026
- const root = getTextOverlayRootElement(nodeEntry);
5027
- if (!root?.children?.length) {
5028
- return [];
5029
- }
5030
-
5031
- return Array.from(root.children).filter(element =>
5032
- !!element
5033
- && !element.classList?.contains?.('resize-handle')
5034
- && (element.style.display !== 'none' || element.offsetWidth > 0 || element.offsetHeight > 0));
5035
- }
5036
-
5037
- function ensureTextOverlaySourceStyleState(element) {
5038
- if (!element) {
5039
- return null;
5040
- }
5041
-
5042
- let state = TEXT_OVERLAY_SOURCE_STYLE_STATE.get(element) || null;
5043
- if (!state) {
5044
- state = {
5045
- opacity: element.style.opacity,
5046
- pointerEvents: element.style.pointerEvents,
5047
- userSelect: element.style.userSelect,
5048
- webkitUserSelect: element.style.webkitUserSelect,
5049
- caretColor: element.style.caretColor,
5050
- contentVisibility: element.style.contentVisibility,
5051
- containIntrinsicSize: element.style.containIntrinsicSize,
5052
- contain: element.style.contain
5053
- };
5054
- TEXT_OVERLAY_SOURCE_STYLE_STATE.set(element, state);
5055
- }
5056
-
5057
- return state;
5058
- }
5059
-
5060
- function resetTextOverlaySourcePresentation(element) {
5061
- if (!element) {
5062
- return;
5063
- }
5064
-
5065
- element.classList?.remove?.(TEXT_OVERLAY_SOURCE_SUSPENDED_CLASS);
5066
- element.removeAttribute?.(TEXT_OVERLAY_SOURCE_SUSPENDED_ATTR);
5067
- element.style.opacity = '';
5068
- element.style.pointerEvents = '';
5069
- element.style.userSelect = '';
5070
- element.style.webkitUserSelect = '';
5071
- element.style.caretColor = '';
5072
- element.style.contentVisibility = '';
5073
- element.style.containIntrinsicSize = '';
5074
- element.style.contain = '';
5075
- }
5076
-
5077
- function suspendTextOverlaySourceTarget(element) {
5078
- if (!element) {
5079
- return;
5080
- }
5081
-
5082
- ensureTextOverlaySourceStyleState(element);
5083
-
5084
- const rect = element.getBoundingClientRect();
5085
- const width = Math.max(1, Math.round(Number(rect.width || element.offsetWidth || 1)));
5086
- const height = Math.max(1, Math.round(Number(rect.height || element.offsetHeight || 1)));
5087
-
5088
- element.classList?.add?.(TEXT_OVERLAY_SOURCE_SUSPENDED_CLASS);
5089
- element.setAttribute?.(TEXT_OVERLAY_SOURCE_SUSPENDED_ATTR, 'true');
5090
- element.style.pointerEvents = 'none';
5091
- element.style.userSelect = 'none';
5092
- element.style.webkitUserSelect = 'none';
5093
- element.style.caretColor = 'transparent';
5094
- element.style.opacity = '0';
5095
- element.style.contain = 'layout style paint';
5096
- // Keep scroll metrics alive while the overlay clone is visible. If this
5097
- // becomes content-visibility:hidden, scrollHeight/clientHeight collapse
5098
- // and overlay scroll can no longer be mapped back to CSS3D accurately.
5099
- element.style.contentVisibility = 'visible';
5100
- element.style.containIntrinsicSize = '';
5101
- }
5102
-
5103
- function restoreTextOverlaySourceTarget(element) {
5104
- if (!element) {
5105
- return;
5106
- }
5107
-
5108
- const state = TEXT_OVERLAY_SOURCE_STYLE_STATE.get(element) || null;
5109
- if (!state) {
5110
- resetTextOverlaySourcePresentation(element);
5111
- return;
5112
- }
5113
-
5114
- element.classList?.remove?.(TEXT_OVERLAY_SOURCE_SUSPENDED_CLASS);
5115
- element.removeAttribute?.(TEXT_OVERLAY_SOURCE_SUSPENDED_ATTR);
5116
- element.style.opacity = state.opacity;
5117
- element.style.pointerEvents = state.pointerEvents;
5118
- element.style.userSelect = state.userSelect;
5119
- element.style.webkitUserSelect = state.webkitUserSelect;
5120
- element.style.caretColor = state.caretColor;
5121
- element.style.contentVisibility = state.contentVisibility;
5122
- element.style.containIntrinsicSize = state.containIntrinsicSize;
5123
- element.style.contain = state.contain;
5124
- TEXT_OVERLAY_SOURCE_STYLE_STATE.delete(element);
5125
- }
5126
-
5127
- function stripTextOverlayPresentationOverrides(root) {
5128
- if (!root) {
5129
- return;
5130
- }
5131
-
5132
- const resetTarget = element => {
5133
- if (!element) {
5134
- return;
5135
- }
5136
-
5137
- resetTextOverlaySourcePresentation(element);
5138
- };
5139
-
5140
- if (root.hasAttribute?.(TEXT_OVERLAY_SOURCE_SUSPENDED_ATTR) || root.classList?.contains?.(TEXT_OVERLAY_SOURCE_SUSPENDED_CLASS)) {
5141
- resetTarget(root);
5142
- }
5143
- root.querySelectorAll?.(`[${TEXT_OVERLAY_SOURCE_SUSPENDED_ATTR}], .${TEXT_OVERLAY_SOURCE_SUSPENDED_CLASS}`)?.forEach?.(resetTarget);
5144
- }
5145
-
5146
- function getNativeTextSelectionSourceNodeId(module) {
5147
- return String(module?._nativeTextSelectionSourceNodeId || '').trim();
5148
- }
5149
-
5150
- function hasNativeTextSelectionSource(module, nodeId = null) {
5151
- const activeId = getNativeTextSelectionSourceNodeId(module);
5152
- if (!activeId) {
5153
- return false;
5154
- }
5155
-
5156
- if (nodeId === null) {
5157
- return true;
5158
- }
5159
-
5160
- return activeId === String(nodeId || '').trim();
5161
- }
5162
-
5163
- function activateNativeTextSelectionSource(module, nodeId) {
5164
- const id = String(nodeId || '').trim();
5165
- if (!module || !id) {
5166
- return false;
5167
- }
5168
-
5169
- module._nativeTextSelectionSourceNodeId = id;
5170
- ensureTextOverlaySourceVisible(module, id);
5171
- return true;
5172
- }
5173
-
5174
- function clearNativeTextSelectionSource(module, nodeId = null) {
5175
- const activeId = getNativeTextSelectionSourceNodeId(module);
5176
- const requestedId = nodeId === null ? activeId : String(nodeId || '').trim();
5177
- if (!module || !activeId || !requestedId || activeId !== requestedId) {
5178
- return false;
5179
- }
5180
-
5181
- module._nativeTextSelectionSourceNodeId = null;
5182
- return true;
5183
- }
5184
-
5185
- function isTextOverlaySelectionNode(module, nodeEntry) {
5186
- const contentType = String(nodeEntry?.model?.contentType ?? nodeEntry?.model?.ContentType ?? '').toLowerCase();
5187
- if (contentType !== 'text' && contentType !== 'markdown') {
5188
- return false;
5189
- }
5190
-
5191
- const nodeId = String(getNodeId(nodeEntry?.model) || '').trim();
5192
- return hasNativeTextSelectionSource(module, nodeId);
5193
- }
5194
-
5195
- function setTextOverlaySourceActive(nodeEntry, isActive) {
5196
- if (isCss3dMediaNode(nodeEntry?.model)) {
5197
- restoreCss3dMediaOverlayState(nodeEntry.model, nodeEntry.cssObject);
5198
- nodeEntry._textOverlayActive = false; nodeEntry._css3dSourceSuspended = false;
5199
- return;
5200
- }
5201
-
5202
- const host = getTextOverlayHostElement(nodeEntry);
5203
- if (!host?.classList) {
5204
- return;
5205
- }
5206
-
5207
- host.classList.toggle('mind-map-text-overlay-active', !!isActive);
5208
- getTextOverlaySourceTargets(nodeEntry).forEach(target => {
5209
- if (isActive) {
5210
- suspendTextOverlaySourceTarget(target);
5211
- } else {
5212
- restoreTextOverlaySourceTarget(target);
5213
- }
5214
- });
5215
- nodeEntry._textOverlayActive = nodeEntry._css3dSourceSuspended = !!isActive;
5216
- }
5217
-
5218
- function getTextOverlayPlacementInfo(module, element) {
5219
- if (!module?.container || !element) {
5220
- return null;
5221
- }
5222
-
5223
- const rect = element.getBoundingClientRect();
5224
- const containerRect = module.container.getBoundingClientRect();
5225
- const width = Math.max(0, rect.width || 0);
5226
- const height = Math.max(0, rect.height || 0);
5227
- if (width < 1 || height < 1) {
5228
- return null;
5229
- }
5230
-
5231
- return {
5232
- left: rect.left - containerRect.left,
5233
- top: rect.top - containerRect.top,
5234
- width,
5235
- height,
5236
- baseWidth: Math.max(1, Number(element.offsetWidth || width || 1)),
5237
- baseHeight: Math.max(1, Number(element.offsetHeight || height || 1)),
5238
- right: rect.left - containerRect.left + width,
5239
- bottom: rect.top - containerRect.top + height
5240
- };
5241
- }
5242
-
5243
- function doesTextOverlayRectOverlap(a, b, padding = 0) {
5244
- if (!a || !b) {
5245
- return false;
5246
- }
5247
-
5248
- const inset = Number.isFinite(Number(padding)) ? Number(padding) : 0;
5249
- return !(
5250
- (a.left + a.width + inset) < b.left
5251
- || (b.left + b.width + inset) < a.left
5252
- || (a.top + a.height + inset) < b.top
5253
- || (b.top + b.height + inset) < a.top
5254
- );
5255
- }
5256
-
5257
- function isTextOverlayPlacementVisible(module, placement, options = {}) {
5258
- if (!module?.container || !placement) {
5259
- return false;
5260
- }
5261
-
5262
- const { ignoreMinSize = false } = options;
5263
- if (!ignoreMinSize && (placement.width < TEXT_OVERLAY_MIN_WIDTH || placement.height < TEXT_OVERLAY_MIN_HEIGHT)) {
5264
- return false;
5265
- }
5266
-
5267
- const maxWidth = Number(module.container.clientWidth || 0);
5268
- const maxHeight = Number(module.container.clientHeight || 0);
5269
- if (!(maxWidth > 0) || !(maxHeight > 0)) {
5270
- return false;
5271
- }
5272
-
5273
- return !(
5274
- placement.right < 0
5275
- || placement.left > maxWidth
5276
- || placement.bottom < 0
5277
- || placement.top > maxHeight
5278
- );
5279
- }
5280
-
5281
- function getTextOverlayPriority(module, nodeEntry) {
5282
- const nodeModel = nodeEntry?.model;
5283
- const nodeId = String(getNodeId(nodeModel) || '').trim();
5284
- if (!nodeModel || !nodeId) {
5285
- return Number.NEGATIVE_INFINITY;
5286
- }
5287
-
5288
- let priority = 0;
5289
- if (String(module?.selectedNodeIdJs || '').trim() === nodeId) {
5290
- priority += 100000;
5291
- } else if (module?.multiSelectedNodeIds?.has?.(nodeId)) {
5292
- priority += 50000;
5293
- }
5294
-
5295
- const width = Math.max(1, Number(nodeModel?.width || nodeModel?.Width || 0));
5296
- const height = Math.max(1, Number(nodeModel?.height || nodeModel?.Height || 0));
5297
- priority += Math.min(6000, (width * height) / 18);
5298
-
5299
- if (module?.camera) {
5300
- const centerX = Number(nodeModel?.positionX ?? nodeModel?.PositionX ?? nodeModel?.x ?? nodeModel?.X ?? 0) + (width * 0.5);
5301
- const centerY = Number(nodeModel?.positionY ?? nodeModel?.PositionY ?? nodeModel?.y ?? nodeModel?.Y ?? 0) - (height * 0.5);
5302
- const dx = Math.abs(centerX - Number(module.camera.position?.x || 0));
5303
- const dy = Math.abs(centerY - Number(module.camera.position?.y || 0));
5304
- priority += Math.max(0, 24000 - (dx + dy));
5305
- }
5306
-
5307
- const zIndex = Number(nodeEntry?.cssObject?.element?.style?.zIndex || 0);
5308
- if (Number.isFinite(zIndex)) {
5309
- priority += zIndex * 10;
5310
- }
5311
-
5312
- return priority;
5313
- }
5314
-
5315
- function isAlwaysTextOverlayNode(nodeEntry) {
5316
- const contentType = String(nodeEntry?.model?.contentType ?? nodeEntry?.model?.ContentType ?? '').toLowerCase();
5317
- return contentType === 'markdown' || contentType === 'text';
5318
- }
5319
-
5320
- function getTextOverlayContentSignature(nodeEntry) {
5321
- const model = nodeEntry?.model || {};
5322
- const contentType = String(model.contentType ?? model.ContentType ?? '').toLowerCase();
5323
- const prompt = String(model.prompt ?? model.Prompt ?? '');
5324
- const response = String(model.response ?? model.Response ?? '');
5325
- const isLoading = (model.isLoading ?? model.IsLoading ?? false) ? '1' : '0';
5326
- const width = Math.max(0, Number(model.width ?? model.Width ?? 0));
5327
- const height = Math.max(0, Number(model.height ?? model.Height ?? 0));
5328
- return `${contentType}||${prompt}||${response}||${isLoading}||${width}||${height}`;
5329
- }
5330
-
5331
- function getTextOverlayLayoutSignature(sourceElement, mode = 'full', hostPlacement = null) {
5332
- if (!sourceElement) {
5333
- return '';
5334
- }
5031
+ const {
5032
+ getTextOverlaySourceTargets,
5033
+ ensureTextOverlaySourceStyleState,
5034
+ resetTextOverlaySourcePresentation,
5035
+ suspendTextOverlaySourceTarget,
5036
+ restoreTextOverlaySourceTarget,
5037
+ stripTextOverlayPresentationOverrides,
5038
+ getNativeTextSelectionSourceNodeId,
5039
+ hasNativeTextSelectionSource,
5040
+ setNativeTextSelectionOwnerClass,
5041
+ activateNativeTextSelectionSource,
5042
+ clearNativeTextSelectionSource,
5043
+ isTextOverlaySelectionNode,
5044
+ setTextOverlaySourceActive
5045
+ } = window.MindMapCss3dHotPath.installTextSource({
5046
+ getModule: () => _module,
5047
+ supportsTextOverlay,
5048
+ getTextOverlayRenderMode,
5049
+ getTextOverlayHostElement,
5050
+ getTextOverlayRootElement,
5051
+ isCss3dMediaNode,
5052
+ restoreCss3dMediaOverlayState,
5053
+ ensureTextOverlaySourceVisible,
5054
+ getNodeId
5055
+ });
5335
5056
 
5336
- if (mode === 'memo') {
5337
- const titleInput = sourceElement.querySelector('.map-node-memo__title');
5338
- const bodyView = sourceElement.querySelector('.map-node-memo__body-view');
5339
- const hostWidth = Math.round(Number(hostPlacement?.baseWidth || sourceElement.offsetWidth || 0));
5340
- const hostHeight = Math.round(Number(hostPlacement?.baseHeight || sourceElement.offsetHeight || 0));
5341
- const titleSignature = titleInput
5342
- ? `${titleInput.offsetLeft}:${titleInput.offsetTop}:${titleInput.offsetWidth}:${titleInput.offsetHeight}:${titleInput.style.display}`
5343
- : 'title:none';
5344
- const bodySignature = bodyView
5345
- ? `${bodyView.offsetLeft}:${bodyView.offsetTop}:${bodyView.offsetWidth}:${bodyView.offsetHeight}:${bodyView.style.display}`
5346
- : 'body:none';
5347
- return `${mode}||${hostWidth}x${hostHeight}||${titleSignature}||${bodySignature}`;
5348
- }
5349
-
5350
- const rootWidth = Math.round(Number(sourceElement.offsetWidth || 0));
5351
- const rootHeight = Math.round(Number(sourceElement.offsetHeight || 0));
5352
- const childSignature = Array.from(sourceElement.children || []).map(child =>
5353
- `${child.tagName}:${child.offsetWidth}:${child.offsetHeight}:${child.style.display}`).join('|');
5354
- return `${mode}||${rootWidth}x${rootHeight}||${childSignature}`;
5355
- }
5057
+ const {
5058
+ getTextOverlayPlacementInfo,
5059
+ doesTextOverlayRectOverlap,
5060
+ isTextOverlayPlacementVisible,
5061
+ getTextOverlayPriority,
5062
+ isAlwaysTextOverlayNode,
5063
+ getTextOverlayContentSignature,
5064
+ getTextOverlayLayoutSignature
5065
+ } = window.MindMapCss3dHotPath.installOverlayGeometry({
5066
+ getNodeId,
5067
+ minWidth: TEXT_OVERLAY_MIN_WIDTH,
5068
+ minHeight: TEXT_OVERLAY_MIN_HEIGHT
5069
+ });
5356
5070
 
5357
5071
  function stripOverlayCloneIds(root) {
5358
5072
  if (!root) {
@@ -14923,6 +14637,7 @@
14923
14637
  const remoteFleetHostLeaseTimers = new Map();
14924
14638
  const remoteFleetLocalHostTargets = new Map();
14925
14639
  const remoteFleetBinaryFrameSessions = new Map();
14640
+ const remoteFleetAtlasSessions = new Map();
14926
14641
  const remoteFleetLatestBinaryFrames = new Map();
14927
14642
  const remoteFleetFrameBlobCache = new Map();
14928
14643
  let remoteFleetBridgeStatusPromise = null;
@@ -15137,6 +14852,7 @@
15137
14852
  closeRemoteFleetControlNodeSession(bodyView, 'clear');
15138
14853
  if (options.keepBinaryFrameSocket !== true) {
15139
14854
  releaseRemoteFleetBinaryFrameSocket(bodyView);
14855
+ releaseRemoteFleetAtlasSocket(bodyView);
15140
14856
  }
15141
14857
  if (bodyView._remoteFleetLiveRefreshTimer) {
15142
14858
  clearInterval(bodyView._remoteFleetLiveRefreshTimer);
@@ -15252,6 +14968,17 @@
15252
14968
  return url.toString();
15253
14969
  }
15254
14970
 
14971
+ function buildRemoteFleetAtlasWsUrl(status) {
14972
+ const baseUrl = String(status?.__remoteFleetBridgeBaseUrl || window.location?.origin || '').trim();
14973
+ const path = String(status?.remoteAtlasWsPath || '/api/remote/atlas/ws').trim() || '/api/remote/atlas/ws';
14974
+ if (!baseUrl) return '';
14975
+ const url = new URL(path, baseUrl);
14976
+ url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
14977
+ const bridgeToken = String(status?.bridgeToken || '').trim();
14978
+ if (bridgeToken) url.searchParams.set('token', bridgeToken);
14979
+ return url.toString();
14980
+ }
14981
+
15255
14982
  async function parseRemoteFleetBinaryFrameMessage(data) {
15256
14983
  let buffer = null;
15257
14984
  if (data instanceof ArrayBuffer) {
@@ -15923,6 +15650,100 @@
15923
15650
  }
15924
15651
  }
15925
15652
 
15653
+ function paintRemoteFleetAtlasFrame(session, frame) {
15654
+ const atlasCanvas = session?.atlasCanvas;
15655
+ const tiles = Array.isArray(session?.layout?.tiles) ? session.layout.tiles : [];
15656
+ if (!atlasCanvas || tiles.length === 0) return;
15657
+ const targets = new Set();
15658
+ session.bodies.forEach(body => getRemoteFleetFramePatchTargets(body).forEach(target => targets.add(target)));
15659
+ const tileByDevice = new Map(tiles.map(tile => [String(tile.deviceId || '').trim(), tile]));
15660
+ targets.forEach(target => {
15661
+ target.querySelectorAll('[data-remote-fleet-device-preview]').forEach(preview => {
15662
+ const tile = tileByDevice.get(String(preview.dataset.deviceId || '').trim());
15663
+ if (!tile) return;
15664
+ const canvas = ensureRemoteFleetFrameCanvas(preview);
15665
+ const width = Math.max(1, Number(tile.width || 0) | 0);
15666
+ const height = Math.max(1, Number(tile.height || 0) | 0);
15667
+ canvas.width = width;
15668
+ canvas.height = height;
15669
+ const context = canvas.getContext('2d', { alpha: false, desynchronized: true });
15670
+ context?.drawImage(atlasCanvas, Number(tile.x || 0), Number(tile.y || 0), width, height, 0, 0, width, height);
15671
+ canvas.style.display = 'block';
15672
+ const image = preview.querySelector?.('img[data-remote-fleet-frame-image="true"]');
15673
+ if (image) image.style.display = 'none';
15674
+ preview.dataset.remoteFleetFrameKind = 'live';
15675
+ preview.dataset.remoteFleetFrameSeq = String(frame.frameSeq || 0);
15676
+ preview.dataset.remoteFleetFrameUrl = '';
15677
+ preview.dataset.remoteFleetHasFrame = 'true';
15678
+ });
15679
+ });
15680
+ window.RuntimeTrace?.emit?.('remote.atlas.painted', { nodeId: session.nodeId, frameSeq: frame.frameSeq || 0, tiles: tiles.length });
15681
+ }
15682
+
15683
+ function startRemoteFleetAtlasSocket(bodyView, getDeviceIds, options = {}) {
15684
+ const nodeId = String(bodyView?.dataset?.nodeId || '').trim();
15685
+ if (!nodeId || typeof WebSocket !== 'function') return false;
15686
+ let session = remoteFleetAtlasSessions.get(nodeId);
15687
+ if (!session) {
15688
+ session = { nodeId, bodies: new Set(), ws: null, wsOpening: false, getDeviceIds: null, layout: null, atlasCanvas: document.createElement('canvas'), fallbackStarted: false };
15689
+ remoteFleetAtlasSessions.set(nodeId, session);
15690
+ }
15691
+ session.bodies.add(bodyView);
15692
+ session.getDeviceIds = getDeviceIds;
15693
+ session.options = { fps: 20, width: Number(options.width || 1920) || 1920, height: Number(options.height || 1080) || 1080, tileWidth: Number(options.tileWidth || 320) || 320, tileHeight: Number(options.tileHeight || 180) || 180 };
15694
+ const fallback = () => {
15695
+ if (session.fallbackStarted) return;
15696
+ session.fallbackStarted = true;
15697
+ try { session.ws?.close?.(); } catch { /* encoder failure fallback */ }
15698
+ session.bodies.forEach(body => startRemoteFleetBinaryFrameSocket(body, session.getDeviceIds, { autoStartLive: true, fps: 20, maxWidth: 960, maxHeight: 540, quality: 60, mode: 'mode2-lzo', streamPurpose: 'wall' }));
15699
+ window.RuntimeTrace?.emit?.('remote.atlas.fallback', { nodeId: session.nodeId, mode: 'mode2-lzo' });
15700
+ };
15701
+ session.fallback = fallback;
15702
+ if (session.ws || session.wsOpening) return true;
15703
+ session.wsOpening = true;
15704
+ getRemoteFleetBridgeStatusForFrames().then(status => {
15705
+ const wsUrl = buildRemoteFleetAtlasWsUrl(status);
15706
+ if (!wsUrl) throw new Error('remote-atlas-ws-url-unavailable');
15707
+ const ws = new WebSocket(wsUrl);
15708
+ session.ws = ws;
15709
+ ws.binaryType = 'arraybuffer';
15710
+ ws.onopen = () => {
15711
+ session.wsOpening = false;
15712
+ ws.send(JSON.stringify({ type: 'configure', deviceIds: getRemoteFleetBinaryFrameDeviceIds(session), fps: 20, width: session.options.width, height: session.options.height, tileWidth: session.options.tileWidth, tileHeight: session.options.tileHeight }));
15713
+ window.RuntimeTrace?.emit?.('remote.atlas.wsOpen', { nodeId: session.nodeId });
15714
+ };
15715
+ ws.onmessage = event => {
15716
+ if (typeof event.data === 'string') {
15717
+ try {
15718
+ const payload = JSON.parse(event.data);
15719
+ if (payload?.type === 'Mode4AtlasLayout') session.layout = payload;
15720
+ if (payload?.type === 'Mode4AtlasStatus' && (payload.state === 'error' || payload.error)) fallback();
15721
+ } catch { /* ignore status text */ }
15722
+ return;
15723
+ }
15724
+ parseRemoteFleetBinaryFrameMessage(event.data).then(frame => {
15725
+ if (!frame || String(frame.frameMode || frame.mode || '').toLowerCase() !== 'mode4-h264-atlas') return;
15726
+ session.atlasCanvas.width = Number(frame.width || session.options.width) || session.options.width;
15727
+ session.atlasCanvas.height = Number(frame.height || session.options.height) || session.options.height;
15728
+ window.MindExecRemoteCodecs?.decodeH264Frame?.(session.atlasCanvas, frame, () => paintRemoteFleetAtlasFrame(session, frame));
15729
+ }).catch(() => undefined);
15730
+ };
15731
+ ws.onerror = () => { fallback(); try { ws.close(); } catch {} };
15732
+ ws.onclose = () => { session.wsOpening = false; if (session.ws === ws) session.ws = null; if (!session.fallbackStarted) fallback(); };
15733
+ }).catch(error => { session.wsOpening = false; fallback(); window.RuntimeTrace?.emit?.('remote.atlas.wsOpenFailed', { nodeId, error: error?.message || String(error || '') }); });
15734
+ return true;
15735
+ }
15736
+
15737
+ function releaseRemoteFleetAtlasSocket(bodyView) {
15738
+ const nodeId = String(bodyView?.dataset?.nodeId || '').trim();
15739
+ const session = nodeId ? remoteFleetAtlasSessions.get(nodeId) : null;
15740
+ if (!session) return;
15741
+ session.bodies.delete(bodyView);
15742
+ if (session.bodies.size > 0) return;
15743
+ try { session.ws?.close?.(); } catch {}
15744
+ remoteFleetAtlasSessions.delete(nodeId);
15745
+ }
15746
+
15926
15747
  function startRemoteFleetBinaryFrameSocket(bodyView, getDeviceIds, options = {}) {
15927
15748
  const nodeId = String(bodyView?.dataset?.nodeId || '').trim();
15928
15749
  if (!nodeId || typeof WebSocket !== 'function') {
@@ -20712,22 +20533,20 @@
20712
20533
  || hasActiveLiveStream
20713
20534
  || (autoMonitorState && hasVisibleFrameTarget);
20714
20535
  if (shouldUseBinaryFrameSocket) {
20715
- const binaryFrameSocketStarted = startRemoteFleetBinaryFrameSocket(bodyView, () => {
20536
+ const atlasSocketStarted = startRemoteFleetAtlasSocket(bodyView, () => {
20716
20537
  const liveIds = getVisibleLiveFrameDeviceIds();
20717
20538
  return liveIds.length > 0 ? liveIds : getVisibleFrameDeviceIds();
20718
20539
  }, {
20719
- autoStartLive: true,
20720
20540
  fps: REMOTE_FLEET_MONITOR_LIVE_FPS,
20721
- maxWidth: 960,
20722
- maxHeight: 540,
20723
- quality: 60,
20724
- mode: 'mode2-lzo',
20725
- streamPurpose: 'wall'
20541
+ width: 1920,
20542
+ height: 1080,
20543
+ tileWidth: 320,
20544
+ tileHeight: 180
20726
20545
  });
20727
- if (!binaryFrameSocketStarted) {
20546
+ if (!atlasSocketStarted) {
20728
20547
  window.RuntimeTrace?.emit?.('remote.frame.wsUnavailable', {
20729
20548
  nodeId,
20730
- reason: 'binary-frame-socket-not-started'
20549
+ reason: 'atlas-frame-socket-not-started'
20731
20550
  });
20732
20551
  ensureVisibleRemoteFleetLiveStreams().catch(error => {
20733
20552
  window.RuntimeTrace?.emit?.('remote.live.autoStartFailed', {
@@ -20738,7 +20557,7 @@
20738
20557
  } else {
20739
20558
  window.RuntimeTrace?.emit?.('remote.live.wsAutoStartRequested', {
20740
20559
  nodeId,
20741
- transport: 'ws-binary',
20560
+ transport: 'ws-atlas-h264',
20742
20561
  fps: REMOTE_FLEET_MONITOR_LIVE_FPS,
20743
20562
  visibleFrameTargets: visibleFrameDeviceIds.length,
20744
20563
  visibleLiveTargets: getVisibleLiveFrameDeviceIds().length
@@ -20758,6 +20577,7 @@
20758
20577
  }, REMOTE_FLEET_LIVE_REFRESH_MS);
20759
20578
  } else {
20760
20579
  releaseRemoteFleetBinaryFrameSocket(bodyView);
20580
+ releaseRemoteFleetAtlasSocket(bodyView);
20761
20581
  if (autoMonitorState && hasMonitorTargets) {
20762
20582
  startRemoteFleetFrameLoop(bodyView, REMOTE_FLEET_THUMBNAIL_FRAME_REFRESH_MS, () => refreshRemoteFleetVisibleFrames(true));
20763
20583
  startRemoteFleetMonitorRefreshTimer(REMOTE_FLEET_MONITOR_REFRESH_MS, 'visible-devices');
@@ -24246,6 +24066,7 @@
24246
24066
  function syncCss3dContent(nodeModel, cssObject) {
24247
24067
  if (!nodeModel || !cssObject || !cssObject.element) return;
24248
24068
  const nodeId = String(getNodeId(nodeModel) || '').trim();
24069
+ window.MindMapCss3dHotPath?.invalidateDomRefsByCssObject?.(_module, cssObject, nodeId);
24249
24070
  if (_module && nodeId) {
24250
24071
  const overlayV2Cards = _module._textOverlayV2State?.cards || null;
24251
24072
  const selectionCard = overlayV2Cards?.get?.(`selection:${nodeId}`) || null;
@@ -25016,6 +24837,9 @@
25016
24837
  window.MindMapCss3DManager = {
25017
24838
  activateSelectableTextOverlay: activateSelectableTextOverlay,
25018
24839
  activateNativeTextSelectionSource: activateNativeTextSelectionSource,
24840
+ applyVisibilityDiff: (module, enteredIds, exitedIds) =>
24841
+ window.MindMapCss3dHotPath?.applyVisibilityDiff?.(module, enteredIds, exitedIds) || { complete: false, reason: 'hotpath-unavailable' },
24842
+ setNativeTextSelectionOwnerClass: setNativeTextSelectionOwnerClass,
25019
24843
  beginNodeEditingOverlay: beginNodeEditingOverlay,
25020
24844
  bindMemoWheelRouting: bindMemoWheelRouting,
25021
24845
  bindNoteEditingWheelZoom: bindNoteEditingWheelZoom,
@@ -25026,6 +24850,8 @@
25026
24850
  createNodeViewElement: createNodeViewElement,
25027
24851
  getNodeViewHostPolicy: getNodeViewHostPolicy,
25028
24852
  getNodeViewPrimaryHost: getNodeViewPrimaryHost,
24853
+ getDomRefs: (entry, module = _module) => window.MindMapCss3dHotPath?.getDomRefs?.(entry, module) || null,
24854
+ invalidateDomRefs: (entry) => window.MindMapCss3dHotPath?.invalidateDomRefs?.(entry),
25029
24855
  createEditingOverlayContent: createEditingOverlayContent,
25030
24856
  clearEditingOverlay: clearEditingOverlay,
25031
24857
  getTextInteractionContentSelectors: getTextInteractionContentSelectors,