Feedback round 2: strings filter, key sync, fixed clef, unified metronome

- Strings filter: per-string toggle buttons (replaces fret-window-only
  semantics as a third 'limits notes' control); combines with fret window
  and key filter in targetPool (fretted instruments).
- Key sync checkbox: display key signature can follow the target key
  (major/minor mapping), default off — both remain independently settable.
- LiveNoteStaff: optional fixed clef — guitar/bass now keep their usual
  clef instead of flipping at middle C; octave markers handle range.
- Unified metronome widget (MetronomeWidget) with animated linear pendulum
  synced to the audible click; shown in ALL modes next to the tuner.
  Phrase BPM now reads from settings.rhythm.bpm (single source); the
  phrase-local BPM control was removed from the setup panel.
- Tests: 160/160; tsc + eslint clean; build ok.
This commit is contained in:
OpenClaw
2026-09-14 12:38:22 +00:00
parent 15b8705907
commit b214c209f9
11 changed files with 445 additions and 194 deletions

View File

@@ -6,7 +6,10 @@ export interface PracticeFilter {
keyEnabled: boolean;
keyTonic: string;
keyMode: string; // ModeId
/** Restrict target notes to a fret window (fretted instruments only). */
/** Restrict target notes to selected strings (fretted instruments only).
* Empty array = no restriction (all strings). Index 0 = lowest string. */
strings: number[];
/** Restrict target notes to a fret range (fretted instruments only). */
fretWindowEnabled: boolean;
fretMin: number;
fretMax: number;
@@ -16,6 +19,7 @@ export const DEFAULT_PRACTICE_FILTER: PracticeFilter = {
keyEnabled: false,
keyTonic: 'C',
keyMode: 'major',
strings: [],
fretWindowEnabled: false,
fretMin: 0,
fretMax: 4,
@@ -101,6 +105,8 @@ export interface AppSettings {
showTuningMeter: boolean;
tuningId: string;
keySignature: string;
/** Keep display key signature in sync with the target-key control. */
keyFollowsTarget?: boolean;
instrument: string;
rhythm: RhythmSettings;
zenMode: boolean;
@@ -128,6 +134,7 @@ export const DEFAULT_SETTINGS: AppSettings = {
showTuningMeter: false,
tuningId: 'standard',
keySignature: 'C',
keyFollowsTarget: false,
instrument: 'guitar',
rhythm: {
mode: 'bpm',