diff --git a/src/ui/Mobile/Apps/Terminal/Terminal.tsx b/src/ui/Mobile/Apps/Terminal/Terminal.tsx index 5b3d1435..e4415681 100644 --- a/src/ui/Mobile/Apps/Terminal/Terminal.tsx +++ b/src/ui/Mobile/Apps/Terminal/Terminal.tsx @@ -405,7 +405,7 @@ style.innerHTML = ` font-feature-settings: "liga" 1, "calt" 1; } -.xterm .xterm-screen .xterm-char[data-char-code^="\\uE"] { +.xterm .xterm-screen .xterm-char[data-char-code^="\uE000"] { font-family: 'JetBrains Mono Nerd Font', 'MesloLGS NF', 'FiraCode Nerd Font' !important; } `; diff --git a/src/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx b/src/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx index ca295c52..68c40217 100644 --- a/src/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx +++ b/src/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx @@ -9,59 +9,137 @@ interface TerminalKeyboardProps { export function TerminalKeyboard({onSendInput}: TerminalKeyboardProps) { const [layoutName, setLayoutName] = useState("default"); + const [isCtrl, setIsCtrl] = useState(false); + const [isAlt, setIsAlt] = useState(false); - const onKeyPress = (button: string) => { + const onKeyPress = async (button: string) => { if (button === "{shift}") { setLayoutName("shift"); return; } - if (button === "{unshift}") { setLayoutName("default"); return; } - if (button === "{more}") { - setLayoutName("more") + setLayoutName("more"); return; } - if (button === "{less}") { setLayoutName("default"); return; } - if (button === "{hide}") { setLayoutName("hide"); return; } - if (button === "{unhide}") { setLayoutName("default"); return; } - onSendInput(button); + if (button === "{ctrl}") { + setIsCtrl(prev => !prev); + return; + } + if (button === "{alt}") { + setIsAlt(prev => !prev); + return; + } + + if (button === "{paste}") { + if (navigator.clipboard?.readText) { + try { + const text = await navigator.clipboard.readText(); + if (text) { + onSendInput(text); + } + } catch (err) { + + } + } + return; + } + + let input = button; + + const specialKeyMap: { [key: string]: string } = { + "{esc}": "\x1b", "{enter}": "\r", "{tab}": "\t", "{backspace}": "\x7f", + "{arrowUp}": "\x1b[A", "{arrowDown}": "\x1b[B", "{arrowRight}": "\x1b[C", "{arrowLeft}": "\x1b[D", + "{home}": "\x1b[H", "{end}": "\x1b[F", "{pgUp}": "\x1b[5~", "{pgDn}": "\x1b[6~", + "F1": "\x1bOP", "F2": "\x1bOQ", "F3": "\x1bOR", "F4": "\x1bOS", + "F5": "\x1b[15~", "F6": "\x1b[17~", "F7": "\x1b[18~", "F8": "\x1b[19~", + "F9": "\x1b[20~", "F10": "\x1b[21~", "F11": "\x1b[23~", "F12": "\x1b[24~", + "{space}": " " + }; + + if (specialKeyMap[input]) { + input = specialKeyMap[input]; + } + + if (isCtrl) { + if (input.length === 1) { + const charCode = input.toUpperCase().charCodeAt(0); + if (charCode >= 64 && charCode <= 95) { + input = String.fromCharCode(charCode - 64); + } + } + } + + if (isAlt) { + input = `\x1b${input}`; + } + + onSendInput(input); }; + const buttonTheme = [ + { + class: "hg-space-big", + buttons: "{space}", + }, + { + class: "hg-space-medium", + buttons: "{enter} {backspace}", + }, + { + class: "hg-space-small", + buttons: "{hide} {less} {more}", + } + ]; + + if (isCtrl) { + buttonTheme.push({class: "key-active", buttons: "{ctrl}"}); + } + if (isAlt) { + buttonTheme.push({class: "key-active", buttons: "{alt}"}); + } + return (
", + "F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12", + "{arrowLeft} {arrowRight} {arrowUp} {arrowDown} {paste} {backspace}", "{hide} {less} {space} {enter}", ], hide: [ @@ -73,7 +151,7 @@ export function TerminalKeyboard({onSendInput}: TerminalKeyboardProps) { display={{ "{shift}": "up", "{unshift}": "dn", - "{backspace}": "del", + "{backspace}": "back", "{more}": "more", "{less}": "less", "{space}": "space", @@ -84,24 +162,20 @@ export function TerminalKeyboard({onSendInput}: TerminalKeyboardProps) { "{arrowDown}": "↓", "{hide}": "hide", "{unhide}": "unhide", + "{esc}": "esc", + "{tab}": "tab", + "{ctrl}": "ctrl", + "{alt}": "alt", + "{paste}": "paste", + "{end}": "end", + "{home}": "home", + "{pgUp}": "pgUp", + "{pgDn}": "pgDn", }} theme={"hg-theme-default dark-theme"} useTouchEvents={true} - buttonTheme={[ - { - class: "hg-space-big", - buttons: "{space}", - }, - { - class: "hg-space-medium", - buttons: "{enter} {backspace}", - }, - { - class: "hg-space-small", - buttons: "{hide} {less} {more}", - } - ]} + buttonTheme={buttonTheme} />
); -} \ No newline at end of file +} diff --git a/src/ui/Mobile/Apps/Terminal/kb-dark-theme.css b/src/ui/Mobile/Apps/Terminal/kb-dark-theme.css index d2f70424..9e8a4908 100644 --- a/src/ui/Mobile/Apps/Terminal/kb-dark-theme.css +++ b/src/ui/Mobile/Apps/Terminal/kb-dark-theme.css @@ -22,6 +22,11 @@ background: rgba(83, 83, 83, 0.5); } +.dark-theme .hg-button.key-active { + background: rgba(126, 126, 126, 0.5); + color: white; +} + .hg-space-big { width: 100px; } diff --git a/src/ui/Mobile/MobileApp.tsx b/src/ui/Mobile/MobileApp.tsx index 73591a7a..bf6b47ff 100644 --- a/src/ui/Mobile/MobileApp.tsx +++ b/src/ui/Mobile/MobileApp.tsx @@ -1,8 +1,8 @@ -import {useRef} from "react"; +import {useRef, FC} from "react"; import {Terminal} from "@/ui/Mobile/Apps/Terminal/Terminal.tsx"; import {TerminalKeyboard} from "@/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx"; -export function MobileApp() { +export const MobileApp: FC = () => { const terminalRef = useRef(null); function handleKeyboardInput(input: string) { @@ -34,16 +34,18 @@ export function MobileApp() { return (
- +
+ +
@@ -52,4 +54,4 @@ export function MobileApp() {
) -} \ No newline at end of file +}