leaderboard-raderna i overlay är tätare igen
This commit is contained in:
30
src/app.js
30
src/app.js
@@ -1083,6 +1083,7 @@ let selectedTeamEditId = null;
|
||||
let quickAddDraft = null;
|
||||
let overlaySyncTimer = null;
|
||||
let overlayRotationTimer = null;
|
||||
let overlayLiveRefreshTimer = null;
|
||||
let overlayRotationIndex = 0;
|
||||
let overlayEvents = [];
|
||||
let lastOverlayLeaderKeyBySession = {};
|
||||
@@ -1131,6 +1132,7 @@ async function init() {
|
||||
if (overlayMode) {
|
||||
startOverlaySync();
|
||||
startOverlayRotation();
|
||||
startOverlayLiveRefresh();
|
||||
if (state.settings.wsUrl) {
|
||||
connectDecoder();
|
||||
}
|
||||
@@ -1704,6 +1706,15 @@ function startOverlayRotation() {
|
||||
}, 8000);
|
||||
}
|
||||
|
||||
function startOverlayLiveRefresh() {
|
||||
clearInterval(overlayLiveRefreshTimer);
|
||||
overlayLiveRefreshTimer = setInterval(() => {
|
||||
if (currentView === "overlay" && ["leaderboard", "tv", "team"].includes(overlayViewMode)) {
|
||||
renderOverlay();
|
||||
}
|
||||
}, 250);
|
||||
}
|
||||
|
||||
function renderNav() {
|
||||
if (overlayMode) {
|
||||
dom.nav.innerHTML = "";
|
||||
@@ -5679,16 +5690,20 @@ function buildLeaderboard(session) {
|
||||
const distanceToTargetMs = Math.abs(targetMs - totalElapsedMs);
|
||||
const seedMetric = getCompetitorSeedMetric(session, row);
|
||||
const passings = getCompetitorPassings(session, row);
|
||||
const latestPassing = passings.length ? passings[passings.length - 1] : null;
|
||||
const previousLapMs = passings.length >= 2 ? Number(passings[passings.length - 2].lapMs || 0) : null;
|
||||
const lastLapMs = latestPassing ? Number(latestPassing.lapMs || 0) : Number(row.lastLapMs || 0) || 0;
|
||||
const bestLapMs = Number(row.bestLapMs || 0) || 0;
|
||||
const lastPassingTs = latestPassing ? Number(latestPassing.timestamp || 0) : Number(row.lastTimestamp || 0) || 0;
|
||||
const lapDeltaMs =
|
||||
row.lastLapMs && previousLapMs && row.lastLapMs > 0 && previousLapMs > 0 ? row.lastLapMs - previousLapMs : null;
|
||||
lastLapMs && previousLapMs && lastLapMs > 0 && previousLapMs > 0 ? lastLapMs - previousLapMs : null;
|
||||
const predictionBaseMs =
|
||||
Number(row.lastLapMs || 0) > 0
|
||||
? Number(row.lastLapMs)
|
||||
: Number(row.bestLapMs || 0) > 0
|
||||
? Number(row.bestLapMs)
|
||||
lastLapMs > 0
|
||||
? lastLapMs
|
||||
: bestLapMs > 0
|
||||
? bestLapMs
|
||||
: null;
|
||||
const currentLapElapsedMs = row.lastTimestamp ? Math.max(0, nowTs - row.lastTimestamp) : 0;
|
||||
const currentLapElapsedMs = lastPassingTs ? Math.max(0, nowTs - lastPassingTs) : 0;
|
||||
const predictedRemainingMs = predictionBaseMs ? Math.max(0, predictionBaseMs - currentLapElapsedMs) : null;
|
||||
const predictedProgress = predictionBaseMs ? Math.min(1.25, currentLapElapsedMs / predictionBaseMs) : 0;
|
||||
const predictionTone =
|
||||
@@ -5699,6 +5714,9 @@ function buildLeaderboard(session) {
|
||||
: "late";
|
||||
return {
|
||||
...row,
|
||||
lastLapMs,
|
||||
bestLapMs,
|
||||
lastTimestamp: lastPassingTs || row.lastTimestamp,
|
||||
totalElapsedMs,
|
||||
distanceToTargetMs,
|
||||
seedMetric,
|
||||
|
||||
110
src/styles.css
110
src/styles.css
@@ -780,7 +780,7 @@ select:focus {
|
||||
|
||||
.overlay-shell {
|
||||
min-height: 100vh;
|
||||
padding: 14px;
|
||||
padding: 10px;
|
||||
background:
|
||||
radial-gradient(circle at 15% 0%, rgba(225, 6, 0, 0.18), transparent 30%),
|
||||
radial-gradient(circle at 100% 80%, rgba(37, 59, 103, 0.22), transparent 30%),
|
||||
@@ -790,15 +790,15 @@ select:focus {
|
||||
.overlay-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.overlay-header-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@@ -809,15 +809,15 @@ select:focus {
|
||||
.overlay-kicker-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 2px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.overlay-header h1 {
|
||||
margin: 0;
|
||||
font-family: Orbitron, sans-serif;
|
||||
font-size: clamp(1.05rem, 1.7vw, 1.6rem);
|
||||
font-size: clamp(0.92rem, 1.35vw, 1.25rem);
|
||||
line-height: 1.02;
|
||||
}
|
||||
|
||||
@@ -826,13 +826,13 @@ select:focus {
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
font-size: 0.62rem;
|
||||
font-size: 0.56rem;
|
||||
}
|
||||
|
||||
.overlay-header-sub {
|
||||
margin: 3px 0 0;
|
||||
margin: 1px 0 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.74rem;
|
||||
font-size: 0.66rem;
|
||||
}
|
||||
|
||||
.overlay-meta {
|
||||
@@ -844,7 +844,7 @@ select:focus {
|
||||
|
||||
.overlay-clock {
|
||||
font-family: Orbitron, sans-serif;
|
||||
font-size: clamp(1.35rem, 2.3vw, 2.2rem);
|
||||
font-size: clamp(1.12rem, 1.9vw, 1.7rem);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
@@ -856,13 +856,13 @@ select:focus {
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
font-size: 0.62rem;
|
||||
font-size: 0.56rem;
|
||||
}
|
||||
|
||||
.overlay-board {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.85fr) minmax(210px, 0.38fr);
|
||||
gap: 10px;
|
||||
grid-template-columns: minmax(0, 1.92fr) minmax(180px, 0.31fr);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.overlay-board-tv {
|
||||
@@ -964,12 +964,12 @@ select:focus {
|
||||
}
|
||||
|
||||
.overlay-table-wrap {
|
||||
padding: 6px 8px 8px;
|
||||
padding: 4px 6px 6px;
|
||||
}
|
||||
|
||||
.overlay-display-wrap {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.overlay-fastest-banner,
|
||||
@@ -984,8 +984,8 @@ select:focus {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: end;
|
||||
gap: 12px;
|
||||
padding: 10px 12px;
|
||||
gap: 8px;
|
||||
padding: 7px 10px;
|
||||
background:
|
||||
linear-gradient(135deg, rgba(225, 6, 0, 0.18), rgba(225, 6, 0, 0.04)),
|
||||
rgba(7, 12, 20, 0.92);
|
||||
@@ -1002,20 +1002,20 @@ select:focus {
|
||||
display: block;
|
||||
margin-top: 2px;
|
||||
font-family: Orbitron, sans-serif;
|
||||
font-size: clamp(1.25rem, 2.3vw, 1.9rem);
|
||||
font-size: clamp(1.02rem, 1.7vw, 1.45rem);
|
||||
}
|
||||
|
||||
.overlay-leaderboard-card {
|
||||
padding: 8px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.overlay-leaderboard-card-tv {
|
||||
min-height: calc(100vh - 152px);
|
||||
min-height: calc(100vh - 118px);
|
||||
}
|
||||
|
||||
.overlay-shell-dense .overlay-logo {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.overlay-fastest-banner-dense {
|
||||
@@ -1027,13 +1027,13 @@ select:focus {
|
||||
}
|
||||
|
||||
.overlay-fastest-driver {
|
||||
font-size: 0.9rem;
|
||||
font-size: 0.76rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.overlay-fastest-meta {
|
||||
color: var(--muted);
|
||||
font-size: 0.66rem;
|
||||
font-size: 0.58rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
white-space: nowrap;
|
||||
@@ -1045,24 +1045,24 @@ select:focus {
|
||||
|
||||
.overlay-race-metric strong,
|
||||
.overlay-race-best strong {
|
||||
font-size: clamp(0.88rem, 1.15vw, 1.02rem);
|
||||
font-size: clamp(0.78rem, 0.98vw, 0.92rem);
|
||||
line-height: 1.05;
|
||||
}
|
||||
|
||||
.overlay-race-pos .pos-pill {
|
||||
min-width: 32px;
|
||||
height: 32px;
|
||||
font-size: 0.9rem;
|
||||
min-width: 26px;
|
||||
height: 26px;
|
||||
font-size: 0.76rem;
|
||||
}
|
||||
|
||||
.overlay-shell-dense .pill {
|
||||
padding: 4px 8px;
|
||||
font-size: 0.62rem;
|
||||
padding: 3px 6px;
|
||||
font-size: 0.54rem;
|
||||
}
|
||||
|
||||
.overlay-shell-dense .btn.overlay-fullscreen-btn {
|
||||
padding: 8px 10px;
|
||||
font-size: 0.72rem;
|
||||
padding: 6px 8px;
|
||||
font-size: 0.66rem;
|
||||
}
|
||||
|
||||
.overlay-section-head {
|
||||
@@ -1105,28 +1105,28 @@ select:focus {
|
||||
|
||||
.overlay-side {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
font-size: 0.84rem;
|
||||
gap: 6px;
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
.overlay-side-card {
|
||||
padding: 8px;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.overlay-rotating-card {
|
||||
min-height: 220px;
|
||||
min-height: 180px;
|
||||
}
|
||||
|
||||
.overlay-side-card h3 {
|
||||
margin: 0 0 4px;
|
||||
font-size: 0.86rem;
|
||||
margin: 0 0 3px;
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
.overlay-passing {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 6px;
|
||||
padding: 4px 0;
|
||||
gap: 5px;
|
||||
padding: 3px 0;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
@@ -1135,35 +1135,35 @@ select:focus {
|
||||
}
|
||||
|
||||
.overlay-side-card .overlay-passing strong {
|
||||
font-size: 0.8rem;
|
||||
font-size: 0.72rem;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.overlay-side-card .overlay-passing span {
|
||||
font-family: Orbitron, sans-serif;
|
||||
font-size: 0.72rem;
|
||||
font-size: 0.64rem;
|
||||
color: var(--text);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.overlay-side-card .pill {
|
||||
padding: 3px 7px;
|
||||
font-size: 0.58rem;
|
||||
font-size: 0.54rem;
|
||||
}
|
||||
|
||||
.overlay-race-list {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.overlay-race-row {
|
||||
display: grid;
|
||||
grid-template-columns: 48px minmax(200px, 1.55fr) repeat(3, minmax(102px, 0.7fr)) minmax(110px, 0.72fr);
|
||||
gap: 8px;
|
||||
grid-template-columns: 38px minmax(170px, 1.72fr) repeat(3, minmax(90px, 0.62fr)) minmax(95px, 0.66fr);
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
padding: 8px 10px;
|
||||
padding: 5px 7px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
border-radius: 10px;
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
@@ -1179,7 +1179,7 @@ select:focus {
|
||||
}
|
||||
|
||||
.overlay-race-driver strong {
|
||||
font-size: clamp(0.98rem, 1.35vw, 1.18rem);
|
||||
font-size: clamp(0.82rem, 1.04vw, 0.96rem);
|
||||
line-height: 1.05;
|
||||
}
|
||||
|
||||
@@ -1187,32 +1187,32 @@ select:focus {
|
||||
.overlay-race-metric label,
|
||||
.overlay-race-best label {
|
||||
color: var(--muted);
|
||||
font-size: 0.62rem;
|
||||
font-size: 0.54rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
}
|
||||
|
||||
.overlay-prediction {
|
||||
margin-top: 4px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.overlay-prediction-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
margin-bottom: 3px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.overlay-prediction-meta label,
|
||||
.overlay-prediction-meta span {
|
||||
color: var(--muted);
|
||||
font-size: 0.58rem;
|
||||
font-size: 0.5rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
}
|
||||
|
||||
.overlay-prediction-track {
|
||||
height: 3px;
|
||||
height: 2px;
|
||||
border-radius: 999px;
|
||||
overflow: hidden;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
|
||||
Reference in New Issue
Block a user