diff --git a/README.md b/README.md index b043f3b..5cd9ae3 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@    + ## 📖 About diff --git a/img/virtual-keyboard.jpg b/img/virtual-keyboard.jpg new file mode 100644 index 0000000..901b9e7 Binary files /dev/null and b/img/virtual-keyboard.jpg differ diff --git a/ui/package-lock.json b/ui/package-lock.json index 6b6b539..56c72c7 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -11,6 +11,7 @@ "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", "element-plus": "^2.10.1", + "simple-keyboard": "^3.8.69", "vue": "^3.5.16", "vue-axios": "^3.5.2", "vue-clipboard3": "^2.0.0", @@ -3703,6 +3704,12 @@ "node": ">=8" } }, + "node_modules/simple-keyboard": { + "version": "3.8.69", + "resolved": "https://registry.npmjs.org/simple-keyboard/-/simple-keyboard-3.8.69.tgz", + "integrity": "sha512-H/aCx57Tu8xwOTkMrELdJ0mV0s3p1i/AjzKAb+M1TnHCoFyfLumn2SC9pekIOeoB51QENOQycjF/R8SFranwLw==", + "license": "MIT" + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", diff --git a/ui/package.json b/ui/package.json index e2f51b9..f6b32b6 100644 --- a/ui/package.json +++ b/ui/package.json @@ -12,6 +12,7 @@ "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", "element-plus": "^2.10.1", + "simple-keyboard": "^3.8.69", "vue": "^3.5.16", "vue-axios": "^3.5.2", "vue-clipboard3": "^2.0.0", diff --git a/ui/src/components/RttyKeyboard.vue b/ui/src/components/RttyKeyboard.vue new file mode 100644 index 0000000..a4c689d --- /dev/null +++ b/ui/src/components/RttyKeyboard.vue @@ -0,0 +1,491 @@ + + + + ⋮⋮ + {{ $t('Virtual Keyboard') }} + ✕ + + + + + + + + diff --git a/ui/src/components/RttyTerm.vue b/ui/src/components/RttyTerm.vue index c256aa9..1c51aa7 100644 --- a/ui/src/components/RttyTerm.vue +++ b/ui/src/components/RttyTerm.vue @@ -1,6 +1,8 @@ + ⌨ + {{ $t("Select file") }} @@ -24,9 +26,9 @@ import useClipboard from 'vue-clipboard3' import { Terminal } from '@xterm/xterm' import { FitAddon } from '@xterm/addon-fit' import '@xterm/xterm/css/xterm.css' - import OverlayAddon from '../xterm-addon/xterm-addon-overlay' import ContextMenu from '../components/ContextMenu.vue' +import RttyKeyboard from '../components/RttyKeyboard.vue' const LoginErrorOffline = 4000 const LoginErrorBusy = 4001 @@ -83,6 +85,8 @@ let socket = null let term = null let fitAddon = null let unack = 0 +const showKeyboard = ref(false) +const isConnected = ref(false) const copyText = async(text) => { try { @@ -95,6 +99,12 @@ const copyText = async(text) => { const showContextmenu = (e) => contextmenuPos.value = { x: e.clientX, y: e.clientY } +const toggleKeyboard = () => showKeyboard.value = !showKeyboard.value + +const hideKeyboard = () => showKeyboard.value = false + +const handleKeypress = (keyData) => sendTermData(keyData) + const onContextmenuClick = (name) => { if (name === 'copy') { const text = term.getSelection() @@ -234,6 +244,8 @@ const closed = () => { if (term) term.write('\n\n\r\x1B[1;3;31mConnection is closed.\x1B[0m') dispose() + isConnected.value = false + showKeyboard.value = false emit('close', props.panelId) } @@ -264,6 +276,9 @@ const openTerm = () => { window.addEventListener('rtty-resize', fitTerm) fitTerm() + nextTick(() => term.focus()) + + isConnected.value = true } const dispose = () => disposables.forEach(d => d.dispose()) @@ -368,6 +383,7 @@ onUnmounted(() => { window.removeEventListener('rtty-resize', fitTerm) dispose() + if (term) term.dispose() @@ -379,6 +395,8 @@ onUnmounted(() => {