@mindexec/cli 0.2.453 → 0.2.454

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 (33) hide show
  1. package/electron/main.cjs +12 -0
  2. package/electron/source-smoke.mjs +15 -0
  3. package/package.json +2 -2
  4. package/remote-fast/osx-arm64/mindexec-remote-fast.dll +0 -0
  5. package/remote-fast/osx-x64/mindexec-remote-fast.dll +0 -0
  6. package/remote-fast/win-x64/mindexec-remote-fast.dll +0 -0
  7. package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +210 -244
  8. package/wwwroot/_content/MindExecution.Shared/js/mind-map-interactions.js +77 -103
  9. package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-renderer.js +5 -7
  10. package/wwwroot/_content/MindExecution.Shared/js/mind-map-logic-workers.js +9 -3
  11. package/wwwroot/_content/MindExecution.Shared/js/mind-map-render-plan.js +294 -12
  12. package/wwwroot/_framework/{MindExecution.Core.9h7x2mjn0w.dll → MindExecution.Core.sxhdhda5s2.dll} +0 -0
  13. package/wwwroot/_framework/{MindExecution.Kernel.8te3ay3qs6.dll → MindExecution.Kernel.j8gyjmvupu.dll} +0 -0
  14. package/wwwroot/_framework/{MindExecution.Plugins.Admin.imt43kggvu.dll → MindExecution.Plugins.Admin.91tk6u6ry5.dll} +0 -0
  15. package/wwwroot/_framework/{MindExecution.Plugins.Business.26yozgyvan.dll → MindExecution.Plugins.Business.b7h6v1eygj.dll} +0 -0
  16. package/wwwroot/_framework/{MindExecution.Plugins.Concept.k7fd1qvmfx.dll → MindExecution.Plugins.Concept.i2zgmkmpwv.dll} +0 -0
  17. package/wwwroot/_framework/{MindExecution.Plugins.Directory.88ng22x3y0.dll → MindExecution.Plugins.Directory.r6is6647n2.dll} +0 -0
  18. package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.ll20yqlc09.dll → MindExecution.Plugins.PlanMaster.s95n9skblk.dll} +0 -0
  19. package/wwwroot/_framework/{MindExecution.Plugins.YouTube.gqu5xngvav.dll → MindExecution.Plugins.YouTube.33l2m0y23q.dll} +0 -0
  20. package/wwwroot/_framework/{MindExecution.Shared.6ivt1fatt3.dll → MindExecution.Shared.hvehzbzkt7.dll} +0 -0
  21. package/wwwroot/_framework/{MindExecution.Web.7tki7xqpt0.dll → MindExecution.Web.krui41i71h.dll} +0 -0
  22. package/wwwroot/_framework/blazor.boot.json +21 -21
  23. package/wwwroot/app-icon-1024.png +0 -0
  24. package/wwwroot/apple-touch-icon.png +0 -0
  25. package/wwwroot/favicon-32x32.png +0 -0
  26. package/wwwroot/favicon.ico +0 -0
  27. package/wwwroot/icon-192.png +0 -0
  28. package/wwwroot/icon-512.png +0 -0
  29. package/wwwroot/index.html +8 -4
  30. package/wwwroot/manifest.webmanifest +21 -19
  31. package/wwwroot/mindexec-favicon-v2.png +0 -0
  32. package/wwwroot/service-worker-assets.js +51 -31
  33. package/wwwroot/service-worker.js +1 -1
@@ -5,7 +5,6 @@ window.MindMapInteractions = (function () {
5
5
  const MOTION_DOM_FANOUT_DELAY_MS = 180;
6
6
  const MOTION_DOM_FANOUT_ENABLED = false;
7
7
  const MOTION_WILL_CHANGE_ENABLE_DELAY_MS = 240;
8
- const WHEEL_ZOOM_TARGET_UPDATE_MODE = 'raf-coalesced-direct';
9
8
  const PRIMARY_CLICK_DELAY_MS = 280;
10
9
  const BACKGROUND_PRIMARY_CLICK_DELAY_MS = 320;
11
10
  const eventHandlers = new WeakMap();
@@ -601,20 +600,6 @@ window.MindMapInteractions = (function () {
601
600
  window.MindMapTextOverlayV2?.invalidateView?.(module);
602
601
  }
603
602
 
604
- function markCameraNavigationForceFrames(module, frames = 2) {
605
- if (!module) {
606
- return;
607
- }
608
-
609
- const safeFrames = Math.max(0, Math.floor(Number(frames || 0)));
610
- if (safeFrames <= 0) {
611
- return;
612
- }
613
-
614
- module._forceUpdateFrames = Math.max(Number(module._forceUpdateFrames || 0), safeFrames);
615
- module._panLiveRefreshForceFrames = Math.max(Number(module._panLiveRefreshForceFrames || 0), safeFrames);
616
- }
617
-
618
603
  function requestPanLiveRefreshFrames(module) {
619
604
  if (!module) {
620
605
  return;
@@ -622,17 +607,7 @@ window.MindMapInteractions = (function () {
622
607
  wakeCameraNavigationAnimation(module, 'pan-input');
623
608
  }
624
609
 
625
- function applyImmediateCameraNavigationFeedback(module, reason = 'camera-navigation-input', options = {}) {
626
- if (module && typeof module.applyImmediateCameraNavigationFeedback === 'function') {
627
- module.applyImmediateCameraNavigationFeedback(reason, options);
628
- }
629
- }
630
-
631
- function wakeCameraNavigationAnimation(module, reason = 'camera-navigation-input', options = {}) {
632
- markCameraNavigationForceFrames(module, options?.forceFrames ?? 0);
633
- if (options?.immediate === true) {
634
- applyImmediateCameraNavigationFeedback(module, reason, options);
635
- }
610
+ function wakeCameraNavigationAnimation(module, reason = 'camera-navigation-input') {
636
611
  if (module && typeof module.requestAnimationWake === 'function') {
637
612
  module.requestAnimationWake(reason);
638
613
  }
@@ -6117,15 +6092,16 @@ window.MindMapInteractions = (function () {
6117
6092
  // 휠 버퍼 상태 (모듈별로 관리)
6118
6093
  const wheelBuffers = new WeakMap();
6119
6094
  const wheelAnalysisCache = new WeakMap();
6120
-
6095
+
6121
6096
  function getWheelBuffer(module) {
6122
6097
  if (!wheelBuffers.has(module)) {
6123
6098
  wheelBuffers.set(module, {
6124
- deltaY: 0, // 누적된 deltaY
6125
- lastClientX: 0, // 마지막 마우스 X 위치
6126
- lastClientY: 0, // 마지막 마우스 Y 위치
6127
- pending: false, // rAF 대기 중 여부
6128
- frameId: null // rAF ID
6099
+ deltaY: 0,
6100
+ lastClientX: 0,
6101
+ lastClientY: 0,
6102
+ firstInputAt: 0,
6103
+ lastInputAt: 0,
6104
+ pending: false
6129
6105
  });
6130
6106
  }
6131
6107
  return wheelBuffers.get(module);
@@ -6160,22 +6136,6 @@ window.MindMapInteractions = (function () {
6160
6136
  return wheelNow;
6161
6137
  }
6162
6138
 
6163
- function scheduleWheelZoomFrame(module, wheelBuffer, callback) {
6164
- if (!module || !wheelBuffer || wheelBuffer.pending === true) {
6165
- return;
6166
- }
6167
-
6168
- wheelBuffer.pending = true;
6169
- const scheduleFrame = typeof requestAnimationFrame === 'function'
6170
- ? requestAnimationFrame
6171
- : (cb) => setTimeout(() => cb(performance.now()), 16);
6172
- wheelBuffer.frameId = scheduleFrame(() => {
6173
- wheelBuffer.pending = false;
6174
- wheelBuffer.frameId = null;
6175
- callback?.();
6176
- });
6177
- }
6178
-
6179
6139
  function matchesLetterShortcut(e, code, fallbackKey) {
6180
6140
  if (!e) {
6181
6141
  return false;
@@ -6401,7 +6361,7 @@ window.MindMapInteractions = (function () {
6401
6361
  module._lastPanInputAt = panInputAt;
6402
6362
  module._deferPassiveOverlayRefresh = true;
6403
6363
  module._cameraNavigationOverlayInputTime = panInputAt;
6404
- wakeCameraNavigationAnimation(module, 'trackpad-pan-input', { forceFrames: 3 });
6364
+ wakeCameraNavigationAnimation(module, 'trackpad-pan-input');
6405
6365
 
6406
6366
  if (module.isSelecting) {
6407
6367
  updateSelectionBox(module);
@@ -6419,50 +6379,78 @@ window.MindMapInteractions = (function () {
6419
6379
  applyTrackpadPanDelta(module, wheelAnalysis.deltaX, wheelAnalysis.deltaY);
6420
6380
  }
6421
6381
 
6422
- function bufferWheelEvent(module, e, analysis = null) {
6423
- const wheelBuffer = getWheelBuffer(module);
6424
- const deltaY = Number((analysis || getWheelEventAnalysis(module, e)).deltaY || 0);
6425
- if (deltaY === 0) {
6382
+ function bufferWheelDelta(module, deltaY, clientX, clientY, inputTime = 0) {
6383
+ const normalizedDeltaY = Number(deltaY || 0);
6384
+ if (!module || !Number.isFinite(normalizedDeltaY) || normalizedDeltaY === 0) {
6426
6385
  return;
6427
6386
  }
6428
6387
 
6429
- if (WHEEL_ZOOM_TARGET_UPDATE_MODE === 'event-direct') {
6430
- const wheelNow = getWheelTimestamp();
6431
- markCanvasWheelActivity(module, wheelNow, { throttleMs: WHEEL_ACTIVITY_BURST_INTERVAL_MS });
6432
- performCameraZoomBuffered(module, deltaY, e.clientX, e.clientY, { inputTime: wheelNow });
6433
- return;
6388
+ const wheelBuffer = getWheelBuffer(module);
6389
+ const wheelNow = Number(inputTime || 0) > 0 ? Number(inputTime) : getWheelTimestamp();
6390
+ if (wheelBuffer.pending !== true) {
6391
+ wheelBuffer.firstInputAt = wheelNow;
6392
+ }
6393
+ wheelBuffer.deltaY += normalizedDeltaY;
6394
+ wheelBuffer.lastClientX = Number(clientX || 0);
6395
+ wheelBuffer.lastClientY = Number(clientY || 0);
6396
+ wheelBuffer.lastInputAt = wheelNow;
6397
+ wheelBuffer.pending = true;
6398
+ wakeCameraNavigationAnimation(module, 'wheel-zoom-input');
6399
+ }
6400
+
6401
+ function bufferWheelEvent(module, e, analysis = null) {
6402
+ const wheelAnalysis = analysis || getWheelEventAnalysis(module, e);
6403
+ bufferWheelDelta(module, wheelAnalysis.deltaY, e?.clientX, e?.clientY, getWheelTimestamp());
6404
+ }
6405
+
6406
+ function consumePendingWheelZoom(module, frameTime = 0) {
6407
+ const wheelBuffer = wheelBuffers.get(module);
6408
+ if (!module || wheelBuffer?.pending !== true) {
6409
+ return false;
6434
6410
  }
6435
6411
 
6436
- wheelBuffer.deltaY += deltaY;
6437
- wheelBuffer.lastClientX = e.clientX;
6438
- wheelBuffer.lastClientY = e.clientY;
6439
- scheduleWheelZoomFrame(module, wheelBuffer, () => {
6440
- const accumulatedDeltaY = Number(wheelBuffer.deltaY || 0);
6441
- const clientX = wheelBuffer.lastClientX;
6442
- const clientY = wheelBuffer.lastClientY;
6443
- wheelBuffer.deltaY = 0;
6444
- if (Math.abs(accumulatedDeltaY) <= 0.001) {
6445
- return;
6446
- }
6412
+ const accumulatedDeltaY = Number(wheelBuffer.deltaY || 0);
6413
+ const clientX = Number(wheelBuffer.lastClientX || 0);
6414
+ const clientY = Number(wheelBuffer.lastClientY || 0);
6415
+ const firstInputAt = Number(wheelBuffer.firstInputAt || 0);
6416
+ const lastInputAt = Number(wheelBuffer.lastInputAt || 0);
6417
+ wheelBuffer.deltaY = 0;
6418
+ wheelBuffer.firstInputAt = 0;
6419
+ wheelBuffer.lastInputAt = 0;
6420
+ wheelBuffer.pending = false;
6421
+
6422
+ if (Math.abs(accumulatedDeltaY) <= 0.001) {
6423
+ return false;
6424
+ }
6447
6425
 
6448
- const wheelNow = getWheelTimestamp();
6449
- markCanvasWheelActivity(module, wheelNow, { throttleMs: WHEEL_ACTIVITY_BURST_INTERVAL_MS });
6450
- performCameraZoomBuffered(module, accumulatedDeltaY, clientX, clientY, { inputTime: wheelNow });
6426
+ const canonicalFrameTime = Number(frameTime || 0) > 0 ? Number(frameTime) : getWheelTimestamp();
6427
+ markCanvasWheelActivity(module, lastInputAt || canonicalFrameTime, {
6428
+ throttleMs: WHEEL_ACTIVITY_BURST_INTERVAL_MS
6451
6429
  });
6430
+ module._lastWheelInputToFrameLatencyMs = firstInputAt > 0
6431
+ ? Math.max(0, canonicalFrameTime - firstInputAt)
6432
+ : 0;
6433
+ module._wheelCanonicalConsumeCount = Number(module._wheelCanonicalConsumeCount || 0) + 1;
6434
+ return performCameraZoomBuffered(
6435
+ module,
6436
+ accumulatedDeltaY,
6437
+ clientX,
6438
+ clientY
6439
+ );
6452
6440
  }
6453
6441
 
6454
6442
  /**
6455
6443
  * 버퍼된 휠 데이터로 카메라 줌 수행
6456
6444
  * - 기존 performCameraZoom과 동일하지만 event 객체 대신 누적된 값 사용
6457
6445
  */
6458
- function performCameraZoomBuffered(module, deltaY, clientX, clientY, options = {}) {
6446
+ function performCameraZoomBuffered(module, deltaY, clientX, clientY) {
6459
6447
  if (!module || !module.camera || !module.container) {
6460
6448
  /*
6461
6449
  // ▼▼▼ [Fix] 안전 검사 추가 ▼▼▼
6462
6450
  if (!module || !module.camera || !module.container) {
6463
6451
  */
6464
6452
  console.warn('[Wheel Buffer] Module, camera, or container not ready');
6465
- return;
6453
+ return false;
6466
6454
  }
6467
6455
  /*
6468
6456
  // ▲▲▲ [Fix] ▲▲▲
@@ -6485,21 +6473,14 @@ window.MindMapInteractions = (function () {
6485
6473
  scheduleMotionWillChangeEnable(module);
6486
6474
  }
6487
6475
  }
6488
- // ▼▼▼ [Fix] 휠 입력 시간 기록 (줌 종료 타이밍 계산용) ▼▼▼
6489
6476
  // Keep wheel zoom in the cheap active-zoom local grid branch when the
6490
- // pointer has not moved. Exact grid style is reconciled after settle.
6477
+ // pointer has not moved. Exact grid style is reconciled on the first
6478
+ // following canonical frame that has no wheel input.
6491
6479
  if (module._isLocalSnapGridThemeEnabled?.() === true ||
6492
6480
  module._localSnapGridVisible === true ||
6493
6481
  module._localSnapGridLayer?.isConnected === true) {
6494
6482
  module.setLocalSnapGridClientPoint?.(clientX, clientY);
6495
6483
  }
6496
- module._zoomInputTime = Number(options?.inputTime || 0) > 0
6497
- ? Number(options.inputTime)
6498
- : performance.now();
6499
- // ▲▲▲ [Fix] ▲▲▲
6500
- // Reset zoom fallback flag on new input
6501
- // ▲▲▲ [Perf] ▲▲▲
6502
-
6503
6484
  const viewportMetrics = getCachedViewportMetrics(module);
6504
6485
  const viewportWidth = Math.max(1, Number(viewportMetrics.width || 0));
6505
6486
  const viewportHeight = Math.max(1, Number(viewportMetrics.height || 0));
@@ -6513,13 +6494,10 @@ window.MindMapInteractions = (function () {
6513
6494
  const worldMouseX = module.camera.position.x + (mouseX * viewWidth) / 2;
6514
6495
  const worldMouseY = module.camera.position.y + (mouseY * viewHeight) / 2;
6515
6496
 
6516
- const fixedZoomStep = Number(options.fixedZoomStep);
6517
6497
  const trackpadBoost = Math.abs(deltaY) < WHEEL_ZOOM_TRACKPAD_DELTA
6518
6498
  ? WHEEL_ZOOM_TRACKPAD_BOOST
6519
6499
  : 1;
6520
- const zoomStep = Number.isFinite(fixedZoomStep)
6521
- ? clampWheelZoomStep(fixedZoomStep)
6522
- : clampWheelZoomStep(deltaY * WHEEL_ZOOM_SENSITIVITY * trackpadBoost);
6500
+ const zoomStep = clampWheelZoomStep(deltaY * WHEEL_ZOOM_SENSITIVITY * trackpadBoost);
6523
6501
  const zoomAmount = module.targetZ * zoomStep;
6524
6502
  let newZ = module.targetZ + zoomAmount;
6525
6503
  newZ = Math.max(MIN_CAMERA_Z, Math.min(newZ, MAX_CAMERA_Z));
@@ -6529,7 +6507,7 @@ window.MindMapInteractions = (function () {
6529
6507
  if (Math.abs(newZ - module.targetZ) < 0.01) {
6530
6508
  // 경계값에 도달했으므로 줌 상태 종료 처리
6531
6509
  stopZoomInteractionState(module);
6532
- return;
6510
+ return false;
6533
6511
  }
6534
6512
 
6535
6513
  // ▼▼▼ [Changed] Smooth zoom: only update targets, let animate() interpolate ▼▼▼
@@ -6542,14 +6520,6 @@ window.MindMapInteractions = (function () {
6542
6520
  const newY = worldMouseY - (worldMouseY - module.targetY) * zoomRatio;
6543
6521
  module.targetX = newX;
6544
6522
  module.targetY = newY;
6545
- applyImmediateCameraNavigationFeedback(module, 'wheel-zoom-input', {
6546
- renderWebgl: false,
6547
- syncAutomationEdges: false,
6548
- syncLocalSnapGrid: false,
6549
- syncMotionGrid: false
6550
- });
6551
- const settleFrames = 2;
6552
- wakeCameraNavigationAnimation(module, 'wheel-zoom-input', { forceFrames: settleFrames });
6553
6523
  // ▲▲▲ [Changed] ▲▲▲
6554
6524
 
6555
6525
  // ▼▼▼ [Perf] 줌 종료 감지 및 CSS3D 업데이트 타이머 ▼▼▼
@@ -6562,12 +6532,14 @@ window.MindMapInteractions = (function () {
6562
6532
  console.log(`[Perf] Buffered zoom total: ${(t3 - t0).toFixed(1)}ms | z: ${cameraZ} -> ${newZ.toFixed(0)} | delta: ${deltaY.toFixed(1)}`);
6563
6533
  }
6564
6534
  }
6535
+ return true;
6565
6536
  }
6566
6537
  // ▲▲▲ [New] 휠 이벤트 버퍼링 시스템 ▲▲▲
6567
6538
 
6568
6539
  function performCameraZoom(module, e) {
6569
- if (!e) return;
6570
- return performCameraZoomBuffered(module, e.deltaY, e.clientX, e.clientY);
6540
+ if (!e) return false;
6541
+ bufferWheelDelta(module, normalizeWheelDeltaY(e), e.clientX, e.clientY, getWheelTimestamp());
6542
+ return true;
6571
6543
  }
6572
6544
 
6573
6545
  function beginPanFromMouseEvent(module, e, targetOverride = null) {
@@ -6703,7 +6675,7 @@ window.MindMapInteractions = (function () {
6703
6675
  module._deferPassiveOverlayRefresh = false;
6704
6676
  module._overlayDirty = true;
6705
6677
  window.MindMapTextOverlayV2?.invalidateView?.(module);
6706
- wakeCameraNavigationAnimation(module, 'ctrl-wheel-pan-input', { forceFrames: 3 });
6678
+ wakeCameraNavigationAnimation(module, 'ctrl-wheel-pan-input');
6707
6679
 
6708
6680
  if (module.isSelecting) {
6709
6681
  updateSelectionBox(module);
@@ -7001,7 +6973,7 @@ window.MindMapInteractions = (function () {
7001
6973
 
7002
6974
  e.preventDefault();
7003
6975
  e.stopPropagation();
7004
- performCameraZoomBuffered(module, gestureDeltaY, clientX, clientY);
6976
+ bufferWheelDelta(module, gestureDeltaY, clientX, clientY, getWheelTimestamp());
7005
6977
  }
7006
6978
 
7007
6979
  function onGestureEnd(module, e) {
@@ -7794,11 +7766,12 @@ window.MindMapInteractions = (function () {
7794
7766
  clearMotionWillChangeEnable(moduleInstance, { disableIfIdle: true });
7795
7767
  const wheelBuffer = wheelBuffers.get(moduleInstance);
7796
7768
  cancelPendingPrimaryClick(moduleInstance);
7797
- if (wheelBuffer?.frameId) {
7798
- cancelAnimationFrame(wheelBuffer.frameId);
7799
- wheelBuffer.frameId = null;
7769
+ if (wheelBuffer) {
7800
7770
  wheelBuffer.pending = false;
7801
7771
  wheelBuffer.deltaY = 0;
7772
+ wheelBuffer.firstInputAt = 0;
7773
+ wheelBuffer.lastInputAt = 0;
7774
+ wheelBuffers.delete(moduleInstance);
7802
7775
  }
7803
7776
  if (moduleInstance.cssRenderer && moduleInstance.cssRenderer.domElement) {
7804
7777
  moduleInstance.cssRenderer.domElement.removeEventListener('mousedown', handlers.boundOnResizeHandleCapture, true);
@@ -7893,6 +7866,7 @@ window.MindMapInteractions = (function () {
7893
7866
  isTrackpadPinchGesture: isTrackpadPinchGesture,
7894
7867
  routeWheelEventToZoom: routeWheelEventToZoom,
7895
7868
  routeCanvasWheelEvent: routeCanvasWheelEvent,
7869
+ consumePendingWheelZoom: consumePendingWheelZoom,
7896
7870
  invokeUndoRedo: invokeUndoRedo,
7897
7871
  setBrowserSelectionLock: setBrowserSelectionLock,
7898
7872
  clearNativeBrowserSelection: clearNativeBrowserSelection,
@@ -51,7 +51,7 @@
51
51
  // ▲▲▲ [Usage] ▲▲▲
52
52
 
53
53
  // Procedural line rendering settings
54
- const LOD_RENDERER_BUILD_ID = '20260727-mid-line-invariant-v847';
54
+ const LOD_RENDERER_BUILD_ID = '20260728-resident-cache-v848';
55
55
  const DirtyKind = Object.freeze({
56
56
  ResidentFullRebuild: 'resident-full-rebuild',
57
57
  ResidentPatch: 'resident-patch',
@@ -981,7 +981,7 @@
981
981
  this._lineMeasureFont = '';
982
982
  this._consoleNodeIdToIndex = new Map();
983
983
  this._lodConsoleProxyNodeIds = new Set();
984
- this._lodImageCssFallbackNodeIds = new Set();
984
+ this._lodImageCssFallbackNodeIds = window.MindMapRenderPlan?.createTrackedLodImageCssFallbackSet?.(this) || new Set();
985
985
  this._lodTemplateCssNodeIds = new Set();
986
986
  this._lodCleanupPending = true;
987
987
  this._lodCleanupDone = false;
@@ -3410,7 +3410,7 @@
3410
3410
  const imageInstanceRowCount = this.imageInstanceData?.nodeIds?.length || 0;
3411
3411
  const hasSelectionDrift = this._lastAppliedLodSelectionKey !== selectionKey;
3412
3412
  const usesCssImageFallbacks = this._shouldUseCssImageFallbackInResidentLod(module, lodBand);
3413
- const usesAnimatedGifCssFallbacks = this._hasAnimatedGifCssFallbackCandidates(module);
3413
+ const usesAnimatedGifCssFallbacks = this._hasAnimatedGifCssFallbackCandidates(module, selectionKey);
3414
3414
  const usesAnyImageCssFallbacks = usesCssImageFallbacks || usesAnimatedGifCssFallbacks;
3415
3415
  const imageCssFallbackCount = this._lodImageCssFallbackNodeIds?.size || 0;
3416
3416
  const activeImageCssFallbackCount = this._getActiveCssMediaLodFallbackCount(module);
@@ -7006,9 +7006,7 @@
7006
7006
  return count;
7007
7007
  }
7008
7008
 
7009
- _hasAnimatedGifCssFallbackCandidates(module = this._module) {
7010
- return window.MindMapRenderPlan?.hasAnimatedGifCssFallbackCandidates?.(this, module, isAnimatedGifImageModel) === true;
7011
- }
7009
+ _hasAnimatedGifCssFallbackCandidates(module=this._module,key='') { return window.MindMapRenderPlan?.hasAnimatedGifCssFallbackCandidates?.(this,module,isAnimatedGifImageModel,key||buildLodSelectionKey(module?.multiSelectedNodeIds||null,module?.selectedNodeIdJs||null))===true; }
7012
7010
 
7013
7011
  _shouldPreserveCssMediaFallbackForInteraction(entry, module = this._module) {
7014
7012
  const nodeId = String(entry?.model?.id || entry?.glObject?.userData?.nodeId || '').trim();
@@ -9670,7 +9668,7 @@
9670
9668
  this._fullResImageVisualIds?.delete?.(nodeId);
9671
9669
  this._nearPriorityRecordById?.delete?.(nodeId);
9672
9670
  this._lodConsoleProxyNodeIds?.delete?.(nodeId);
9673
- this._lodImageCssFallbackNodeIds?.delete?.(nodeId);
9671
+ this._lodImageCssFallbackNodeIds.delete(nodeId);
9674
9672
  this._lodTemplateCssNodeIds?.delete?.(nodeId);
9675
9673
  this._fullResCssFringePreparedIds?.delete?.(nodeId);
9676
9674
  removedAny = true;
@@ -1,7 +1,7 @@
1
1
  (function () {
2
2
  'use strict';
3
3
 
4
- const LOGIC_WORKER_BRIDGE_BUILD_ID = '20260713-worker-visibility-sequence-v007';
4
+ const LOGIC_WORKER_BRIDGE_BUILD_ID = '20260728-cached-viewport-v008';
5
5
  const VISIBILITY_WORKER_URL = `_content/MindExecution.Shared/js/mind-map-visibility-worker.js?v=${LOGIC_WORKER_BRIDGE_BUILD_ID}`;
6
6
  const LOD_PLAN_WORKER_URL = `_content/MindExecution.Shared/js/mind-map-lod-plan-worker.js?v=${LOGIC_WORKER_BRIDGE_BUILD_ID}`;
7
7
  const NODE_SEARCH_WORKER_URL = `_content/MindExecution.Shared/js/mind-map-node-search-worker.js?v=${LOGIC_WORKER_BRIDGE_BUILD_ID}`;
@@ -709,8 +709,14 @@
709
709
  return false;
710
710
  }
711
711
 
712
- const viewportWidth = Math.max(1, Number(activeModule.container?.clientWidth || activeModule._lastViewportWidth || 1));
713
- const viewportHeight = Math.max(1, Number(activeModule.container?.clientHeight || activeModule._lastViewportHeight || 1));
712
+ const cachedViewportWidth = Number(activeModule._lastViewportWidth || 0);
713
+ const cachedViewportHeight = Number(activeModule._lastViewportHeight || 0);
714
+ const viewportWidth = cachedViewportWidth > 0
715
+ ? cachedViewportWidth
716
+ : Math.max(1, Number(activeModule.container?.clientWidth || 1));
717
+ const viewportHeight = cachedViewportHeight > 0
718
+ ? cachedViewportHeight
719
+ : Math.max(1, Number(activeModule.container?.clientHeight || 1));
714
720
  const now = (typeof performance !== 'undefined' && typeof performance.now === 'function')
715
721
  ? performance.now()
716
722
  : Date.now();