Skip to content

Commit dfd9912

Browse files
committed
Practice mode now returns to your settings after
1 parent 689a30c commit dfd9912

2 files changed

Lines changed: 87 additions & 7 deletions

File tree

src/app/App.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ export default function App() {
115115
scaleOptions: theoryDomain.scale.scaleOptions,
116116
setRoot: theoryDomain.system.setRoot,
117117
setScale: theoryDomain.scale.setScale,
118+
selectedRoot: theoryDomain.system.root,
119+
selectedScale: theoryDomain.scale.scale,
118120
},
119121
});
120122
const orchestration = useAppOrchestration({

src/app/containers/usePracticePanelState.js

Lines changed: 85 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export default function usePracticePanelState({
2121
metronomeDefaults,
2222
randomizeConfig,
2323
}) {
24+
const { selectedRoot, selectedScale } = randomizeConfig;
2425
const [randomizeMode, setRandomizeMode] = React.useState(
2526
RANDOMIZE_MODES.Both,
2627
);
@@ -65,6 +66,57 @@ export default function usePracticePanelState({
6566
const [barsRemaining, setBarsRemaining] = React.useState(safeBarsPerScale);
6667
const barsRemainingRef = React.useRef(safeBarsPerScale);
6768
const pendingRandomizedScaleRef = React.useRef(null);
69+
const practiceStartSelectionRef = React.useRef(null);
70+
const randomizedDuringPracticeRef = React.useRef(false);
71+
const isPlayingRef = React.useRef(false);
72+
73+
const capturePracticeStartSelection = useCallback(() => {
74+
if (practiceStartSelectionRef.current) return;
75+
practiceStartSelectionRef.current = {
76+
root: selectedRoot,
77+
scale: selectedScale,
78+
};
79+
}, [selectedRoot, selectedScale]);
80+
81+
const markRandomizedDuringPractice = useCallback(() => {
82+
if (!isPlayingRef.current) return;
83+
capturePracticeStartSelection();
84+
randomizedDuringPracticeRef.current = true;
85+
}, [capturePracticeStartSelection]);
86+
87+
const restorePracticeStartSelection = useCallback(() => {
88+
if (!randomizedDuringPracticeRef.current) return;
89+
90+
const originalSelection = practiceStartSelectionRef.current;
91+
if (!originalSelection) return;
92+
93+
if (
94+
typeof originalSelection.root === "string" &&
95+
originalSelection.root.length
96+
) {
97+
randomizeConfig.setRoot?.(originalSelection.root);
98+
}
99+
if (
100+
typeof originalSelection.scale === "string" &&
101+
originalSelection.scale.length
102+
) {
103+
randomizeConfig.setScale?.(originalSelection.scale);
104+
}
105+
}, [randomizeConfig]);
106+
107+
const randomizeNowForPractice = useCallback(() => {
108+
markRandomizedDuringPractice();
109+
randomizeNow?.();
110+
}, [markRandomizedDuringPractice, randomizeNow]);
111+
112+
const applyPickedScaleForPractice = useCallback(
113+
(result) => {
114+
markRandomizedDuringPractice();
115+
applyPickedScale?.(result);
116+
},
117+
[applyPickedScale, markRandomizedDuringPractice],
118+
);
119+
68120
const handleMetronomeBeat = useCallback(
69121
({ beat }) => {
70122
if (beat !== 1 || !autoAdvanceEnabled) return;
@@ -91,9 +143,9 @@ export default function usePracticePanelState({
91143
const pendingResult = pendingRandomizedScaleRef.current;
92144

93145
if (pendingResult) {
94-
applyPickedScale?.(pendingResult);
146+
applyPickedScaleForPractice?.(pendingResult);
95147
} else {
96-
randomizeNow?.();
148+
randomizeNowForPractice?.();
97149
}
98150

99151
pendingRandomizedScaleRef.current = null;
@@ -108,10 +160,10 @@ export default function usePracticePanelState({
108160
[
109161
announceCountInBeforeChange,
110162
autoAdvanceEnabled,
111-
applyPickedScale,
163+
applyPickedScaleForPractice,
112164
pickRandomizedScale,
113165
randomizeMode,
114-
randomizeNow,
166+
randomizeNowForPractice,
115167
safeBarsPerScale,
116168
],
117169
);
@@ -129,12 +181,33 @@ export default function usePracticePanelState({
129181
onBeat: handleMetronomeBeat,
130182
});
131183

184+
React.useEffect(() => {
185+
if (metronomeEngine.isPlaying && !isPlayingRef.current) {
186+
practiceStartSelectionRef.current = null;
187+
randomizedDuringPracticeRef.current = false;
188+
capturePracticeStartSelection();
189+
}
190+
191+
if (!metronomeEngine.isPlaying && isPlayingRef.current) {
192+
restorePracticeStartSelection();
193+
practiceStartSelectionRef.current = null;
194+
randomizedDuringPracticeRef.current = false;
195+
pendingRandomizedScaleRef.current = null;
196+
}
197+
198+
isPlayingRef.current = metronomeEngine.isPlaying;
199+
}, [
200+
capturePracticeStartSelection,
201+
metronomeEngine.isPlaying,
202+
restorePracticeStartSelection,
203+
]);
204+
132205
const practiceActions = usePracticeActions({
133206
isPlaying: metronomeEngine.isPlaying,
134207
startMetronome: metronomeEngine.start,
135208
stopMetronome: metronomeEngine.stop,
136209
setBpm: metronomeSetters.setBpm,
137-
randomizeNow,
210+
randomizeNow: randomizeNowForPractice,
138211
randomizeFromHotkey,
139212
});
140213

@@ -152,10 +225,15 @@ export default function usePracticePanelState({
152225
() => ({
153226
randomizeMode,
154227
setRandomizeMode,
155-
randomizeNow,
228+
randomizeNow: randomizeNowForPractice,
156229
randomizeFromHotkey,
157230
}),
158-
[randomizeMode, setRandomizeMode, randomizeNow, randomizeFromHotkey],
231+
[
232+
randomizeMode,
233+
setRandomizeMode,
234+
randomizeNowForPractice,
235+
randomizeFromHotkey,
236+
],
159237
);
160238
const metronome = useMemo(
161239
() => ({

0 commit comments

Comments
 (0)