From 41d6d458f796cacab4589c999f0ecb2dab3ff669 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2026 04:22:25 +0000 Subject: [PATCH] feat: persist player name in localStorage for auto-fill on subsequent games - Add PLAYER_NAME_STORAGE_KEY ('teeter_player_name') following existing convention - Save player name to localStorage on score submission - Pre-fill name input with saved name on qualifying game-over screens - Select pre-filled text for easy replacement - First-time players still see empty input field - Applied to both js/main.js and public/js/main.js Co-Authored-By: bot_apk --- js/main.js | 20 +++++++++++++++++++- public/js/main.js | 20 +++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/js/main.js b/js/main.js index dec5dc1..23a5a2b 100644 --- a/js/main.js +++ b/js/main.js @@ -42,6 +42,7 @@ const levelEl = document.getElementById('level'); const timerEl = document.getElementById('timer'); const STORAGE_KEY = 'teeter_highscores'; +const PLAYER_NAME_STORAGE_KEY = 'teeter_player_name'; const MAX_SCORES = 10; const NON_QUALIFYING_DELAY = 2000; const CHUNK_LENGTH = 20; @@ -140,6 +141,18 @@ function renderLeaderboard() { function showLeaderboard() { renderLeaderboard(); leaderboardPanel.classList.add('visible'); } function hideLeaderboard() { leaderboardPanel.classList.remove('visible'); } +// --- Player name persistence --- + +function loadPlayerName() { + try { + return localStorage.getItem(PLAYER_NAME_STORAGE_KEY) || ''; + } catch { return ''; } +} + +function savePlayerName(name) { + try { localStorage.setItem(PLAYER_NAME_STORAGE_KEY, name); } catch {} +} + // --- Game over flow --- function enterGameOver() { @@ -152,8 +165,12 @@ function enterGameOver() { if (scoreQualifies(finalScore)) { gameoverMessage.textContent = 'New high score!'; nameEntry.classList.add('visible'); - nameInput.value = ''; + const savedName = loadPlayerName(); + nameInput.value = savedName; nameInput.focus(); + if (savedName) { + nameInput.select(); + } } else { gameoverMessage.textContent = ''; nameEntry.classList.remove('visible'); @@ -168,6 +185,7 @@ function enterGameOver() { function submitScore() { let name = nameInput.value.trim(); if (!name) name = 'Anonymous'; + savePlayerName(name); addScore(name, finalScore); exitGameOver(); } diff --git a/public/js/main.js b/public/js/main.js index a6a9882..12b9971 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -52,6 +52,7 @@ const sensitivityReset = document.getElementById('sensitivity-reset'); const INIT_TIMEOUT_MS = 15000; const SENSITIVITY_STORAGE_KEY = 'teeter_sensitivity'; +const PLAYER_NAME_STORAGE_KEY = 'teeter_player_name'; const MAX_SCORES = 10; const NON_QUALIFYING_DELAY = 2000; const CHUNK_LENGTH = 20; @@ -136,6 +137,18 @@ function saveSensitivity(val) { try { localStorage.setItem(SENSITIVITY_STORAGE_KEY, String(val)); } catch {} } +// --- Player name persistence --- + +function loadPlayerName() { + try { + return localStorage.getItem(PLAYER_NAME_STORAGE_KEY) || ''; + } catch { return ''; } +} + +function savePlayerName(name) { + try { localStorage.setItem(PLAYER_NAME_STORAGE_KEY, name); } catch {} +} + function showSettings() { settingsPanel.classList.add('visible'); } function hideSettings() { settingsPanel.classList.remove('visible'); } @@ -294,8 +307,12 @@ async function enterGameOver() { if (qualifies) { gameoverMessage.textContent = 'New high score!'; nameEntry.classList.add('visible'); - nameInput.value = ''; + const savedName = loadPlayerName(); + nameInput.value = savedName; nameInput.focus(); + if (savedName) { + nameInput.select(); + } } else { gameoverMessage.textContent = ''; nameEntry.classList.remove('visible'); @@ -306,6 +323,7 @@ async function enterGameOver() { async function submitScore() { let name = nameInput.value.trim(); if (!name) name = 'Anonymous'; + savePlayerName(name); nameSubmit.disabled = true; nameSubmit.textContent = 'Submitting...'; const result = await addScore(name, finalScore);