diff --git a/src/App.css b/src/App.css index c34cb53..6de08e0 100644 --- a/src/App.css +++ b/src/App.css @@ -82,13 +82,32 @@ .success-message { color: white; - font-size: 2.5rem; - font-weight: 800; - background-color: rgba(0, 0, 0, 0.7); + background-color: rgba(0, 0, 0, 0.75); padding: 1rem 2rem; - border-radius: 50px; + border-radius: 40px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); backdrop-filter: blur(4px); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + line-height: 1.1; + text-align: center; +} + +.success-prefix { + font-size: 1.5rem; + font-weight: 700; + opacity: 0.9; + text-transform: uppercase; + letter-spacing: 0.05em; + margin-bottom: 0.2rem; +} + +.success-note { + font-size: 4rem; + font-weight: 800; + text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); } .instruction-text { diff --git a/src/App.tsx b/src/App.tsx index d00c1ed..3e72345 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -53,6 +53,8 @@ function App() { customMaxFret: 12, autoPlaySightReading: false, autoPlayVolume: 0.5, + virtualGuitarVolume: 0.5, + virtualGuitarMute: false, disableAnimation: false }); @@ -252,7 +254,9 @@ function App() { // Virtual Guitar Handler const handleVirtualGuitarPlay = useCallback((playedMidi: number) => { - playNote(playedMidi, 0.5); // Feedback sound + if (!settings.virtualGuitarMute) { + playNote(playedMidi, 0.5, settings.virtualGuitarVolume ?? 0.5); // Feedback sound + } setVirtualNote(playedMidi); // Clear the note visualization after a short delay @@ -266,7 +270,7 @@ function App() { handleMatchSuccess(); } } - }, [playNote, targetMidi, feedbackMessage, handleMatchSuccess]); + }, [playNote, targetMidi, feedbackMessage, handleMatchSuccess, settings]); // Match Logic useEffect(() => { @@ -428,7 +432,16 @@ function App() { {!settings.zenMode && (
{feedbackMessage ? ( -
{feedbackMessage}
+
+ {feedbackMessage.startsWith("Good! ") ? ( + <> +
Good!
+
{feedbackMessage.replace("Good! ", "")}
+ + ) : ( + feedbackMessage + )} +
) : (
{settings.gameMode === 'ear_training' ? "Listen and play the note" : "Play the note above"} diff --git a/src/components/Controls.tsx b/src/components/Controls.tsx index 58ac322..0c9b182 100644 --- a/src/components/Controls.tsx +++ b/src/components/Controls.tsx @@ -31,6 +31,8 @@ export interface AppSettings { customMaxFret?: number; autoPlaySightReading?: boolean; autoPlayVolume?: number; + virtualGuitarVolume?: number; + virtualGuitarMute?: boolean; disableAnimation?: boolean; } diff --git a/src/components/SettingsModal.tsx b/src/components/SettingsModal.tsx index 3166bc2..1aadf7d 100644 --- a/src/components/SettingsModal.tsx +++ b/src/components/SettingsModal.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { X, Volume2 } from 'lucide-react'; +import { X, Volume2, VolumeX } from 'lucide-react'; import type { AppSettings } from './Controls'; interface SettingsModalProps { @@ -39,6 +39,36 @@ export const SettingsModal: React.FC = ({ isOpen, onClose, s
+
+
+ + +
+
+ {settings.virtualGuitarMute ? : } + onUpdateSettings({ ...settings, virtualGuitarVolume: parseFloat(e.target.value) })} + style={{ flex: 1 }} + disabled={settings.virtualGuitarMute} + /> +
+
+ +
+ {/* Auto Play Settings */}
@@ -63,28 +93,26 @@ export const SettingsModal: React.FC = ({ isOpen, onClose, s
- {(settings.gameMode === 'ear_training' || settings.autoPlaySightReading) && ( -
- - onUpdateSettings({ ...settings, autoPlayVolume: parseFloat(e.target.value) })} - style={{ flex: 1 }} - /> -
- )} -

- {settings.gameMode === 'ear_training' - ? "Automatically plays the note audio (Required for Ear Training)." - : "Automatically plays the note audio when a new note appears."} -

+
+ + onUpdateSettings({ ...settings, autoPlayVolume: parseFloat(e.target.value) })} + style={{ flex: 1 }} + /> +
- +

+ {settings.gameMode === 'ear_training' + ? "Automatically plays the note audio (Required for Ear Training)." + : "Automatically plays the note audio when a new note appears."} +

+
); };