Improved playback of terminal sessions, #3336
Ylian Saint-Hilaire committed
Dec 13, 2021 at 15:18 UTC
22014f82b35d6746df189115d4fb33a10886a90e
1 file changed
+52
-5
views/player.handlebars
+52
-5
@@ -8,6 +8,7 @@
8
<meta name="format-detection" content="telephone=no" />
9
<meta name="robots" content="noindex,nofollow">
10
<link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS" />
11
+ <link type="text/css" href="styles/xterm.css" media="screen" rel="stylesheet" title="CSS" />
12
<link rel="apple-touch-icon" href="/favicon-303x303.png" />
13
<script type="text/javascript" src="scripts/common-0.0.1{{min}}.js"></script>
14
<script type="text/javascript" src="scripts/agent-desktop-0.0.2{{min}}.js"></script>
@@ -17,6 +18,8 @@
18
<script type="text/javascript" src="scripts/zlib-inflate{{min}}.js"></script>
19
<script type="text/javascript" src="scripts/zlib-adler32{{min}}.js"></script>
20
<script type="text/javascript" src="scripts/zlib-crc32{{min}}.js"></script>
21
+ <script type="text/javascript" src="scripts/xterm-min.js"></script>
22
+ <script type="text/javascript" src="scripts/xterm-addon-fit-min.js"></script>
23
<script keeplink=1 type="text/javascript" src="scripts/webm-writer.js"></script>
24
<script keeplink=1 type="text/javascript" src="scripts/filesaver.min.js"></script>
25
</head>
@@ -43,6 +46,8 @@
46
<div id=TermParent style="display:none">
47
<pre id=Term></pre>
48
</div>
49
+ <div id=XTermParent style="display:none;overflow:scroll;max-height:calc(100vh - 58px);height:calc(100vh - 58px)">
50
+ </div>
51
<div id=p11DeskConsoleMsg style="display:none;cursor:pointer;position:absolute;left:30px;top:17px;color:yellow;background-color:rgba(0,0,0,0.6);padding:10px;border-radius:5px" onclick=clearConsoleMsg()></div>
52
</div>
53
<div id=deskarea2 style="">
@@ -115,6 +120,7 @@
120
var browser = null;
121
var domainUrl = '{{{domainurl}}}';
122
var urlargs;
123
+ var term = null;
124
125
// Streaming values
126
var ws = null;
@@ -414,6 +420,7 @@
420
}
421
QV('DeskParent', true);
422
QV('TermParent', false);
423
+ QV('XTermParent', false);
424
QV('ConvertAsWebM', false);
425
if (recFileMetadata.protocol == 1) {
426
// MeshCentral remote terminal
@@ -526,11 +533,21 @@
533
videoWriterCurrentFrame = time;
534
}
535
536
+ // MeshCentral Terminal options
537
+ if ((type == 2) && !flagBinary && flagUser && (data.length > 2) && (data[0] == '{')) {
538
+ var parsed = null;
539
+ try { parsed = JSON.parse(data); } catch (ex) { }
540
+ if ((parsed != null) && ((parsed.type == 'options') || (parsed.type == 'termsize')) && (typeof parsed.cols == 'number') && (typeof parsed.rows == 'number')) {
541
+ term.resize(parsed.cols, parsed.rows);
542
+ //console.log('termsize', parsed.cols, parsed.rows);
543
+ }
544
+ }
545
+
546
if ((type == 2) && flagBinary && !flagUser) {
547
// Device --> User data
548
if (recFileProtocol == 1) {
549
// MeshCentral Terminal
533
- agentTerminal.ProcessData(data);
550
+ writeXTerm(data);
551
} else if (recFileProtocol == 2) {
552
// MeshCentral Remote Desktop
553
var view = new Uint8Array(data.length);
@@ -582,6 +599,7 @@
599
}
600
601
function cleanup() {
602
+ clearXTerm();
603
recFile = null;
604
recFilePtr = 0;
605
recFileMetadata = null;
@@ -610,6 +628,7 @@
628
}
629
QV('DeskParent', true);
630
QV('TermParent', false);
631
+ QV('XTermParent', false);
632
}
633
634
function ondrop(e) {
@@ -740,6 +759,7 @@
759
760
function togglePause() {
761
if (xxdialogMode) return;
762
+ if (term != null) return;
763
if (recFile != null) { if (playing == true) { pause(); } else { if (recFilePtr != recFile.size) { play(); } } } return false;
764
}
765
@@ -752,11 +772,13 @@
772
QE('PlayButton', false);
773
QE('PauseButton', true);
774
QE('RestartButton', false);
755
- if ((recFileProtocol == 1) && (agentTerminal == null)) {
775
+ if ((recFileProtocol == 1) && (term == null)) {
776
QV('DeskParent', false);
757
- QV('TermParent', true);
758
- agentTerminal = CreateAmtRemoteTerminal('Term', {});
759
- agentTerminal.State = 3;
777
+ QV('TermParent', false);
778
+ QV('XTermParent', true);
779
+ setupXTerm();
780
+ //agentTerminal = CreateAmtRemoteTerminal('Term', {});
781
+ //agentTerminal.State = 3;
782
}
783
readNextBlock(processBlock);
784
}
@@ -792,6 +814,8 @@
814
QH('timespan', '00:00:00');
815
QV('DeskParent', true);
816
QV('TermParent', false);
817
+ QV('XTermParent', false);
818
+ clearXTerm();
819
if (agentDesktop) {
820
agentDesktop.Canvas.clearRect(0, 0, agentDesktop.CanvasId.width, agentDesktop.CanvasId.height);
821
} else if (amtDesktop) {
@@ -1045,6 +1069,29 @@
1069
return chars;
1070
}
1071
1072
+ function setupXTerm() {
1073
+ // Setup the terminal
1074
+ if (term != null) { term.dispose(); }
1075
+ term = new Terminal();
1076
+ term.open(Q('XTermParent'));
1077
+ term.onData(function (data) { if (tunnel != null) { tunnel.sendText(data); } })
1078
+ term.resize(80, 25);
1079
+ //term.setOption('convertEol', true); // Consider \n to be \r\n, this should be taken care of by "termios"
1080
+ }
1081
+
1082
+ function clearXTerm() {
1083
+ if (term != null) { term.dispose(); term = null; }
1084
+ }
1085
+
1086
+ function writeXTerm(data) {
1087
+ if (term == null) return;
1088
+ if (typeof data == 'string') {
1089
+ term.writeUtf8(data);
1090
+ } else {
1091
+ term.writeUtf8(new Uint8Array(data));
1092
+ }
1093
+ }
1094
+
1095
start();
1096
</script>
1097
</body>