Files
Re-Commander/public/home.js

216 lines
6.3 KiB
JavaScript
Raw Normal View History

2026-04-19 15:18:29 +03:00
'use strict';
// ── WebSocket Setup ──────────────────────────────────────────────────────────
let ws;
let connected = false;
function connectWS() {
const proto = location.protocol === 'https:' ? 'wss' : 'ws';
ws = new WebSocket(`${proto}://${location.host}/ws`);
ws.onopen = () => {
connected = true;
updateStatus();
};
ws.onclose = () => {
connected = false;
updateStatus();
setTimeout(connectWS, 2000);
};
ws.onerror = () => {};
ws.onmessage = (e) => {
let msg;
try { msg = JSON.parse(e.data); } catch { return; }
handleServerMessage(msg);
};
}
function handleServerMessage(msg) {
if (msg.type === 'status') {
updateStatus();
}
}
function updateStatus() {
const dot = document.getElementById('status-dot');
const lbl = document.getElementById('status-label');
if (connected) {
dot.className = 'ok';
lbl.textContent = 'Ready';
} else {
dot.className = '';
lbl.textContent = 'Connecting…';
}
}
// ── Connection Management ────────────────────────────────────────────────────
let selectedRobot = null;
let selectedMode = null;
let connections = [];
const STORAGE_KEY = 're-commander-connections';
// Load connections from localStorage
function loadConnections() {
const stored = localStorage.getItem(STORAGE_KEY);
connections = stored ? JSON.parse(stored) : [];
renderConnections();
}
// Save connections to localStorage
function saveConnections() {
localStorage.setItem(STORAGE_KEY, JSON.stringify(connections));
}
// Render connections list
function renderConnections() {
const list = document.getElementById('connections-list');
if (connections.length === 0) {
list.innerHTML = '<div style="color:var(--muted);font-size:12px;text-align:center;padding:20px 0;">No saved connections</div>';
return;
}
list.innerHTML = connections.map((conn, idx) => `
<div class="connection-item" data-index="${idx}">
<div class="connection-info">
<div class="connection-name">${conn.name}</div>
<div class="connection-ip">${conn.ip}</div>
</div>
<button class="connection-delete" data-index="${idx}">Delete</button>
</div>
`).join('');
// Add click handlers to select connection
document.querySelectorAll('.connection-item').forEach(item => {
const idx = parseInt(item.dataset.index);
item.addEventListener('click', (e) => {
if (!e.target.classList.contains('connection-delete')) {
selectConnection(idx);
}
});
});
// Add click handlers to delete button
document.querySelectorAll('.connection-delete').forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
const idx = parseInt(btn.dataset.index);
deleteConnection(idx);
});
});
// Highlight selected connection
if (selectedRobot !== null && selectedRobot < connections.length) {
document.querySelector(`.connection-item[data-index="${selectedRobot}"]`)?.classList.add('selected');
}
}
function selectConnection(idx) {
selectedRobot = idx;
const conn = connections[idx];
sessionStorage.setItem('selectedRobot', conn.ip);
sessionStorage.setItem('selectedRobotName', conn.name);
renderConnections();
updateLaunchButton();
}
function deleteConnection(idx) {
connections.splice(idx, 1);
saveConnections();
if (selectedRobot === idx) {
selectedRobot = null;
sessionStorage.removeItem('selectedRobot');
sessionStorage.removeItem('selectedRobotName');
}
renderConnections();
updateLaunchButton();
}
// Add new connection
document.getElementById('btn-add-connection').addEventListener('click', () => {
const ip = document.getElementById('robot-ip').value.trim();
if (!ip) {
alert('Please enter a robot IP or hostname');
return;
}
// Check if already exists
if (connections.find(c => c.ip === ip)) {
alert('This connection already exists');
return;
}
// Generate a name
const name = `Robot (${ip})`;
connections.push({ name, ip });
saveConnections();
renderConnections();
// Clear input and select the new connection
document.getElementById('robot-ip').value = '';
selectConnection(connections.length - 1);
});
// Handle Enter key in IP input
document.getElementById('robot-ip').addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
document.getElementById('btn-add-connection').click();
}
});
// ── Mode Selection ───────────────────────────────────────────────────────────
document.querySelectorAll('.mode-btn').forEach(btn => {
btn.addEventListener('click', function () {
const mode = this.dataset.mode;
selectedMode = mode;
// Remove active class from all mode buttons
document.querySelectorAll('.mode-btn').forEach(b => b.classList.remove('active'));
this.classList.add('active');
updateLaunchButton();
});
});
function updateLaunchButton() {
const btn = document.getElementById('btn-launch');
if (selectedRobot !== null && selectedMode) {
btn.disabled = false;
} else {
btn.disabled = true;
}
}
// ── Launch ───────────────────────────────────────────────────────────────────
document.getElementById('btn-launch').addEventListener('click', () => {
if (selectedRobot === null || !selectedMode) {
alert('Please select both a robot and a mode');
return;
}
const conn = connections[selectedRobot];
// Store selection in sessionStorage
sessionStorage.setItem('selectedRobot', conn.ip);
sessionStorage.setItem('selectedRobotName', conn.name);
sessionStorage.setItem('selectedMode', selectedMode);
// Navigate to the appropriate page
const modeFile = selectedMode + '.html';
window.location.href = modeFile;
});
// ── Initialization ───────────────────────────────────────────────────────────
connectWS();
loadConnections();