feat: hide IP addresses by default, click to reveal
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>
This commit is contained in:
@@ -109,6 +109,23 @@
|
|||||||
|
|
||||||
Router.start('#app-view');
|
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 ----
|
// ---- Initial state ----
|
||||||
showDisconnected();
|
showDisconnected();
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -59,7 +59,11 @@ function PlayerInfoPage(params, container) {
|
|||||||
var fieldsHtml = '';
|
var fieldsHtml = '';
|
||||||
for (var key in info) {
|
for (var key in info) {
|
||||||
if (info.hasOwnProperty(key)) {
|
if (info.hasOwnProperty(key)) {
|
||||||
fieldsHtml += '<div class="col-sm-4"><p>' + key + ': <span class="badge">' + info[key] + '</span></p></div>';
|
var value = info[key];
|
||||||
|
if (key === 'Address') {
|
||||||
|
value = maskIp(value);
|
||||||
|
}
|
||||||
|
fieldsHtml += '<div class="col-sm-4"><p>' + key + ': <span class="badge">' + value + '</span></p></div>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.getElementById('pi-fields').innerHTML = fieldsHtml;
|
document.getElementById('pi-fields').innerHTML = fieldsHtml;
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ function PlayerListPage(params, container) {
|
|||||||
'<td><a href="#/' + address + '/player/' + p.SteamID + '/">' + (p.DisplayName || '') + '</a></td>' +
|
'<td><a href="#/' + address + '/player/' + p.SteamID + '/">' + (p.DisplayName || '') + '</a></td>' +
|
||||||
'<td class="text-end"><a href="#/' + address + '/player/' + p.SteamID + '/">' + p.SteamID + '</a></td>' +
|
'<td class="text-end"><a href="#/' + address + '/player/' + p.SteamID + '/">' + p.SteamID + '</a></td>' +
|
||||||
'<td class="text-end"' + fadeClass + '>' + (p.VoiationLevel || 0) + '</td>' +
|
'<td class="text-end"' + fadeClass + '>' + (p.VoiationLevel || 0) + '</td>' +
|
||||||
'<td class="text-end">' + (p.Address || '') + '</td>' +
|
'<td class="text-end ip-cell">' + maskIp(p.Address) + '</td>' +
|
||||||
'<td class="text-end">' + (p.Ping || 0) + '</td>' +
|
'<td class="text-end">' + (p.Ping || 0) + '</td>' +
|
||||||
'<td class="text-end">' + secondsToDuration(p.ConnectedSeconds || 0) + '</td>' +
|
'<td class="text-end">' + secondsToDuration(p.ConnectedSeconds || 0) + '</td>' +
|
||||||
'</tr>';
|
'</tr>';
|
||||||
|
|||||||
@@ -47,6 +47,20 @@ a:hover { color: #fff; text-decoration: none; }
|
|||||||
/* Fade utility */
|
/* Fade utility */
|
||||||
.fade { opacity: 0.5; }
|
.fade { opacity: 0.5; }
|
||||||
|
|
||||||
|
/* IP address masking */
|
||||||
|
.ip-masked {
|
||||||
|
cursor: pointer;
|
||||||
|
color: rgba(255,255,255,0.35);
|
||||||
|
transition: color 0.2s;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.ip-masked:hover {
|
||||||
|
color: var(--rcon-accent);
|
||||||
|
}
|
||||||
|
.ip-revealed {
|
||||||
|
color: rgba(255,255,255,0.85);
|
||||||
|
}
|
||||||
|
|
||||||
/* Table styles */
|
/* Table styles */
|
||||||
#PlayerListController .table-responsive {
|
#PlayerListController .table-responsive {
|
||||||
min-height: calc(100vh - 200px);
|
min-height: calc(100vh - 200px);
|
||||||
|
|||||||
Reference in New Issue
Block a user