@mindexec/cli 0.2.440 → 0.2.442
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/package.json +1 -1
- package/remote-fast/osx-arm64/MacScreenCaptureKitH264.swift +339 -0
- package/remote-fast/osx-arm64/MacSystemAudioCapture.swift +214 -0
- package/remote-fast/osx-arm64/UnixRawCaptureHelper.mjs +80 -0
- package/remote-fast/osx-arm64/livedesk-raw-capture-resampler.mjs +73 -0
- package/remote-fast/osx-arm64/mindexec-remote-fast.dll +0 -0
- package/remote-fast/osx-x64/MacScreenCaptureKitH264.swift +339 -0
- package/remote-fast/osx-x64/MacSystemAudioCapture.swift +214 -0
- package/remote-fast/osx-x64/UnixRawCaptureHelper.mjs +80 -0
- package/remote-fast/osx-x64/livedesk-raw-capture-resampler.mjs +73 -0
- package/remote-fast/osx-x64/mindexec-remote-fast.dll +0 -0
- package/remote-fast/win-x64/NAudio.Asio.dll +0 -0
- package/remote-fast/win-x64/NAudio.Core.dll +0 -0
- package/remote-fast/win-x64/NAudio.Midi.dll +0 -0
- package/remote-fast/win-x64/NAudio.Wasapi.dll +0 -0
- package/remote-fast/win-x64/NAudio.WinForms.dll +0 -0
- package/remote-fast/win-x64/NAudio.WinMM.dll +0 -0
- package/remote-fast/win-x64/NAudio.dll +0 -0
- package/remote-fast/win-x64/SharpGen.Runtime.COM.dll +0 -0
- package/remote-fast/win-x64/SharpGen.Runtime.dll +0 -0
- package/remote-fast/win-x64/Vortice.DXGI.dll +0 -0
- package/remote-fast/win-x64/Vortice.Direct3D11.dll +0 -0
- package/remote-fast/win-x64/Vortice.DirectX.dll +0 -0
- package/remote-fast/win-x64/Vortice.Mathematics.dll +0 -0
- package/remote-fast/win-x64/mindexec-remote-fast.deps.json +238 -0
- package/remote-fast/win-x64/mindexec-remote-fast.dll +0 -0
- package/remote-fast/win-x64/mindexec-remote-fast.exe +0 -0
- package/remote-hub.js +42 -3
- package/server.js +22 -6
- package/wwwroot/_content/MindExecution.Shared/css/mind-map-overrides.css +49 -0
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +6 -2
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +70 -60
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-multi-select.js +32 -6
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-remote-codecs.js +126 -0
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-video-playback-controls.js +95 -0
- package/wwwroot/_framework/{MindExecution.Core.808jj176e1.dll → MindExecution.Core.nxjlewduna.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Kernel.75hxk08tt0.dll → MindExecution.Kernel.vrfi63yg9f.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Admin.0zkmk8wahq.dll → MindExecution.Plugins.Admin.1rcwhdxl0r.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Business.vyw3769hrw.dll → MindExecution.Plugins.Business.rx0eieg51y.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.cvmglrxsjb.dll → MindExecution.Plugins.Concept.zzczjzhvk1.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Directory.jtw9q1dm9n.dll → MindExecution.Plugins.Directory.bsorcntiwp.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.8hmc6ps1ux.dll → MindExecution.Plugins.PlanMaster.i5j9t4f1jf.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.xb9sou9ox0.dll → MindExecution.Plugins.YouTube.1mpn9satft.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.pqab76cjb6.dll → MindExecution.Shared.mpi1gzau9b.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Web.mc24u4bzol.dll → MindExecution.Web.nxykcyxd02.dll} +0 -0
- package/wwwroot/_framework/blazor.boot.json +21 -21
- package/wwwroot/index.html +3 -1
- package/wwwroot/service-worker-assets.js +35 -27
- package/wwwroot/service-worker.js +1 -1
|
@@ -7204,8 +7204,12 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
|
|
|
7204
7204
|
window.MindMapMenuManager.hideMenu();
|
|
7205
7205
|
}
|
|
7206
7206
|
_profileSection('menu');
|
|
7207
|
-
if (isMultiSelectOverlayUiEnabled && window.MindMapMultiSelect
|
|
7208
|
-
|
|
7207
|
+
if (isMultiSelectOverlayUiEnabled && window.MindMapMultiSelect) {
|
|
7208
|
+
if (shouldDeferFloatingUiDuringMotion === true) {
|
|
7209
|
+
window.MindMapMultiSelect.updateForCameraMotion?.();
|
|
7210
|
+
} else {
|
|
7211
|
+
window.MindMapMultiSelect.update();
|
|
7212
|
+
}
|
|
7209
7213
|
} else if (!isMultiSelectOverlayUiEnabled && window.MindMapMultiSelect?.hide) {
|
|
7210
7214
|
window.MindMapMultiSelect.hide();
|
|
7211
7215
|
}
|
|
@@ -2013,6 +2013,7 @@
|
|
|
2013
2013
|
const preferredSource = getCss3dVideoDeferredSource(videoEl, nodeModel);
|
|
2014
2014
|
if (videoEl.dataset) {
|
|
2015
2015
|
videoEl.dataset.lodMediaSuspended = 'false';
|
|
2016
|
+
videoEl.dataset.videoPositionRestorePending = preferredSource ? 'true' : 'false';
|
|
2016
2017
|
}
|
|
2017
2018
|
videoEl.preload = videoEl.dataset?.lodSuspendedPreload || 'metadata';
|
|
2018
2019
|
|
|
@@ -3223,7 +3224,6 @@
|
|
|
3223
3224
|
const normalizedIntent = normalizeVideoNodePlaybackIntent(intent) || 'pause';
|
|
3224
3225
|
if (nodeModel) {
|
|
3225
3226
|
nodeModel._videoPlayIntent = normalizedIntent;
|
|
3226
|
-
setNodeMetadataValue(nodeModel, VIDEO_PLAYBACK_INTENT_METADATA_KEY, normalizedIntent);
|
|
3227
3227
|
}
|
|
3228
3228
|
if (videoEl?.dataset) {
|
|
3229
3229
|
videoEl.autoplay = normalizedIntent === 'play';
|
|
@@ -3233,6 +3233,7 @@
|
|
|
3233
3233
|
if (options?.persist === true) {
|
|
3234
3234
|
persistVideoNodePlaybackIntent(nodeModel, normalizedIntent);
|
|
3235
3235
|
}
|
|
3236
|
+
window.MindMapVideoPlaybackControls?.sync?.(videoEl, normalizedIntent);
|
|
3236
3237
|
return normalizedIntent;
|
|
3237
3238
|
}
|
|
3238
3239
|
|
|
@@ -3290,50 +3291,13 @@
|
|
|
3290
3291
|
}
|
|
3291
3292
|
|
|
3292
3293
|
function bindVideoPlaybackStateTracking(videoEl, nodeModel) {
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
}
|
|
3301
|
-
|
|
3302
|
-
if (videoEl.dataset) {
|
|
3303
|
-
videoEl.dataset.videoPlaybackStateBoundNodeId = nodeId || '';
|
|
3304
|
-
}
|
|
3305
|
-
|
|
3306
|
-
const rememberTimeOnly = () => {
|
|
3307
|
-
const currentTime = Number(videoEl.currentTime || 0);
|
|
3308
|
-
if (Number.isFinite(currentTime) && currentTime >= 0) {
|
|
3309
|
-
nodeModel._videoPlaybackCurrentTime = currentTime;
|
|
3310
|
-
if (videoEl.dataset) {
|
|
3311
|
-
videoEl.dataset.videoLastKnownTime = String(currentTime);
|
|
3312
|
-
}
|
|
3313
|
-
}
|
|
3314
|
-
};
|
|
3315
|
-
|
|
3316
|
-
const markPlaying = () => {
|
|
3317
|
-
rememberVideoNodeRuntimePlayback(nodeModel, videoEl, { forceIntent: true });
|
|
3318
|
-
setVideoNodePlaybackIntent(nodeModel, videoEl, 'play');
|
|
3319
|
-
};
|
|
3320
|
-
|
|
3321
|
-
const markPaused = () => {
|
|
3322
|
-
rememberTimeOnly();
|
|
3323
|
-
if (videoEl.dataset?.visibilityPaused === 'true' || videoEl.dataset?.videoResumePending === 'true') {
|
|
3324
|
-
return;
|
|
3325
|
-
}
|
|
3326
|
-
setVideoNodePlaybackIntent(nodeModel, videoEl, 'pause');
|
|
3327
|
-
};
|
|
3328
|
-
|
|
3329
|
-
videoEl.addEventListener('play', markPlaying, { passive: true });
|
|
3330
|
-
videoEl.addEventListener('playing', markPlaying, { passive: true });
|
|
3331
|
-
videoEl.addEventListener('pause', markPaused, { passive: true });
|
|
3332
|
-
videoEl.addEventListener('timeupdate', rememberTimeOnly, { passive: true });
|
|
3333
|
-
videoEl.addEventListener('seeking', rememberTimeOnly, { passive: true });
|
|
3334
|
-
videoEl.addEventListener('loadedmetadata', () => {
|
|
3335
|
-
restoreVideoNodeRuntimePlaybackPosition(nodeModel, videoEl);
|
|
3336
|
-
}, { passive: true });
|
|
3294
|
+
return window.MindMapVideoPlaybackControls?.bindState?.(videoEl, nodeModel, {
|
|
3295
|
+
getNodeId,
|
|
3296
|
+
getIntent: getVideoNodePlaybackIntent,
|
|
3297
|
+
rememberRuntime: rememberVideoNodeRuntimePlayback,
|
|
3298
|
+
restorePosition: restoreVideoNodeRuntimePlaybackPosition,
|
|
3299
|
+
setIntent: setVideoNodePlaybackIntent
|
|
3300
|
+
});
|
|
3337
3301
|
}
|
|
3338
3302
|
|
|
3339
3303
|
function ensureVideoNodePlaybackState(nodeModel, videoEl) {
|
|
@@ -4498,12 +4462,12 @@
|
|
|
4498
4462
|
syncMediaLoadingRowForElement(mediaEl, nodeModel, contentTypeLower);
|
|
4499
4463
|
mediaEl.dataset.assetRefreshAttempted = '';
|
|
4500
4464
|
if (contentTypeLower === 'video') {
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4465
|
+
restoreVideoNodeRuntimePlaybackPosition(nodeModel, mediaEl);
|
|
4466
|
+
mediaEl.dataset.videoPositionRestorePending = 'false';
|
|
4467
|
+
const entry = getNodeEntryById(getNodeId(nodeModel));
|
|
4468
|
+
if (getVideoNodePlaybackIntent(nodeModel, mediaEl) === 'play' &&
|
|
4469
|
+
mediaEl.dataset?.userPaused !== 'true' && entry?.cssObject) {
|
|
4470
|
+
playVideoNodeForVisibility(nodeModel, entry.cssObject, mediaEl);
|
|
4507
4471
|
}
|
|
4508
4472
|
}
|
|
4509
4473
|
};
|
|
@@ -14927,9 +14891,9 @@
|
|
|
14927
14891
|
const REMOTE_FLEET_MONITOR_REFRESH_MS = 10000;
|
|
14928
14892
|
const REMOTE_FLEET_EMPTY_MONITOR_REFRESH_MS = 2500;
|
|
14929
14893
|
const REMOTE_FLEET_LIVE_REFRESH_MS = 30000;
|
|
14930
|
-
const REMOTE_FLEET_MONITOR_LIVE_FPS =
|
|
14894
|
+
const REMOTE_FLEET_MONITOR_LIVE_FPS = 20;
|
|
14931
14895
|
const REMOTE_FLEET_LIVE_FRAME_REFRESH_MS = Math.round(1000 / REMOTE_FLEET_MONITOR_LIVE_FPS);
|
|
14932
|
-
const REMOTE_FLEET_CONTROL_LIVE_FPS =
|
|
14896
|
+
const REMOTE_FLEET_CONTROL_LIVE_FPS = 30;
|
|
14933
14897
|
const REMOTE_FLEET_CONTROL_FRAME_REFRESH_MS = Math.round(1000 / REMOTE_FLEET_CONTROL_LIVE_FPS);
|
|
14934
14898
|
const REMOTE_FLEET_CONTROL_INPUT_MOVE_MS = 16;
|
|
14935
14899
|
const REMOTE_FLEET_CONTROL_INPUT_QUEUE_LIMIT = 64;
|
|
@@ -15703,7 +15667,8 @@
|
|
|
15703
15667
|
Number(liveOptions.maxWidth || 0) || 0,
|
|
15704
15668
|
Number(liveOptions.maxHeight || 0) || 0,
|
|
15705
15669
|
Number(liveOptions.quality || 0) || 0,
|
|
15706
|
-
String(liveOptions.mode || '')
|
|
15670
|
+
String(liveOptions.mode || ''),
|
|
15671
|
+
String(liveOptions.streamPurpose || 'wall')
|
|
15707
15672
|
].join('|');
|
|
15708
15673
|
const key = `${deviceIds.join('\n')}::${optionKey}`;
|
|
15709
15674
|
const now = getRemoteFleetFrameNow();
|
|
@@ -15728,7 +15693,9 @@
|
|
|
15728
15693
|
maxWidth: liveOptions.maxWidth,
|
|
15729
15694
|
maxHeight: liveOptions.maxHeight,
|
|
15730
15695
|
quality: liveOptions.quality,
|
|
15731
|
-
mode: liveOptions.mode
|
|
15696
|
+
mode: liveOptions.mode,
|
|
15697
|
+
frameMode: liveOptions.mode,
|
|
15698
|
+
streamPurpose: liveOptions.streamPurpose || 'wall'
|
|
15732
15699
|
}));
|
|
15733
15700
|
return true;
|
|
15734
15701
|
}
|
|
@@ -15988,7 +15955,8 @@
|
|
|
15988
15955
|
maxWidth: Number(options.maxWidth || 960) || 960,
|
|
15989
15956
|
maxHeight: Number(options.maxHeight || 540) || 540,
|
|
15990
15957
|
quality: Number(options.quality || 60) || 60,
|
|
15991
|
-
mode: String(options.mode || '
|
|
15958
|
+
mode: String(options.mode || 'mode3-h264-hw'),
|
|
15959
|
+
streamPurpose: String(options.streamPurpose || 'wall')
|
|
15992
15960
|
};
|
|
15993
15961
|
bodyView._remoteFleetBinaryFrameSession = session;
|
|
15994
15962
|
primeRemoteFleetRenderedFrameSurfaces(bodyView, 'ws-start');
|
|
@@ -17222,6 +17190,20 @@
|
|
|
17222
17190
|
}
|
|
17223
17191
|
|
|
17224
17192
|
function applyRemoteFleetFramePatchToPreview(preview, frame) {
|
|
17193
|
+
if (frame?._remoteFleetBinaryFrame === true
|
|
17194
|
+
&& frame?._remoteFleetPayloadBlob
|
|
17195
|
+
&& String(frame.codec || '').toLowerCase().includes('h264')
|
|
17196
|
+
&& window.MindExecRemoteCodecs?.decodeH264Frame) {
|
|
17197
|
+
const canvas = ensureRemoteFleetFrameCanvas(preview);
|
|
17198
|
+
if (canvas) {
|
|
17199
|
+
canvas.style.display = 'block';
|
|
17200
|
+
preview.querySelector?.('img[data-remote-fleet-frame-image="true"]')?.style.setProperty('display', 'none');
|
|
17201
|
+
window.MindExecRemoteCodecs.decodeH264Frame(canvas, frame).catch?.(() => undefined);
|
|
17202
|
+
preview.dataset.remoteFleetFrameKind = String(frame.kind || 'live').toLowerCase();
|
|
17203
|
+
preview.dataset.remoteFleetFrameSeq = String(frame.frameSeq || 0);
|
|
17204
|
+
return true;
|
|
17205
|
+
}
|
|
17206
|
+
}
|
|
17225
17207
|
if (frame?._remoteFleetBinaryFrame === true && frame?._remoteFleetPayloadBlob) {
|
|
17226
17208
|
preview._remoteFleetPendingImageFrame = null;
|
|
17227
17209
|
delete preview.dataset.remoteFleetPendingImageKind;
|
|
@@ -17451,7 +17433,8 @@
|
|
|
17451
17433
|
maxWidth: 1280,
|
|
17452
17434
|
maxHeight: 720,
|
|
17453
17435
|
quality: 65,
|
|
17454
|
-
mode: '
|
|
17436
|
+
mode: 'mode3-h264-hw',
|
|
17437
|
+
streamPurpose: 'control'
|
|
17455
17438
|
})) {
|
|
17456
17439
|
return false;
|
|
17457
17440
|
}
|
|
@@ -17474,7 +17457,8 @@
|
|
|
17474
17457
|
maxWidth: 1280,
|
|
17475
17458
|
maxHeight: 720,
|
|
17476
17459
|
quality: 65,
|
|
17477
|
-
mode: '
|
|
17460
|
+
mode: 'mode3-h264-hw',
|
|
17461
|
+
streamPurpose: 'control'
|
|
17478
17462
|
};
|
|
17479
17463
|
controlSession.binaryFrameSession = binarySession;
|
|
17480
17464
|
controlSession.binaryFramePreferred = true;
|
|
@@ -17550,6 +17534,22 @@
|
|
|
17550
17534
|
session.lastControlFrameSeq = frameSeq;
|
|
17551
17535
|
}
|
|
17552
17536
|
|
|
17537
|
+
if (frame._remoteFleetPayloadBlob
|
|
17538
|
+
&& String(frame.codec || '').toLowerCase().includes('h264')
|
|
17539
|
+
&& window.MindExecRemoteCodecs?.decodeH264Frame) {
|
|
17540
|
+
const painted = await window.MindExecRemoteCodecs.decodeH264Frame(session.canvas, frame);
|
|
17541
|
+
if (painted && session.active) {
|
|
17542
|
+
session.canvas.dataset.remoteFleetFrameKind = 'live';
|
|
17543
|
+
session.canvas.dataset.remoteFleetFrameSeq = String(frameSeq || 0);
|
|
17544
|
+
session.canvas.style.display = 'block';
|
|
17545
|
+
session.lastControlFrameAt = Date.now();
|
|
17546
|
+
session.status.textContent = `Control ${REMOTE_FLEET_CONTROL_LIVE_FPS}fps`;
|
|
17547
|
+
session.placeholder?.remove?.();
|
|
17548
|
+
session.placeholder = null;
|
|
17549
|
+
}
|
|
17550
|
+
return painted;
|
|
17551
|
+
}
|
|
17552
|
+
|
|
17553
17553
|
let bitmap = null;
|
|
17554
17554
|
try {
|
|
17555
17555
|
if (frame._remoteFleetPayloadBlob && typeof createImageBitmap === 'function') {
|
|
@@ -17820,11 +17820,16 @@
|
|
|
17820
17820
|
}
|
|
17821
17821
|
|
|
17822
17822
|
const input = createRemoteFleetControlInput(session, payload);
|
|
17823
|
+
const inputSeq = Number(session.inputSeq || 0) + 1;
|
|
17824
|
+
session.inputSeq = inputSeq;
|
|
17825
|
+
input.inputSeq = inputSeq;
|
|
17826
|
+
input.requestAck = String(input.type || '').toLowerCase() !== 'pointermove' || inputSeq % 6 === 0;
|
|
17823
17827
|
const envelope = {
|
|
17824
17828
|
type: 'input',
|
|
17825
17829
|
nodeId: session.nodeId,
|
|
17826
17830
|
deviceId: session.deviceId,
|
|
17827
17831
|
requestId: `input-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
17832
|
+
fireAndForget: input.requestAck !== true,
|
|
17828
17833
|
input
|
|
17829
17834
|
};
|
|
17830
17835
|
|
|
@@ -18351,7 +18356,7 @@
|
|
|
18351
18356
|
maxWidth: 1280,
|
|
18352
18357
|
maxHeight: 720,
|
|
18353
18358
|
quality: 65,
|
|
18354
|
-
mode: '
|
|
18359
|
+
mode: 'mode3-h264-hw'
|
|
18355
18360
|
});
|
|
18356
18361
|
attachRemoteFleetControlBinaryFrameSession(session, bodyView);
|
|
18357
18362
|
stage.focus?.({ preventScroll: true });
|
|
@@ -20712,7 +20717,8 @@
|
|
|
20712
20717
|
maxWidth: 960,
|
|
20713
20718
|
maxHeight: 540,
|
|
20714
20719
|
quality: 60,
|
|
20715
|
-
mode: '
|
|
20720
|
+
mode: 'mode3-h264-hw',
|
|
20721
|
+
streamPurpose: 'wall'
|
|
20716
20722
|
});
|
|
20717
20723
|
if (!binaryFrameSocketStarted) {
|
|
20718
20724
|
window.RuntimeTrace?.emit?.('remote.frame.wsUnavailable', {
|
|
@@ -23678,6 +23684,10 @@
|
|
|
23678
23684
|
|
|
23679
23685
|
responseDiv.appendChild(video);
|
|
23680
23686
|
responseDiv.appendChild(canvasProxy);
|
|
23687
|
+
window.MindMapVideoPlaybackControls?.mount?.(responseDiv, video, {
|
|
23688
|
+
getIntent: () => getVideoNodePlaybackIntent(nodeModel, video),
|
|
23689
|
+
onToggle: shouldPlay => setVideoNodePlayback(getNodeId(nodeModel), shouldPlay)
|
|
23690
|
+
});
|
|
23681
23691
|
} else if (contentTypeLower === 'embed') {
|
|
23682
23692
|
responseDiv.className = 'node-response embed-content';
|
|
23683
23693
|
responseDiv.style.cssText = `width: 100%; height: 100%; display: block; position: relative; pointer-events: auto; padding: 0 !important; margin: 0 !important; background: transparent; border: 0 !important; overflow: hidden; scrollbar-width: none;`;
|
|
@@ -343,7 +343,7 @@
|
|
|
343
343
|
return nodeEntry?.model?.contentType === 'image' ? nodeId : null;
|
|
344
344
|
}
|
|
345
345
|
|
|
346
|
-
function updateSingleImageOverlay() {
|
|
346
|
+
function updateSingleImageOverlay(forceWorldProjection = false) {
|
|
347
347
|
if (!_module || !singleImageOverlay || !_module.camera || !_module.container) return;
|
|
348
348
|
|
|
349
349
|
const nodeId = getSingleSelectedImageNodeId();
|
|
@@ -360,7 +360,10 @@
|
|
|
360
360
|
return;
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
-
|
|
363
|
+
// Camera-only motion must stay on the projection fast path. Reading the
|
|
364
|
+
// CSS node rect here can force layout and may still reflect the previous
|
|
365
|
+
// CSS3D camera transform when this overlay is updated in the same frame.
|
|
366
|
+
const screenRect = forceWorldProjection ? null : getNodeScreenRect(nodeEntry);
|
|
364
367
|
if (screenRect) {
|
|
365
368
|
const screenWidth = Math.max(0, screenRect.right - screenRect.left);
|
|
366
369
|
const screenHeight = Math.max(0, screenRect.bottom - screenRect.top);
|
|
@@ -1594,6 +1597,28 @@
|
|
|
1594
1597
|
updateMultiSelectOverlay();
|
|
1595
1598
|
updateSingleImageOverlay();
|
|
1596
1599
|
}
|
|
1600
|
+
|
|
1601
|
+
// Camera-only fast path: currentBounds and node world frames are already
|
|
1602
|
+
// canonical, so reproject only the fixed overlays. This deliberately avoids
|
|
1603
|
+
// selected-node scans, DOM layout reads, menu work, and renderer rebuilds.
|
|
1604
|
+
function updateForCameraMotion() {
|
|
1605
|
+
if (!_module || !_module.camera || !_module.container) return false;
|
|
1606
|
+
|
|
1607
|
+
let updated = false;
|
|
1608
|
+
if (multiSelectOverlay &&
|
|
1609
|
+
multiSelectOverlay.style.display !== 'none' &&
|
|
1610
|
+
currentBounds) {
|
|
1611
|
+
updateOverlayPosition(null, true);
|
|
1612
|
+
updated = true;
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
if (getSingleSelectedImageNodeId()) {
|
|
1616
|
+
updateSingleImageOverlay(true);
|
|
1617
|
+
updated = true;
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
return updated;
|
|
1621
|
+
}
|
|
1597
1622
|
// ▲▲▲ [Perf] ▲▲▲
|
|
1598
1623
|
|
|
1599
1624
|
// ▼▼▼ [New] Dynamic menu button creation based on selection type ▼▼▼
|
|
@@ -1701,10 +1726,11 @@
|
|
|
1701
1726
|
|
|
1702
1727
|
window.MindMapMultiSelect = {
|
|
1703
1728
|
init,
|
|
1704
|
-
showMultiSelectBounds,
|
|
1705
|
-
hide,
|
|
1706
|
-
update,
|
|
1707
|
-
|
|
1729
|
+
showMultiSelectBounds,
|
|
1730
|
+
hide,
|
|
1731
|
+
update,
|
|
1732
|
+
updateForCameraMotion,
|
|
1733
|
+
checkAndUpdateDisplay,
|
|
1708
1734
|
getSelectedImageNodeIds,
|
|
1709
1735
|
fitTextNodesToContentAndReflowY,
|
|
1710
1736
|
isResizing: () => isResizing,
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const decoderByCanvas = new WeakMap();
|
|
5
|
+
const MAX_DECODE_QUEUE = 3;
|
|
6
|
+
|
|
7
|
+
function emit(type, data) {
|
|
8
|
+
window.RuntimeTrace?.emit?.(type, data);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function getDecoderState(canvas) {
|
|
12
|
+
let state = decoderByCanvas.get(canvas);
|
|
13
|
+
if (state) return state;
|
|
14
|
+
state = {
|
|
15
|
+
decoder: null,
|
|
16
|
+
generation: 0,
|
|
17
|
+
width: 0,
|
|
18
|
+
height: 0,
|
|
19
|
+
pending: 0,
|
|
20
|
+
lastSeq: 0,
|
|
21
|
+
lastPaintAt: 0
|
|
22
|
+
};
|
|
23
|
+
decoderByCanvas.set(canvas, state);
|
|
24
|
+
return state;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function closeDecoder(state) {
|
|
28
|
+
try { state.decoder?.close?.(); } catch { /* stale decoder */ }
|
|
29
|
+
state.decoder = null;
|
|
30
|
+
state.pending = 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function ensureDecoder(canvas, frame, state) {
|
|
34
|
+
if (typeof VideoDecoder !== 'function' || typeof EncodedVideoChunk !== 'function') {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const width = Number(frame.width || 0) || canvas.width || 1920;
|
|
39
|
+
const height = Number(frame.height || 0) || canvas.height || 1080;
|
|
40
|
+
const key = `${width}x${height}`;
|
|
41
|
+
if (state.decoder && state.width === width && state.height === height) {
|
|
42
|
+
return state.decoder;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
closeDecoder(state);
|
|
46
|
+
state.width = width;
|
|
47
|
+
state.height = height;
|
|
48
|
+
const generation = ++state.generation;
|
|
49
|
+
const decoder = new VideoDecoder({
|
|
50
|
+
output(videoFrame) {
|
|
51
|
+
if (generation !== state.generation) {
|
|
52
|
+
videoFrame.close?.();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
canvas.width = videoFrame.displayWidth || width;
|
|
57
|
+
canvas.height = videoFrame.displayHeight || height;
|
|
58
|
+
const context = canvas.getContext('2d', { alpha: false, desynchronized: true });
|
|
59
|
+
context?.drawImage(videoFrame, 0, 0, canvas.width, canvas.height);
|
|
60
|
+
state.lastPaintAt = performance.now();
|
|
61
|
+
emit('remote.h264.paint', { frameSeq: state.lastSeq, width: canvas.width, height: canvas.height });
|
|
62
|
+
} finally {
|
|
63
|
+
videoFrame.close?.();
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
error(error) {
|
|
67
|
+
emit('remote.h264.decodeFailed', { error: error?.message || String(error || ''), frameSeq: state.lastSeq });
|
|
68
|
+
closeDecoder(state);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
try {
|
|
72
|
+
decoder.configure({
|
|
73
|
+
codec: String(frame.codec || 'avc1.42E01E'),
|
|
74
|
+
codedWidth: width,
|
|
75
|
+
codedHeight: height,
|
|
76
|
+
hardwareAcceleration: 'prefer-software',
|
|
77
|
+
optimizeForLatency: true,
|
|
78
|
+
avc: { format: String(frame.h264Format || 'annexb').toLowerCase() === 'avc' ? 'avc' : 'annexb' }
|
|
79
|
+
});
|
|
80
|
+
} catch (error) {
|
|
81
|
+
emit('remote.h264.configureFailed', { key, error: error?.message || String(error || '') });
|
|
82
|
+
try { decoder.close(); } catch { /* ignore */ }
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
state.decoder = decoder;
|
|
86
|
+
return decoder;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function decode(canvas, frame) {
|
|
90
|
+
const payload = frame?._remoteFleetPayloadBlob;
|
|
91
|
+
if (!canvas || !payload || !String(frame?.codec || '').toLowerCase().includes('h264')) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
const state = getDecoderState(canvas);
|
|
95
|
+
const seq = Number(frame.streamFrameSeq || frame.frameSeq || 0) || 0;
|
|
96
|
+
if (seq > 0 && seq <= state.lastSeq) return true;
|
|
97
|
+
state.lastSeq = seq;
|
|
98
|
+
const decoder = ensureDecoder(canvas, frame, state);
|
|
99
|
+
if (!decoder || decoder.state === 'closed') return false;
|
|
100
|
+
if (state.pending >= MAX_DECODE_QUEUE) {
|
|
101
|
+
emit('remote.h264.drop', { reason: 'decode-queue', frameSeq: seq });
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
state.pending += 1;
|
|
105
|
+
try {
|
|
106
|
+
const bytes = new Uint8Array(await payload.arrayBuffer());
|
|
107
|
+
if (!bytes.length) return false;
|
|
108
|
+
const timestamp = Number(frame.timestampUs || 0) || Math.round(performance.now() * 1000);
|
|
109
|
+
decoder.decode(new EncodedVideoChunk({
|
|
110
|
+
type: frame.isKeyFrame === true || String(frame.chunkType || '').toLowerCase() === 'key' ? 'key' : 'delta',
|
|
111
|
+
timestamp,
|
|
112
|
+
duration: Number(frame.durationUs || 0) || undefined,
|
|
113
|
+
data: bytes
|
|
114
|
+
}));
|
|
115
|
+
return true;
|
|
116
|
+
} catch (error) {
|
|
117
|
+
emit('remote.h264.decodeSubmitFailed', { error: error?.message || String(error || ''), frameSeq: seq });
|
|
118
|
+
closeDecoder(state);
|
|
119
|
+
return false;
|
|
120
|
+
} finally {
|
|
121
|
+
state.pending = Math.max(0, state.pending - 1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
window.MindExecRemoteCodecs = Object.freeze({ decodeH264Frame: decode });
|
|
126
|
+
})();
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Selected video-node playback chrome. Runtime playback ownership stays in the CSS3D manager.
|
|
2
|
+
(function () {
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
function sync(videoEl, intent) {
|
|
6
|
+
const control = videoEl?.closest?.('.video-content')?.querySelector?.('.mind-map-video-playback-control');
|
|
7
|
+
if (!control) return false;
|
|
8
|
+
|
|
9
|
+
const wantsPlayback = String(intent || '').toLowerCase() === 'play' &&
|
|
10
|
+
videoEl?.dataset?.userPaused !== 'true';
|
|
11
|
+
control.dataset.playbackIntent = wantsPlayback ? 'play' : 'pause';
|
|
12
|
+
control.setAttribute('aria-label', wantsPlayback ? 'Pause video' : 'Play video');
|
|
13
|
+
control.setAttribute('aria-pressed', wantsPlayback ? 'true' : 'false');
|
|
14
|
+
const icon = control.querySelector?.('.mind-map-video-playback-control__icon');
|
|
15
|
+
const status = control.querySelector?.('.mind-map-video-playback-control__status');
|
|
16
|
+
if (icon) icon.textContent = wantsPlayback ? '❚❚' : '▶';
|
|
17
|
+
if (status) status.textContent = wantsPlayback ? 'Playing' : 'Paused';
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function mount(host, videoEl, options = {}) {
|
|
22
|
+
if (!host || !videoEl) return null;
|
|
23
|
+
const existing = host.querySelector?.('.mind-map-video-playback-control');
|
|
24
|
+
if (existing) return existing;
|
|
25
|
+
|
|
26
|
+
const control = document.createElement('button');
|
|
27
|
+
control.type = 'button';
|
|
28
|
+
control.className = 'mind-map-video-playback-control';
|
|
29
|
+
const icon = document.createElement('span');
|
|
30
|
+
icon.className = 'mind-map-video-playback-control__icon';
|
|
31
|
+
icon.setAttribute('aria-hidden', 'true');
|
|
32
|
+
const status = document.createElement('span');
|
|
33
|
+
status.className = 'mind-map-video-playback-control__status';
|
|
34
|
+
control.appendChild(icon);
|
|
35
|
+
control.appendChild(status);
|
|
36
|
+
|
|
37
|
+
const stopPointerOwnership = event => event.stopPropagation();
|
|
38
|
+
control.addEventListener('pointerdown', stopPointerOwnership);
|
|
39
|
+
control.addEventListener('mousedown', stopPointerOwnership);
|
|
40
|
+
control.addEventListener('dblclick', stopPointerOwnership);
|
|
41
|
+
control.addEventListener('click', event => {
|
|
42
|
+
event.preventDefault();
|
|
43
|
+
event.stopPropagation();
|
|
44
|
+
const shouldPlay = String(options.getIntent?.() || '').toLowerCase() !== 'play';
|
|
45
|
+
options.onToggle?.(shouldPlay);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
host.appendChild(control);
|
|
49
|
+
sync(videoEl, options.getIntent?.());
|
|
50
|
+
return control;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function bindState(videoEl, nodeModel, operations = {}) {
|
|
54
|
+
if (!videoEl || !nodeModel) return false;
|
|
55
|
+
const nodeId = operations.getNodeId?.(nodeModel) || '';
|
|
56
|
+
if (videoEl.dataset?.videoPlaybackStateBoundNodeId === nodeId) return false;
|
|
57
|
+
if (videoEl.dataset) videoEl.dataset.videoPlaybackStateBoundNodeId = nodeId;
|
|
58
|
+
|
|
59
|
+
const rememberTimeOnly = () => {
|
|
60
|
+
if (videoEl.dataset?.lodMediaSuspended === 'true' ||
|
|
61
|
+
videoEl.dataset?.videoPositionRestorePending === 'true') return;
|
|
62
|
+
const currentTime = Number(videoEl.currentTime || 0);
|
|
63
|
+
if (!Number.isFinite(currentTime) || currentTime < 0) return;
|
|
64
|
+
nodeModel._videoPlaybackCurrentTime = currentTime;
|
|
65
|
+
if (videoEl.dataset) videoEl.dataset.videoLastKnownTime = String(currentTime);
|
|
66
|
+
};
|
|
67
|
+
const markPlaying = () => {
|
|
68
|
+
operations.rememberRuntime?.(nodeModel, videoEl, { forceIntent: true });
|
|
69
|
+
operations.setIntent?.(nodeModel, videoEl, 'play');
|
|
70
|
+
};
|
|
71
|
+
const markPaused = () => {
|
|
72
|
+
rememberTimeOnly();
|
|
73
|
+
if (videoEl.dataset?.visibilityPaused === 'true' ||
|
|
74
|
+
videoEl.dataset?.videoResumePending === 'true' ||
|
|
75
|
+
videoEl.dataset?.lodMediaSuspended === 'true') {
|
|
76
|
+
sync(videoEl, operations.getIntent?.(nodeModel, videoEl));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
operations.setIntent?.(nodeModel, videoEl, 'pause');
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
videoEl.addEventListener('play', markPlaying, { passive: true });
|
|
83
|
+
videoEl.addEventListener('playing', markPlaying, { passive: true });
|
|
84
|
+
videoEl.addEventListener('pause', markPaused, { passive: true });
|
|
85
|
+
videoEl.addEventListener('timeupdate', rememberTimeOnly, { passive: true });
|
|
86
|
+
videoEl.addEventListener('seeking', rememberTimeOnly, { passive: true });
|
|
87
|
+
videoEl.addEventListener('loadedmetadata', () => {
|
|
88
|
+
operations.restorePosition?.(nodeModel, videoEl);
|
|
89
|
+
if (videoEl.dataset) videoEl.dataset.videoPositionRestorePending = 'false';
|
|
90
|
+
}, { passive: true });
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
window.MindMapVideoPlaybackControls = { bindState, mount, sync };
|
|
95
|
+
})();
|
package/wwwroot/_framework/{MindExecution.Core.808jj176e1.dll → MindExecution.Core.nxjlewduna.dll}
RENAMED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/wwwroot/_framework/{MindExecution.Web.mc24u4bzol.dll → MindExecution.Web.nxykcyxd02.dll}
RENAMED
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mainAssemblyName": "MindExecution.Web",
|
|
3
3
|
"resources": {
|
|
4
|
-
"hash": "sha256-
|
|
4
|
+
"hash": "sha256-WNzAmWuVhn9JyBiHwwIttruk/GbsVNnakpghIldcLg8=",
|
|
5
5
|
"fingerprinting": {
|
|
6
6
|
"Google.Protobuf.9h59ukbel7.dll": "Google.Protobuf.dll",
|
|
7
7
|
"Markdig.d1j7v41cl1.dll": "Markdig.dll",
|
|
@@ -122,16 +122,16 @@
|
|
|
122
122
|
"System.brmz7yk5qh.dll": "System.dll",
|
|
123
123
|
"netstandard.b50t77veor.dll": "netstandard.dll",
|
|
124
124
|
"System.Private.CoreLib.g6ztz7cmo2.dll": "System.Private.CoreLib.dll",
|
|
125
|
-
"MindExecution.Core.
|
|
126
|
-
"MindExecution.Kernel.
|
|
127
|
-
"MindExecution.Plugins.Admin.
|
|
128
|
-
"MindExecution.Plugins.Business.
|
|
129
|
-
"MindExecution.Plugins.Concept.
|
|
130
|
-
"MindExecution.Plugins.Directory.
|
|
131
|
-
"MindExecution.Plugins.PlanMaster.
|
|
132
|
-
"MindExecution.Plugins.YouTube.
|
|
133
|
-
"MindExecution.Shared.
|
|
134
|
-
"MindExecution.Web.
|
|
125
|
+
"MindExecution.Core.nxjlewduna.dll": "MindExecution.Core.dll",
|
|
126
|
+
"MindExecution.Kernel.vrfi63yg9f.dll": "MindExecution.Kernel.dll",
|
|
127
|
+
"MindExecution.Plugins.Admin.1rcwhdxl0r.dll": "MindExecution.Plugins.Admin.dll",
|
|
128
|
+
"MindExecution.Plugins.Business.rx0eieg51y.dll": "MindExecution.Plugins.Business.dll",
|
|
129
|
+
"MindExecution.Plugins.Concept.zzczjzhvk1.dll": "MindExecution.Plugins.Concept.dll",
|
|
130
|
+
"MindExecution.Plugins.Directory.bsorcntiwp.dll": "MindExecution.Plugins.Directory.dll",
|
|
131
|
+
"MindExecution.Plugins.PlanMaster.i5j9t4f1jf.dll": "MindExecution.Plugins.PlanMaster.dll",
|
|
132
|
+
"MindExecution.Plugins.YouTube.1mpn9satft.dll": "MindExecution.Plugins.YouTube.dll",
|
|
133
|
+
"MindExecution.Shared.mpi1gzau9b.dll": "MindExecution.Shared.dll",
|
|
134
|
+
"MindExecution.Web.nxykcyxd02.dll": "MindExecution.Web.dll",
|
|
135
135
|
"dotnet.native.566r55w3xu.js": "dotnet.native.js",
|
|
136
136
|
"dotnet.native.x6q5aixc38.wasm": "dotnet.native.wasm",
|
|
137
137
|
"dotnet.js": "dotnet.js",
|
|
@@ -276,18 +276,18 @@
|
|
|
276
276
|
"System.Xml.XDocument.sn51jas17n.dll": "sha256-GNI2kFgFmPTwzuzwUn8gxK+AzGLUWRJFdg9JzIbrybQ=",
|
|
277
277
|
"System.brmz7yk5qh.dll": "sha256-CfM2miyj1KHApFmqMdLYWio3S/jrdON2pW9Xr2nTwlo=",
|
|
278
278
|
"netstandard.b50t77veor.dll": "sha256-//jQGOXjb8ET8WtXgOJrAxLx6E7zDJ5RjRRutwkvmxo=",
|
|
279
|
-
"MindExecution.Core.
|
|
280
|
-
"MindExecution.Kernel.
|
|
281
|
-
"MindExecution.Plugins.Business.
|
|
282
|
-
"MindExecution.Plugins.Concept.
|
|
283
|
-
"MindExecution.Plugins.PlanMaster.
|
|
284
|
-
"MindExecution.Shared.
|
|
285
|
-
"MindExecution.Web.
|
|
279
|
+
"MindExecution.Core.nxjlewduna.dll": "sha256-K/aYKYR7u21eWdPhsuyT3DfAcldItQ9fUJDpyAW1Yk8=",
|
|
280
|
+
"MindExecution.Kernel.vrfi63yg9f.dll": "sha256-pQ3AG4I0yHOE+LjWf41pPTzD6WAPx5QEVQR99tgmjv8=",
|
|
281
|
+
"MindExecution.Plugins.Business.rx0eieg51y.dll": "sha256-wXky9gfkYuS9LpiAJcaHL2ySg388QTlafZ7dDYaYGkc=",
|
|
282
|
+
"MindExecution.Plugins.Concept.zzczjzhvk1.dll": "sha256-caSJdsMUA/y2XoLlC69Ml7LVPyEklu9iUqK8LbLH/Ac=",
|
|
283
|
+
"MindExecution.Plugins.PlanMaster.i5j9t4f1jf.dll": "sha256-NsaH6mfDGUtq96FRS/yR+b5QyLzjVWublyCQBKugpss=",
|
|
284
|
+
"MindExecution.Shared.mpi1gzau9b.dll": "sha256-Bk/J98QCHrurXfAfiETiavqv5g5jXQ73yvEdYibuIrU=",
|
|
285
|
+
"MindExecution.Web.nxykcyxd02.dll": "sha256-JW4hqFR8NT2yFKIvMflIhM8Wks9Dec4w+0ofv69tU6w="
|
|
286
286
|
},
|
|
287
287
|
"lazyAssembly": {
|
|
288
|
-
"MindExecution.Plugins.Admin.
|
|
289
|
-
"MindExecution.Plugins.Directory.
|
|
290
|
-
"MindExecution.Plugins.YouTube.
|
|
288
|
+
"MindExecution.Plugins.Admin.1rcwhdxl0r.dll": "sha256-jV0N8WevIxIidWNinjH1vZ+NS+eKshBtlZpvb6vCfmg=",
|
|
289
|
+
"MindExecution.Plugins.Directory.bsorcntiwp.dll": "sha256-O07lrIPzxWQRivTDifZBsSoG+ZMptwdu2Ey2e9sF0M0=",
|
|
290
|
+
"MindExecution.Plugins.YouTube.1mpn9satft.dll": "sha256-l6UnB6LB9UHscjF/q5j8F2fKCunQ63w6mkwEEuWK3tg="
|
|
291
291
|
}
|
|
292
292
|
},
|
|
293
293
|
"cacheBootResources": true,
|