-
Notifications
You must be signed in to change notification settings - Fork 0
Enhance Race Readiness UX and Typing Error Signaling (Miscellaneous Polishing) #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR enhances the race readiness UX for public lobbies and improves error signaling during typing. The changes add visual indicators to show minimum player count requirements, track typing errors in real-time for spectators, and provide better visual feedback through styled error banners and progress bars.
Key Changes
- Added lobby status pill showing player readiness counts and minimum player requirements for public races
- Introduced inline typing error banner with improved styling and error propagation from client through server to all race participants
- Enhanced player progress bars with error indicators and contextual ready button states
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| server/controllers/socket-handlers.js | Added hasError field to race progress tracking and broadcast to enable error state visibility for spectators |
| client/src/context/RaceContext.jsx | Updated to emit hasError status and map it to hasMistake property for player state |
| client/src/pages/Race.jsx | Added minimum player logic, readiness calculations, and removed unused useRef import |
| client/src/components/Typing.jsx | Moved error message to new typing-error-banner component positioned below snippet display |
| client/src/components/Typing.css | Added styling for typing-error-banner with animation and added padding-bottom to typing-area |
| client/src/components/PlayerStatusBar.jsx | Implemented pill state management for lobby status display and error indicators on progress bars |
| client/src/components/PlayerStatusBar.css | Added extensive styling for status pill, error indicators, and enhanced progress bar states |
| .env.example | Updated SMTP_OAUTH_CACHE with realistic JSON template structure |
Comments suppressed due to low confidence (18)
client/src/components/Typing.jsx:45
- Unused variable updateProgress.
const { raceState, setRaceState, typingState, setTypingState, updateProgress, handleInput: raceHandleInput, loadNewSnippet } = useRace();
client/src/components/Typing.jsx:51
- Unused variable lastTabPress.
const [lastTabPress, setLastTabPress] = useState(0);
client/src/components/Typing.jsx:51
- Unused variable setLastTabPress.
const [lastTabPress, setLastTabPress] = useState(0);
client/src/components/Typing.jsx:58
- Unused variable tabActionInProgressRef.
const tabActionInProgressRef = useRef(false);
client/src/context/RaceContext.jsx:570
- Unused variable currentMode.
const currentMode = modeOverride || testMode;
client/src/context/RaceContext.jsx:571
- Unused variable currentDuration.
const currentDuration = durationOverride || testDuration;
client/src/context/RaceContext.jsx:657
- Unused variable isTimedMode.
const isTimedMode = !!(raceState.snippet?.is_timed_test || raceState.timedTest?.enabled || raceState.settings?.testMode === 'timed');
client/src/pages/Race.jsx:23
- Unused variable typingState.
typingState,
client/src/context/RaceContext.jsx:784
- Unused variable wordStart.
let wordStart = 0;
client/src/context/RaceContext.jsx:845
- Unused variable isMultiplayer.
const isMultiplayer = raceState.type !== 'practice';
server/controllers/socket-handlers.js:10
- Unused variable analytics.
const analytics = require('../utils/analytics');
server/controllers/socket-handlers.js:1731
- Unused variable timers.
for (const [key, timers] of inactivityTimers.entries()) {
server/controllers/socket-handlers.js:1836
- Unused variable startPracticeCountdown.
const startPracticeCountdown = async (io, code) => {
server/controllers/socket-handlers.js:186
- The value assigned to newHostAssigned here is unused.
newHostAssigned = true;
server/controllers/socket-handlers.js:1757
- The value assigned to isTimed here is unused.
isTimed = true;
client/src/components/Typing.jsx:733
- Avoid automated semicolon insertion (98% of all statements in the enclosing function have an explicit semicolon).
}
client/src/components/Typing.jsx:591
- This use of variable 'interval' always evaluates to false.
if (interval) clearInterval(interval);
server/controllers/socket-handlers.js:1731
- For loop variable timers is not used in the loop body.
for (const [key, timers] of inactivityTimers.entries()) {
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 0%, 100% { opacity: 0.9; transform: translate(-50%, 10%) scale(1); } | ||
| 50% { opacity: 1; transform: translate(-50%, 10%) scale(1.05); } |
Copilot
AI
Nov 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The animation transform values are inconsistent with the base style. The base .typing-error-banner uses transform: translate(-50%, 100%) to position the banner below the snippet, but the bannerPulse animation uses translate(-50%, 10%) which would cause the banner to jump to a different position during animation. The animation should maintain the same Y-axis translation as the base transform.
Suggested fix:
@keyframes bannerPulse {
0%, 100% { opacity: 0.9; transform: translate(-50%, 100%) scale(1); }
50% { opacity: 1; transform: translate(-50%, 100%) scale(1.05); }
}| 0%, 100% { opacity: 0.9; transform: translate(-50%, 10%) scale(1); } | |
| 50% { opacity: 1; transform: translate(-50%, 10%) scale(1.05); } | |
| 0%, 100% { opacity: 0.9; transform: translate(-50%, 100%) scale(1); } | |
| 50% { opacity: 1; transform: translate(-50%, 100%) scale(1.05); } |
| AZURE_CLIENT_ID= | ||
| SMTP_SENDER=[email protected] | ||
| SMTP_OAUTH_CACHE= (optional; JSON blob of MSAL cache for headless servers) | ||
| SMTP_OAUTH_CACHE= {"Account":{},"IdToken":{},"AccessToken":{},"RefreshToken":{},"AppMetadata":{}} |
Copilot
AI
Nov 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a space after the equals sign before the JSON value. While this may work in some environments, it could cause parsing issues as the leading space might be included in the environment variable value. Consider removing the space for consistency with other JSON-valued environment variables, or ensure the consuming code trims whitespace.
Suggested fix:
SMTP_OAUTH_CACHE={"Account":{},"IdToken":{},"AccessToken":{},"RefreshToken":{},"AppMetadata":{}}
| SMTP_OAUTH_CACHE= {"Account":{},"IdToken":{},"AccessToken":{},"RefreshToken":{},"AppMetadata":{}} | |
| SMTP_OAUTH_CACHE={"Account":{},"IdToken":{},"AccessToken":{},"RefreshToken":{},"AppMetadata":{}} |
| @@ -1,4 +1,4 @@ | |||
| import { useState, useEffect, useRef } from 'react'; | |||
| import { useState, useEffect } from 'react'; | |||
| import { Link, useNavigate } from 'react-router-dom'; | |||
Copilot
AI
Nov 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import Link.
| import { Link, useNavigate } from 'react-router-dom'; | |
| import { useNavigate } from 'react-router-dom'; |
|
|
||
| function Race() { | ||
| const navigate = useNavigate(); | ||
| const { socket } = useSocket(); |
Copilot
AI
Nov 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused variable socket.
| const { socket } = useSocket(); |
fixing login/logout redirects; adding unit tests [ALL UNIT-TEST RELATED FILES/CODE IS AI-GENERATED]
Summary
Added public race UX elements to show minimum player count; fixed player progress bar tracking bugs; changed mistake popup styling
Implementation Notes
badges plus richer styling
SMTP_OAUTH_CACHE JSON template