Added maskIp() helper that replaces IPs with ••••••••. A global delegated click handler reveals the address on click. Applied to: - Player list 'Address' column - Player info 'Address' field Styled .ip-masked with dimmed text and purple hover glow. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
132 lines
4.9 KiB
JavaScript
132 lines
4.9 KiB
JavaScript
/**
|
|
* Main application — layout management, header updates, sidebar nav, routing.
|
|
*/
|
|
(function () {
|
|
'use strict';
|
|
|
|
var elConnect = document.getElementById('app-connect');
|
|
var elConnected = document.getElementById('app-connected');
|
|
var elHeader = document.getElementById('server-header');
|
|
var elSidebar = document.getElementById('sidebar-nav');
|
|
|
|
// ---- Sidebar navigation ----
|
|
var navPages = [
|
|
{ title: 'Server', path: '/:address/info' },
|
|
{ title: 'Console', path: '/:address/console' },
|
|
{ title: 'Chat', path: '/:address/chat' },
|
|
{ title: 'Player List', path: '/:address/playerlist' }
|
|
];
|
|
|
|
function renderSidebar(address) {
|
|
var html = '';
|
|
for (var i = 0; i < navPages.length; i++) {
|
|
var url = navPages[i].path.replace(':address', address);
|
|
var linkCls = (window._currentPage === navPages[i].title) ? ' nav-link active' : 'nav-link';
|
|
html += '<li class="nav-item"><a class="' + linkCls + '" href="#' + url + '">' + navPages[i].title + '</a></li>';
|
|
}
|
|
elSidebar.innerHTML = html;
|
|
}
|
|
|
|
function setActivePage(title) {
|
|
window._currentPage = title;
|
|
if (Rcon.isConnected()) renderSidebar(Rcon.getAddress());
|
|
}
|
|
|
|
// ---- Header update ----
|
|
var headerTimer = null;
|
|
|
|
function updateHeader() {
|
|
Rcon.request('serverinfo', function (msg) {
|
|
var data = JSON.parse(msg.Message);
|
|
document.getElementById('header-hostname').textContent = data.Hostname || 'Rust Server';
|
|
document.getElementById('header-uptime').innerHTML = '<i class="bi bi-clock"></i> ' + secondsToDuration(data.Uptime);
|
|
document.getElementById('header-map').innerHTML = '<i class="bi bi-globe2"></i> ' + (data.Map || '');
|
|
document.getElementById('header-players').innerHTML = '<i class="bi bi-people-fill"></i> ' + formatNumber(data.Players) + '/' + formatNumber(data.MaxPlayers);
|
|
document.getElementById('header-fps').innerHTML = '<i class="bi bi-speedometer2"></i> ' + formatNumber(data.Framerate) + 'fps';
|
|
document.getElementById('header-entities').innerHTML = '<i class="bi bi-boxes"></i> ' + formatNumber(data.EntityCount);
|
|
|
|
// Cache for late-arriving pages (e.g. serverInfo) and broadcast to listeners
|
|
window._lastServerInfo = data;
|
|
document.dispatchEvent(new CustomEvent('serverinfo-update', { detail: data }));
|
|
});
|
|
}
|
|
|
|
function startHeaderUpdates() {
|
|
updateHeader();
|
|
headerTimer = setInterval(updateHeader, 1000);
|
|
}
|
|
|
|
function stopHeaderUpdates() {
|
|
if (headerTimer) { clearInterval(headerTimer); headerTimer = null; }
|
|
}
|
|
|
|
// ---- Disconnect button ----
|
|
document.getElementById('btn-disconnect').addEventListener('click', function () {
|
|
if (confirm('Do you really want to disconnect?')) {
|
|
Rcon.disconnect();
|
|
}
|
|
});
|
|
|
|
// ---- Layout toggling ----
|
|
function showConnected(address) {
|
|
elConnect.innerHTML = '';
|
|
elConnect.style.display = 'none';
|
|
elConnected.style.display = 'block';
|
|
elHeader.style.display = 'block';
|
|
renderSidebar(address);
|
|
startHeaderUpdates();
|
|
}
|
|
|
|
function showDisconnected() {
|
|
stopHeaderUpdates();
|
|
elConnected.style.display = 'none';
|
|
elHeader.style.display = 'none';
|
|
elConnect.style.display = 'block';
|
|
// Clear any stale router content
|
|
document.getElementById('app-view').innerHTML = '';
|
|
ConnectPage([], elConnect);
|
|
}
|
|
|
|
// ---- Events ----
|
|
Rcon.on('connected', function () {
|
|
var addr = Rcon.getAddress();
|
|
showConnected(addr);
|
|
// navigate() directly so it works even when the hash already matches
|
|
// (e.g. F5 reload then clicking a saved connection)
|
|
Router.navigate('#/' + addr + '/info');
|
|
});
|
|
|
|
Rcon.on('disconnected', function () {
|
|
showDisconnected();
|
|
});
|
|
|
|
// ---- Router setup ----
|
|
Router.add(/^\/([^/]+)\/info$/, 'Server', function (p, c) { setActivePage('Server'); ServerInfoPage(p, c); });
|
|
Router.add(/^\/([^/]+)\/console$/, 'Console', function (p, c) { setActivePage('Console'); ConsolePage(p, c); });
|
|
Router.add(/^\/([^/]+)\/chat$/, 'Chat', function (p, c) { setActivePage('Chat'); ChatPage(p, c); });
|
|
Router.add(/^\/([^/]+)\/playerlist$/, 'Player List', function (p, c) { setActivePage('Player List'); PlayerListPage(p, c); });
|
|
Router.add(/^\/([^/]+)\/player\/([^/]+)\/?$/, 'Player Info', function (p, c) { setActivePage('Player Info'); PlayerInfoPage(p, c); });
|
|
|
|
Router.start('#app-view');
|
|
|
|
// ---- IP address masking ----
|
|
window.maskIp = function (ip) {
|
|
if (!ip) return '';
|
|
return '<span class="ip-masked" data-ip="' + ip + '" title="Click to reveal IP">••••••••</span>';
|
|
};
|
|
|
|
document.addEventListener('click', function (e) {
|
|
var el = e.target.closest('.ip-masked');
|
|
if (el) {
|
|
el.classList.remove('ip-masked');
|
|
el.classList.add('ip-revealed');
|
|
el.textContent = el.dataset.ip;
|
|
el.title = '';
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
|
|
// ---- Initial state ----
|
|
showDisconnected();
|
|
})();
|