From 9f4d000c398222fb49605509df2103e75144bc2e Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Fri, 6 Mar 2026 18:57:50 +0000 Subject: [PATCH] alpha-base3_pass2 --- assets/js/main.js | 79 ++++++++++++++++++++++++++++++++++++++++++----- index.php | 3 +- 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/assets/js/main.js b/assets/js/main.js index 45bb0c7..e1e75b2 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -27,6 +27,9 @@ const app = { // Relay State currentParticipant: 1, participantNames: [], + relayParticipantStartTime: 0, + relayParticipantElapsed: 0, + relayColors: ['#3b82f6', '#10b981', '#ef4444', '#f59e0b', '#8b5cf6', '#ec4899', '#06b6d4', '#f97316', '#14b8a6', '#6366f1', '#a855f7', '#d946ef'], // Custom State customActivities: [ @@ -63,6 +66,7 @@ const app = { landingClock: document.getElementById('landing-clock'), mainTimer: document.getElementById('main-timer'), subTimer: document.getElementById('sub-timer'), + relayParticipantTimer: document.getElementById('relay-participant-timer'), viewLanding: document.getElementById('view-landing'), viewTimer: document.getElementById('view-timer'), timerTitle: document.getElementById('timer-title'), @@ -135,6 +139,7 @@ const app = { init() { console.log('Timer App Initializing...'); this.initDarkMode(); + this.shuffleRelayColors(); this.updateLandingClock(); this.bindEvents(); this.renderCustomBuilder(); @@ -143,6 +148,13 @@ const app = { this.bindKeyboardShortcuts(); }, + shuffleRelayColors() { + for (let i = this.relayColors.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [this.relayColors[i], this.relayColors[j]] = [this.relayColors[j], this.relayColors[i]]; + } + }, + bindKeyboardShortcuts() { document.addEventListener('keydown', (e) => { if (this.currentView !== 'timer' || !this.currentMode) return; @@ -155,10 +167,18 @@ const app = { if (e.key === ' ' || e.code === 'Space') { e.preventDefault(); - if (!this.isRunning || this.isPaused) { - this.handleStartClick(); + if (this.currentMode === 'lap') { + if (!this.isRunning || this.isPaused) { + this.handleStartClick(); + } else { + this.recordLap(); + } } else { - this.pauseTimer(); + if (!this.isRunning || this.isPaused) { + this.handleStartClick(); + } else { + this.pauseTimer(); + } } } else if (e.key === 'Escape' || e.code === 'Escape') { e.preventDefault(); @@ -232,7 +252,15 @@ const app = { } }); - this.el.toggleDisplayMode.addEventListener('change', () => this.updateDisplay()); + this.el.toggleDisplayMode.addEventListener('change', () => { + const label = this.el.displayModeContainer.querySelector('label'); + if (this.el.toggleDisplayMode.checked) { + label.textContent = 'Activity Progress'; + } else { + label.textContent = 'Timer Progress'; + } + this.updateDisplay(); + }); }, updateLandingClock() { @@ -286,6 +314,10 @@ const app = { this.el.savedTimersContainer.classList.remove('d-none'); this.el.relayConfig.classList.add('d-none'); this.el.displayModeContainer.classList.remove('d-none'); + + // Set initial label based on toggle state + const label = this.el.displayModeContainer.querySelector('label'); + label.textContent = this.el.toggleDisplayMode.checked ? 'Activity Progress' : 'Timer Progress'; } else if (mode.hasRelay) { this.el.customBuilder.classList.add('d-none'); this.el.relayConfig.classList.remove('d-none'); @@ -310,6 +342,7 @@ const app = { this.el.restAlertContainer.classList.toggle('d-none', !mode.isCustom); this.el.activeActivityName.classList.add('d-none'); this.el.relayActiveParticipantContainer.classList.add('d-none'); + this.el.relayParticipantTimer.classList.add('d-none'); // Options Dropdown visibility logic this.el.optionsDropdown.classList.toggle('d-none', modeKey === 'time-watch'); @@ -367,9 +400,8 @@ const app = { this.el.participantCount.value = count; let html = ''; - const colors = ['#3b82f6', '#10b981', '#ef4444', '#f59e0b', '#8b5cf6', '#ec4899', '#06b6d4', '#f97316', '#14b8a6', '#6366f1', '#a855f7', '#d946ef']; for (let i = 1; i <= count; i++) { - const defaultColor = colors[(i - 1) % colors.length]; + const defaultColor = this.relayColors[(i - 1) % this.relayColors.length]; html += `
#${i} @@ -482,13 +514,23 @@ const app = { this.el.relayActiveParticipantContainer.classList.remove('d-none'); this.el.relayParticipantCountBox.classList.add('d-none'); this.updateRelayActiveDisplay(); + this.relayParticipantStartTime = now; + this.relayParticipantElapsed = 0; + this.el.relayParticipantTimer.classList.add('d-none'); } if (this.isPaused) { const offset = (isCountdownMode) ? (this.countdownStartValue - this.elapsedTime) : this.elapsedTime; this.startTime = now - offset; + + if (mode.hasRelay) { + this.relayParticipantStartTime = now - this.relayParticipantElapsed; + } } else { this.startTime = now; + if (mode.hasRelay) { + this.relayParticipantStartTime = now; + } } this.isRunning = true; @@ -520,6 +562,9 @@ const app = { pauseTimer() { if (!this.isRunning || this.isPaused) return; + + const mode = this.modes[this.currentMode]; + if (mode && !mode.allowPause) return; this.isPaused = true; this.pausedTime = this.elapsedTime; @@ -551,6 +596,7 @@ const app = { this.el.btnReset.disabled = false; this.el.mainTimer.classList.remove('timer-alert'); this.el.relayActiveParticipantContainer.classList.add('d-none'); + this.el.relayParticipantTimer.classList.add('d-none'); if (this.currentMode === 'countdown') { this.el.countdownInputs.classList.remove('d-none'); @@ -584,6 +630,8 @@ const app = { this.currentParticipant = 1; this.currentActivityIndex = 0; this.lastPlayedSecond = -1; + this.relayParticipantStartTime = 0; + this.relayParticipantElapsed = 0; this.el.listBody.innerHTML = ''; this.el.mainTimer.classList.remove('timer-finish'); @@ -598,6 +646,7 @@ const app = { this.el.btnRelaySplit.disabled = false; this.el.activeActivityName.classList.add('d-none'); this.el.relayActiveParticipantContainer.classList.add('d-none'); + this.el.relayParticipantTimer.classList.add('d-none'); this.el.relayParticipantCountBox.classList.remove('d-none'); this.el.sessionTitle.disabled = false; @@ -697,6 +746,10 @@ const app = { } else { // Standard count up this.elapsedTime = now - this.startTime; + + if (mode.hasRelay) { + this.relayParticipantElapsed = now - this.relayParticipantStartTime; + } } this.updateDisplay(); @@ -782,6 +835,10 @@ const app = { this.el.mainTimer.textContent = this.formatTime(ms, format); } this.el.subTimer.classList.add('d-none'); + + if (this.currentMode === 'relay' && !this.el.relayParticipantTimer.classList.contains('d-none')) { + this.el.relayParticipantTimer.textContent = this.formatTime(this.relayParticipantElapsed, 'hh:mm:ss.ms'); + } }, getTotalProgress() { @@ -854,6 +911,7 @@ const app = { const maxParticipants = parseInt(this.el.participantCount.value) || 1; if (this.currentParticipant > maxParticipants) { this.el.relayActiveParticipantContainer.classList.add('d-none'); + this.el.relayParticipantTimer.classList.add('d-none'); return; } @@ -882,6 +940,11 @@ const app = { const colorInput = document.querySelector(`.participant-color-input[data-index="${this.currentParticipant}"]`); const color = colorInput ? colorInput.value : '#3b82f6'; + // Show secondary timer after first split + if (this.history.length >= 0) { + this.el.relayParticipantTimer.classList.remove('d-none'); + } + // If it's the last participant, mark as final but keep their name if (this.currentParticipant === maxParticipants) { isFinal = true; @@ -901,6 +964,8 @@ const app = { if (!isFinal) { this.currentParticipant++; this.updateRelayActiveDisplay(); + this.relayParticipantStartTime = performance.now(); + this.relayParticipantElapsed = 0; } else { this.stopTimer(); this.el.btnRelaySplit.disabled = true; @@ -1283,4 +1348,4 @@ const app = { }; // Start the app -document.addEventListener('DOMContentLoaded', () => app.init()); \ No newline at end of file +document.addEventListener('DOMContentLoaded', () => app.init()); diff --git a/index.php b/index.php index 236aba3..a746724 100644 --- a/index.php +++ b/index.php @@ -293,13 +293,14 @@ $projectImage = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
00:00:00
+
00:00:00.00
00:00:00
- +