Fix mobile keybar Ctrl/Shift modifiers not applying to keyboard input
- Apply Ctrl modifier to letters typed via mobile keyboard (e.g., Ctrl+D sends 0x04) - Apply Shift modifier to uppercase letters typed via mobile keyboard - Apply modifiers to arrow keys and Tab in keydown handler - Deactivate modifiers after key is sent Bump to v0.6.3
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "textual-webterm"
|
name = "textual-webterm"
|
||||||
version = "0.6.2"
|
version = "0.6.3"
|
||||||
description = "Serve terminal sessions over the web"
|
description = "Serve terminal sessions over the web"
|
||||||
authors = ["Will McGugan <will@textualize.io>"]
|
authors = ["Will McGugan <will@textualize.io>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -497,38 +497,66 @@ class WebTerminal {
|
|||||||
textarea.addEventListener("input", () => {
|
textarea.addEventListener("input", () => {
|
||||||
const value = textarea.value;
|
const value = textarea.value;
|
||||||
if (value) {
|
if (value) {
|
||||||
this.send(["stdin", value]);
|
let toSend = value;
|
||||||
|
// Apply Shift modifier (uppercase letters)
|
||||||
|
if (this.shiftActive && value.length === 1) {
|
||||||
|
toSend = value.toUpperCase();
|
||||||
|
}
|
||||||
|
// Apply Ctrl modifier if active (convert letters to control codes)
|
||||||
|
if (this.ctrlActive && value.length === 1) {
|
||||||
|
const code = toSend.toUpperCase().charCodeAt(0);
|
||||||
|
if (code >= 65 && code <= 90) {
|
||||||
|
toSend = String.fromCharCode(code - 64); // Ctrl+A = 0x01, Ctrl+D = 0x04, etc.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.send(["stdin", toSend]);
|
||||||
textarea.value = "";
|
textarea.value = "";
|
||||||
|
this.deactivateModifiers();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle special navigation keys via keydown (not covered by beforeinput)
|
// Handle special navigation keys via keydown (not covered by beforeinput)
|
||||||
textarea.addEventListener("keydown", (e) => {
|
textarea.addEventListener("keydown", (e) => {
|
||||||
let seq: string | null = null;
|
let seq: string | null = null;
|
||||||
|
let deactivate = false;
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
case "Escape":
|
case "Escape":
|
||||||
seq = "\x1b";
|
seq = "\x1b";
|
||||||
|
deactivate = true;
|
||||||
break;
|
break;
|
||||||
case "ArrowUp":
|
case "ArrowUp":
|
||||||
seq = "\x1b[A";
|
|
||||||
break;
|
|
||||||
case "ArrowDown":
|
case "ArrowDown":
|
||||||
seq = "\x1b[B";
|
|
||||||
break;
|
|
||||||
case "ArrowRight":
|
case "ArrowRight":
|
||||||
seq = "\x1b[C";
|
case "ArrowLeft": {
|
||||||
break;
|
const dir = e.key === "ArrowUp" ? "A" : e.key === "ArrowDown" ? "B" : e.key === "ArrowRight" ? "C" : "D";
|
||||||
case "ArrowLeft":
|
if (this.ctrlActive && this.shiftActive) {
|
||||||
seq = "\x1b[D";
|
seq = `\x1b[1;6${dir}`;
|
||||||
|
} else if (this.ctrlActive) {
|
||||||
|
seq = `\x1b[1;5${dir}`;
|
||||||
|
} else if (this.shiftActive) {
|
||||||
|
seq = `\x1b[1;2${dir}`;
|
||||||
|
} else {
|
||||||
|
seq = `\x1b[${dir}`;
|
||||||
|
}
|
||||||
|
deactivate = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case "Tab":
|
case "Tab":
|
||||||
seq = "\t";
|
if (this.shiftActive) {
|
||||||
|
seq = "\x1b[Z"; // Back-tab
|
||||||
|
} else {
|
||||||
|
seq = "\t";
|
||||||
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
deactivate = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (seq) {
|
if (seq) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.send(["stdin", seq]);
|
this.send(["stdin", seq]);
|
||||||
|
if (deactivate) {
|
||||||
|
this.deactivateModifiers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user