94 lines
3.2 KiB
JavaScript
94 lines
3.2 KiB
JavaScript
let socket;
|
|
let heartbeatInterval;
|
|
|
|
function connect() {
|
|
// Use wss:// for secure connections (in production) or ws:// for local
|
|
const protocol = window.location.protocol === "https:" ? "wss" : "ws";
|
|
socket = new WebSocket(`${protocol}://${window.location.host}`);
|
|
|
|
socket.onopen = () => {
|
|
console.log("WebSocket connection established.");
|
|
// Start a heartbeat to keep the connection alive
|
|
clearInterval(heartbeatInterval); // Clear previous interval if it exists
|
|
heartbeatInterval = setInterval(() => {
|
|
if (socket.readyState === WebSocket.OPEN) {
|
|
// Sending a simple ping message. The server's 'ws' library will handle this
|
|
// automatically to keep the connection from being marked as idle by proxies.
|
|
socket.send(JSON.stringify({ type: "ping" }));
|
|
}
|
|
}, 30000); // every 30 seconds
|
|
};
|
|
|
|
socket.onmessage = (event) => {
|
|
// The server's 'ws' library might automatically respond to pings with pongs.
|
|
// We can safely ignore them, along with our own pings if they get echoed.
|
|
if (event.data.includes("ping") || event.data.includes("pong")) {
|
|
return;
|
|
}
|
|
|
|
const data = JSON.parse(event.data);
|
|
|
|
// --- This is our client-side message router ---
|
|
switch (data.type) {
|
|
case "activityLogUpdate":
|
|
handleActivityLogUpdate(data.payload);
|
|
break;
|
|
case "systemResourcesUpdate":
|
|
handleSystemResourceUpdate(data.payload);
|
|
break;
|
|
// Add more cases here for other real-time updates
|
|
default:
|
|
console.log("Received unknown message type:", data.type);
|
|
}
|
|
};
|
|
|
|
socket.onclose = () => {
|
|
console.log(
|
|
"WebSocket connection closed. Attempting to reconnect in 3 seconds...",
|
|
);
|
|
clearInterval(heartbeatInterval); // Stop the heartbeat when the connection is lost
|
|
// **This is the key part:** Wait 3 seconds, then try to connect again.
|
|
setTimeout(connect, 3000);
|
|
};
|
|
|
|
socket.onerror = (error) => {
|
|
console.error("WebSocket Error:", error);
|
|
// The 'onclose' event will fire automatically after an error,
|
|
// which will then trigger our reconnection logic.
|
|
socket.close(); // Ensure the socket is closed to trigger onclose
|
|
};
|
|
}
|
|
|
|
function handleActivityLogUpdate(payload) {
|
|
const activityLog = document.getElementById("activity-log");
|
|
if (!activityLog || !payload.message) return;
|
|
|
|
const newLogItem = document.createElement("p");
|
|
const styledMessage = payload.message.replace(
|
|
/(\[[^\]]+\])/,
|
|
'<span class="timestamp">$1</span>',
|
|
);
|
|
newLogItem.innerHTML = styledMessage;
|
|
|
|
activityLog.prepend(newLogItem);
|
|
|
|
while (activityLog.children.length > 20) {
|
|
activityLog.lastChild.remove();
|
|
}
|
|
}
|
|
|
|
function handleSystemResourceUpdate(payload) {
|
|
// Conceptual: Find the memory percentage element and update its text and style
|
|
const memPercentage = document.querySelector(".metric-header strong"); // Simplified selector
|
|
const memProgressBar = document.querySelector(".progress-bar.memory"); // Simplified selector
|
|
|
|
if (memPercentage)
|
|
memPercentage.textContent = `${payload.memory.percentage}%`;
|
|
if (memProgressBar)
|
|
memProgressBar.style.width = `${payload.memory.percentage}%`;
|
|
|
|
console.log("System resources updated!", payload);
|
|
}
|
|
|
|
// --- Initial Connection ---
|
|
connect();
|