termites 1.0.33 → 1.0.34
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 +38 -14
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -1095,10 +1095,10 @@ class TermitesServer {
|
|
|
1095
1095
|
};
|
|
1096
1096
|
|
|
1097
1097
|
toolbar.querySelectorAll('button').forEach(btn => {
|
|
1098
|
-
|
|
1099
|
-
const
|
|
1100
|
-
|
|
1101
|
-
|
|
1098
|
+
let repeatInterval = null;
|
|
1099
|
+
const isArrowKey = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(btn.dataset.key);
|
|
1100
|
+
|
|
1101
|
+
const sendKey = () => {
|
|
1102
1102
|
const mod = btn.dataset.mod;
|
|
1103
1103
|
const key = btn.dataset.key;
|
|
1104
1104
|
const seq = btn.dataset.seq;
|
|
@@ -1106,7 +1106,6 @@ class TermitesServer {
|
|
|
1106
1106
|
if (mod) {
|
|
1107
1107
|
modifiers[mod] = !modifiers[mod];
|
|
1108
1108
|
btn.classList.toggle('active', modifiers[mod]);
|
|
1109
|
-
// Set timeout to auto-reset Ctrl after 10 seconds (for IME users)
|
|
1110
1109
|
if (mod === 'ctrl' && modifiers.ctrl) {
|
|
1111
1110
|
if (window.ctrlTimeout) clearTimeout(window.ctrlTimeout);
|
|
1112
1111
|
window.ctrlTimeout = setTimeout(() => {
|
|
@@ -1114,7 +1113,6 @@ class TermitesServer {
|
|
|
1114
1113
|
btn.classList.remove('active');
|
|
1115
1114
|
}, 10000);
|
|
1116
1115
|
}
|
|
1117
|
-
// Don't focus terminal when toggling modifier, keep keyboard open
|
|
1118
1116
|
return;
|
|
1119
1117
|
}
|
|
1120
1118
|
|
|
@@ -1123,21 +1121,17 @@ class TermitesServer {
|
|
|
1123
1121
|
data = seq;
|
|
1124
1122
|
} else if (key) {
|
|
1125
1123
|
if (modifiers.ctrl) {
|
|
1126
|
-
// Ctrl + key
|
|
1127
1124
|
if (ctrlKeyMap[key]) {
|
|
1128
1125
|
data = ctrlKeyMap[key];
|
|
1129
1126
|
} else if (key.length === 1) {
|
|
1130
|
-
// Ctrl + letter (e.g., Ctrl+C = \\x03)
|
|
1131
1127
|
data = String.fromCharCode(key.toUpperCase().charCodeAt(0) - 64);
|
|
1132
1128
|
} else {
|
|
1133
1129
|
data = keyMap[key] || '';
|
|
1134
1130
|
}
|
|
1135
1131
|
} else if (modifiers.alt) {
|
|
1136
|
-
// Alt + key
|
|
1137
1132
|
if (altKeyMap[key]) {
|
|
1138
1133
|
data = altKeyMap[key];
|
|
1139
1134
|
} else if (key.length === 1) {
|
|
1140
|
-
// Alt + letter sends ESC + letter
|
|
1141
1135
|
data = '\\x1b' + key;
|
|
1142
1136
|
} else {
|
|
1143
1137
|
data = keyMap[key] || '';
|
|
@@ -1149,17 +1143,47 @@ class TermitesServer {
|
|
|
1149
1143
|
|
|
1150
1144
|
if (data && ws?.readyState === WebSocket.OPEN && selectedClientId) {
|
|
1151
1145
|
ws.send(JSON.stringify({ type: 'input', clientId: selectedClientId, text: data }));
|
|
1152
|
-
|
|
1146
|
+
}
|
|
1147
|
+
};
|
|
1148
|
+
|
|
1149
|
+
const startRepeat = (e) => {
|
|
1150
|
+
e.preventDefault();
|
|
1151
|
+
e.stopPropagation();
|
|
1152
|
+
sendKey();
|
|
1153
|
+
// For arrow keys, start repeating after initial press
|
|
1154
|
+
if (isArrowKey && !btn.dataset.mod) {
|
|
1155
|
+
repeatInterval = setInterval(sendKey, 100);
|
|
1156
|
+
}
|
|
1157
|
+
// Reset modifiers after use (except for arrow keys during repeat)
|
|
1158
|
+
if (!isArrowKey) {
|
|
1159
|
+
modifiers.ctrl = false;
|
|
1160
|
+
modifiers.alt = false;
|
|
1161
|
+
if (window.ctrlTimeout) { clearTimeout(window.ctrlTimeout); window.ctrlTimeout = null; }
|
|
1162
|
+
toolbar.querySelectorAll('.mod-btn').forEach(b => b.classList.remove('active'));
|
|
1163
|
+
}
|
|
1164
|
+
};
|
|
1165
|
+
|
|
1166
|
+
const stopRepeat = () => {
|
|
1167
|
+
if (repeatInterval) {
|
|
1168
|
+
clearInterval(repeatInterval);
|
|
1169
|
+
repeatInterval = null;
|
|
1170
|
+
}
|
|
1171
|
+
// Reset modifiers after arrow key release
|
|
1172
|
+
if (isArrowKey) {
|
|
1153
1173
|
modifiers.ctrl = false;
|
|
1154
1174
|
modifiers.alt = false;
|
|
1155
1175
|
if (window.ctrlTimeout) { clearTimeout(window.ctrlTimeout); window.ctrlTimeout = null; }
|
|
1156
1176
|
toolbar.querySelectorAll('.mod-btn').forEach(b => b.classList.remove('active'));
|
|
1157
1177
|
}
|
|
1158
|
-
// Only focus terminal for non-modifier buttons
|
|
1159
1178
|
term.focus();
|
|
1160
1179
|
};
|
|
1161
|
-
|
|
1162
|
-
btn.addEventListener('
|
|
1180
|
+
|
|
1181
|
+
btn.addEventListener('touchstart', startRepeat, { passive: false });
|
|
1182
|
+
btn.addEventListener('touchend', stopRepeat);
|
|
1183
|
+
btn.addEventListener('touchcancel', stopRepeat);
|
|
1184
|
+
btn.addEventListener('mousedown', startRepeat);
|
|
1185
|
+
btn.addEventListener('mouseup', stopRepeat);
|
|
1186
|
+
btn.addEventListener('mouseleave', stopRepeat);
|
|
1163
1187
|
});
|
|
1164
1188
|
|
|
1165
1189
|
// History button
|