Skip to content

Conversation

@deepfates
Copy link
Owner

Summary

  • track pressed keys inside useKeyboardControls to repeat held inputs and surface simultaneous key combinations to the interface logic
  • switch the gamepad and menu buttons to pointer-driven press handlers so touch inputs can be held, multi-touched, and avoid accidental context menus
  • extend the interface control handler to recognize a SELECT+ENTER combo, closing menus before running the Enter action so multi-button inputs can diverge from single presses

Testing

  • npm run lint (fails: ESLint configuration file is missing in the project)

https://chatgpt.com/codex/tasks/task_e_68cf1709948083278a204de2532d9a4d

Copy link
Contributor

Copilot AI left a 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 enables holdable onscreen controls with support for key combinations and improved touch handling for a gamepad-style interface. The changes enhance the user experience by allowing keys to be held for repeated actions and supporting multi-button combinations like SELECT+ENTER.

  • Enhanced keyboard controls to track pressed keys and support key combinations with repeating behavior
  • Converted mouse-based button interactions to pointer events for better touch device support
  • Added combo key handling in the interface logic, specifically SELECT+ENTER for menu navigation

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
client/interface/types/index.ts Updated interface props from mouse events to generic press events
client/interface/hooks/useKeyboardControls.ts Complete rewrite to track pressed keys, handle repeating, and support combinations
client/interface/components/MenuButton.tsx Converted from mouse to pointer events with proper touch handling
client/interface/components/GamepadButton.tsx Converted from mouse to pointer events with proper touch handling
client/interface/components/DPad.tsx Updated prop names to match new interface
client/interface/Interface.tsx Modified action handler to process key combinations and multiple keys

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 99 to 102
void triggerAction();
repeatIntervalRef.current = window.setInterval(() => {
void triggerAction();
}, REPEAT_INTERVAL);
Copy link

Copilot AI Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The repeat mechanism triggers actions without checking if keys are still pressed. If keys are released during the timeout/interval, actions will continue firing. Consider checking pressedKeysRef.current.length > 0 before calling triggerAction().

Suggested change
void triggerAction();
repeatIntervalRef.current = window.setInterval(() => {
void triggerAction();
}, REPEAT_INTERVAL);
if (pressedKeysRef.current.length > 0) {
void triggerAction();
repeatIntervalRef.current = window.setInterval(() => {
if (pressedKeysRef.current.length > 0) {
void triggerAction();
} else {
stopRepeat();
}
}, REPEAT_INTERVAL);
} else {
stopRepeat();
}

Copilot uses AI. Check for mistakes.
isPressedRef.current = false;

if (event.currentTarget.hasPointerCapture?.(event.pointerId)) {
event.currentTarget.releasePointerCapture(event.pointerId);
Copy link

Copilot AI Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using optional chaining on hasPointerCapture but calling releasePointerCapture unconditionally. If hasPointerCapture doesn't exist, releasePointerCapture will also likely not exist and will throw an error. Wrap the releasePointerCapture call in a try-catch or check for its existence.

Suggested change
event.currentTarget.releasePointerCapture(event.pointerId);
if (event.currentTarget.releasePointerCapture) {
event.currentTarget.releasePointerCapture(event.pointerId);
}

Copilot uses AI. Check for mistakes.
isPressedRef.current = false;

if (event.currentTarget.hasPointerCapture?.(event.pointerId)) {
event.currentTarget.releasePointerCapture(event.pointerId);
Copy link

Copilot AI Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using optional chaining on hasPointerCapture but calling releasePointerCapture unconditionally. If hasPointerCapture doesn't exist, releasePointerCapture will also likely not exist and will throw an error. Wrap the releasePointerCapture call in a try-catch or check for its existence.

Suggested change
event.currentTarget.releasePointerCapture(event.pointerId);
if (event.currentTarget.releasePointerCapture) {
event.currentTarget.releasePointerCapture(event.pointerId);
}

Copilot uses AI. Check for mistakes.
Comment on lines 186 to 188
const comboKey = Array.from(keySet).sort().join("+");
switch (comboKey) {
case "Enter+`":
Copy link

Copilot AI Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The combo key generation uses string concatenation which could lead to ambiguous combinations. For example, keys 'A+B' and 'AB' would be indistinguishable. Consider using a more robust delimiter or key format to avoid potential conflicts.

Suggested change
const comboKey = Array.from(keySet).sort().join("+");
switch (comboKey) {
case "Enter+`":
const comboKey = JSON.stringify(Array.from(keySet).sort());
switch (comboKey) {
case JSON.stringify(["Enter", "`"].sort()):

Copilot uses AI. Check for mistakes.
@deepfates deepfates requested a review from Copilot September 20, 2025 22:32
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

if (pressedKeysRef.current.length === 0) {
return;
}
pressedKeysRef.current.length = 0;
Copy link

Copilot AI Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Setting array length to 0 is less explicit than using pressedKeysRef.current = [] or pressedKeysRef.current.splice(0). Consider using a more conventional array clearing method for better code clarity.

Copilot uses AI. Check for mistakes.
window.removeEventListener("keyup", handleKeyUp);
window.removeEventListener("blur", handleBlur);
stopRepeat();
pressedKeysRef.current.length = 0;
Copy link

Copilot AI Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Setting array length to 0 is less explicit than using pressedKeysRef.current = [] or pressedKeysRef.current.splice(0). Consider using a more conventional array clearing method for better code clarity.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants