Skip to content

Commit d1fba95

Browse files
committed
fix: local debug
1 parent baf611e commit d1fba95

File tree

5 files changed

+51
-56
lines changed

5 files changed

+51
-56
lines changed

src/components/fm.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,7 @@ const FMComponent: React.FC<FMProps & JSX.IntrinsicElements["div"]> = ({ wsUrl,
6767

6868
useEffect(() => {
6969
return () => {
70-
if (wsRef.current) {
71-
wsRef.current.close();
72-
}
70+
wsRef.current?.close();
7371
};
7472
}, []);
7573

src/components/terminal.tsx

Lines changed: 22 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,43 +10,46 @@ import {
1010
import { Terminal } from "@xterm/xterm";
1111
import { AttachAddon } from "@xterm/addon-attach";
1212
import { FitAddon } from '@xterm/addon-fit';
13-
import { useRef, useEffect, useState } from "react";
13+
import { useRef, useEffect, useState, useMemo } from "react";
1414
import { sleep } from "@/lib/utils";
15-
import { IconButton } from "./xui/icon-button";
1615
import "@xterm/xterm/css/xterm.css";
17-
import { createTerminal } from "@/api/terminal";
18-
import { ModelCreateTerminalResponse } from "@/types";
1916
import { useParams } from 'react-router-dom';
2017
import { Button } from "./ui/button";
2118
import { toast } from "sonner";
2219
import { FMCard } from "./fm";
20+
import useTerminal from "@/hooks/useTerminal";
21+
import { IconButton } from "./xui/icon-button";
2322

2423
interface XtermProps {
2524
wsUrl: string;
2625
setClose: React.Dispatch<React.SetStateAction<boolean>>;
2726
}
2827

2928
const XtermComponent: React.FC<XtermProps & JSX.IntrinsicElements["div"]> = ({ wsUrl, setClose, ...props }) => {
30-
const terminalRef = useRef<HTMLDivElement>(null);
29+
const terminalIdRef = useRef<HTMLDivElement>(null);
30+
const terminalRef = useRef<Terminal | null>(null);
3131
const wsRef = useRef<WebSocket | null>(null);
3232

3333
useEffect(() => {
3434
return () => {
35-
if (wsRef.current) {
36-
wsRef.current.close();
37-
}
35+
wsRef.current?.close();
36+
terminalRef.current?.dispose();
3837
};
3938
}, []);
4039

4140
useEffect(() => {
41+
terminalRef.current = new Terminal({
42+
cursorBlink: true,
43+
fontSize: 16,
44+
});
4245
const ws = new WebSocket(wsUrl);
4346
wsRef.current = ws;
4447
ws.binaryType = "arraybuffer";
4548
ws.onopen = () => {
4649
onResize();
4750
}
4851
ws.onclose = () => {
49-
terminal.dispose();
52+
terminalRef.current?.dispose();
5053
setClose(true);
5154
}
5255
ws.onerror = (e) => {
@@ -57,18 +60,12 @@ const XtermComponent: React.FC<XtermProps & JSX.IntrinsicElements["div"]> = ({ w
5760
}
5861
}, [wsUrl]);
5962

60-
const terminal = useRef(
61-
new Terminal({
62-
cursorBlink: true,
63-
fontSize: 16,
64-
})
65-
).current;
6663

6764
const fitAddon = useRef(new FitAddon()).current;
6865
const sendResize = useRef(false);
6966

7067
const doResize = () => {
71-
if (!terminalRef.current) return;
68+
if (!terminalIdRef.current) return;
7269

7370
fitAddon.fit();
7471

@@ -104,48 +101,27 @@ const XtermComponent: React.FC<XtermProps & JSX.IntrinsicElements["div"]> = ({ w
104101
};
105102

106103
useEffect(() => {
107-
if (!wsRef.current || !terminalRef.current) return;
104+
if (!wsRef.current || !terminalIdRef.current || !terminalRef.current) return;
108105
const attachAddon = new AttachAddon(wsRef.current);
109-
terminal.loadAddon(attachAddon);
110-
terminal.loadAddon(fitAddon);
111-
terminal.open(terminalRef.current);
106+
terminalRef.current.loadAddon(attachAddon);
107+
terminalRef.current.loadAddon(fitAddon);
108+
terminalRef.current.open(terminalIdRef.current);
112109
window.addEventListener('resize', onResize);
113110
return () => {
114111
window.removeEventListener('resize', onResize);
115112
if (wsRef.current) {
116113
wsRef.current.close();
117114
}
118115
};
119-
}, [wsRef.current, terminal]);
116+
}, [wsRef.current, terminalRef.current, terminalIdRef.current]);
120117

121-
return <div ref={terminalRef} {...props} />;
118+
return <div ref={terminalIdRef} {...props} />;
122119
};
123120

124121
export const TerminalPage = () => {
125-
const [terminal, setTerminal] = useState<ModelCreateTerminalResponse | null>(null);
126-
const [open, setOpen] = useState(false);
127-
128122
const { id } = useParams<{ id: string }>();
129-
130-
const fetchTerminal = async () => {
131-
if (id && !terminal) {
132-
try {
133-
const createdTerminal = await createTerminal(Number(id));
134-
setTerminal(createdTerminal);
135-
} catch (e) {
136-
toast("Terminal API Error", {
137-
description: "View console for details.",
138-
})
139-
console.error("fetch error", e);
140-
return;
141-
}
142-
}
143-
}
144-
145-
useEffect(() => {
146-
fetchTerminal();
147-
}, [id]);
148-
123+
const [open, setOpen] = useState(false);
124+
const terminal = useTerminal(id ? parseInt(id) : undefined);
149125
return (
150126
<div className="px-8">
151127
<div className="flex mt-6 mb-4">
@@ -158,7 +134,7 @@ export const TerminalPage = () => {
158134
</div>
159135
{terminal?.session_id
160136
?
161-
<XtermComponent className="max-h-[60%] mb-5" wsUrl={`/api/v1/ws/terminal/${terminal.session_id}`} setClose={setOpen} />
137+
<XtermComponent className="max-h-[60%] mb-5" wsUrl={`/api/v1/ws/terminal/${terminal?.session_id}`} setClose={setOpen} />
162138
:
163139
<p>The server does not exist, or have not been connected yet.</p>
164140
}

src/hooks/useTerminal.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { createTerminal } from "@/api/terminal";
2+
import { ModelCreateTerminalResponse } from "@/types";
3+
import { useState, useEffect } from "react";
4+
5+
export default function useTerminal(serverId?: number) {
6+
const [terminal, setTerminal] = useState<ModelCreateTerminalResponse | null>(null);
7+
8+
async function fetchTerminal() {
9+
try {
10+
const response = await createTerminal(serverId!);
11+
setTerminal(response);
12+
} catch (error) {
13+
console.error("Failed to fetch terminal:", error);
14+
}
15+
}
16+
17+
useEffect(() => {
18+
if (!serverId) return;
19+
fetchTerminal();
20+
}, [serverId]);
21+
22+
return terminal;
23+
}

src/main.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,5 @@ const router = createBrowserRouter([
119119
]);
120120

121121
createRoot(document.getElementById('root')!).render(
122-
<StrictMode>
123-
<RouterProvider router={router} />
124-
</StrictMode>,
122+
<RouterProvider router={router} />
125123
)

vite.config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ export default defineConfig({
77
plugins: [react()],
88
server: {
99
proxy: {
10-
'/api': {
11-
target: 'http://localhost:8008',
10+
'^/api/v1/ws/.*': {
11+
target: "ws://localhost:8008",
1212
changeOrigin: true,
13+
ws: true,
1314
},
14-
'/api/v1/ws': {
15+
'/api': {
1516
target: 'http://localhost:8008',
1617
changeOrigin: true,
17-
ws: true,
1818
},
1919
},
2020
},

0 commit comments

Comments
 (0)