move tuner

This commit is contained in:
2025-12-27 12:57:58 +01:00
parent 6dff107043
commit 31843095a3
2 changed files with 71 additions and 50 deletions

View File

@@ -306,6 +306,13 @@ function App() {
return getFretboardPositions(targetMidi, currentTuning); return getFretboardPositions(targetMidi, currentTuning);
}, [settings.showHint, targetMidi, currentTuning, currentInstrumentDef]); }, [settings.showHint, targetMidi, currentTuning, currentInstrumentDef]);
// Auto-enable mic when tuner is turned on
useEffect(() => {
if (settings.showTuningMeter && !listening) {
setListening(true);
}
}, [settings.showTuningMeter, listening]);
return ( return (
<div className={`app-container ${settings.zenMode ? 'zen-mode' : ''}`}> <div className={`app-container ${settings.zenMode ? 'zen-mode' : ''}`}>
{!settings.zenMode && ( {!settings.zenMode && (
@@ -423,9 +430,6 @@ function App() {
{listening ? <Mic size={28} /> : <MicOff size={28} />} {listening ? <Mic size={28} /> : <MicOff size={28} />}
</button> </button>
{settings.showTuningMeter && pitchData ? (
<TuningMeter cents={pitchData.cents} noteName={pitchData.note} />
) : (
<div className={`pitch-readout ${pitchData ? 'active' : ''}`}> <div className={`pitch-readout ${pitchData ? 'active' : ''}`}>
{pitchData ? ( {pitchData ? (
<> <>
@@ -438,7 +442,6 @@ function App() {
<span className="placeholder">{listening ? "Listening..." : "Mic Off"}</span> <span className="placeholder">{listening ? "Listening..." : "Mic Off"}</span>
)} )}
</div> </div>
)}
</div> </div>
) )
} }
@@ -446,13 +449,17 @@ function App() {
{!settings.zenMode && ( {!settings.zenMode && (
<footer className="settings-footer"> <footer className="settings-footer">
<Controls settings={settings} onUpdateSettings={setSettings} /> <Controls
settings={settings}
onUpdateSettings={setSettings}
currentPitch={pitchData ? { note: pitchData.note, cents: pitchData.cents } : null}
/>
<div className="app-subtitle"> <div className="app-subtitle">
<a href="http://jensmohrmann.de" target="_blank" rel="noopener noreferrer">jensmohrmann.de</a> <a href="http://jensmohrmann.de" target="_blank" rel="noopener noreferrer">jensmohrmann.de</a>
</div> </div>
</footer> </footer>
) )}
}
{/* Floating Zen Mode Button (Toggle) */} {/* Floating Zen Mode Button (Toggle) */}
<button <button
@@ -464,7 +471,8 @@ function App() {
</button> </button>
{/* Help Popup */} {/* Help Popup */}
{showHelp && ( {
showHelp && (
<div className="help-popup-overlay" onClick={() => setShowHelp(false)}> <div className="help-popup-overlay" onClick={() => setShowHelp(false)}>
<div className="help-popup" onClick={e => e.stopPropagation()}> <div className="help-popup" onClick={e => e.stopPropagation()}>
<button className="help-close" onClick={() => setShowHelp(false)}><X size={20} /></button> <button className="help-close" onClick={() => setShowHelp(false)}><X size={20} /></button>
@@ -496,7 +504,8 @@ function App() {
</div> </div>
</div> </div>
</div> </div>
)} )
}
</div > </div >
); );
} }

View File

@@ -2,6 +2,7 @@ import { Settings, Guitar, Music, Gauge } from 'lucide-react';
import { TUNINGS, INSTRUMENT_TUNINGS } from '../music/Tunings'; import { TUNINGS, INSTRUMENT_TUNINGS } from '../music/Tunings';
import { INSTRUMENT_DEFINITIONS } from '../music/InstrumentConfigs'; import { INSTRUMENT_DEFINITIONS } from '../music/InstrumentConfigs';
import { getTempoMarking } from '../music/TempoMarkings'; import { getTempoMarking } from '../music/TempoMarkings';
import { TuningMeter } from './TuningMeter';
export type Difficulty = string; export type Difficulty = string;
@@ -33,9 +34,10 @@ export interface AppSettings {
interface ControlsProps { interface ControlsProps {
settings: AppSettings; settings: AppSettings;
onUpdateSettings: (s: AppSettings) => void; onUpdateSettings: (s: AppSettings) => void;
currentPitch: { note: string; cents: number } | null;
} }
export const Controls: React.FC<ControlsProps> = ({ settings, onUpdateSettings }) => { export const Controls: React.FC<ControlsProps> = ({ settings, onUpdateSettings, currentPitch }) => {
const handleDifficultyChange = (e: React.ChangeEvent<HTMLSelectElement>) => { const handleDifficultyChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
onUpdateSettings({ ...settings, difficulty: e.target.value as Difficulty }); onUpdateSettings({ ...settings, difficulty: e.target.value as Difficulty });
}; };
@@ -223,6 +225,16 @@ export const Controls: React.FC<ControlsProps> = ({ settings, onUpdateSettings }
<div className="switch-thumb" /> <div className="switch-thumb" />
</button> </button>
</div> </div>
{settings.showTuningMeter && currentPitch && (
<div style={{ paddingTop: '8px', borderTop: '1px solid rgba(255,255,255,0.1)' }}>
<TuningMeter cents={currentPitch.cents} noteName={currentPitch.note} />
</div>
)}
{settings.showTuningMeter && !currentPitch && (
<div style={{ paddingTop: '8px', borderTop: '1px solid rgba(255,255,255,0.1)', fontSize: '11px', opacity: 0.5, textAlign: 'center' }}>
Listening...
</div>
)}
</div> </div>
{/* Tool 2: Metronome */} {/* Tool 2: Metronome */}