termites 1.0.5 → 1.0.6
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/server.js +25 -5
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -574,7 +574,8 @@ class TermitesServer {
|
|
|
574
574
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css">
|
|
575
575
|
<style>
|
|
576
576
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
577
|
-
|
|
577
|
+
html { height: 100%; overflow: hidden; }
|
|
578
|
+
body { height: 100vh; height: 100dvh; display: flex; flex-direction: column; transition: background 0.3s; font-family: monospace; overflow: hidden; position: fixed; width: 100%; }
|
|
578
579
|
.header {
|
|
579
580
|
padding: 10px 12px; display: flex; align-items: center; gap: 12px;
|
|
580
581
|
border-bottom: 1px solid; transition: all 0.3s; flex-shrink: 0;
|
|
@@ -589,7 +590,7 @@ class TermitesServer {
|
|
|
589
590
|
.header-title .host { color: var(--host-color, #859900); }
|
|
590
591
|
.header-title .sep { color: var(--sep-color, #657b83); }
|
|
591
592
|
.no-client { color: #888; font-style: italic; }
|
|
592
|
-
#terminal-container { flex: 1; padding: 4px; transition: background 0.3s; overflow: hidden; }
|
|
593
|
+
#terminal-container { flex: 1; padding: 4px; transition: background 0.3s; overflow: hidden; min-height: 0; }
|
|
593
594
|
.xterm { height: 100%; }
|
|
594
595
|
.overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.4); z-index: 99; opacity: 0; visibility: hidden; transition: all 0.3s; }
|
|
595
596
|
.overlay.open { opacity: 1; visibility: visible; }
|
|
@@ -954,8 +955,10 @@ class TermitesServer {
|
|
|
954
955
|
};
|
|
955
956
|
|
|
956
957
|
toolbar.querySelectorAll('button').forEach(btn => {
|
|
957
|
-
|
|
958
|
+
// Use touchstart to prevent losing focus on terminal
|
|
959
|
+
const handler = (e) => {
|
|
958
960
|
e.preventDefault();
|
|
961
|
+
e.stopPropagation();
|
|
959
962
|
const mod = btn.dataset.mod;
|
|
960
963
|
const key = btn.dataset.key;
|
|
961
964
|
const seq = btn.dataset.seq;
|
|
@@ -963,6 +966,8 @@ class TermitesServer {
|
|
|
963
966
|
if (mod) {
|
|
964
967
|
modifiers[mod] = !modifiers[mod];
|
|
965
968
|
btn.classList.toggle('active', modifiers[mod]);
|
|
969
|
+
console.log('Modifier toggled:', mod, modifiers[mod]);
|
|
970
|
+
// Don't focus terminal when toggling modifier, keep keyboard open
|
|
966
971
|
return;
|
|
967
972
|
}
|
|
968
973
|
|
|
@@ -992,8 +997,11 @@ class TermitesServer {
|
|
|
992
997
|
modifiers.alt = false;
|
|
993
998
|
toolbar.querySelectorAll('.mod-btn').forEach(b => b.classList.remove('active'));
|
|
994
999
|
}
|
|
1000
|
+
// Only focus terminal for non-modifier buttons
|
|
995
1001
|
term.focus();
|
|
996
|
-
}
|
|
1002
|
+
};
|
|
1003
|
+
btn.addEventListener('touchstart', handler, { passive: false });
|
|
1004
|
+
btn.addEventListener('click', handler);
|
|
997
1005
|
});
|
|
998
1006
|
}
|
|
999
1007
|
|
|
@@ -1052,11 +1060,13 @@ class TermitesServer {
|
|
|
1052
1060
|
term.onData(data => {
|
|
1053
1061
|
if (ws?.readyState === WebSocket.OPEN && selectedClientId) {
|
|
1054
1062
|
let sendData = data;
|
|
1063
|
+
console.log('Input received:', data, 'Ctrl active:', modifiers.ctrl);
|
|
1055
1064
|
// Apply Ctrl modifier to keyboard input
|
|
1056
1065
|
if (modifiers.ctrl && data.length === 1) {
|
|
1057
1066
|
const code = data.toUpperCase().charCodeAt(0);
|
|
1058
1067
|
if (code >= 65 && code <= 90) { // A-Z
|
|
1059
1068
|
sendData = String.fromCharCode(code - 64);
|
|
1069
|
+
console.log('Sending Ctrl+' + data.toUpperCase());
|
|
1060
1070
|
}
|
|
1061
1071
|
// Reset Ctrl after use
|
|
1062
1072
|
modifiers.ctrl = false;
|
|
@@ -1065,7 +1075,7 @@ class TermitesServer {
|
|
|
1065
1075
|
ws.send(JSON.stringify({ type: 'input', clientId: selectedClientId, text: sendData }));
|
|
1066
1076
|
}
|
|
1067
1077
|
});
|
|
1068
|
-
|
|
1078
|
+
function handleResize() {
|
|
1069
1079
|
fitAddon.fit();
|
|
1070
1080
|
if (ws?.readyState === WebSocket.OPEN && selectedClientId) {
|
|
1071
1081
|
ws.send(JSON.stringify({
|
|
@@ -1073,7 +1083,16 @@ class TermitesServer {
|
|
|
1073
1083
|
cols: term.cols, rows: term.rows
|
|
1074
1084
|
}));
|
|
1075
1085
|
}
|
|
1086
|
+
}
|
|
1087
|
+
window.addEventListener('resize', handleResize);
|
|
1088
|
+
window.addEventListener('orientationchange', () => {
|
|
1089
|
+
// Delay fit after orientation change to let browser settle
|
|
1090
|
+
setTimeout(handleResize, 100);
|
|
1076
1091
|
});
|
|
1092
|
+
// Also handle visual viewport changes (mobile keyboard show/hide)
|
|
1093
|
+
if (window.visualViewport) {
|
|
1094
|
+
window.visualViewport.addEventListener('resize', handleResize);
|
|
1095
|
+
}
|
|
1077
1096
|
connect();
|
|
1078
1097
|
applyTheme(currentTheme);
|
|
1079
1098
|
}
|
|
@@ -1123,6 +1142,7 @@ class TermitesServer {
|
|
|
1123
1142
|
case 'output':
|
|
1124
1143
|
if (d.clientId === selectedClientId) {
|
|
1125
1144
|
term.write(d.data);
|
|
1145
|
+
term.scrollToBottom();
|
|
1126
1146
|
}
|
|
1127
1147
|
break;
|
|
1128
1148
|
}
|