This commit is contained in:
ACoolName 2024-06-02 16:55:50 +03:00
parent a1a7d94ed1
commit 03ed3eefd5

View File

@ -1,11 +1,11 @@
// terminal.tsx
// src/components/Terminal.tsx // src/components/Terminal.tsx
import React, { useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import { Terminal } from 'xterm'; import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit'; import { FitAddon } from 'xterm-addon-fit';
import 'xterm/css/xterm.css'; import 'xterm/css/xterm.css';
const useTerminalResize = (terminalRef: React.RefObject<HTMLDivElement>, fitAddon: FitAddon, newWindow: Window | null) => {
const useTerminalResize = (terminalRef: React.RefObject<HTMLDivElement>, fitAddon: FitAddon) => {
useEffect(() => { useEffect(() => {
const handleResize = () => { const handleResize = () => {
if (fitAddon && terminalRef.current) { if (fitAddon && terminalRef.current) {
@ -13,62 +13,43 @@ const useTerminalResize = (terminalRef: React.RefObject<HTMLDivElement>, fitAddo
} }
}; };
if (newWindow) {
newWindow.addEventListener('resize', handleResize);
} else {
window.addEventListener('resize', handleResize); window.addEventListener('resize', handleResize);
}
// Fit the terminal initially
handleResize(); handleResize();
return () => { return () => {
if (newWindow) {
newWindow.removeEventListener('resize', handleResize);
} else {
window.removeEventListener('resize', handleResize); window.removeEventListener('resize', handleResize);
}
}; };
}, [terminalRef, fitAddon, newWindow]); }, [terminalRef, fitAddon]);
}; };
function TerminalComponent (p: {websocket: string|null}) { function TerminalComponent (p: {websocket: string|null}) {
const { websocket } = p; const {websocket} = p
const terminalRef = useRef<HTMLDivElement | null>(null); const terminalRef = useRef<HTMLDivElement>(null);
const terminal = useRef<Terminal | null>(null); const terminal = useRef<Terminal | null>(null);
const fitAddon = useRef<FitAddon | null>(null); const fitAddon = useRef<FitAddon | null>(null);
const newWindow = useRef<Window | null>(null);
useEffect(() => { useEffect(() => {
newWindow.current = window.open('', '', 'width=800,height=600');
if (newWindow.current) {
newWindow.current.document.title = "Terminal";
const terminalDiv = newWindow.current.document.createElement('div');
terminalDiv.style.width = '100%';
terminalDiv.style.height = '100%';
newWindow.current.document.body.appendChild(terminalDiv);
terminalRef.current = terminalDiv;
if (terminalRef.current) { if (terminalRef.current) {
terminal.current = new Terminal(); terminal.current = new Terminal();
fitAddon.current = new FitAddon(); fitAddon.current = new FitAddon();
terminal.current.loadAddon(fitAddon.current); terminal.current.loadAddon(fitAddon.current);
terminal.current.open(terminalRef.current); terminal.current.open(terminalRef.current);
fitAddon.current.fit(); fitAddon.current.fit();
if (websocket == null){ if (websocket == null){
return ()=>{ return ()=>{
terminal.current?.dispose(); terminal.current?.dispose();
newWindow.current?.close(); }
};
} }
const socket = new WebSocket(websocket); const socket = new WebSocket(websocket);
socket.onerror = (ev)=>{ socket.onerror = (ev)=>{
console.log(ev); console.log(ev)
}; }
socket.addEventListener('open', () => { socket.addEventListener('open', () => {
socket.send(JSON.stringify({CommandType: 'resize', Arguments: `${terminal.current?.cols}x${terminal.current?.rows}`})); socket.send(JSON.stringify({CommandType: 'resize', Arguments: `${terminal.current?.cols}x${terminal.current?.rows}`}));
@ -76,7 +57,7 @@ function TerminalComponent(p: { websocket: string | null }) {
terminal.current.onResize(({cols, rows})=>{ terminal.current.onResize(({cols, rows})=>{
socket.send(JSON.stringify({CommandType: 'resize', Arguments: `${cols}x${rows}`})); socket.send(JSON.stringify({CommandType: 'resize', Arguments: `${cols}x${rows}`}));
}); })
socket.addEventListener('message', (event) => { socket.addEventListener('message', (event) => {
terminal.current?.write(JSON.parse(event.data)); terminal.current?.write(JSON.parse(event.data));
@ -87,18 +68,16 @@ function TerminalComponent(p: { websocket: string | null }) {
}); });
return () => { return () => {
console.log("closed websocket"); console.log("closed websocket")
terminal.current?.dispose(); terminal.current?.dispose();
socket.close(); socket.close();
newWindow.current?.close();
}; };
} }
}
}, []); }, []);
useTerminalResize(terminalRef, fitAddon.current!, newWindow.current); useTerminalResize(terminalRef, fitAddon.current!)
return null; return <div ref={terminalRef} style={{ width: '100%', height: '100%' }}></div>;
}; };
export default TerminalComponent; export default TerminalComponent;