feedback5 WAC: players rebind the in-match shortcuts in 设置 → 快捷键 (community request 「快捷键可不可以自己设置」, the owner's decision of 2026-10-07)
- The settings (sp.pref.settings) hold a key map, action → KeyboardEvent.code, for refresh / freeze / level-up / retreat / sell / ready (the ready key also pauses a solo battle); the defaults are the 0.1.4 keys R F D Q X Space, so nothing changes for a player who never opens the section. sanitizeSettings keeps each saved key that may be a shortcut and gives any other its default; not a map, or two actions on one key, gives the defaults. - One lookup, actionForKey (the character typed first, then the physical key: the 0.1.4 code-or-key match, identical for the defaults), serves shortcutFor(e, keys) in game.js and the facing wheel; the modifier, text-field, repeat and overlay guards are unchanged. The shop bar, ready / pause and underframe key hints read the map. - 设置 → 快捷键 (the one SettingsModal, in a match and on the title screen): each action with its key; click or Enter waits, the next key binds; Esc cancels (the dialog stays open), Tab leaves; Ctrl / Alt / ⌘ combinations and the interface keys (Esc, Tab, Enter, arrows, F1–F12) are refused; a key in use is swapped and the line under the list names both; 恢复默认. Esc stays fixed. Touch-only devices: a keyboard note and a folded list; one column under 768 px. - Tests: test/ui/feedback5-hotkeys.test.js (map, sanitising, conflicts, lookup, capture, handlers and hints with a rebound key), test/ui/gameLogic.test.js (sanitizeSettings now returns keys), test/ui/hotkeys.e2e.test.js (SP_E2E=1: 撤退 rebound to W with the keyboard only in the mock match; phone width). Golden unchanged (client UI only).
This commit is contained in:
1 parent
30d9a41c51
commit
f2bec76176
14 files changed
+772
-61
No files matched your search
@@ -80,7 +80,7 @@ import { Ticker } from '../ui/ticker.js';
|
||||
import { EmoteWheel } from '../ui/emotes.js';
|
||||
import { EffectsList } from '../ui/effectsList.js';
|
||||
import { CombatHud } from '../ui/combatHud.js';
|
||||
import { SettingsModal } from '../ui/settings.js';
|
||||
import { SettingsModal, settingsStore } from '../ui/settings.js';
|
||||
import { ExitModal, AwayOverlay, awayStore } from '../ui/matchChrome.js';
|
||||
import { openGuide } from '../ui/guide.js';
|
||||
import { actions } from '../ui/gameActions.js';
|
||||
@@ -1094,7 +1094,7 @@ function MatchScreen() {
|
||||
// ---- keyboard ---------------------------------------------------------------------------------------------
|
||||
useEffect(() => {
|
||||
const onKey = async (e) => {
|
||||
const act = shortcutFor(e);
|
||||
const act = shortcutFor(e, settingsStore.get().keys); // the player's key map (设置 → 快捷键)
|
||||
const L = live.current;
|
||||
// dialogs / the guide own the keyboard; behind the 本局信息 / 敌方情报 drawer only Esc (closing it) acts
|
||||
if (shortcutBlocked(act, { modal: !!document.querySelector('.modal, .guide'), drawer: !!L.drawer })) return;
|
||||
@@ -1108,7 +1108,7 @@ function MatchScreen() {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
// Space pauses / resumes a solo battle (the official battle key)
|
||||
// the ready key (Space unless rebound) pauses / resumes a solo battle (Space: the official battle key)
|
||||
if (act === 'ready' && (L.canPause || L.paused)) {
|
||||
e.preventDefault();
|
||||
if (e.target instanceof HTMLElement && e.target.closest('button, [role="button"]')) e.target.blur();
|
||||
@@ -1116,7 +1116,7 @@ function MatchScreen() {
|
||||
return;
|
||||
}
|
||||
if (L.pub?.phase !== PHASE.PREP || !L.priv) return;
|
||||
e.preventDefault(); // a focused HUD button must not also activate (Space) — see shortcutFor
|
||||
e.preventDefault(); // a focused HUD button must not also activate (Space, or any key bound) — see shortcutFor
|
||||
if (act === 'ready' && e.target instanceof HTMLElement && e.target.closest('button, [role="button"]')) e.target.blur();
|
||||
if (act === 'ready') {
|
||||
const refused = !L.priv.ready ? shopBlockReason('ready', { priv: L.priv, editable: true }) : null;
|
||||
|
||||
Reference in new issue
Block a user