From f18b9fab72031dc2e715e4fa6a371e4b16777182 Mon Sep 17 00:00:00 2001 From: Sterling Archer Date: Thu, 13 Aug 2026 22:15:22 -0700 Subject: [PATCH] Obfuscate Anker device serial-number with asterisks until mouse-over --- solixauto/monitor.py | 72 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/solixauto/monitor.py b/solixauto/monitor.py index 50ed457..e5d77c7 100644 --- a/solixauto/monitor.py +++ b/solixauto/monitor.py @@ -581,6 +581,16 @@ PAGE = """ color: var(--ink-soft); } + .serial-tag { + cursor: pointer; + user-select: none; + } + + .serial-tag:hover, .serial-tag:focus-visible { + color: var(--ink); + outline: none; + } + .readouts { display: grid; grid-template-columns: repeat(auto-fit, minmax(108px, 1fr)); @@ -1240,11 +1250,71 @@ function nameCell(d, kind, cls) { return '' + esc(d.name) + ''; } +const serialRevealUntil = new Map(); + +function maskSerial(serial) { + if (serial.length <= 5) return serial; + return '*****' + serial.slice(-5); +} + function serialTag(d) { if (!d.serial) return ''; - return '(' + esc(d.serial) + ')'; + const revealed = (serialRevealUntil.get(d.serial) || 0) > Date.now(); + const shown = revealed ? d.serial : maskSerial(d.serial); + return '(' + + esc(shown) + ')'; } +function scheduleSerialRemask(serial) { + setTimeout(() => { + if ((serialRevealUntil.get(serial) || 0) <= Date.now()) { + serialRevealUntil.delete(serial); + document.querySelectorAll('.serial-tag').forEach(span => { + if (span.dataset.serial === serial && !span.matches(':hover')) { + span.textContent = '(' + maskSerial(serial) + ')'; + span.dataset.revealed = '0'; + } + }); + } + }, 5100); +} + +function revealSerialClick(span) { + const serial = span.dataset.serial; + if (!serial) return; + serialRevealUntil.set(serial, Date.now() + 5000); + span.textContent = '(' + serial + ')'; + span.dataset.revealed = '1'; + scheduleSerialRemask(serial); +} + +document.addEventListener('mouseenter', event => { + const span = event.target.closest && event.target.closest('.serial-tag'); + if (span) span.textContent = '(' + span.dataset.serial + ')'; +}, true); + +document.addEventListener('mouseleave', event => { + const span = event.target.closest && event.target.closest('.serial-tag'); + if (span && span.dataset.revealed !== '1') { + span.textContent = '(' + maskSerial(span.dataset.serial) + ')'; + } +}, true); + +document.addEventListener('click', event => { + const span = event.target.closest('.serial-tag'); + if (span) revealSerialClick(span); +}); + +document.addEventListener('keydown', event => { + if (event.key !== 'Enter' && event.key !== ' ') return; + const span = event.target.closest && event.target.closest('.serial-tag'); + if (!span) return; + event.preventDefault(); + revealSerialClick(span); +}); + function startEdit(span) { if (span.dataset.editing) return; span.dataset.editing = '1';