@mindexec/cli 0.2.59 → 0.2.61
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 +2 -2
- package/remote-hub.js +52 -0
- package/scripts/remote-http-smoke.mjs +13 -0
- package/scripts/remote-hub-smoke.mjs +19 -1
- package/server.js +4 -0
- package/wwwroot/_content/MindExecution.Shared/css/app.css +1 -1
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +556 -17
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-menu-manager.js +64 -18
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-nodes.js +2 -2
- package/wwwroot/_framework/MindExecution.Core.csfu1xtj3l.dll +0 -0
- package/wwwroot/_framework/{MindExecution.Kernel.cqcbagjpqb.dll → MindExecution.Kernel.mdo1lzjvvp.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Admin.tsn0j478un.dll → MindExecution.Plugins.Admin.5fctwf65dx.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Business.xg74dmn0vz.dll → MindExecution.Plugins.Business.nwivpk9djf.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.xyf0dtv4lr.dll → MindExecution.Plugins.Concept.aa243ne54e.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Directory.9i4bd043ia.dll → MindExecution.Plugins.Directory.jnzcrwl049.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.6awpgrbi0w.dll → MindExecution.Plugins.PlanMaster.udoktewe31.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.phonjrgb40.dll → MindExecution.Plugins.YouTube.z4bhlt9iy7.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.wv4gm07egs.dll → MindExecution.Shared.32hytvk3ws.dll} +0 -0
- package/wwwroot/_framework/MindExecution.Web.730hm0dubp.dll +0 -0
- package/wwwroot/_framework/blazor.boot.json +21 -21
- package/wwwroot/index.html +3 -3
- package/wwwroot/service-worker-assets.js +27 -27
- package/wwwroot/service-worker.js +1 -1
- package/wwwroot/_framework/MindExecution.Core.fu1rl67yt3.dll +0 -0
- package/wwwroot/_framework/MindExecution.Web.2qteyfmk41.dll +0 -0
|
@@ -9838,6 +9838,7 @@
|
|
|
9838
9838
|
const edges = collectBusinessAutomationEdges(module);
|
|
9839
9839
|
const relationContext = syncBusinessAutomationSelectionContext(module, {
|
|
9840
9840
|
edges,
|
|
9841
|
+
force: true,
|
|
9841
9842
|
scheduleRender: false
|
|
9842
9843
|
});
|
|
9843
9844
|
if (_businessAutomationSelectedEdgeId
|
|
@@ -9939,12 +9940,12 @@
|
|
|
9939
9940
|
d: pathData,
|
|
9940
9941
|
class: `mind-map-business-automation-edge-path${isSelected ? ' is-selected' : ''}${isRelationHighlighted ? ' is-relation-highlight' : ''}`,
|
|
9941
9942
|
stroke: theme.edge,
|
|
9942
|
-
'stroke-width': isSelected ? '3.6' : (isRelationHighlighted ? (isContextEdge ? '2.
|
|
9943
|
-
opacity: isSelected ? '0.96' : (isRelationHighlighted ? '0.
|
|
9943
|
+
'stroke-width': isSelected ? '3.6' : (isRelationHighlighted ? (isContextEdge ? '2.45' : '2.65') : (isContextEdge ? '2.1' : '2.4')),
|
|
9944
|
+
opacity: isSelected ? '0.96' : (isRelationHighlighted ? (isContextEdge ? '0.72' : '0.78') : (isContextEdge ? '0.68' : '0.82')),
|
|
9944
9945
|
'stroke-dasharray': isContextEdge ? '7 7' : '',
|
|
9945
9946
|
filter: isSelected
|
|
9946
9947
|
? `drop-shadow(0 0 7px ${theme.edge})`
|
|
9947
|
-
: (isRelationHighlighted ? `drop-shadow(0 0
|
|
9948
|
+
: (isRelationHighlighted ? `drop-shadow(0 0 3px ${theme.edge})` : '')
|
|
9948
9949
|
});
|
|
9949
9950
|
path.style.pointerEvents = 'none';
|
|
9950
9951
|
path.dataset.edgeId = edge.id;
|
|
@@ -9953,21 +9954,21 @@
|
|
|
9953
9954
|
const sourceDot = createBusinessAutomationSvgElement('circle', {
|
|
9954
9955
|
cx: source.x.toFixed(1),
|
|
9955
9956
|
cy: source.y.toFixed(1),
|
|
9956
|
-
r:
|
|
9957
|
+
r: isSelected ? '4.2' : (isRelationHighlighted ? '3.7' : '3.2'),
|
|
9957
9958
|
fill: '#ffffff',
|
|
9958
9959
|
stroke: theme.edge,
|
|
9959
9960
|
'stroke-width': '1.8',
|
|
9960
|
-
opacity:
|
|
9961
|
+
opacity: isSelected ? '0.96' : (isRelationHighlighted ? '0.84' : (isContextEdge ? '0.82' : '0.96'))
|
|
9961
9962
|
});
|
|
9962
9963
|
sourceDot.style.pointerEvents = 'none';
|
|
9963
9964
|
const targetDot = createBusinessAutomationSvgElement('circle', {
|
|
9964
9965
|
cx: target.x.toFixed(1),
|
|
9965
9966
|
cy: target.y.toFixed(1),
|
|
9966
|
-
r:
|
|
9967
|
+
r: isSelected ? '4.2' : (isRelationHighlighted ? '3.7' : '3.2'),
|
|
9967
9968
|
fill: theme.edge,
|
|
9968
9969
|
stroke: '#ffffff',
|
|
9969
9970
|
'stroke-width': '1.4',
|
|
9970
|
-
opacity:
|
|
9971
|
+
opacity: isSelected ? '0.96' : (isRelationHighlighted ? '0.84' : (isContextEdge ? '0.82' : '0.96'))
|
|
9971
9972
|
});
|
|
9972
9973
|
targetDot.style.pointerEvents = 'none';
|
|
9973
9974
|
|
|
@@ -12863,6 +12864,7 @@
|
|
|
12863
12864
|
const REMOTE_FLEET_HOST_LEASE_REFRESH_MS = 10000;
|
|
12864
12865
|
const remoteFleetHostLeaseTimers = new Map();
|
|
12865
12866
|
const remoteFleetLocalHostTargets = new Map();
|
|
12867
|
+
let activeRemoteFleetControlPopup = null;
|
|
12866
12868
|
|
|
12867
12869
|
function findRemoteFleetBodyByNodeId(nodeId) {
|
|
12868
12870
|
const id = String(nodeId || '').trim();
|
|
@@ -13233,7 +13235,7 @@
|
|
|
13233
13235
|
if (canvas.height !== nextHeight) {
|
|
13234
13236
|
canvas.height = nextHeight;
|
|
13235
13237
|
}
|
|
13236
|
-
return { width: nextWidth, height: nextHeight };
|
|
13238
|
+
return { width: nextWidth, height: nextHeight, cssWidth, cssHeight, dpr };
|
|
13237
13239
|
}
|
|
13238
13240
|
|
|
13239
13241
|
function getRemoteFleetBitmapSize(bitmap) {
|
|
@@ -13245,7 +13247,7 @@
|
|
|
13245
13247
|
};
|
|
13246
13248
|
}
|
|
13247
13249
|
|
|
13248
|
-
function drawRemoteFleetFrameToCanvas(canvas, bitmap) {
|
|
13250
|
+
function drawRemoteFleetFrameToCanvas(canvas, bitmap, fitMode = 'cover') {
|
|
13249
13251
|
if (!canvas || !bitmap) {
|
|
13250
13252
|
return false;
|
|
13251
13253
|
}
|
|
@@ -13272,18 +13274,40 @@
|
|
|
13272
13274
|
let sy = 0;
|
|
13273
13275
|
let sw = source.width;
|
|
13274
13276
|
let sh = source.height;
|
|
13275
|
-
|
|
13276
|
-
|
|
13277
|
-
|
|
13278
|
-
|
|
13279
|
-
|
|
13280
|
-
|
|
13277
|
+
let dx = 0;
|
|
13278
|
+
let dy = 0;
|
|
13279
|
+
let dw = size.width;
|
|
13280
|
+
let dh = size.height;
|
|
13281
|
+
if (fitMode === 'contain') {
|
|
13282
|
+
if (sourceAspect > targetAspect) {
|
|
13283
|
+
dh = size.width / sourceAspect;
|
|
13284
|
+
dy = (size.height - dh) / 2;
|
|
13285
|
+
} else if (sourceAspect < targetAspect) {
|
|
13286
|
+
dw = size.height * sourceAspect;
|
|
13287
|
+
dx = (size.width - dw) / 2;
|
|
13288
|
+
}
|
|
13289
|
+
} else {
|
|
13290
|
+
if (sourceAspect > targetAspect) {
|
|
13291
|
+
sw = source.height * targetAspect;
|
|
13292
|
+
sx = (source.width - sw) / 2;
|
|
13293
|
+
} else if (sourceAspect < targetAspect) {
|
|
13294
|
+
sh = source.width / targetAspect;
|
|
13295
|
+
sy = (source.height - sh) / 2;
|
|
13296
|
+
}
|
|
13281
13297
|
}
|
|
13282
13298
|
|
|
13283
13299
|
context.imageSmoothingEnabled = true;
|
|
13284
13300
|
context.imageSmoothingQuality = 'medium';
|
|
13301
|
+
context.fillStyle = '#020617';
|
|
13285
13302
|
context.clearRect(0, 0, size.width, size.height);
|
|
13286
|
-
context.
|
|
13303
|
+
context.fillRect(0, 0, size.width, size.height);
|
|
13304
|
+
context.drawImage(bitmap, sx, sy, sw, sh, dx, dy, dw, dh);
|
|
13305
|
+
canvas._remoteFleetContentRect = {
|
|
13306
|
+
left: dx / size.dpr,
|
|
13307
|
+
top: dy / size.dpr,
|
|
13308
|
+
width: dw / size.dpr,
|
|
13309
|
+
height: dh / size.dpr
|
|
13310
|
+
};
|
|
13287
13311
|
return true;
|
|
13288
13312
|
}
|
|
13289
13313
|
|
|
@@ -13696,6 +13720,503 @@
|
|
|
13696
13720
|
bodyView._remoteFleetFrameLoopRaf = requestRemoteFleetFrameLoopFrame(loop);
|
|
13697
13721
|
}
|
|
13698
13722
|
|
|
13723
|
+
function getRemoteFleetControlPoint(event, canvas, allowClamp = false) {
|
|
13724
|
+
if (!event || !canvas) {
|
|
13725
|
+
return null;
|
|
13726
|
+
}
|
|
13727
|
+
|
|
13728
|
+
const canvasRect = canvas.getBoundingClientRect?.();
|
|
13729
|
+
if (!canvasRect || canvasRect.width <= 0 || canvasRect.height <= 0) {
|
|
13730
|
+
return null;
|
|
13731
|
+
}
|
|
13732
|
+
|
|
13733
|
+
const content = canvas._remoteFleetContentRect || {
|
|
13734
|
+
left: 0,
|
|
13735
|
+
top: 0,
|
|
13736
|
+
width: canvasRect.width,
|
|
13737
|
+
height: canvasRect.height
|
|
13738
|
+
};
|
|
13739
|
+
if (!content.width || !content.height) {
|
|
13740
|
+
return null;
|
|
13741
|
+
}
|
|
13742
|
+
|
|
13743
|
+
let x = event.clientX - canvasRect.left - content.left;
|
|
13744
|
+
let y = event.clientY - canvasRect.top - content.top;
|
|
13745
|
+
const outside = x < 0 || y < 0 || x > content.width || y > content.height;
|
|
13746
|
+
if (outside && !allowClamp) {
|
|
13747
|
+
return null;
|
|
13748
|
+
}
|
|
13749
|
+
|
|
13750
|
+
x = Math.max(0, Math.min(content.width, x));
|
|
13751
|
+
y = Math.max(0, Math.min(content.height, y));
|
|
13752
|
+
return {
|
|
13753
|
+
normalizedX: x / content.width,
|
|
13754
|
+
normalizedY: y / content.height
|
|
13755
|
+
};
|
|
13756
|
+
}
|
|
13757
|
+
|
|
13758
|
+
function getRemoteFleetPointerButton(event) {
|
|
13759
|
+
switch (Number(event?.button ?? 0)) {
|
|
13760
|
+
case 1:
|
|
13761
|
+
return 'middle';
|
|
13762
|
+
case 2:
|
|
13763
|
+
return 'right';
|
|
13764
|
+
default:
|
|
13765
|
+
return 'left';
|
|
13766
|
+
}
|
|
13767
|
+
}
|
|
13768
|
+
|
|
13769
|
+
function closeRemoteFleetControlPopup(reason = 'close') {
|
|
13770
|
+
const session = activeRemoteFleetControlPopup;
|
|
13771
|
+
if (!session) {
|
|
13772
|
+
return;
|
|
13773
|
+
}
|
|
13774
|
+
|
|
13775
|
+
activeRemoteFleetControlPopup = null;
|
|
13776
|
+
session.active = false;
|
|
13777
|
+
if (session.timer) {
|
|
13778
|
+
clearTimeout(session.timer);
|
|
13779
|
+
session.timer = null;
|
|
13780
|
+
}
|
|
13781
|
+
if (session.moveTimer) {
|
|
13782
|
+
clearTimeout(session.moveTimer);
|
|
13783
|
+
session.moveTimer = null;
|
|
13784
|
+
}
|
|
13785
|
+
session.overlay?.remove?.();
|
|
13786
|
+
window.RuntimeTrace?.emit?.('remote.control.closed', {
|
|
13787
|
+
nodeId: session.nodeId,
|
|
13788
|
+
deviceId: session.deviceId,
|
|
13789
|
+
reason
|
|
13790
|
+
});
|
|
13791
|
+
|
|
13792
|
+
if (session.startedStream && !session.wasLiveActive) {
|
|
13793
|
+
invokeDotNetAsync('StopRemoteFleetLiveStreamFromJs', session.nodeId, session.deviceId, session.streamId || '')
|
|
13794
|
+
.catch(() => undefined);
|
|
13795
|
+
}
|
|
13796
|
+
}
|
|
13797
|
+
|
|
13798
|
+
async function paintRemoteFleetControlFrame(session, frame) {
|
|
13799
|
+
if (!session?.active || !frame || !isRemoteFleetFrameSource(frame.frameUrl)) {
|
|
13800
|
+
return false;
|
|
13801
|
+
}
|
|
13802
|
+
|
|
13803
|
+
try {
|
|
13804
|
+
const bitmap = await loadRemoteFleetFrameBitmap(frame);
|
|
13805
|
+
if (!bitmap || !session.active) {
|
|
13806
|
+
return false;
|
|
13807
|
+
}
|
|
13808
|
+
|
|
13809
|
+
requestRemoteFleetFrameLoopFrame(() => {
|
|
13810
|
+
if (!session.active || !document.body.contains(session.overlay)) {
|
|
13811
|
+
if (typeof bitmap.close === 'function') {
|
|
13812
|
+
bitmap.close();
|
|
13813
|
+
}
|
|
13814
|
+
return;
|
|
13815
|
+
}
|
|
13816
|
+
|
|
13817
|
+
drawRemoteFleetFrameToCanvas(session.canvas, bitmap, 'contain');
|
|
13818
|
+
session.canvas.style.display = 'block';
|
|
13819
|
+
if (typeof bitmap.close === 'function') {
|
|
13820
|
+
bitmap.close();
|
|
13821
|
+
}
|
|
13822
|
+
});
|
|
13823
|
+
return true;
|
|
13824
|
+
} catch {
|
|
13825
|
+
return false;
|
|
13826
|
+
}
|
|
13827
|
+
}
|
|
13828
|
+
|
|
13829
|
+
function sendRemoteFleetControlInput(session, payload, throttleMove = false) {
|
|
13830
|
+
if (!session?.active || !payload?.type) {
|
|
13831
|
+
return;
|
|
13832
|
+
}
|
|
13833
|
+
|
|
13834
|
+
const send = next => {
|
|
13835
|
+
if (!session.active) {
|
|
13836
|
+
return;
|
|
13837
|
+
}
|
|
13838
|
+
invokeDotNetAsync('SendRemoteFleetInputFromJs', session.nodeId, session.deviceId, {
|
|
13839
|
+
...next,
|
|
13840
|
+
controlLeaseId: session.controlLeaseId,
|
|
13841
|
+
issuedAt: new Date().toISOString()
|
|
13842
|
+
}).catch(error => {
|
|
13843
|
+
session.status.textContent = error?.message || 'Input failed';
|
|
13844
|
+
});
|
|
13845
|
+
};
|
|
13846
|
+
|
|
13847
|
+
if (!throttleMove) {
|
|
13848
|
+
send(payload);
|
|
13849
|
+
return;
|
|
13850
|
+
}
|
|
13851
|
+
|
|
13852
|
+
const now = performance.now();
|
|
13853
|
+
const elapsed = now - (session.lastMoveSentAt || 0);
|
|
13854
|
+
if (elapsed >= 32) {
|
|
13855
|
+
session.lastMoveSentAt = now;
|
|
13856
|
+
send(payload);
|
|
13857
|
+
return;
|
|
13858
|
+
}
|
|
13859
|
+
|
|
13860
|
+
session.pendingMove = payload;
|
|
13861
|
+
if (session.moveTimer) {
|
|
13862
|
+
return;
|
|
13863
|
+
}
|
|
13864
|
+
|
|
13865
|
+
session.moveTimer = setTimeout(() => {
|
|
13866
|
+
session.moveTimer = null;
|
|
13867
|
+
const next = session.pendingMove;
|
|
13868
|
+
session.pendingMove = null;
|
|
13869
|
+
if (next) {
|
|
13870
|
+
session.lastMoveSentAt = performance.now();
|
|
13871
|
+
send(next);
|
|
13872
|
+
}
|
|
13873
|
+
}, Math.max(1, 32 - elapsed));
|
|
13874
|
+
}
|
|
13875
|
+
|
|
13876
|
+
function bindRemoteFleetControlInput(session) {
|
|
13877
|
+
const { overlay, shell, stage, canvas } = session;
|
|
13878
|
+
let pointerActive = false;
|
|
13879
|
+
|
|
13880
|
+
['mousedown', 'mouseup', 'click', 'dblclick', 'keydown', 'keyup', 'wheel', 'contextmenu'].forEach(eventName => {
|
|
13881
|
+
overlay.addEventListener(eventName, event => event.stopPropagation(), true);
|
|
13882
|
+
});
|
|
13883
|
+
|
|
13884
|
+
stage.addEventListener('pointerdown', event => {
|
|
13885
|
+
const point = getRemoteFleetControlPoint(event, canvas, false);
|
|
13886
|
+
if (!point) {
|
|
13887
|
+
return;
|
|
13888
|
+
}
|
|
13889
|
+
|
|
13890
|
+
event.preventDefault();
|
|
13891
|
+
event.stopPropagation();
|
|
13892
|
+
pointerActive = true;
|
|
13893
|
+
shell.focus({ preventScroll: true });
|
|
13894
|
+
stage.setPointerCapture?.(event.pointerId);
|
|
13895
|
+
sendRemoteFleetControlInput(session, {
|
|
13896
|
+
type: 'pointerDown',
|
|
13897
|
+
...point,
|
|
13898
|
+
button: getRemoteFleetPointerButton(event)
|
|
13899
|
+
});
|
|
13900
|
+
});
|
|
13901
|
+
|
|
13902
|
+
stage.addEventListener('pointermove', event => {
|
|
13903
|
+
const point = getRemoteFleetControlPoint(event, canvas, pointerActive);
|
|
13904
|
+
if (!point) {
|
|
13905
|
+
return;
|
|
13906
|
+
}
|
|
13907
|
+
|
|
13908
|
+
event.preventDefault();
|
|
13909
|
+
event.stopPropagation();
|
|
13910
|
+
sendRemoteFleetControlInput(session, {
|
|
13911
|
+
type: 'pointerMove',
|
|
13912
|
+
...point,
|
|
13913
|
+
button: getRemoteFleetPointerButton(event)
|
|
13914
|
+
}, true);
|
|
13915
|
+
});
|
|
13916
|
+
|
|
13917
|
+
stage.addEventListener('pointerup', event => {
|
|
13918
|
+
const point = getRemoteFleetControlPoint(event, canvas, true);
|
|
13919
|
+
event.preventDefault();
|
|
13920
|
+
event.stopPropagation();
|
|
13921
|
+
pointerActive = false;
|
|
13922
|
+
stage.releasePointerCapture?.(event.pointerId);
|
|
13923
|
+
if (!point) {
|
|
13924
|
+
return;
|
|
13925
|
+
}
|
|
13926
|
+
|
|
13927
|
+
sendRemoteFleetControlInput(session, {
|
|
13928
|
+
type: 'pointerUp',
|
|
13929
|
+
...point,
|
|
13930
|
+
button: getRemoteFleetPointerButton(event)
|
|
13931
|
+
});
|
|
13932
|
+
});
|
|
13933
|
+
|
|
13934
|
+
stage.addEventListener('pointercancel', event => {
|
|
13935
|
+
pointerActive = false;
|
|
13936
|
+
stage.releasePointerCapture?.(event.pointerId);
|
|
13937
|
+
});
|
|
13938
|
+
|
|
13939
|
+
stage.addEventListener('wheel', event => {
|
|
13940
|
+
const point = getRemoteFleetControlPoint(event, canvas, false);
|
|
13941
|
+
if (!point) {
|
|
13942
|
+
return;
|
|
13943
|
+
}
|
|
13944
|
+
|
|
13945
|
+
event.preventDefault();
|
|
13946
|
+
event.stopPropagation();
|
|
13947
|
+
sendRemoteFleetControlInput(session, {
|
|
13948
|
+
type: 'wheel',
|
|
13949
|
+
...point,
|
|
13950
|
+
deltaX: event.deltaX,
|
|
13951
|
+
deltaY: event.deltaY
|
|
13952
|
+
});
|
|
13953
|
+
}, { passive: false });
|
|
13954
|
+
|
|
13955
|
+
stage.addEventListener('contextmenu', event => {
|
|
13956
|
+
event.preventDefault();
|
|
13957
|
+
event.stopPropagation();
|
|
13958
|
+
});
|
|
13959
|
+
|
|
13960
|
+
shell.addEventListener('keydown', event => {
|
|
13961
|
+
if (event.target?.closest?.('[data-remote-fleet-control-close="true"]')) {
|
|
13962
|
+
return;
|
|
13963
|
+
}
|
|
13964
|
+
|
|
13965
|
+
event.preventDefault();
|
|
13966
|
+
event.stopPropagation();
|
|
13967
|
+
sendRemoteFleetControlInput(session, {
|
|
13968
|
+
type: 'keyDown',
|
|
13969
|
+
key: event.key,
|
|
13970
|
+
code: event.code,
|
|
13971
|
+
repeat: event.repeat === true
|
|
13972
|
+
});
|
|
13973
|
+
});
|
|
13974
|
+
|
|
13975
|
+
shell.addEventListener('keyup', event => {
|
|
13976
|
+
if (event.target?.closest?.('[data-remote-fleet-control-close="true"]')) {
|
|
13977
|
+
return;
|
|
13978
|
+
}
|
|
13979
|
+
|
|
13980
|
+
event.preventDefault();
|
|
13981
|
+
event.stopPropagation();
|
|
13982
|
+
sendRemoteFleetControlInput(session, {
|
|
13983
|
+
type: 'keyUp',
|
|
13984
|
+
key: event.key,
|
|
13985
|
+
code: event.code,
|
|
13986
|
+
repeat: event.repeat === true
|
|
13987
|
+
});
|
|
13988
|
+
});
|
|
13989
|
+
}
|
|
13990
|
+
|
|
13991
|
+
function openRemoteFleetControlPopup(bodyView, nodeModel, deviceId) {
|
|
13992
|
+
const nodeId = String(nodeModel?.id ?? nodeModel?.Id ?? '').trim();
|
|
13993
|
+
const targetId = String(deviceId || '').trim();
|
|
13994
|
+
if (!bodyView || !nodeId || !targetId) {
|
|
13995
|
+
return;
|
|
13996
|
+
}
|
|
13997
|
+
|
|
13998
|
+
closeRemoteFleetControlPopup('replace');
|
|
13999
|
+
const devices = parseRemoteFleetDevices(nodeModel);
|
|
14000
|
+
const device = devices.find(item => getRemoteFleetDeviceId(item) === targetId) || null;
|
|
14001
|
+
const name = device ? getRemoteFleetDeviceName(device) : targetId;
|
|
14002
|
+
const wasLiveActive = device ? isRemoteFleetLiveActive(device) : false;
|
|
14003
|
+
|
|
14004
|
+
const overlay = document.createElement('div');
|
|
14005
|
+
overlay.dataset.remoteFleetControlPopup = 'true';
|
|
14006
|
+
overlay.style.cssText = `
|
|
14007
|
+
position: fixed;
|
|
14008
|
+
inset: 0;
|
|
14009
|
+
z-index: 2147483000;
|
|
14010
|
+
display: grid;
|
|
14011
|
+
place-items: center;
|
|
14012
|
+
padding: 24px;
|
|
14013
|
+
background: rgba(15, 23, 42, 0.24);
|
|
14014
|
+
pointer-events: auto;
|
|
14015
|
+
box-sizing: border-box;
|
|
14016
|
+
`;
|
|
14017
|
+
|
|
14018
|
+
const shell = document.createElement('section');
|
|
14019
|
+
shell.tabIndex = 0;
|
|
14020
|
+
shell.dataset.remoteFleetControlShell = 'true';
|
|
14021
|
+
shell.style.cssText = `
|
|
14022
|
+
width: min(96vw, 1280px);
|
|
14023
|
+
height: min(90vh, 860px);
|
|
14024
|
+
min-width: min(720px, calc(100vw - 28px));
|
|
14025
|
+
min-height: min(420px, calc(100vh - 28px));
|
|
14026
|
+
display: flex;
|
|
14027
|
+
flex-direction: column;
|
|
14028
|
+
overflow: hidden;
|
|
14029
|
+
border-radius: 8px;
|
|
14030
|
+
border: 1px solid rgba(148, 163, 184, 0.34);
|
|
14031
|
+
background: #020617;
|
|
14032
|
+
box-shadow: 0 24px 70px rgba(15, 23, 42, 0.35);
|
|
14033
|
+
outline: none;
|
|
14034
|
+
box-sizing: border-box;
|
|
14035
|
+
`;
|
|
14036
|
+
|
|
14037
|
+
const header = document.createElement('header');
|
|
14038
|
+
header.style.cssText = `
|
|
14039
|
+
flex: 0 0 auto;
|
|
14040
|
+
height: 42px;
|
|
14041
|
+
display: flex;
|
|
14042
|
+
align-items: center;
|
|
14043
|
+
justify-content: space-between;
|
|
14044
|
+
gap: 12px;
|
|
14045
|
+
padding: 0 10px 0 14px;
|
|
14046
|
+
background: rgba(15, 23, 42, 0.96);
|
|
14047
|
+
border-bottom: 1px solid rgba(148, 163, 184, 0.20);
|
|
14048
|
+
box-sizing: border-box;
|
|
14049
|
+
`;
|
|
14050
|
+
|
|
14051
|
+
const title = document.createElement('strong');
|
|
14052
|
+
title.textContent = name;
|
|
14053
|
+
title.title = `${name} (${targetId})`;
|
|
14054
|
+
title.style.cssText = `
|
|
14055
|
+
min-width: 0;
|
|
14056
|
+
color: #f8fafc;
|
|
14057
|
+
font-size: 13px;
|
|
14058
|
+
font-weight: 950;
|
|
14059
|
+
line-height: 1;
|
|
14060
|
+
letter-spacing: 0;
|
|
14061
|
+
overflow: hidden;
|
|
14062
|
+
text-overflow: ellipsis;
|
|
14063
|
+
white-space: nowrap;
|
|
14064
|
+
`;
|
|
14065
|
+
|
|
14066
|
+
const right = document.createElement('div');
|
|
14067
|
+
right.style.cssText = 'flex:0 0 auto;display:flex;align-items:center;gap:8px;min-width:0;';
|
|
14068
|
+
const status = document.createElement('span');
|
|
14069
|
+
status.dataset.remoteFleetControlStatus = 'true';
|
|
14070
|
+
status.textContent = 'Connecting';
|
|
14071
|
+
status.style.cssText = `
|
|
14072
|
+
color: #cbd5e1;
|
|
14073
|
+
font-size: 11px;
|
|
14074
|
+
font-weight: 850;
|
|
14075
|
+
letter-spacing: 0;
|
|
14076
|
+
white-space: nowrap;
|
|
14077
|
+
`;
|
|
14078
|
+
const closeButton = document.createElement('button');
|
|
14079
|
+
closeButton.type = 'button';
|
|
14080
|
+
closeButton.dataset.remoteFleetControlClose = 'true';
|
|
14081
|
+
closeButton.textContent = 'X';
|
|
14082
|
+
closeButton.title = 'Close';
|
|
14083
|
+
closeButton.style.cssText = `
|
|
14084
|
+
width: 30px;
|
|
14085
|
+
height: 30px;
|
|
14086
|
+
display: inline-flex;
|
|
14087
|
+
align-items: center;
|
|
14088
|
+
justify-content: center;
|
|
14089
|
+
border-radius: 7px;
|
|
14090
|
+
border: 1px solid rgba(148, 163, 184, 0.34);
|
|
14091
|
+
background: rgba(30, 41, 59, 0.96);
|
|
14092
|
+
color: #f8fafc;
|
|
14093
|
+
font-size: 13px;
|
|
14094
|
+
font-weight: 950;
|
|
14095
|
+
line-height: 1;
|
|
14096
|
+
cursor: pointer;
|
|
14097
|
+
pointer-events: auto;
|
|
14098
|
+
`;
|
|
14099
|
+
|
|
14100
|
+
const stage = document.createElement('div');
|
|
14101
|
+
stage.dataset.remoteFleetControlStage = 'true';
|
|
14102
|
+
stage.style.cssText = `
|
|
14103
|
+
position: relative;
|
|
14104
|
+
flex: 1 1 auto;
|
|
14105
|
+
min-height: 0;
|
|
14106
|
+
overflow: hidden;
|
|
14107
|
+
background: #020617;
|
|
14108
|
+
cursor: crosshair;
|
|
14109
|
+
touch-action: none;
|
|
14110
|
+
`;
|
|
14111
|
+
|
|
14112
|
+
const canvas = document.createElement('canvas');
|
|
14113
|
+
canvas.dataset.remoteFleetControlCanvas = 'true';
|
|
14114
|
+
canvas.style.cssText = `
|
|
14115
|
+
position: absolute;
|
|
14116
|
+
inset: 0;
|
|
14117
|
+
width: 100%;
|
|
14118
|
+
height: 100%;
|
|
14119
|
+
display: block;
|
|
14120
|
+
background: #020617;
|
|
14121
|
+
`;
|
|
14122
|
+
|
|
14123
|
+
right.appendChild(status);
|
|
14124
|
+
right.appendChild(closeButton);
|
|
14125
|
+
header.appendChild(title);
|
|
14126
|
+
header.appendChild(right);
|
|
14127
|
+
stage.appendChild(canvas);
|
|
14128
|
+
shell.appendChild(header);
|
|
14129
|
+
shell.appendChild(stage);
|
|
14130
|
+
overlay.appendChild(shell);
|
|
14131
|
+
document.body.appendChild(overlay);
|
|
14132
|
+
|
|
14133
|
+
const session = {
|
|
14134
|
+
active: true,
|
|
14135
|
+
nodeId,
|
|
14136
|
+
deviceId: targetId,
|
|
14137
|
+
overlay,
|
|
14138
|
+
shell,
|
|
14139
|
+
stage,
|
|
14140
|
+
canvas,
|
|
14141
|
+
status,
|
|
14142
|
+
wasLiveActive,
|
|
14143
|
+
startedStream: false,
|
|
14144
|
+
streamId: '',
|
|
14145
|
+
controlLeaseId: `control-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
14146
|
+
timer: null,
|
|
14147
|
+
moveTimer: null,
|
|
14148
|
+
pendingMove: null,
|
|
14149
|
+
lastMoveSentAt: 0
|
|
14150
|
+
};
|
|
14151
|
+
activeRemoteFleetControlPopup = session;
|
|
14152
|
+
bindRemoteFleetControlInput(session);
|
|
14153
|
+
|
|
14154
|
+
const refresh = async () => {
|
|
14155
|
+
if (!session.active) {
|
|
14156
|
+
return;
|
|
14157
|
+
}
|
|
14158
|
+
|
|
14159
|
+
try {
|
|
14160
|
+
const result = await invokeDotNetAsync('GetRemoteFleetFrameFromJs', nodeId, targetId, 'live');
|
|
14161
|
+
const frame = normalizeRemoteFleetFramePayload(result?.frame || result?.Frame, 'live');
|
|
14162
|
+
if (frame) {
|
|
14163
|
+
frame.deviceId = frame.deviceId || targetId;
|
|
14164
|
+
await paintRemoteFleetControlFrame(session, frame);
|
|
14165
|
+
applyRemoteFleetFramePatches(bodyView, [frame]);
|
|
14166
|
+
status.textContent = 'Control';
|
|
14167
|
+
} else if (result?.error || result?.Error) {
|
|
14168
|
+
status.textContent = result.error || result.Error;
|
|
14169
|
+
}
|
|
14170
|
+
} catch (error) {
|
|
14171
|
+
status.textContent = error?.message || 'Frame failed';
|
|
14172
|
+
} finally {
|
|
14173
|
+
if (session.active) {
|
|
14174
|
+
session.timer = setTimeout(refresh, REMOTE_FLEET_LIVE_FRAME_REFRESH_MS);
|
|
14175
|
+
}
|
|
14176
|
+
}
|
|
14177
|
+
};
|
|
14178
|
+
|
|
14179
|
+
closeButton.addEventListener('click', event => {
|
|
14180
|
+
event.preventDefault();
|
|
14181
|
+
event.stopPropagation();
|
|
14182
|
+
closeRemoteFleetControlPopup('button');
|
|
14183
|
+
});
|
|
14184
|
+
overlay.addEventListener('pointerdown', event => {
|
|
14185
|
+
if (event.target === overlay) {
|
|
14186
|
+
event.preventDefault();
|
|
14187
|
+
event.stopPropagation();
|
|
14188
|
+
shell.focus({ preventScroll: true });
|
|
14189
|
+
}
|
|
14190
|
+
});
|
|
14191
|
+
|
|
14192
|
+
shell.focus({ preventScroll: true });
|
|
14193
|
+
window.RuntimeTrace?.emit?.('remote.control.opened', {
|
|
14194
|
+
nodeId,
|
|
14195
|
+
deviceId: targetId
|
|
14196
|
+
});
|
|
14197
|
+
|
|
14198
|
+
invokeDotNetAsync('StartRemoteFleetLiveStreamFromJs', nodeId, targetId)
|
|
14199
|
+
.then(async result => {
|
|
14200
|
+
if (!session.active) {
|
|
14201
|
+
return;
|
|
14202
|
+
}
|
|
14203
|
+
|
|
14204
|
+
await syncRemoteFleetNodeStateFromResult(result);
|
|
14205
|
+
session.startedStream = result?.success === true || result?.Success === true;
|
|
14206
|
+
session.streamId = String(result?.streamId || result?.StreamId || '');
|
|
14207
|
+
status.textContent = session.startedStream ? 'Control' : (result?.error || result?.Error || 'View');
|
|
14208
|
+
refresh();
|
|
14209
|
+
})
|
|
14210
|
+
.catch(error => {
|
|
14211
|
+
if (!session.active) {
|
|
14212
|
+
return;
|
|
14213
|
+
}
|
|
14214
|
+
|
|
14215
|
+
status.textContent = error?.message || 'Start failed';
|
|
14216
|
+
refresh();
|
|
14217
|
+
});
|
|
14218
|
+
}
|
|
14219
|
+
|
|
13699
14220
|
function isRemoteFleetLiveActive(device) {
|
|
13700
14221
|
return getRemoteFleetDeviceField(device, 'liveStreamActive', 'LiveStreamActive', false) === true;
|
|
13701
14222
|
}
|
|
@@ -15155,7 +15676,15 @@
|
|
|
15155
15676
|
: 'Offline';
|
|
15156
15677
|
|
|
15157
15678
|
panel.dataset.deviceId = deviceId;
|
|
15158
|
-
|
|
15679
|
+
const detailPreview = createDevicePreview(device, 'detail');
|
|
15680
|
+
detailPreview.style.cursor = 'pointer';
|
|
15681
|
+
detailPreview.addEventListener('dblclick', event => {
|
|
15682
|
+
event.preventDefault();
|
|
15683
|
+
event.stopPropagation();
|
|
15684
|
+
bodyView.dataset.remoteFleetSelectedDeviceId = deviceId;
|
|
15685
|
+
openRemoteFleetControlPopup(bodyView, nodeModel, deviceId);
|
|
15686
|
+
});
|
|
15687
|
+
panel.appendChild(detailPreview);
|
|
15159
15688
|
|
|
15160
15689
|
const header = document.createElement('div');
|
|
15161
15690
|
header.style.cssText = 'display:flex;align-items:flex-start;justify-content:space-between;gap:8px;min-width:0;';
|
|
@@ -15712,6 +16241,14 @@
|
|
|
15712
16241
|
['mousedown', 'mouseup', 'dblclick'].forEach(eventName => {
|
|
15713
16242
|
card.addEventListener(eventName, event => event.stopPropagation());
|
|
15714
16243
|
});
|
|
16244
|
+
card.addEventListener('dblclick', event => {
|
|
16245
|
+
event.preventDefault();
|
|
16246
|
+
event.stopPropagation();
|
|
16247
|
+
const deviceId = String(card.dataset.deviceId || '').trim();
|
|
16248
|
+
if (!deviceId) return;
|
|
16249
|
+
bodyView.dataset.remoteFleetSelectedDeviceId = deviceId;
|
|
16250
|
+
openRemoteFleetControlPopup(bodyView, nodeModel, deviceId);
|
|
16251
|
+
});
|
|
15715
16252
|
const selectCard = event => {
|
|
15716
16253
|
event.preventDefault();
|
|
15717
16254
|
event.stopPropagation();
|
|
@@ -20057,6 +20594,8 @@
|
|
|
20057
20594
|
renderRemoteFleetMonitorForTest: renderRemoteFleetMonitor,
|
|
20058
20595
|
renderRemoteFleetDeviceForTest: renderRemoteFleetDevice,
|
|
20059
20596
|
applyRemoteFleetFramePatchesForTest: applyRemoteFleetFramePatches,
|
|
20597
|
+
openRemoteFleetControlPopupForTest: openRemoteFleetControlPopup,
|
|
20598
|
+
closeRemoteFleetControlPopupForTest: closeRemoteFleetControlPopup,
|
|
20060
20599
|
renderBusinessAutomationEdges: renderBusinessAutomationEdges,
|
|
20061
20600
|
scheduleBusinessAutomationEdgeRender: scheduleBusinessAutomationEdgeRender,
|
|
20062
20601
|
syncBusinessAutomationSelectionContext: syncBusinessAutomationSelectionContext,
|