termites 1.0.11 → 1.0.13

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 (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +36 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "termites",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Web terminal with server-client architecture for remote shell access",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server.js CHANGED
@@ -953,6 +953,13 @@ class TermitesServer {
953
953
  'ArrowRight': '\\x1b[1;5C',
954
954
  'ArrowLeft': '\\x1b[1;5D'
955
955
  };
956
+ // Alt + key sequences
957
+ const altKeyMap = {
958
+ 'ArrowUp': '\\x1b[1;3A',
959
+ 'ArrowDown': '\\x1b[1;3B',
960
+ 'ArrowRight': '\\x1b[1;3C',
961
+ 'ArrowLeft': '\\x1b[1;3D'
962
+ };
956
963
 
957
964
  toolbar.querySelectorAll('button').forEach(btn => {
958
965
  // Use touchstart to prevent losing focus on terminal
@@ -966,7 +973,14 @@ class TermitesServer {
966
973
  if (mod) {
967
974
  modifiers[mod] = !modifiers[mod];
968
975
  btn.classList.toggle('active', modifiers[mod]);
969
- console.log('Modifier toggled:', mod, modifiers[mod]);
976
+ // Set timeout to auto-reset Ctrl after 10 seconds (for IME users)
977
+ if (mod === 'ctrl' && modifiers.ctrl) {
978
+ if (window.ctrlTimeout) clearTimeout(window.ctrlTimeout);
979
+ window.ctrlTimeout = setTimeout(() => {
980
+ modifiers.ctrl = false;
981
+ btn.classList.remove('active');
982
+ }, 10000);
983
+ }
970
984
  // Don't focus terminal when toggling modifier, keep keyboard open
971
985
  return;
972
986
  }
@@ -985,6 +999,16 @@ class TermitesServer {
985
999
  } else {
986
1000
  data = keyMap[key] || '';
987
1001
  }
1002
+ } else if (modifiers.alt) {
1003
+ // Alt + key
1004
+ if (altKeyMap[key]) {
1005
+ data = altKeyMap[key];
1006
+ } else if (key.length === 1) {
1007
+ // Alt + letter sends ESC + letter
1008
+ data = '\\x1b' + key;
1009
+ } else {
1010
+ data = keyMap[key] || '';
1011
+ }
988
1012
  } else {
989
1013
  data = keyMap[key] || '';
990
1014
  }
@@ -995,6 +1019,7 @@ class TermitesServer {
995
1019
  // Reset modifiers after use
996
1020
  modifiers.ctrl = false;
997
1021
  modifiers.alt = false;
1022
+ if (window.ctrlTimeout) { clearTimeout(window.ctrlTimeout); window.ctrlTimeout = null; }
998
1023
  toolbar.querySelectorAll('.mod-btn').forEach(b => b.classList.remove('active'));
999
1024
  }
1000
1025
  // Only focus terminal for non-modifier buttons
@@ -1057,20 +1082,23 @@ class TermitesServer {
1057
1082
  term.loadAddon(fitAddon);
1058
1083
  term.open(document.getElementById('terminal-container'));
1059
1084
  fitAddon.fit();
1085
+ let ctrlTimeout = null;
1060
1086
  term.onData(data => {
1061
1087
  if (ws?.readyState === WebSocket.OPEN && selectedClientId) {
1062
1088
  let sendData = data;
1063
- console.log('Input received:', data, 'Ctrl active:', modifiers.ctrl);
1064
1089
  // Apply Ctrl modifier to keyboard input
1065
- if (modifiers.ctrl && data.length === 1) {
1066
- const code = data.toUpperCase().charCodeAt(0);
1090
+ if (modifiers.ctrl) {
1091
+ // Handle single character or IME input
1092
+ const char = data.length >= 1 ? data[0] : '';
1093
+ const code = char.toUpperCase().charCodeAt(0);
1067
1094
  if (code >= 65 && code <= 90) { // A-Z
1068
1095
  sendData = String.fromCharCode(code - 64);
1069
- console.log('Sending Ctrl+' + data.toUpperCase());
1096
+ console.log('Sending Ctrl+' + char.toUpperCase());
1097
+ // Reset Ctrl after successful use
1098
+ modifiers.ctrl = false;
1099
+ if (ctrlTimeout) { clearTimeout(ctrlTimeout); ctrlTimeout = null; }
1100
+ document.querySelectorAll('.mod-btn[data-mod="ctrl"]').forEach(b => b.classList.remove('active'));
1070
1101
  }
1071
- // Reset Ctrl after use
1072
- modifiers.ctrl = false;
1073
- document.querySelectorAll('.mod-btn').forEach(b => b.classList.remove('active'));
1074
1102
  }
1075
1103
  ws.send(JSON.stringify({ type: 'input', clientId: selectedClientId, text: sendData }));
1076
1104
  term.scrollToBottom();