Skip to content

Commit 6a0fca1

Browse files
committed
leaderboard now works.
1 parent 7832d06 commit 6a0fca1

4 files changed

Lines changed: 156 additions & 103 deletions

File tree

index.html

Lines changed: 56 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,6 @@
112112
<div id="finalTime" class="score-value">0:00.00</div>
113113
<div id="missionPerformance" class="performance-rating">Calculating...</div>
114114
<div id="leaderboardSubmit" class="leaderboard-submit hidden">
115-
<!-- Shown when signed in -->
116-
<div class="submit-signed-in" style="display:none;">
117-
<div class="submit-row">
118-
<input type="text" id="playerNameInput" placeholder="Enter your name" maxlength="16"
119-
class="player-name-input" autocomplete="off" spellcheck="false">
120-
<button id="submitScoreBtn" class="btn-submit-score" onclick="submitScore()">
121-
<i class="iconoir-send"></i>
122-
</button>
123-
</div>
124-
</div>
125115
<!-- Shown when anonymous -->
126116
<div class="submit-anon">
127117
<button class="btn-sign-in-to-submit" onclick="openAuthModal()">
@@ -158,16 +148,6 @@
158148
<div id="victoryTime" class="score-value">5:00.00</div>
159149
<div id="victoryPerformance" class="performance-rating perfect">MAX SURVIVAL</div>
160150
<div id="victoryLeaderboardSubmit" class="leaderboard-submit hidden">
161-
<!-- Shown when signed in -->
162-
<div class="submit-signed-in" style="display:none;">
163-
<div class="submit-row">
164-
<input type="text" id="victoryPlayerNameInput" placeholder="Enter your name" maxlength="16"
165-
class="player-name-input" autocomplete="off" spellcheck="false">
166-
<button id="victorySubmitScoreBtn" class="btn-submit-score" onclick="submitScore()">
167-
<i class="iconoir-send"></i>
168-
</button>
169-
</div>
170-
</div>
171151
<!-- Shown when anonymous -->
172152
<div class="submit-anon">
173153
<button class="btn-sign-in-to-submit" onclick="openAuthModal()">
@@ -633,43 +613,37 @@ <h2 class="mobile-menu-title">REFLECTIONS</h2>
633613
}
634614

635615
// Score submission to Firebase leaderboard
616+
// Auto-submit score to leaderboard. Called when:
617+
// 1. Game over modal appears and user is signed in
618+
// 2. User signs in from auth modal while game over modal is showing
619+
window.submitScore = submitScore;
636620
async function submitScore() {
637-
if (!window.game || !window.leaderboardService || !window.firebaseAuth) {
638-
showToast('Leaderboard not available. Please refresh.');
639-
return;
640-
}
621+
if (!window.game || !window.leaderboardService || !window.firebaseAuth) return;
641622

642623
const auth = window.firebaseAuth;
643624
const service = window.leaderboardService;
644625
const game = window.game;
645626

646-
// Require sign-in — anonymous users must sign in first
647-
if (auth.isAnonymous()) {
648-
openAuthModal();
649-
return;
650-
}
627+
// Must be signed in and game must be over
628+
if (auth.isAnonymous() || !game.gameOver || game.gameTime <= 0) return;
651629

652-
// Get name from whichever modal is visible
653-
const nameInput = document.getElementById('playerNameInput');
654-
const victoryNameInput = document.getElementById('victoryPlayerNameInput');
655-
const activeInput = !document.getElementById('victoryModal').classList.contains('hidden')
656-
? victoryNameInput : nameInput;
657-
const statusEl = !document.getElementById('victoryModal').classList.contains('hidden')
630+
// Find the visible status element
631+
const isVictory = !document.getElementById('victoryModal').classList.contains('hidden');
632+
const statusEl = isVictory
658633
? document.getElementById('victoryScoreSubmitStatus')
659634
: document.getElementById('scoreSubmitStatus');
660635

661-
const name = (activeInput ? activeInput.value : '').trim();
662-
if (name) {
663-
auth.setDisplayName(name);
664-
}
665-
666-
// Disable buttons during submission
667-
const btns = document.querySelectorAll('.btn-submit-score');
668-
btns.forEach(b => b.disabled = true);
636+
// Don't re-submit if already submitted this game
637+
if (statusEl && statusEl.dataset.submitted === 'true') return;
669638

670639
try {
671-
statusEl.textContent = 'Submitting...';
672-
statusEl.style.color = 'var(--text-secondary)';
640+
if (statusEl) {
641+
statusEl.textContent = 'Submitting score...';
642+
statusEl.style.color = 'var(--text-secondary)';
643+
}
644+
645+
// Hide the sign-in prompt since we're signed in
646+
document.querySelectorAll('.submit-anon').forEach(el => el.style.display = 'none');
673647

674648
const mode = game.isDailyChallenge ? 'daily' : 'main';
675649
const DailyChallenge = (await import('./js/validation/DailyChallenge.js')).DailyChallenge;
@@ -686,56 +660,50 @@ <h2 class="mobile-menu-title">REFLECTIONS</h2>
686660
spawnerCount: game.spawners.length,
687661
});
688662

689-
if (result.isNewBest) {
690-
statusEl.textContent = 'New personal best!';
691-
statusEl.style.color = '#FFD700';
692-
693-
// Video upload for main game top 10
694-
if (mode === 'main' && window.videoUploader) {
695-
const isTop = await service.isTop10(game.gameTime);
696-
if (isTop) {
697-
const recorder = game.replayRecorder;
698-
let videoBlob = recorder.videoBlob;
699-
700-
// Generate MP4 if no video but canvas replay exists
701-
if (!videoBlob && recorder.canGenerateMP4()) {
702-
statusEl.textContent = 'Top 10! Generating replay...';
703-
await game.generateReplayMP4();
704-
videoBlob = recorder.videoBlob;
705-
}
706-
707-
if (videoBlob) {
708-
statusEl.textContent = 'Top 10! Uploading replay...';
709-
await window.videoUploader.uploadReplayVideo(
710-
videoBlob, game.gameTime, result.docId,
711-
(percent) => {
712-
statusEl.textContent = `Uploading replay... ${percent}%`;
713-
}
714-
);
715-
statusEl.textContent = 'Top 10! Replay uploaded!';
716-
} else {
717-
statusEl.textContent = 'Top 10! Score submitted!';
663+
if (statusEl) {
664+
statusEl.dataset.submitted = 'true';
665+
666+
if (result.isNewBest) {
667+
statusEl.textContent = 'Score submitted - new personal best!';
668+
statusEl.style.color = '#FFD700';
669+
670+
// Video upload for main game top 10
671+
if (mode === 'main' && window.videoUploader) {
672+
const isTop = await service.isTop10(game.gameTime);
673+
if (isTop) {
674+
const recorder = game.replayRecorder;
675+
let videoBlob = recorder.videoBlob;
676+
677+
if (!videoBlob && recorder.canGenerateMP4()) {
678+
statusEl.textContent = 'Top 10! Generating replay...';
679+
await game.generateReplayMP4();
680+
videoBlob = recorder.videoBlob;
681+
}
682+
683+
if (videoBlob) {
684+
statusEl.textContent = 'Top 10! Uploading replay...';
685+
await window.videoUploader.uploadReplayVideo(
686+
videoBlob, game.gameTime, result.docId,
687+
(percent) => {
688+
statusEl.textContent = `Uploading replay... ${percent}%`;
689+
}
690+
);
691+
statusEl.textContent = 'Top 10! Replay uploaded!';
692+
}
718693
}
719694
}
695+
} else {
696+
statusEl.textContent = 'Score submitted';
697+
statusEl.style.color = 'var(--text-secondary)';
720698
}
721-
} else {
722-
statusEl.textContent = 'Score submitted (not a new best)';
723-
statusEl.style.color = 'var(--text-secondary)';
724-
}
725-
726-
// Hide the input, show submitted state
727-
const submitContainer = activeInput.closest('.leaderboard-submit');
728-
if (submitContainer) {
729-
const submitRow = submitContainer.querySelector('.submit-row');
730-
if (submitRow) submitRow.style.display = 'none';
731699
}
732700

733701
} catch (error) {
734702
console.error('Score submission failed:', error);
735-
statusEl.textContent = 'Submission failed. Try again.';
736-
statusEl.style.color = '#E84E6A';
737-
} finally {
738-
btns.forEach(b => b.disabled = false);
703+
if (statusEl) {
704+
statusEl.textContent = 'Submission failed';
705+
statusEl.style.color = '#E84E6A';
706+
}
739707
}
740708
}
741709

js/classes/Game.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,9 +1653,16 @@ export class Game {
16531653
performanceElement.style.color = '#E84E6A';
16541654
}
16551655

1656+
// Reset submission state for new game
1657+
const gameOverStatus = document.getElementById('scoreSubmitStatus');
1658+
if (gameOverStatus) { gameOverStatus.dataset.submitted = ''; gameOverStatus.textContent = ''; }
1659+
16561660
// Show modal
16571661
document.getElementById('gameOverModal').classList.remove('hidden');
16581662

1663+
// Auto-submit score to leaderboard
1664+
if (typeof window.submitScore === 'function') window.submitScore();
1665+
16591666
// Update status (if element exists)
16601667
const statusEl = document.getElementById('status');
16611668
if (statusEl) {
@@ -1699,9 +1706,16 @@ export class Game {
16991706
// Update modal content
17001707
document.getElementById('victoryTime').textContent = finalTimeString;
17011708

1709+
// Reset submission state for new game
1710+
const victoryStatus = document.getElementById('victoryScoreSubmitStatus');
1711+
if (victoryStatus) { victoryStatus.dataset.submitted = ''; victoryStatus.textContent = ''; }
1712+
17021713
// Show modal
17031714
document.getElementById('victoryModal').classList.remove('hidden');
17041715

1716+
// Auto-submit score to leaderboard
1717+
if (typeof window.submitScore === 'function') window.submitScore();
1718+
17051719
// Update status (if element exists)
17061720
const statusEl = document.getElementById('status');
17071721
if (statusEl) {

js/main.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ async function initFirebaseServices(cacheBust) {
2929
// Update UI when auth state changes (e.g., after Google/email sign-in)
3030
auth.onAuthChange(() => {
3131
syncNameInputs();
32+
// Auto-submit score if game is over and user just signed in
33+
if (window.game && window.game.gameOver && !auth.isAnonymous()) {
34+
if (typeof window.submitScore === 'function') window.submitScore();
35+
}
3236
});
3337

3438
updateSubmitUI(auth);
@@ -37,12 +41,9 @@ async function initFirebaseServices(cacheBust) {
3741
document.querySelectorAll('.leaderboard-submit').forEach(el => el.classList.remove('hidden'));
3842
}
3943

40-
// Toggle between signed-in submit row and anonymous sign-in prompt
44+
// Toggle sign-in prompt visibility based on auth state
4145
function updateSubmitUI(auth) {
4246
const signedIn = auth.isSignedIn();
43-
document.querySelectorAll('.submit-signed-in').forEach(el => {
44-
el.style.display = signedIn ? '' : 'none';
45-
});
4647
document.querySelectorAll('.submit-anon').forEach(el => {
4748
el.style.display = signedIn ? 'none' : '';
4849
});

leaderboard.html

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,16 @@
3030
<link rel="stylesheet" href="styles/game.css">
3131
<style>
3232
html, body {
33-
overflow: auto;
34-
height: auto;
33+
overflow: auto !important;
34+
overflow-y: auto !important;
35+
height: auto !important;
36+
overscroll-behavior: auto !important;
37+
-webkit-user-select: auto !important;
38+
user-select: auto !important;
3539
}
3640
body {
3741
padding: 0;
42+
display: block !important;
3843
}
3944

4045
.leaderboard-container {
@@ -43,18 +48,73 @@
4348
padding: 20px 20px 60px 20px;
4449
}
4550

51+
.page-title-wrapper {
52+
display: flex;
53+
align-items: center;
54+
justify-content: center;
55+
gap: 20px;
56+
margin: 25px auto 20px auto;
57+
max-width: 700px;
58+
padding: 0 20px;
59+
box-sizing: border-box;
60+
}
61+
62+
.title-glow-line {
63+
flex: 1;
64+
height: 3px;
65+
border-radius: 3px;
66+
min-width: 40px;
67+
}
68+
69+
.title-glow-line.left {
70+
background: linear-gradient(to right, transparent 0%, #4E78E8 50%, #8338EC 100%);
71+
box-shadow: 0 0 12px rgba(78, 120, 232, 0.6), 0 0 4px rgba(131, 56, 236, 0.4);
72+
animation: pulseLineLeft 3s ease-in-out infinite;
73+
}
74+
75+
.title-glow-line.right {
76+
background: linear-gradient(to left, transparent 0%, #E87ADC 50%, #FF8FA3 100%);
77+
box-shadow: 0 0 12px rgba(232, 122, 220, 0.6), 0 0 4px rgba(255, 143, 163, 0.4);
78+
animation: pulseLineRight 3s ease-in-out infinite;
79+
}
80+
81+
@keyframes pulseLineLeft {
82+
0%, 100% {
83+
opacity: 0.6;
84+
box-shadow: 0 0 8px rgba(78, 120, 232, 0.4), 0 0 2px rgba(131, 56, 236, 0.3);
85+
}
86+
50% {
87+
opacity: 1;
88+
box-shadow: 0 0 20px rgba(78, 120, 232, 0.8), 0 0 6px rgba(131, 56, 236, 0.5);
89+
}
90+
}
91+
92+
@keyframes pulseLineRight {
93+
0%, 100% {
94+
opacity: 0.6;
95+
box-shadow: 0 0 8px rgba(232, 122, 220, 0.4), 0 0 2px rgba(255, 143, 163, 0.3);
96+
}
97+
50% {
98+
opacity: 1;
99+
box-shadow: 0 0 20px rgba(232, 122, 220, 0.8), 0 0 6px rgba(255, 143, 163, 0.5);
100+
}
101+
}
102+
46103
.page-title {
47104
font-family: 'Space Grotesk', sans-serif;
48105
font-size: 2.2rem;
49106
font-weight: 700;
50107
text-align: center;
51-
margin: 25px 0 20px 0;
52-
background: linear-gradient(135deg, var(--arc), var(--pink));
108+
margin: 0;
109+
padding: 0;
110+
background: linear-gradient(135deg, #4E78E8, #E87ADC);
53111
-webkit-background-clip: text;
54112
-webkit-text-fill-color: transparent;
55113
background-clip: text;
56114
letter-spacing: 3px;
57115
text-transform: uppercase;
116+
white-space: nowrap;
117+
flex-shrink: 0;
58118
}
59119

60120
/* Mode Tabs (Main Game vs Daily) */
@@ -623,7 +683,14 @@
623683
/* Mobile Responsive */
624684
@media (max-width: 600px) {
625685
.page-title {
626-
font-size: 1.8rem;
686+
font-size: 1.3rem;
687+
letter-spacing: 2px;
688+
}
689+
690+
.page-title-wrapper {
691+
gap: 12px;
692+
margin: 20px auto 16px auto;
693+
padding: 0 12px;
627694
}
628695

629696
.mode-tabs {
@@ -700,7 +767,10 @@
700767

701768
.page-title {
702769
font-size: 1.5rem;
703-
margin: 10px 0 15px 0;
770+
}
771+
772+
.page-title-wrapper {
773+
margin: 10px auto 15px auto;
704774
}
705775
}
706776
</style>
@@ -715,10 +785,6 @@
715785
</div>
716786

717787
<div class="navbar-center">
718-
<div class="navbar-timer">
719-
<i class="iconoir-trophy"></i>
720-
<span class="navbar-timer-value" style="min-width: auto;">TOP SCORES</span>
721-
</div>
722788
</div>
723789

724790
<div class="navbar-right">
@@ -731,7 +797,11 @@
731797
</div>
732798
</nav>
733799

734-
<h1 class="page-title"><i class="iconoir-trophy"></i> Leaderboard</h1>
800+
<div class="page-title-wrapper">
801+
<div class="title-glow-line left"></div>
802+
<div class="page-title">Global Leaderboard</div>
803+
<div class="title-glow-line right"></div>
804+
</div>
735805

736806
<div class="leaderboard-container">
737807
<!-- Auth Section -->

0 commit comments

Comments
 (0)