Prepare Build and Testing executable binary / Prepare-Build-Testing-With-Make-Without-sqlite3 (push) Successful in 6s
Prepare Build and Testing executable binary / Prepare-Build-Testing-With-CMake-Without-sqlite3 (push) Successful in 9s
Prepare Build and Testing executable binary / Prepare-Build-Testing-With-Meson-Without-sqlite3 (push) Successful in 7s
196 lines
6.8 KiB
HTML
196 lines
6.8 KiB
HTML
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<title>Web Terminal</title>
|
|
<link rel="stylesheet" href="xterm.css" />
|
|
<style>
|
|
body {
|
|
margin: 0;
|
|
padding: 20px;
|
|
background-color: #1e1e1e;
|
|
color: #fff;
|
|
font-family: Arial, sans-serif;
|
|
height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
#terminal-container {
|
|
flex: 1;
|
|
border: 1px solid #333;
|
|
border-radius: 5px;
|
|
overflow: hidden;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.status {
|
|
padding: 10px;
|
|
border-radius: 3px;
|
|
font-weight: bold;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.connected {
|
|
background-color: #2d5a2d;
|
|
}
|
|
.disconnected {
|
|
background-color: #5a2d2d;
|
|
}
|
|
.connecting {
|
|
background-color: #5a5a2d;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Web Terminal</h1>
|
|
<div class="status connecting" id="status">Connecting...</div>
|
|
<div id="terminal-container"></div>
|
|
|
|
<script src="xterm.js"></script>
|
|
<script src="xterm-addon-fit.js"></script>
|
|
<script>
|
|
class WebTerminal {
|
|
constructor() {
|
|
this.terminal = new Terminal({
|
|
cursorBlink: true,
|
|
theme: {
|
|
background: "#000000",
|
|
foreground: "#ffffff",
|
|
cursor: "#ffffff",
|
|
},
|
|
});
|
|
|
|
this.fitAddon = new FitAddon.FitAddon();
|
|
this.terminal.loadAddon(this.fitAddon);
|
|
|
|
this.ws = null;
|
|
this.reconnectAttempts = 0;
|
|
this.maxReconnectAttempts = 5;
|
|
this.reconnectDelay = 3000;
|
|
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
const terminalContainer =
|
|
document.getElementById("terminal-container");
|
|
this.terminal.open(terminalContainer);
|
|
this.fitAddon.fit();
|
|
|
|
this.terminal.writeln("Welcome to Web Terminal");
|
|
this.terminal.writeln("Connecting to server...");
|
|
|
|
this.connect();
|
|
|
|
// Handle terminal input
|
|
this.terminal.onData((data) => {
|
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
this.ws.send(data);
|
|
}
|
|
});
|
|
|
|
// Handle resize
|
|
window.addEventListener("resize", () => {
|
|
this.fitAddon.fit();
|
|
this.sendResize();
|
|
});
|
|
|
|
// Handle page unload
|
|
window.addEventListener("beforeunload", () => {
|
|
if (this.ws) {
|
|
this.ws.close();
|
|
}
|
|
});
|
|
}
|
|
|
|
connect() {
|
|
this.updateStatus("Connecting...", "connecting");
|
|
|
|
const protocol =
|
|
window.location.protocol === "https:" ? "wss:" : "ws:";
|
|
const wsUrl = `${protocol}//${window.location.host}/ws`;
|
|
|
|
this.ws = new WebSocket(wsUrl);
|
|
|
|
this.ws.onopen = () => {
|
|
console.log("WebSocket connected");
|
|
this.reconnectAttempts = 0;
|
|
this.updateStatus("Connected", "connected");
|
|
this.terminal.clear();
|
|
this.sendResize();
|
|
};
|
|
|
|
this.ws.onmessage = (event) => {
|
|
if (typeof event.data === "string") {
|
|
this.terminal.write(event.data);
|
|
} else {
|
|
// Handle binary data
|
|
const reader = new FileReader();
|
|
reader.onload = () => {
|
|
const data = new Uint8Array(reader.result);
|
|
this.terminal.write(data);
|
|
};
|
|
reader.readAsArrayBuffer(event.data);
|
|
}
|
|
};
|
|
|
|
this.ws.onclose = (event) => {
|
|
console.log(
|
|
"WebSocket disconnected:",
|
|
event.code,
|
|
event.reason,
|
|
);
|
|
this.updateStatus("Disconnected", "disconnected");
|
|
|
|
if (
|
|
this.reconnectAttempts < this.maxReconnectAttempts
|
|
) {
|
|
this.reconnectAttempts++;
|
|
const delay =
|
|
this.reconnectDelay * this.reconnectAttempts;
|
|
this.terminal.write(
|
|
`\r\nConnection lost. Reconnecting in ${delay / 1000}s...\r\n`,
|
|
);
|
|
|
|
setTimeout(() => {
|
|
this.connect();
|
|
}, delay);
|
|
} else {
|
|
this.terminal.write(
|
|
"\r\nFailed to reconnect. Please refresh the page.\r\n",
|
|
);
|
|
}
|
|
};
|
|
|
|
this.ws.onerror = (error) => {
|
|
console.error("WebSocket error:", error);
|
|
this.updateStatus("Connection Error", "disconnected");
|
|
};
|
|
}
|
|
|
|
sendResize() {
|
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
const dimensions = this.terminal;
|
|
const resizeMsg = {
|
|
cols: dimensions.cols,
|
|
rows: dimensions.rows,
|
|
};
|
|
this.ws.send(JSON.stringify(resizeMsg));
|
|
}
|
|
}
|
|
|
|
updateStatus(text, className) {
|
|
const status = document.getElementById("status");
|
|
status.textContent = text;
|
|
status.className = `status ${className}`;
|
|
}
|
|
}
|
|
|
|
// Initialize terminal when page loads
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
new WebTerminal();
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|