mirror of
https://github.com/khairul169/home-lab.git
synced 2025-04-28 16:49:36 +07:00
94 lines
2.2 KiB
TypeScript
94 lines
2.2 KiB
TypeScript
import { Platform } from "react-native";
|
|
import { Terminal } from "xterm";
|
|
import { FitAddon } from "xterm-addon-fit";
|
|
import { AttachAddon } from "xterm-addon-attach";
|
|
|
|
import Box from "@ui/Box";
|
|
import Text from "@ui/Text";
|
|
import React, { useEffect, useRef } from "react";
|
|
import "xterm/css/xterm.css";
|
|
import { API_BASEURL } from "@/lib/constants";
|
|
import authStore, { useAuth } from "@/stores/authStore";
|
|
|
|
const isWeb = Platform.OS === "web";
|
|
|
|
const TerminalPage = () => {
|
|
const { token } = useAuth();
|
|
const terminalRef = useRef<any>();
|
|
const fitRef = useRef<FitAddon | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (!isWeb || !token) {
|
|
return;
|
|
}
|
|
|
|
const term = new Terminal({ theme: { background: "#1d1e2b" } });
|
|
const fitAddon = new FitAddon();
|
|
term.loadAddon(fitAddon);
|
|
|
|
const baseUrl = API_BASEURL.replace("https://", "wss://").replace(
|
|
"http://",
|
|
"ws://"
|
|
);
|
|
const socket = new WebSocket(baseUrl + "/terminal?token=" + token);
|
|
const attachAddon = new AttachAddon(socket);
|
|
|
|
// Attach the socket to term
|
|
term.loadAddon(attachAddon);
|
|
term.open(terminalRef.current);
|
|
|
|
fitAddon.fit();
|
|
fitRef.current = fitAddon;
|
|
|
|
const sendResizeSignal = (data: { cols: number; rows: number }) => {
|
|
socket.send("resize:" + [data.cols, data.rows].join(","));
|
|
};
|
|
|
|
term.onResize(sendResizeSignal);
|
|
setTimeout(() => {
|
|
sendResizeSignal({ cols: term.cols, rows: term.rows });
|
|
}, 1000);
|
|
|
|
return () => {
|
|
attachAddon.dispose();
|
|
fitAddon.dispose();
|
|
term.dispose();
|
|
fitRef.current = null;
|
|
};
|
|
}, [token]);
|
|
|
|
useEffect(() => {
|
|
if (!isWeb) {
|
|
return;
|
|
}
|
|
|
|
const onResize = () => {
|
|
if (fitRef.current) {
|
|
fitRef.current.fit();
|
|
}
|
|
};
|
|
|
|
window.addEventListener("resize", onResize);
|
|
return () => {
|
|
window.removeEventListener("resize", onResize);
|
|
};
|
|
}, []);
|
|
|
|
if (!isWeb) {
|
|
return (
|
|
<Box className="p-8">
|
|
<Text className="text-center">Only web platform suppported.</Text>
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div
|
|
ref={terminalRef}
|
|
style={{ height: "100vh", background: "#1d1e2b", padding: 16 }}
|
|
/>
|
|
);
|
|
};
|
|
|
|
export default TerminalPage;
|