diff --git a/src/ui/Mobile/Apps/Terminal/Terminal.tsx b/src/ui/Mobile/Apps/Terminal/Terminal.tsx index af0c9c80..1739b9f2 100644 --- a/src/ui/Mobile/Apps/Terminal/Terminal.tsx +++ b/src/ui/Mobile/Apps/Terminal/Terminal.tsx @@ -105,6 +105,17 @@ export const Terminal = forwardRef(function SSHTerminal( textarea.setAttribute("readonly", "true"); textarea.setAttribute("inputmode", "none"); textarea.style.caretColor = "transparent"; + + const preventKeyboard = () => { + textarea.blur(); + }; + + textarea.addEventListener('focus', preventKeyboard); + textarea.blur(); // Initial blur + + return () => { + textarea.removeEventListener('focus', preventKeyboard); + }; } }, [terminal]); diff --git a/src/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx b/src/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx index 35f42222..24a95178 100644 --- a/src/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx +++ b/src/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx @@ -1,4 +1,4 @@ -import React, {useState} from "react"; +import React, {useState, useCallback} from "react"; import Keyboard from "react-simple-keyboard"; import "react-simple-keyboard/build/css/index.css"; import "./kb-dark-theme.css"; @@ -12,29 +12,35 @@ export function TerminalKeyboard({onSendInput}: TerminalKeyboardProps) { const [isCtrl, setIsCtrl] = useState(false); const [isAlt, setIsAlt] = useState(false); - const onKeyPress = async (button: string) => { - if (button === "{shift}") { - setLayoutName("shift"); + const handlePaste = useCallback(async () => { + if (navigator.clipboard?.readText) { + try { + const text = await navigator.clipboard.readText(); + if (text) { + onSendInput(text); + } + } catch (err) { + console.error("Failed to read clipboard:", err); + } + } + }, [onSendInput]); + + const onKeyPress = useCallback((button: string) => { + const layoutMap: { [key: string]: string } = { + "{shift}": "shift", + "{unshift}": "default", + "{symbols}": "symbols", + "{fn}": "fn", + "{abc}": "default", + }; + + if (layoutMap[button]) { + setLayoutName(layoutMap[button]); return; } - if (button === "{unshift}") { - setLayoutName("default"); - return; - } - if (button === "{more}") { - setLayoutName("more"); - return; - } - if (button === "{less}") { - setLayoutName("default"); - return; - } - if (button === "{hide}") { - setLayoutName("hide"); - return; - } - if (button === "{unhide}") { - setLayoutName("default"); + + if (button === "{paste}") { + handlePaste(); return; } @@ -42,25 +48,12 @@ export function TerminalKeyboard({onSendInput}: TerminalKeyboardProps) { 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 } = { @@ -80,6 +73,7 @@ export function TerminalKeyboard({onSendInput}: TerminalKeyboardProps) { if (isCtrl) { if (input.length === 1) { const charCode = input.toUpperCase().charCodeAt(0); + // @, A-Z, [, \, ], ^, _ if (charCode >= 64 && charCode <= 95) { input = String.fromCharCode(charCode - 64); } @@ -90,9 +84,9 @@ export function TerminalKeyboard({onSendInput}: TerminalKeyboardProps) { input = `\x1b${input}`; } - navigator.vibrate(20) + navigator.vibrate(20); onSendInput(input); - }; + }, [isCtrl, isAlt, onSendInput, handlePaste]); const buttonTheme = [ { @@ -102,10 +96,6 @@ export function TerminalKeyboard({onSendInput}: TerminalKeyboardProps) { { class: "hg-space-medium", buttons: "{enter} {backspace}", - }, - { - class: "hg-space-small", - buttons: "{hide} {less} {more}", } ]; @@ -116,67 +106,71 @@ export function TerminalKeyboard({onSendInput}: TerminalKeyboardProps) { buttonTheme.push({class: "key-active", buttons: "{alt}"}); } + const layout = { + default: [ + "q w e r t y u i o p", + "a s d f g h j k l", + "{shift} z x c v b n m {backspace}", + "{symbols} {ctrl} {alt} {space} {enter}", + ], + shift: [ + "Q W E R T Y U I O P", + "A S D F G H J K L", + "{unshift} Z X C V B N M {backspace}", + "{symbols} {ctrl} {alt} {space} {enter}", + ], + symbols: [ + "1 2 3 4 5 6 7 8 9 0", + "! @ # $ % ^ & * ( )", + "- _ = + [ ] { } \\ |", + "~ ` ' \" ; : , . / < > ?", + "{abc} {fn} {space} {backspace}", + ], + fn: [ + "F1 F2 F3 F4 F5 F6", + "F7 F8 F9 F10 F11 F12", + "{esc} {tab} {home} {end}", + "{pgUp} {pgDn} {arrowUp} {arrowDown}", + "{abc} {arrowLeft} {arrowRight} {paste} {backspace}", + ] + }; + + const display = { + "{shift}": "⇧", + "{unshift}": "⇧", + "{backspace}": "⌫", + "{symbols}": "?123", + "{abc}": "abc", + "{fn}": "Fn", + "{space}": "space", + "{enter}": "enter", + "{arrowLeft}": "←", + "{arrowRight}": "→", + "{arrowUp}": "↑", + "{arrowDown}": "↓", + "{esc}": "esc", + "{tab}": "tab", + "{ctrl}": "ctrl", + "{alt}": "alt", + "{paste}": "paste", + "{end}": "end", + "{home}": "home", + "{pgUp}": "pgUp", + "{pgDn}": "pgDn", + }; + return (
", - "F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12", - "{arrowLeft} {arrowRight} {arrowUp} {arrowDown} {paste} {backspace}", - "{hide} {less} {space} {enter}", - ], - hide: [ - "{unhide}" - ] - }} + layout={layout} layoutName={layoutName} onKeyPress={onKeyPress} - display={{ - "{shift}": "up", - "{unshift}": "dn", - "{backspace}": "back", - "{more}": "more", - "{less}": "less", - "{space}": "space", - "{enter}": "enter", - "{arrowLeft}": "←", - "{arrowRight}": "→", - "{arrowUp}": "↑", - "{arrowDown}": "↓", - "{hide}": "hide", - "{unhide}": "unhide", - "{esc}": "esc", - "{tab}": "tab", - "{ctrl}": "ctrl", - "{alt}": "alt", - "{paste}": "paste", - "{end}": "end", - "{home}": "home", - "{pgUp}": "pgUp", - "{pgDn}": "pgDn", - }} + display={display} theme={"hg-theme-default dark-theme"} useTouchEvents={true} + disableButtonHold={true} buttonTheme={buttonTheme} />
); -} +} \ No newline at end of file