make existing keybinds configurable (#2881)

## Description:

This PR makes several existing keybinds configurable that were
previously fixed and could not be changed in the keybind settings.

This is one of the required PRs to fully remove all keybind explanations
from the HelpModal.

This work is based on the following feedback by @ryanbarlow97:
> "This probably needs to be redone / removed from help, and just have a
section saying how to get to the keybinds modal inside settings"
>
https://github.com/openfrontio/OpenFrontIO/pull/2872#issuecomment-3740006017

Some keybinds described in the HelpModal already existed internally, but
users had no way to change them.
By making these keybinds configurable, we can now safely replace those
explanations with a simple reference to the keybind settings instead.

This helps:
- Remove keybind explanations from the HelpModal

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

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

aotumuri

Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
This commit is contained in:
Aotumuri
2026-01-13 19:35:38 +09:00
committed by GitHub
parent a40f5b7b8d
commit ed3c7b1a22
4 changed files with 105 additions and 10 deletions
+7
View File
@@ -485,6 +485,11 @@
"build_hydrogen_bomb_desc": "Build a Hydrogen Bomb under your cursor.",
"build_mirv": "Build MIRV",
"build_mirv_desc": "Build a MIRV under your cursor.",
"menu_shortcuts": "Menu Shortcuts",
"build_menu_modifier": "Build Menu Modifier",
"build_menu_modifier_desc": "Hold this key while clicking to open the build menu.",
"emoji_menu_modifier": "Emoji Menu Modifier",
"emoji_menu_modifier_desc": "Hold this key while clicking to open the emoji menu.",
"attack_ratio_controls": "Attack Ratio Controls",
"attack_ratio_up": "Increase Attack Ratio",
"attack_ratio_up_desc": "Increase attack ratio by 10%",
@@ -495,6 +500,8 @@
"boat_attack_desc": "Send a boat attack to the tile under your cursor.",
"ground_attack": "Ground Attack",
"ground_attack_desc": "Send a ground attack to the tile under your cursor.",
"swap_direction": "Swap Rocket Direction",
"swap_direction_desc": "Toggle rocket launch direction (up/down).",
"zoom_controls": "Zoom Controls",
"zoom_out": "Zoom Out",
"zoom_out_desc": "Zoom out the map",
+2 -1
View File
@@ -50,6 +50,7 @@ export class HelpModal extends BaseModal {
zoomIn: "KeyE",
attackRatioDown: "KeyT",
attackRatioUp: "KeyY",
swapDirection: "KeyU",
shiftKey: "ShiftLeft",
modifierKey: isMac ? "MetaLeft" : "ControlLeft",
altKey: "AltLeft",
@@ -181,7 +182,7 @@ export class HelpModal extends BaseModal {
</tr>
<tr class="hover:bg-white/5 transition-colors">
<td class="py-3 pl-4 border-b border-white/5">
${this.renderKey("KeyU")}
${this.renderKey(keybinds.swapDirection)}
</td>
<td class="py-3 border-b border-white/5 text-white/70">
${translateText("help_modal.bomb_direction")}
+54 -9
View File
@@ -360,7 +360,8 @@ export class InputHandler {
this.eventBus.emit(new AlternateViewEvent(false));
}
if (e.key.toLowerCase() === "r" && e.altKey && !e.ctrlKey) {
const resetKey = this.keybinds.resetGfx ?? "KeyR";
if (e.code === resetKey && this.isAltKeyHeld(e)) {
e.preventDefault();
this.eventBus.emit(new RefreshGraphicsEvent());
}
@@ -635,19 +636,63 @@ export class InputHandler {
isModifierKeyPressed(event: PointerEvent): boolean {
return (
(this.keybinds.modifierKey === "AltLeft" && event.altKey) ||
(this.keybinds.modifierKey === "ControlLeft" && event.ctrlKey) ||
(this.keybinds.modifierKey === "ShiftLeft" && event.shiftKey) ||
(this.keybinds.modifierKey === "MetaLeft" && event.metaKey)
((this.keybinds.modifierKey === "AltLeft" ||
this.keybinds.modifierKey === "AltRight") &&
event.altKey) ||
((this.keybinds.modifierKey === "ControlLeft" ||
this.keybinds.modifierKey === "ControlRight") &&
event.ctrlKey) ||
((this.keybinds.modifierKey === "ShiftLeft" ||
this.keybinds.modifierKey === "ShiftRight") &&
event.shiftKey) ||
((this.keybinds.modifierKey === "MetaLeft" ||
this.keybinds.modifierKey === "MetaRight") &&
event.metaKey)
);
}
private isAltKeyHeld(event: KeyboardEvent): boolean {
if (
this.keybinds.altKey === "AltLeft" ||
this.keybinds.altKey === "AltRight"
) {
return event.altKey && !event.ctrlKey;
}
if (
this.keybinds.altKey === "ControlLeft" ||
this.keybinds.altKey === "ControlRight"
) {
return event.ctrlKey;
}
if (
this.keybinds.altKey === "ShiftLeft" ||
this.keybinds.altKey === "ShiftRight"
) {
return event.shiftKey;
}
if (
this.keybinds.altKey === "MetaLeft" ||
this.keybinds.altKey === "MetaRight"
) {
return event.metaKey;
}
return false;
}
isAltKeyPressed(event: PointerEvent): boolean {
return (
(this.keybinds.altKey === "AltLeft" && event.altKey) ||
(this.keybinds.altKey === "ControlLeft" && event.ctrlKey) ||
(this.keybinds.altKey === "ShiftLeft" && event.shiftKey) ||
(this.keybinds.altKey === "MetaLeft" && event.metaKey)
((this.keybinds.altKey === "AltLeft" ||
this.keybinds.altKey === "AltRight") &&
event.altKey) ||
((this.keybinds.altKey === "ControlLeft" ||
this.keybinds.altKey === "ControlRight") &&
event.ctrlKey) ||
((this.keybinds.altKey === "ShiftLeft" ||
this.keybinds.altKey === "ShiftRight") &&
event.shiftKey) ||
((this.keybinds.altKey === "MetaLeft" ||
this.keybinds.altKey === "MetaRight") &&
event.metaKey)
);
}
}
+42
View File
@@ -16,6 +16,9 @@ interface FlagInputModalElement extends HTMLElement {
returnTo?: string;
}
const isMac =
typeof navigator !== "undefined" && /Mac/.test(navigator.userAgent);
const DefaultKeybinds: Record<string, string> = {
toggleView: "Space",
buildCity: "Digit1",
@@ -32,6 +35,7 @@ const DefaultKeybinds: Record<string, string> = {
attackRatioUp: "KeyY",
boatAttack: "KeyB",
groundAttack: "KeyG",
swapDirection: "KeyU",
zoomOut: "KeyQ",
zoomIn: "KeyE",
centerCamera: "KeyC",
@@ -39,6 +43,8 @@ const DefaultKeybinds: Record<string, string> = {
moveLeft: "KeyA",
moveDown: "KeyS",
moveRight: "KeyD",
modifierKey: isMac ? "MetaLeft" : "ControlLeft",
altKey: "AltLeft",
};
@customElement("user-setting")
@@ -575,6 +581,32 @@ export class UserSettingModal extends BaseModal {
@change=${this.handleKeybindChange}
></setting-keybind>
<h2
class="text-blue-200 text-xl font-bold mt-8 mb-3 border-b border-white/10 pb-2"
>
${translateText("user_setting.menu_shortcuts")}
</h2>
<setting-keybind
action="modifierKey"
label=${translateText("user_setting.build_menu_modifier")}
description=${translateText("user_setting.build_menu_modifier_desc")}
.defaultKey=${DefaultKeybinds.modifierKey}
.value=${this.getKeyValue("modifierKey")}
.display=${this.getKeyChar("modifierKey")}
@change=${this.handleKeybindChange}
></setting-keybind>
<setting-keybind
action="altKey"
label=${translateText("user_setting.emoji_menu_modifier")}
description=${translateText("user_setting.emoji_menu_modifier_desc")}
.defaultKey=${DefaultKeybinds.altKey}
.value=${this.getKeyValue("altKey")}
.display=${this.getKeyChar("altKey")}
@change=${this.handleKeybindChange}
></setting-keybind>
<h2
class="text-blue-200 text-xl font-bold mt-8 mb-3 border-b border-white/10 pb-2"
>
@@ -627,6 +659,16 @@ export class UserSettingModal extends BaseModal {
@change=${this.handleKeybindChange}
></setting-keybind>
<setting-keybind
action="swapDirection"
label=${translateText("user_setting.swap_direction")}
description=${translateText("user_setting.swap_direction_desc")}
.defaultKey=${DefaultKeybinds.swapDirection}
.value=${this.getKeyValue("swapDirection")}
.display=${this.getKeyChar("swapDirection")}
@change=${this.handleKeybindChange}
></setting-keybind>
<h2
class="text-blue-200 text-xl font-bold mt-8 mb-3 border-b border-white/10 pb-2"
>