- Multi-architecture Docker image (ARM64 + AMD64) - Kubernetes manifests for 3-replica deployment - Traefik ingress configuration - NGINX Proxy Manager integration - ConfigMap-based configuration - Automated build and deployment scripts - Session monitoring tools
178 lines
4.9 KiB
JavaScript
178 lines
4.9 KiB
JavaScript
// Terminal Initialization Script for socktop webterm
|
|
// Catppuccin Frappe theme with transparency
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
// Catppuccin Frappe theme for xterm
|
|
var term = new Terminal({
|
|
allowTransparency: true,
|
|
fontFamily:
|
|
'"JetBrains Mono", "Fira Code", "Cascadia Code", Consolas, monospace',
|
|
fontSize: 14,
|
|
lineHeight: 1.2,
|
|
cursorBlink: true,
|
|
cursorStyle: "block",
|
|
theme: {
|
|
background: "rgba(48, 52, 70, 0.75)",
|
|
foreground: "#c6d0f5",
|
|
cursor: "#f2d5cf",
|
|
cursorAccent: "#303446",
|
|
selectionBackground: "rgba(202, 158, 230, 0.3)",
|
|
|
|
// ANSI colors
|
|
black: "#51576d",
|
|
red: "#e78284",
|
|
green: "#a6d189",
|
|
yellow: "#e5c890",
|
|
blue: "#8caaee",
|
|
magenta: "#f4b8e4",
|
|
cyan: "#81c8be",
|
|
white: "#b5bfe2",
|
|
|
|
// Bright ANSI colors
|
|
brightBlack: "#626880",
|
|
brightRed: "#e78284",
|
|
brightGreen: "#a6d189",
|
|
brightYellow: "#e5c890",
|
|
brightBlue: "#8caaee",
|
|
brightMagenta: "#f4b8e4",
|
|
brightCyan: "#81c8be",
|
|
brightWhite: "#a5adce",
|
|
},
|
|
});
|
|
|
|
// Create and load the FitAddon
|
|
var fitAddon = new FitAddon.FitAddon();
|
|
term.loadAddon(fitAddon);
|
|
|
|
// Create and load the TerminadoAddon
|
|
var terminadoAddon = new TerminadoAddon();
|
|
term.loadAddon(terminadoAddon);
|
|
|
|
// Open terminal in the container
|
|
var terminalContainer = document.getElementById("terminal");
|
|
term.open(terminalContainer);
|
|
|
|
// Build websocket URL
|
|
var protocol = location.protocol === "https:" ? "wss://" : "ws://";
|
|
var socketURL =
|
|
protocol +
|
|
location.hostname +
|
|
(location.port ? ":" + location.port : "") +
|
|
window.WEBSOCKET_PATH;
|
|
var sock = new WebSocket(socketURL);
|
|
|
|
// Fit-once strategy
|
|
var fitDone = false;
|
|
function fitOnceIfReady() {
|
|
if (fitDone) return;
|
|
if (!terminalContainer) return;
|
|
var w = terminalContainer.clientWidth;
|
|
var h = terminalContainer.clientHeight;
|
|
if (!w || !h) return;
|
|
|
|
try {
|
|
fitAddon.fit();
|
|
fitDone = true;
|
|
} catch (e) {
|
|
console.error("Fit error:", e);
|
|
}
|
|
}
|
|
|
|
// Schedule fit
|
|
if (
|
|
document.readyState === "complete" ||
|
|
document.readyState === "interactive"
|
|
) {
|
|
requestAnimationFrame(fitOnceIfReady);
|
|
} else {
|
|
window.addEventListener(
|
|
"DOMContentLoaded",
|
|
function () {
|
|
requestAnimationFrame(fitOnceIfReady);
|
|
},
|
|
{ once: true },
|
|
);
|
|
}
|
|
window.addEventListener(
|
|
"load",
|
|
function () {
|
|
requestAnimationFrame(fitOnceIfReady);
|
|
setTimeout(fitOnceIfReady, 150);
|
|
},
|
|
{ once: true },
|
|
);
|
|
|
|
// Send size and auto-launch command
|
|
var autoSent = false;
|
|
function sendSizeAndCommandOnce() {
|
|
if (autoSent) return;
|
|
if (!sock || sock.readyState !== WebSocket.OPEN) return;
|
|
if (!fitDone) return;
|
|
|
|
var rows = term.rows || 0;
|
|
var cols = term.cols || 0;
|
|
|
|
if (!rows || !cols) {
|
|
var approxCharW = 9;
|
|
var approxCharH = 18;
|
|
cols = Math.max(
|
|
1,
|
|
Math.floor(terminalContainer.clientWidth / approxCharW),
|
|
);
|
|
rows = Math.max(
|
|
1,
|
|
Math.floor(
|
|
terminalContainer.clientHeight / approxCharH,
|
|
),
|
|
);
|
|
}
|
|
|
|
if (rows > 0 && cols > 0) {
|
|
try {
|
|
terminadoAddon.sendSize(rows, cols);
|
|
terminadoAddon.sendCommand("socktop -P local\r");
|
|
autoSent = true;
|
|
} catch (e) {
|
|
console.error("Failed to send initial commands:", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
// WebSocket event handlers
|
|
sock.addEventListener("open", function () {
|
|
terminadoAddon.attach(sock, true, true);
|
|
requestAnimationFrame(function () {
|
|
fitOnceIfReady();
|
|
setTimeout(sendSizeAndCommandOnce, 120);
|
|
});
|
|
});
|
|
|
|
function onFirstMessage() {
|
|
fitOnceIfReady();
|
|
try {
|
|
sock.removeEventListener("message", onFirstMessage);
|
|
} catch (e) {}
|
|
setTimeout(sendSizeAndCommandOnce, 40);
|
|
}
|
|
sock.addEventListener("message", onFirstMessage);
|
|
|
|
// Handle window resize
|
|
window.addEventListener("resize", function () {
|
|
try {
|
|
fitAddon.fit();
|
|
} catch (e) {
|
|
console.error("Resize fit error:", e);
|
|
}
|
|
});
|
|
|
|
sock.addEventListener("error", function (err) {
|
|
console.error("WebSocket error:", err);
|
|
});
|
|
|
|
sock.addEventListener("close", function () {
|
|
console.log("WebSocket closed");
|
|
});
|
|
})();
|