diff --git a/web/resources/js/app.js b/web/resources/js/app.js index 0a23e8f..29f5ccf 100644 --- a/web/resources/js/app.js +++ b/web/resources/js/app.js @@ -1,3 +1,3 @@ import './bootstrap'; -import { Terminal } from '@xterm/xterm'; + diff --git a/web/resources/js/web-terminal.js b/web/resources/js/web-terminal.js new file mode 100644 index 0000000..0a14b5b --- /dev/null +++ b/web/resources/js/web-terminal.js @@ -0,0 +1,63 @@ +import '@xterm/xterm/css/xterm.css'; +import { Terminal } from '@xterm/xterm'; +import { WebglAddon } from '@xterm/addon-webgl'; +import { CanvasAddon } from '@xterm/addon-canvas'; +import { FitAddon } from '@xterm/addon-fit'; + +let terminalElement = document.getElementById('js-web-terminal'); +if (terminalElement !== null) { + + const terminal = new Terminal({ + allowTransparency: true, + theme: { + background: '#09090b', + foreground: '#cccccc', + selectionBackground: '#399ef440', + black: '#666666', + blue: '#399ef4', + brightBlack: '#666666', + brightBlue: '#399ef4', + brightCyan: '#21c5c7', + brightGreen: '#4eb071', + brightMagenta: '#b168df', + brightRed: '#da6771', + brightWhite: '#efefef', + brightYellow: '#fff099', + cyan: '#21c5c7', + green: '#4eb071', + magenta: '#b168df', + red: '#da6771', + white: '#efefef', + yellow: '#fff099' + } + }); + + if (typeof WebGL2RenderingContext !== 'undefined') { + terminal.loadAddon(new WebglAddon()); + } else { + terminal.loadAddon(new CanvasAddon()); + } + + const fitAddon = new FitAddon(); + terminal.loadAddon(fitAddon); + + terminal.open(terminalElement); + + fitAddon.fit(); + + const socket = new WebSocket(`ws://49.13.166.115:3311`); + socket.addEventListener('open', (_) => { + terminal.onData((data) => socket.send(data)); + socket.addEventListener('message', (evt) => terminal.write(evt.data)); + }); + socket.addEventListener('error', (_) => { + terminal.reset(); + terminal.writeln('Connection error.'); + }); + socket.addEventListener('close', (evt) => { + if (evt.wasClean) { + terminal.reset(); + terminal.writeln(evt.reason ?? 'Connection closed.'); + } + }); +} diff --git a/web/resources/views/filament/pages/terminal.blade.php b/web/resources/views/filament/pages/terminal.blade.php index 2f44a85..9098718 100644 --- a/web/resources/views/filament/pages/terminal.blade.php +++ b/web/resources/views/filament/pages/terminal.blade.php @@ -2,31 +2,10 @@
+ @vite('resources/js/web-terminal.js') +
- -
diff --git a/web/vite.config.js b/web/vite.config.js index bf1bb3a..37cb5f3 100644 --- a/web/vite.config.js +++ b/web/vite.config.js @@ -4,7 +4,11 @@ import laravel, { refreshPaths } from 'laravel-vite-plugin' export default defineConfig({ plugins: [ laravel({ - input: ['resources/css/app.css', 'resources/js/app.js'], + input: [ + 'resources/css/app.css', + 'resources/js/app.js', + 'resources/js/web-terminal.js', + ], refresh: [ ...refreshPaths, 'app/Livewire/**',