Footer tools stacked in all modes; fix silent phrase-mode metronome

Layout: tuner + metronome now stack vertically everywhere (was phrase-only).

Phrase metronome bug: clicks were gated on rhythm.active, but phrase mode
has no on/off switch (the sync checkbox replaces it) and the default is
active:false — so a synced run stayed silent with no in-mode remedy.
Now: phrase mode is always armed (sync checkbox = free vs synced,
sound checkbox = clicks), and phrase clickSound reads rhythm.sound only.
Single-note modes keep the rhythm.active on/off semantics.
This commit is contained in:
2026-09-20 00:10:37 +02:00
parent c1f8f46cfe
commit e43a17efb3
3 changed files with 17 additions and 11 deletions

View File

@@ -55,10 +55,15 @@ export const MetronomeWidget: React.FC<MetronomeWidgetProps> = ({
const isSync = syncMode === 'option' && !!rhythm.syncToExercise;
const runActive = gate === true;
// Phrase mode (syncMode 'option') has no on/off switch — the sync
// checkbox replaces it (unchecked = free metronome, checked = synced to
// the exercise), so the metronome is always armed there. Gating on
// rhythm.active would leave phrase users with no way to enable clicks.
const armed = syncMode === 'option' ? true : rhythm.active;
// Sync: pendulum/click only while the run is active (the run's scheduler
// is the click source; the widget's own scheduler stays off).
// Free/plain: the widget's own scheduler runs whenever armed.
const running = isSync ? runActive : rhythm.active;
const running = isSync ? runActive : armed;
const { restart } = useMetronome({
bpm: rhythm.bpm,
@@ -78,7 +83,6 @@ export const MetronomeWidget: React.FC<MetronomeWidgetProps> = ({
}, [isSync, runActive]);
const beatMs = 60000 / Math.max(1, rhythm.bpm);
const armed = rhythm.active;
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>