Skip to content

Input handler.ts rework#4225

Open
TKTK123456 wants to merge 27 commits into
openfrontio:mainfrom
TKTK123456:InputHandler.ts-Rework
Open

Input handler.ts rework#4225
TKTK123456 wants to merge 27 commits into
openfrontio:mainfrom
TKTK123456:InputHandler.ts-Rework

Conversation

@TKTK123456

@TKTK123456 TKTK123456 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Before opening a PR: discuss new features on Discord first, and file bugs or small improvements as issues. You must be assigned to an approved issue — unsolicited PRs will be auto-closed.

Add approved & assigned issue number here:

Resolves #4193

Description:

Use activeKeys set in places where it is checking if a key is being pressed in a different way, and it makes more sense to use the activeKeys set. Make the overall code of the InputHandler.ts file more consistent and to make it easier to add new keybinds in the future.

Screenshot from 2026-06-13 20-49-56

Please complete the following:

  • I have added screenshots for all UI updates
  • I process any text displayed to the user through translateText() and I've added it to the en.json file
  • I have added relevant tests to the test directory

Please put your Discord username so you can be contacted if a bug or regression is found:

tktk1234567

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c13fe732-026c-4654-bde3-3e41470a4a00

📥 Commits

Reviewing files that changed from the base of the PR and between 8913f16 and c063585.

📒 Files selected for processing (1)
  • src/client/InputHandler.ts
💤 Files with no reviewable changes (1)
  • src/client/InputHandler.ts

Walkthrough

InputHandler now uses a registry for keyboard shortcuts. It stores keybind handlers with conditions, matches keys with real or synthesized events, tracks Alt keys in activeKeys, runs handlers from the registry-based keydown flow, and exposes the Alt-key modifier as a user-configurable setting for graphics refresh.

Changes

Keyboard event data-driven refactoring and Alt-key configuration

Layer / File(s) Summary
Registry type and infrastructure
src/client/InputHandler.ts
Adds the keybind entry shape with handler and condition list, introduces a keybind-to-entry registry, generalizes key matching to accept either keyboard events or synthesized {code, shiftKey} objects, and provides a helper method for appending entries to the registry.
Key tracking and modifier detection
src/client/InputHandler.ts
Records Alt key presses in activeKeys by storing the configured Alt-code value (AltLeft or AltRight), removes the separate Alt-held helper function, and routes Alt-based action checks through registry-based condition predicates.
Build-key matching refinement
src/client/InputHandler.ts
Removes the strict build-key exact-match helper and updates build-key resolution to use the generalized matching function with synthesized events, leaving digit and Numpad alias matching as the remaining fallback logic.
Initialize: register all keybinds
src/client/InputHandler.ts
Registers shortcut handlers through the new registry helper, including repeat-gated actions for pause and game-speed, Alt-gated refresh graphics, forced toggleView state changes, and per-build-type ghost activation with condition gating.
Event dispatch via registry iteration
src/client/InputHandler.ts
Replaces the keydown dispatch chain with registry iteration, key matching against each entry, condition predicate evaluation, preventDefault calls, and handler execution when all predicates pass.
User settings and UI for Alt-key modifier
src/core/game/UserSettings.ts, src/client/UserSettingModal.ts, resources/lang/en.json
Adds a default altKey binding to AltLeft in user settings, includes a keybinds UI entry for the Alt modifier with label and description, handles keybind conflict detection by allowing the AltLeft swap between emojiMenuModifier and altKey, and provides translations for the graphics refresh modifier label and description.

Sequence Diagram(s)

sequenceDiagram
  participant Browser as Browser
  participant InputHandler as InputHandler.keydown
  participant Registry as keybindAndEvent Array
  participant Matcher as keybindMatchesEvent
  participant Active as activeKeys Set
  participant Handler as registered handler

  Browser->>InputHandler: keydown (KeyboardEvent)
  InputHandler->>Active: add configured Alt code when pressed
  InputHandler->>Registry: iterate entries
  Registry->>Matcher: match entry against event or synthesized object
  Matcher->>Active: consult activeKeys for modifier predicates
  InputHandler->>Registry: evaluate predicates, call preventDefault()
  Registry->>Handler: invoke handler when predicates pass
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • openfrontio/OpenFrontIO#4175: Both PRs modify InputHandler to rely on active key tracking and adjust build/emoji menu keybind handling using tracked keys instead of separate modifier helpers.

Suggested reviewers

  • evanpelle

Poem

Keys once tangled, now in rows aligned,
A map of binds, each handler signed.
Alt and Shift tracked, conditions meet,
Users choose—graphics refresh complete.
Input sings—clean logic, rhythm, and mind. 🎵

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning PR addresses the three stated objectives [#4193]: consolidating activeKeys usage, improving code consistency, and simplifying keybind addition. However, code review identified critical bugs that undermine achievement of these goals. Fix reported bugs before merge: restore multi-handler support per key (Map values should be arrays), restore bidirectional Digit↔Numpad aliasing, preserve Alt modifier remapping, remove debug logs, fix typos, and add unit tests covering dispatch, conditions, multi-action keys, and aliasing.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive Title is vague and generic, using only 'Input handler.ts rework' without clearly summarizing the main change or objective. Use a more descriptive title that conveys the core refactoring goal, such as 'Consolidate keybind detection using activeKeys set' or 'Refactor InputHandler to use unified keybind registry'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed Description is related to the changeset, explaining the refactoring intent to use activeKeys more consistently and improve code structure.
Out of Scope Changes check ✅ Passed All changes are scoped to InputHandler refactoring and related keybind UI/settings updates. No extraneous modifications detected beyond the refactoring objective.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/client/InputHandler.ts (1)

1-1: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Prettier formatting issues reported by CI.

Run npx prettier --write src/client/InputHandler.ts to fix the code style issues flagged by the pipeline.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/client/InputHandler.ts` at line 1, This file has Prettier style
violations; run the formatter and commit the changes by executing npx prettier
--write src/client/InputHandler.ts (or run the project's format script) to
update formatting for the InputHandler module; after formatting, verify that
imports like EventBus and GameEvent and any exported class/function in
InputHandler.ts still compile and then re-run CI.

Source: Pipeline failures

🧹 Nitpick comments (1)
src/client/InputHandler.ts (1)

929-941: ⚡ Quick win

Typo in JSDoc and consider a typed structure.

  1. Line 932: "exectued""executed"

  2. The array-based convention [action, ...conditions] works but requires knowing the index contract. A typed object would be clearer and catch misuse at compile time:

interface KeybindEntry {
  action: (e: KeyboardEvent) => void;
  conditions?: Array<(e: KeyboardEvent) => boolean>;
}
private keybindAndEvent = new Map<string, KeybindEntry>();

This makes the structure explicit and gives proper types for actions (void) vs conditions (boolean).

🔤 Minimal fix for typo
-   * `@param` event The code to be exectued when this keybind is pressed
+   * `@param` event The code to be executed when this keybind is pressed
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/client/InputHandler.ts` around lines 929 - 941, Fix the JSDoc typo
("exectued" → "executed") and replace the fragile array convention used by
keybindAndEvent with a typed object: define a KeybindEntry (with action: (e:
KeyboardEvent) => void and optional conditions: Array<(e: KeyboardEvent) =>
boolean>), change the Map type to Map<string, KeybindEntry>, and update
addKeybindAndEvent to accept an action and conditions with those explicit types
(use the symbol addKeybindAndEvent and keybindAndEvent to locate the code); also
update any code that reads from keybindAndEvent to use entry.action and
entry.conditions and adjust return/usage expectations accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/client/InputHandler.ts`:
- Around line 580-592: Rename the misspelled local variable
allConditionsFullfiled to allConditionsFulfilled in the loop inside the
InputHandler logic that iterates over this.keybindAndEvent (the block that uses
keybindMatchesEvent and item[1].slice(1)), updating every reference (assignment,
checks, and the continue branch) to the new name to keep readability consistent;
ensure the same corrected name is used throughout that function scope and no
other behavior changes are introduced.

---

Outside diff comments:
In `@src/client/InputHandler.ts`:
- Line 1: This file has Prettier style violations; run the formatter and commit
the changes by executing npx prettier --write src/client/InputHandler.ts (or run
the project's format script) to update formatting for the InputHandler module;
after formatting, verify that imports like EventBus and GameEvent and any
exported class/function in InputHandler.ts still compile and then re-run CI.

---

Nitpick comments:
In `@src/client/InputHandler.ts`:
- Around line 929-941: Fix the JSDoc typo ("exectued" → "executed") and replace
the fragile array convention used by keybindAndEvent with a typed object: define
a KeybindEntry (with action: (e: KeyboardEvent) => void and optional conditions:
Array<(e: KeyboardEvent) => boolean>), change the Map type to Map<string,
KeybindEntry>, and update addKeybindAndEvent to accept an action and conditions
with those explicit types (use the symbol addKeybindAndEvent and keybindAndEvent
to locate the code); also update any code that reads from keybindAndEvent to use
entry.action and entry.conditions and adjust return/usage expectations
accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 09de9720-a581-40ca-9829-091e215d1987

📥 Commits

Reviewing files that changed from the base of the PR and between 1db02ac and d6b9cd9.

📒 Files selected for processing (1)
  • src/client/InputHandler.ts

Comment thread src/client/InputHandler.ts Outdated
@github-project-automation github-project-automation Bot moved this from Triage to Development in OpenFront Release Management Jun 11, 2026
@TKTK123456

Copy link
Copy Markdown
Contributor Author

@coderabbitai help

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

CodeRabbit commands

These commands are invoked using PR/Issue comments.

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai rate limit to show your current review rate limit status.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai evaluate custom pre-merge check --instructions <custom-checks-instructions> --name <custom-checks-title> [--mode <error|warning>] to validate the custom pre-merge checks instructions. Defaults to error when --mode is omitted.
  • @coderabbitai ignore pre-merge checks to override pre-merge checks and get an approval on PR.
  • @coderabbitai run pre-merge checks to run pre-merge checks on the pull request.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai emit path instructions to emit generated path-specific review instructions for this repository.
  • @coderabbitai resolve merge conflict to automatically resolve merge conflicts.
  • @coderabbitai autofix to automatically fix issues identified in unresolved review comments.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai generate configuration to create a PR that adds the current resolved configuration as .coderabbit.yaml (or show it if already present).
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit configuration file (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, support, documentation and community

  • Visit our status page to check the current availability of CodeRabbit.
  • Create a ticket on our support page for assistance with any issues or questions.
  • Visit our documentation site for detailed information on how to use CodeRabbit.
  • Join our Discord community to connect with other users and get help from the community.
  • Follow us on X/Twitter for updates and announcements.

@TKTK123456

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/client/InputHandler.ts`:
- Around line 317-333: Prettier formatting errors are caused by the block that
defines and transforms buildKeybinds in InputHandler.ts; reformat this section
(variable buildKeybinds, the .map using this.keybinds, the push of numpad keys,
and the for-loop) to match the project's Prettier rules by running the formatter
(run `prettier --write src/client/InputHandler.ts`) or apply equivalent
formatting changes so the file passes CI.
- Around line 317-333: The build keybind registration only adds Numpad0..Numpad9
extras so pressing Digit1 when the keybind is set to Numpad1 bypasses the
fallback; update the registration logic in InputHandler (the buildKeybinds array
mapping and the subsequent push of extras) to also include the Digit0..Digit9
counterparts for each Numpad key (or add a small helper that, for any "NumpadX"
adds both "NumpadX" and "DigitX") so resolveBuildKeybind() will be reached on
both Numpad and Digit keyups; apply the same dual-registration change to the
analogous block around lines 335-347 to cover all build-related keybinds.
- Around line 299-301: Remove the debug console.log calls from the input hot
paths: delete the console.log("TogglePerformanceOverlayEvent") inside the
addKeybindAndEvent handler that emits TogglePerformanceOverlayEvent (and any
other console.log added in the same file during init, e.g., the one around line
334-335). Locate the usages of addKeybindAndEvent and the init/startup code in
InputHandler (search for the string "TogglePerformanceOverlayEvent" and
"console.log") and simply remove the console.log statements so the handler only
calls this.eventBus.emit(new TogglePerformanceOverlayEvent()) and initialization
code has no noisy logs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d0ddfca9-2f39-45ab-94f4-fd62e41f7d9b

📥 Commits

Reviewing files that changed from the base of the PR and between 1db02ac and d8e52eb.

📒 Files selected for processing (1)
  • src/client/InputHandler.ts

Comment thread src/client/InputHandler.ts
Comment thread src/client/InputHandler.ts
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 12, 2026
@TKTK123456

Copy link
Copy Markdown
Contributor Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Reviews resumed.

@TKTK123456

TKTK123456 commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

NVM

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/client/InputHandler.ts (1)

976-986: ⚡ Quick win

Tighten callback types to match KeybindEntry interface.

The event parameter returns any but the interface expects void. The conditions return any but should return boolean. This weakens type checking and can hide bugs.

♻️ Proposed fix
   private addKeybindAndEvent(
     keybind: string,
-    event: (type: KeyboardEvent) => any,
-    ...conditions: ((type: KeyboardEvent) => any)[]
+    event: (type: KeyboardEvent) => void,
+    ...conditions: ((type: KeyboardEvent) => boolean)[]
   ) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/client/InputHandler.ts` around lines 976 - 986, Tighten the callback
signatures in InputHandler.addKeybindAndEvent so they match KeybindEntry: change
the event handler type to return void and the conditions callbacks to return
boolean. Update the addKeybindAndEvent parameter types and the KeybindEntry
assignment in InputHandler to preserve type safety without altering the push
logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/client/InputHandler.ts`:
- Line 230: The `keybindAndEvent` field in the InputHandler class is declared
but never initialized, causing it to be undefined when `addKeybindAndEvent()`
attempts to push entries to it. Additionally, the type annotation `[[string,
KeybindEntry]]` incorrectly represents a fixed-size tuple with one element
rather than a growable array. Initialize the `keybindAndEvent` field with an
empty array at the point of declaration, and correct the type annotation to
properly represent an array of tuples by using `[string, KeybindEntry][]`
instead.
- Around line 365-367: In the buildKeybinds filter operation, replace the loose
equality operator with strict equality. Change the comparison `v != null` to use
`v !== null` in the type guard predicate to comply with the project's strict
equality enforcement rule.

---

Nitpick comments:
In `@src/client/InputHandler.ts`:
- Around line 976-986: Tighten the callback signatures in
InputHandler.addKeybindAndEvent so they match KeybindEntry: change the event
handler type to return void and the conditions callbacks to return boolean.
Update the addKeybindAndEvent parameter types and the KeybindEntry assignment in
InputHandler to preserve type safety without altering the push logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3c4e6e10-ae82-4f71-9031-5e9aad74de9d

📥 Commits

Reviewing files that changed from the base of the PR and between 88e9d36 and d6ca322.

📒 Files selected for processing (1)
  • src/client/InputHandler.ts

Comment thread src/client/InputHandler.ts Outdated
Comment thread src/client/InputHandler.ts
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 13, 2026
@TKTK123456

Copy link
Copy Markdown
Contributor Author

@Celant also how should I keep the remap support for altKey?

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 14, 2026
@TKTK123456

Copy link
Copy Markdown
Contributor Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Reviews resumed.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 14, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 14, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 14, 2026
@iiamlewis

Copy link
Copy Markdown
Contributor

@TKTK123456 (via Discord):

I do want this to be implemented by v32 or early v33

@iiamlewis

Copy link
Copy Markdown
Contributor

@TKTK123456 (via Discord):

And think it should be

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Development

Development

Successfully merging this pull request may close these issues.

InputHandler.ts rework

4 participants