Unified target-note controls: key filter + fret window across all modes

- New shared PracticeFilter settings (keyTonic/keyMode/fretWindow), persisted
  via AppSettings.practice, defaults off (behavior unchanged).
- music/targetPool.ts: single source for the effective target pool —
  base playable range ∩ fret window ∩ key/mode pitch classes (9 modes incl.
  pentatonic, same scale machinery as Phrase Mode).
- useGameLogic now builds validNotes via computeTargetPool.
- TargetNoteControls component (key on/off + tonic/mode, fret window on/off +
  min/max) rendered in Controls for all game modes; key is independent of the
  displayed key signature.
- Phrase Mode binds its key/fret-window setup to the same shared filter
  (read/write mirror) and drops the duplicate controls in its setup panel.
- Tests: targetPool.test.ts (7 cases); suite 156/156 green, build ok.
This commit is contained in:
OpenClaw
2026-09-14 07:16:29 +00:00
parent da060e5bb9
commit 15b8705907
7 changed files with 339 additions and 104 deletions

View File

@@ -3,6 +3,7 @@ import { TUNINGS, INSTRUMENT_TUNINGS } from '../music/Tunings';
import { INSTRUMENT_DEFINITIONS } from '../music/InstrumentConfigs';
import { getTempoMarking } from '../music/TempoMarkings';
import { TuningMeter } from './TuningMeter';
import { TargetNoteControls } from './TargetNoteControls';
import { useSettings } from '../context/useSettings';
import { type Difficulty, type RhythmSettings } from '../types/SettingsTypes';
@@ -193,6 +194,9 @@ export const Controls: React.FC<ControlsProps> = ({ currentPitch }) => {
)}
</div>
{/* Target-note filter: unified controls, all modes */}
<TargetNoteControls />
{/* Bottom Section: Tools Grid (2 Columns now) */}
<div className="tools-grid" style={inPhraseMode ? { gridTemplateColumns: '1fr' } : undefined}>
{/* Tool 1: Tuner */}