Keyboard Shortcuts

This commit is contained in:
2025-12-25 21:23:31 +01:00
parent 894321f0dc
commit 0c2a84464a
5 changed files with 312 additions and 58 deletions

View File

@@ -152,27 +152,7 @@ export const Controls: React.FC<ControlsProps> = ({ settings, onUpdateSettings }
</select>
</div>
<div className="control-group" style={{ borderTop: '1px solid rgba(255,255,255,0.1)', paddingTop: '12px', marginTop: '12px', width: '100%' }}>
<label className="control-label" style={{ marginBottom: '8px' }}>
<span>Game Mode</span>
</label>
<div style={{ display: 'flex', gap: '8px' }}>
<button
className={`control-button ${settings.gameMode === 'sight_reading' ? 'active' : ''}`}
onClick={() => onUpdateSettings({ ...settings, gameMode: 'sight_reading' })}
style={{ flex: 1 }}
>
Sight Reading
</button>
<button
className={`control-button ${settings.gameMode === 'ear_training' ? 'active' : ''}`}
onClick={() => onUpdateSettings({ ...settings, gameMode: 'ear_training' })}
style={{ flex: 1 }}
>
Ear Training
</button>
</div>
</div>
{/* Rhythm Controls */}
<div className="control-group rhythm-group" style={{ borderTop: '1px solid rgba(255,255,255,0.1)', paddingTop: '12px', marginTop: '12px', width: '100%' }}>

View File

@@ -36,6 +36,14 @@ export const SheetMusic: React.FC<SheetMusicProps> = ({
renderer.resize(width, height);
const context = renderer.getContext();
// IMPORTANT: Set global styles for the context to ensure everything draws with correct color
// VexFlow uses context properties for default colors.
// We can't easily extract CSS var value here without getComputedStyle, which is expensive inside render.
// However, VexFlow SVGContext just adds attributes.
// We can set fillStyle/strokeStyle to the var string.
context.setFillStyle("var(--color-text-main)");
context.setStrokeStyle("var(--color-text-main)");
// --- Helper: Decide which clef a note belongs to in Grand Staff ---
// For Grand Staff: usually Split at Middle C (C4 / Midi 60).
// >= 60 -> Treble, < 60 -> Bass.
@@ -45,6 +53,7 @@ export const SheetMusic: React.FC<SheetMusicProps> = ({
let staves: Record<string, Stave> = {};
if (clef === 'grand') {
// Create Treble Stave
const topStave = new Stave(20, 40, width - 30);
@@ -97,8 +106,15 @@ export const SheetMusic: React.FC<SheetMusicProps> = ({
clef: noteClef as 'treble' | 'bass'
});
// Set styles for all notes to use CSS variables if not colored specifically
staveNote.setStyle({ fillStyle: "var(--color-text-main)", strokeStyle: "var(--color-text-main)" });
if (data.accidental) {
staveNote.addModifier(new Accidental(data.accidental));
const accidental = new Accidental(data.accidental);
// Ensure accidentals also use the color
// VexFlow 4 might not inherit automatically in all contexts, but good to be safe.
// However, StaveNote.setStyle usually propagates.
staveNote.addModifier(accidental);
}
if (type === 'played') {
@@ -131,7 +147,14 @@ export const SheetMusic: React.FC<SheetMusicProps> = ({
});
// Add a Question Mark Annotation
ghost.addModifier(new Annotation("?").setVerticalJustification(Annotation.VerticalJustify.CENTER));
const annotation = new Annotation("?");
annotation.setVerticalJustification(Annotation.VerticalJustify.CENTER);
// Annotations don't natively support setStyle in older VexFlow, but let's see.
// In VexFlow 4, Font settings are different.
// We can try to rely on current contexts or just standard fill.
// Actually, context fillStyle affects it.
ghost.addModifier(annotation);
targetObj = { note: ghost, clef: noteClef };
} else {