Fixes in views
This commit is contained in:
@@ -171,7 +171,12 @@ body {
|
||||
letter-spacing: 0.12em;
|
||||
}
|
||||
.foot .warn { color: var(--warn); }
|
||||
#rig { transition: opacity 0.4s ease; }
|
||||
/* Mirrors .station .rig.glitching — bottom telemetry uses the same scramble
|
||||
reveal as the top rig identifier, so it shares the warn-yellow tint. */
|
||||
#rig.glitching {
|
||||
color: var(--warn);
|
||||
text-shadow: 0 0 10px rgba(255, 208, 0, 0.4);
|
||||
}
|
||||
|
||||
/* ───────── Overlays ───────── */
|
||||
#static {
|
||||
@@ -323,55 +328,70 @@ body {
|
||||
// 8 fps — visually almost identical to 12 fps but ~33% less paint work.
|
||||
setInterval(drawNoise, 1000 / 8);
|
||||
|
||||
// ───────── Rig name in the top HUD with periodic glitch-decode ─────────
|
||||
// Reads telemetry.js's window.__TEL.rig (set by telemetry.sh per-rig).
|
||||
// Behaviour: settles on the real name, then every ~9s briefly scrambles
|
||||
// each letter through random glyphs and resolves back left-to-right. Same
|
||||
// effect family as the cyberpunk "decoder" trope; pairs with the CRT
|
||||
// aesthetic rather than fighting it.
|
||||
const rigNameEl = document.getElementById('rigName');
|
||||
const RIG_NAME = (window.__TEL && window.__TEL.rig) || 'UNKNOWN';
|
||||
// ASCII-only glyph pool — tabular_nums keeps width stable in DejaVu Mono.
|
||||
// ───────── Cyberpunk decode/scramble reveal ─────────
|
||||
// Each call: replace target text with random glyphs for `scrambleMs`, then
|
||||
// resolve to `finalText` left-to-right. Same effect family as the cyberpunk
|
||||
// "decoder" trope; pairs with the CRT aesthetic rather than fighting it.
|
||||
// Used by both the top rig identifier and the bottom telemetry rotator.
|
||||
// ASCII-only glyph pool — DejaVu Mono renders these at 1ch each, so the
|
||||
// intermediate frames don't shift width.
|
||||
const GLITCH_GLYPHS = '01ABCDEFGHIJKLMNOPQRSTUVWXYZ#@*?!§%';
|
||||
const glyph = () => GLITCH_GLYPHS[(Math.random() * GLITCH_GLYPHS.length) | 0];
|
||||
const upperRig = RIG_NAME.toUpperCase();
|
||||
|
||||
// Initial reveal: scramble for ~400ms, then resolve l→r.
|
||||
// Subsequent: small idle scramble ~every 9s.
|
||||
function scrambleOnce({ initial = false } = {}) {
|
||||
const len = upperRig.length;
|
||||
if (len === 0) { rigNameEl.textContent = '--'; return; }
|
||||
rigNameEl.classList.add('glitching');
|
||||
const totalScrambleMs = initial ? 600 : 360;
|
||||
const stepMs = 50;
|
||||
const scrambleSteps = Math.max(1, Math.floor(totalScrambleMs / stepMs));
|
||||
// Tracks the in-flight scramble per element so a new call can cancel the
|
||||
// previous one (otherwise back-to-back triggers double up timers).
|
||||
const _scrambleHandles = new WeakMap();
|
||||
function scrambleReveal(el, finalText, opts = {}) {
|
||||
const { scrambleMs = 360, stepMs = 50, resolveStepMs = 60 } = opts;
|
||||
const prev = _scrambleHandles.get(el);
|
||||
if (prev) { clearInterval(prev.s); clearInterval(prev.r); }
|
||||
const len = finalText.length;
|
||||
if (!len) {
|
||||
el.textContent = '';
|
||||
el.classList.remove('glitching');
|
||||
_scrambleHandles.delete(el);
|
||||
return;
|
||||
}
|
||||
el.classList.add('glitching');
|
||||
const scrambleSteps = Math.max(1, Math.floor(scrambleMs / stepMs));
|
||||
const handle = { s: null, r: null };
|
||||
_scrambleHandles.set(el, handle);
|
||||
let step = 0;
|
||||
|
||||
const scrambleTimer = setInterval(() => {
|
||||
handle.s = setInterval(() => {
|
||||
let s = '';
|
||||
for (let i = 0; i < len; i++) s += glyph();
|
||||
rigNameEl.textContent = s;
|
||||
if (++step >= scrambleSteps) {
|
||||
clearInterval(scrambleTimer);
|
||||
// Resolve left-to-right
|
||||
let resolved = 0;
|
||||
const resolveTimer = setInterval(() => {
|
||||
resolved++;
|
||||
let s = upperRig.slice(0, resolved);
|
||||
for (let i = resolved; i < len; i++) s += glyph();
|
||||
rigNameEl.textContent = s;
|
||||
if (resolved >= len) {
|
||||
clearInterval(resolveTimer);
|
||||
rigNameEl.textContent = upperRig;
|
||||
rigNameEl.classList.remove('glitching');
|
||||
}
|
||||
}, 60);
|
||||
}
|
||||
el.textContent = s;
|
||||
if (++step < scrambleSteps) return;
|
||||
clearInterval(handle.s); handle.s = null;
|
||||
let resolved = 0;
|
||||
handle.r = setInterval(() => {
|
||||
resolved++;
|
||||
let s = finalText.slice(0, resolved);
|
||||
for (let i = resolved; i < len; i++) s += glyph();
|
||||
el.textContent = s;
|
||||
if (resolved < len) return;
|
||||
clearInterval(handle.r); handle.r = null;
|
||||
el.textContent = finalText;
|
||||
el.classList.remove('glitching');
|
||||
_scrambleHandles.delete(el);
|
||||
}, resolveStepMs);
|
||||
}, stepMs);
|
||||
}
|
||||
|
||||
// ───────── Rig name in the top HUD ─────────
|
||||
// Reads telemetry.js's window.__TEL.rig (set by telemetry.sh per-rig).
|
||||
// Settles on the real name, then idle-reglitches every ~9s.
|
||||
const rigNameEl = document.getElementById('rigName');
|
||||
const RIG_NAME = (window.__TEL && window.__TEL.rig) || 'UNKNOWN';
|
||||
const upperRig = RIG_NAME.toUpperCase();
|
||||
const scrambleRig = ({ initial = false } = {}) => {
|
||||
if (!upperRig.length) { rigNameEl.textContent = '--'; return; }
|
||||
scrambleReveal(rigNameEl, upperRig, {
|
||||
scrambleMs: initial ? 600 : 360, stepMs: 50, resolveStepMs: 60,
|
||||
});
|
||||
};
|
||||
// First reveal happens shortly after page load; then idle re-glitch.
|
||||
setTimeout(() => scrambleOnce({ initial: true }), 600);
|
||||
setInterval(scrambleOnce, 9000);
|
||||
setTimeout(() => scrambleRig({ initial: true }), 600);
|
||||
setInterval(scrambleRig, 9000);
|
||||
|
||||
// ───────── Telemetry: rotating real-data subtitle ─────────
|
||||
// All lines derive from telemetry.js (window.__TEL), generated by telemetry.sh.
|
||||
@@ -432,24 +452,31 @@ body {
|
||||
];
|
||||
|
||||
let lineIdx = 0;
|
||||
const renderLine = () => {
|
||||
// Pick the next non-null line, advancing lineIdx past dead slots.
|
||||
const nextLine = () => {
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const v = lines[lineIdx]();
|
||||
if (v) { rigEl.textContent = v; return; }
|
||||
if (v) return v;
|
||||
lineIdx = (lineIdx + 1) % lines.length;
|
||||
}
|
||||
rigEl.textContent = '— TELEMETRY OFFLINE —';
|
||||
return '— TELEMETRY OFFLINE —';
|
||||
};
|
||||
|
||||
// Soft crossfade: 0.4s out → swap text → 0.4s in (matches the CSS transition)
|
||||
const FADE_MS = 400;
|
||||
// Initial paint goes in directly so the page loads with content visible;
|
||||
// every subsequent transition uses the scramble reveal (same effect as the
|
||||
// top rig identifier).
|
||||
rigEl.textContent = nextLine();
|
||||
// Bottom lines are much longer than the rig name (~22–55 chars vs ~5–8),
|
||||
// so adapt the per-char resolve step to keep total reveal under ~700ms.
|
||||
const swapLine = () => {
|
||||
rigEl.style.opacity = '0';
|
||||
setTimeout(() => { renderLine(); rigEl.style.opacity = '1'; }, FADE_MS);
|
||||
const text = nextLine();
|
||||
const len = Math.max(text.length, 1);
|
||||
scrambleReveal(rigEl, text, {
|
||||
scrambleMs: 280,
|
||||
stepMs: 45,
|
||||
resolveStepMs: Math.max(15, Math.floor(700 / len)),
|
||||
});
|
||||
};
|
||||
|
||||
renderLine();
|
||||
rigEl.style.opacity = '1';
|
||||
setInterval(() => {
|
||||
lineIdx = (lineIdx + 1) % lines.length;
|
||||
swapLine();
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
"collectedAt": "2026-04-26T20:17:38Z",
|
||||
"rig": "Ignia",
|
||||
"cpu": {
|
||||
"model": "AMD Ryzen 5 2600 Six-Core Processor",
|
||||
"model": "AMD Ryzen 5",
|
||||
"threads": 12
|
||||
},
|
||||
"mem": {
|
||||
"totalGB": 31.3
|
||||
"totalGB": 32
|
||||
},
|
||||
"host": {
|
||||
"kernel": "6.18.23-1-lts"
|
||||
"kernel": "Arch Linux 6.18.23-1-lts"
|
||||
},
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 3060 Ti",
|
||||
|
||||
Reference in New Issue
Block a user