diff --git a/src/App.tsx b/src/App.tsx
index a0fabb0..bb3669f 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,6 +1,6 @@
import { Box, Paper, ThemeProvider, List, ListItem, ListItemButton, ListItemText, SwipeableDrawer, ListItemIcon, IconButton, AppBar, Toolbar, PaletteMode, createTheme, useMediaQuery, useTheme } from "@mui/material";
import React, { Dispatch, ReactNode } from "react";
-import { BrowserRouter, Routes, Route, Navigate, useSearchParams } from "react-router-dom";
+import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
import { ApiWrapper, getDesignTokens, GlobalUserInfo } from "./common";
import { LoginPage } from "./login";
import ServersBoard from "./servers";
@@ -14,7 +14,6 @@ import { SignupPage } from "./signup";
import Brightness4Icon from '@mui/icons-material/Brightness4';
import Brightness7Icon from '@mui/icons-material/Brightness7';
import Cookies from 'js-cookie'
-import TerminalComponent from "./terminal";
const ColorModeContext = React.createContext({ toggleColorMode: () => { } });
@@ -113,7 +112,6 @@ export default function App() {
}),
[],
);
- const [searchParams, setSearchParams] = useSearchParams();
const theme = React.useMemo(() => createTheme(getDesignTokens(mode)), [mode]);
@@ -131,7 +129,6 @@ export default function App() {
} />
} />
} />
- } />
} />
diff --git a/src/common.tsx b/src/common.tsx
index 3c71fba..a3f6772 100644
--- a/src/common.tsx
+++ b/src/common.tsx
@@ -264,12 +264,8 @@ export function ActionItem(p: { action: ActionInfo, identifierSubstring?: string
setFormData(args.formData)
}
- function createTerminalWindow(websocket: string){
- window.open(`/terminal?ws=${encodeURIComponent(websocket)}`, 'Terminal', 'width=800,height=600');
- }
-
return (<>
-
+
{ setForm(false); setFormData({}); }}
open={form}
diff --git a/src/terminal.tsx b/src/terminal.tsx
index eaaeaad..6325466 100644
--- a/src/terminal.tsx
+++ b/src/terminal.tsx
@@ -1,83 +1,104 @@
+// terminal.tsx
// src/components/Terminal.tsx
import React, { useEffect, useRef } from 'react';
import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import 'xterm/css/xterm.css';
-
-const useTerminalResize = (terminalRef: React.RefObject, fitAddon: FitAddon) => {
+const useTerminalResize = (terminalRef: React.RefObject, fitAddon: FitAddon, newWindow: Window | null) => {
useEffect(() => {
- const handleResize = () => {
- if (fitAddon && terminalRef.current) {
- fitAddon.fit();
+ const handleResize = () => {
+ if (fitAddon && terminalRef.current) {
+ fitAddon.fit();
+ }
+ };
+
+ if (newWindow) {
+ newWindow.addEventListener('resize', handleResize);
+ } else {
+ window.addEventListener('resize', handleResize);
}
- };
-
- window.addEventListener('resize', handleResize);
-
- // Fit the terminal initially
- handleResize();
-
- return () => {
- window.removeEventListener('resize', handleResize);
- };
- }, [terminalRef, fitAddon]);
- };
+ handleResize();
-function TerminalComponent (p: {websocket: string|null}) {
- const {websocket} = p
+ return () => {
+ if (newWindow) {
+ newWindow.removeEventListener('resize', handleResize);
+ } else {
+ window.removeEventListener('resize', handleResize);
+ }
+ };
+ }, [terminalRef, fitAddon, newWindow]);
+};
+
+function TerminalComponent(p: { websocket: string | null }) {
+ const { websocket } = p;
const terminalRef = useRef(null);
const terminal = useRef(null);
const fitAddon = useRef(null);
+ const newWindow = useRef(null);
useEffect(() => {
- if (terminalRef.current) {
- terminal.current = new Terminal();
- fitAddon.current = new FitAddon();
- terminal.current.loadAddon(fitAddon.current);
- terminal.current.open(terminalRef.current);
- fitAddon.current.fit();
- if (websocket == null){
-
- return ()=>{
- terminal.current?.dispose();
+ 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) {
+ terminal.current = new Terminal();
+ fitAddon.current = new FitAddon();
+ terminal.current.loadAddon(fitAddon.current);
+ terminal.current.open(terminalRef.current);
+ fitAddon.current.fit();
+
+ if (websocket == null) {
+ return () => {
+ terminal.current?.dispose();
+ newWindow.current?.close();
+ };
}
+
+ const socket = new WebSocket(websocket);
+
+ socket.onerror = (ev) => {
+ console.log(ev);
+ };
+
+ socket.addEventListener('open', () => {
+ socket.send(JSON.stringify({ CommandType: 'resize', Arguments: `${terminal.current?.cols}x${terminal.current?.rows}` }));
+ });
+
+ terminal.current.onResize(({ cols, rows }) => {
+ socket.send(JSON.stringify({ CommandType: 'resize', Arguments: `${cols}x${rows}` }));
+ });
+
+ socket.addEventListener('message', (event) => {
+ terminal.current?.write(JSON.parse(event.data));
+ });
+
+ terminal.current.onData((data) => {
+ socket.send(JSON.stringify({ CommandType: 'insert', Arguments: data }));
+ });
+
+ return () => {
+ console.log("closed websocket");
+ terminal.current?.dispose();
+ socket.close();
+ newWindow.current?.close();
+ };
}
-
- const socket = new WebSocket(websocket);
-
- socket.onerror = (ev)=>{
- console.log(ev)
- }
-
- socket.addEventListener('open', () => {
- socket.send(JSON.stringify({CommandType: 'resize', Arguments: `${terminal.current?.cols}x${terminal.current?.rows}`}));
- });
-
- terminal.current.onResize(({cols, rows})=>{
- socket.send(JSON.stringify({CommandType: 'resize', Arguments: `${cols}x${rows}`}));
- })
-
- socket.addEventListener('message', (event) => {
- terminal.current?.write(JSON.parse(event.data));
- });
-
- terminal.current.onData((data) => {
- socket.send(JSON.stringify({CommandType: 'insert', Arguments: data}));
- });
-
- return () => {
- console.log("closed websocket")
- terminal.current?.dispose();
- socket.close();
- };
}
}, []);
- useTerminalResize(terminalRef, fitAddon.current!)
+ useTerminalResize(terminalRef, fitAddon.current!, newWindow.current);
- return ;
+ return null;
};
export default TerminalComponent;