Skip to content

Commit d288330

Browse files
committed
Restored resize; updated velocity input; made undo a no-op for now
1 parent fcd5967 commit d288330

File tree

3 files changed

+36
-79
lines changed

3 files changed

+36
-79
lines changed

src/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import DeviceSelector from './components/DeviceSelector';
88
import PlayPauseButton from './components/PlayMIDI';
99
import Grids from './components/Grids';
1010
import SaveMIDI from './components/SaveMIDI';
11-
import UndoButton from './components/UndoButton';
11+
// import UndoButton from './components/UndoButton';
1212

1313
const App: React.FC = () => {
1414
const { error, selectedInput, selectedOutput } = useMIDI();
@@ -49,7 +49,7 @@ const App: React.FC = () => {
4949
<h1>MIDI Phase Editor</h1>
5050
<PlayPauseButton />
5151
<BPMInput />
52-
<UndoButton />
52+
{/* <UndoButton /> */}
5353
<SaveMIDI />
5454
<DeviceSelector />
5555
</section>

src/components/GridInput.tsx

Lines changed: 13 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useCallback, useEffect, useRef, useState } from 'react';
1+
import React, { useCallback, useEffect, useRef } from 'react';
22

33
import './GridInput.css';
44
import useMusicStore, { type GridNote } from '../store';
@@ -11,110 +11,48 @@ interface GridInputProps {
1111
gridIndex: number;
1212
}
1313

14-
const debounce = (func: Function, delay: number) => {
15-
let timeoutId: NodeJS.Timeout | null = null;
16-
17-
return (...args: any) => {
18-
if (timeoutId) {
19-
clearTimeout(timeoutId);
20-
}
21-
22-
timeoutId = setTimeout(() => {
23-
func(...args);
24-
}, delay);
25-
};
26-
};
2714

2815
const GridInput: React.FC<GridInputProps> = ({ gridIndex }) => {
29-
const { grids, setGrid, updateNoteVelocity, setOrUpdateNoteInGrid } = useMusicStore();
16+
const { grids, setGrid, updateNoteVelocity, setOrUpdateNoteInGrid, deleteNoteFromGrid } = useMusicStore();
3017
const grid = grids[gridIndex];
3118
const gridRef = useRef<HTMLDivElement | null>(null);
3219
const cellRefs = useRef<(HTMLDivElement | null)[][]>(Array.from({ length: GRID_PITCH_RANGE }, () => Array(grid ? grid.numColumns : 0).fill(null)));
3320

34-
const [isCtrlPressed, setIsCtrlPressed] = useState(false);
35-
const [draggingNote, setDraggingNote] = useState<GridNote | null>(null);
36-
37-
const toggleNote = useCallback((pitch: number, beatIndex: number, velocity: number = 100) => {
21+
const toggleNote = useCallback((pitch: number, beatIndex: number, velocity?: number | undefined) => {
3822
const grid = grids[gridIndex];
3923

4024
const notes = grid.beats[beatIndex]?.notes || {};
4125
const existingNote = notes[pitch];
4226

4327
if (existingNote) {
44-
if (isCtrlPressed) {
45-
// Adjust velocity if CTRL is pressed
28+
if (velocity) {
4629
existingNote.velocity = velocity;
4730
updateNoteVelocity(gridIndex, beatIndex, pitch, velocity);
48-
// dispatchPlayNoteNowEvent(pitch, velocity);
4931
} else {
5032
// Remove the note if it exists and CTRL is not pressed
5133
delete notes[pitch];
52-
setOrUpdateNoteInGrid(gridIndex, beatIndex, { pitch, velocity: 0 }); // Use a default velocity if needed
34+
deleteNoteFromGrid(gridIndex, beatIndex, pitch);
5335
}
5436
} else {
5537
// Add a new note if it does not exist
56-
const newNote: GridNote = { pitch, velocity };
38+
const newNote: GridNote = { pitch, velocity: velocity || 75 };
5739
setOrUpdateNoteInGrid(gridIndex, beatIndex, newNote);
58-
dispatchPlayNoteNowEvent(pitch, velocity);
40+
dispatchPlayNoteNowEvent(pitch, velocity || 75);
5941
}
60-
}, [isCtrlPressed, gridIndex, setOrUpdateNoteInGrid, updateNoteVelocity, grids]);
61-
62-
const debouncedToggleNoteRef = useRef(debounce(toggleNote, 25));
63-
// Update the ref whenever toggleNote changes
64-
useEffect(() => {
65-
debouncedToggleNoteRef.current = debounce(toggleNote, 25);
66-
}, [toggleNote]);
42+
}, [gridIndex, setOrUpdateNoteInGrid, deleteNoteFromGrid, updateNoteVelocity, grids]);
6743

6844
const handleMouseDown = (pitch: number, e: React.MouseEvent<HTMLDivElement>) => {
6945
const beatIndex = Number(e.currentTarget.dataset.beat);
7046
if (e.ctrlKey) {
71-
setIsCtrlPressed(true);
72-
73-
// Access the current grid from the store
74-
const grid = grids[gridIndex];
75-
76-
// Check if the note exists in the specified beat
77-
const note = grid.beats[beatIndex]?.notes[pitch];
78-
79-
// Set dragging note to the existing note or create a new one
80-
setDraggingNote(note || { pitch, velocity: 75 });
47+
const velocity = Number(prompt('Enter new velocity (1-127)', '75'));
48+
if (velocity) {
49+
toggleNote(pitch, beatIndex, velocity);
50+
}
8151
} else {
82-
toggleNote(pitch, beatIndex); // Call toggleNote with the updated signature
52+
toggleNote(pitch, beatIndex);
8353
}
8454
};
8555

86-
const handleMouseMove = useCallback((e: MouseEvent) => {
87-
if (draggingNote && isCtrlPressed) {
88-
if (!gridRef.current?.clientWidth) return;
89-
90-
// Use the dragging note's pitch and calculate the velocity based on the mouse Y position
91-
const velocity = Math.max(0, Math.min(127, 127 - e.clientY / 4));
92-
93-
const beatIndex = Math.floor(e.clientX / (gridRef.current?.clientWidth / grid.numColumns)); // Adjust based on your layout
94-
// toggleNote(draggingNote.pitch, beatIndex, velocity); // Use stored pitch from dragging note
95-
debouncedToggleNoteRef.current(draggingNote.pitch, beatIndex, velocity); // Use debounced function
96-
}
97-
}, [draggingNote, grid.numColumns, isCtrlPressed]);
98-
99-
100-
const handleMouseUp = () => {
101-
setIsCtrlPressed(false);
102-
setDraggingNote(null);
103-
};
104-
105-
// Set up event listeners for drag
106-
useEffect(() => {
107-
if (isCtrlPressed && draggingNote) {
108-
window.addEventListener('mousemove', handleMouseMove);
109-
window.addEventListener('mouseup', handleMouseUp);
110-
}
111-
112-
return () => {
113-
window.removeEventListener('mousemove', handleMouseMove);
114-
window.removeEventListener('mouseup', handleMouseUp);
115-
};
116-
}, [isCtrlPressed, draggingNote, handleMouseMove]);
117-
11856
const calculateOpacity = (velocity: number) => {
11957
return velocity / 127; // Normalize velocity to opacity range [0, 1]
12058
};

src/store.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ export interface MusicState {
3535
setNumColumns: (gridIndex: number, numColumns: number) => void;
3636
updateNoteVelocity: (gridIndex: number, beatIndex: number, pitch: number, velocity: number) => void;
3737
setOrUpdateNoteInGrid: (gridIndex: number, beatIndex: number, note: GridNote) => void;
38+
deleteNoteFromGrid: (gridIndex: number, beatIndex: number, pitch: number) => void;
39+
3840
mergedBeats: MergedBeat[];
3941
mergeGrids: () => void;
4042

@@ -45,15 +47,14 @@ export interface MusicState {
4547

4648
selectedInput: WebMidi.MIDIInput | null;
4749
setSelectedInput: (input: WebMidi.MIDIInput | null) => void;
48-
4950
selectedOutput: WebMidi.MIDIOutput | null;
5051
setSelectedOutput: (output: WebMidi.MIDIOutput | null) => void;
5152

5253
inputs: WebMidi.MIDIInput[];
5354
setInputs: (inputs: WebMidi.MIDIInput[]) => void;
54-
5555
outputs: WebMidi.MIDIOutput[];
5656
setOutputs: (outputs: WebMidi.MIDIOutput[]) => void;
57+
5758
error: string | null;
5859
setError: (error: string | null) => void;
5960

@@ -163,6 +164,22 @@ const useMusicStore = create<MusicState>((set, get) => ({
163164
return { grids: newGrids };
164165
}),
165166

167+
deleteNoteFromGrid: (gridIndex: number, beatIndex: number, pitch: number) =>
168+
set((state) => {
169+
pushToUndoStack();
170+
const newGrids = [...state.grids];
171+
const grid = newGrids[gridIndex];
172+
if (grid) {
173+
const notes = grid.beats[beatIndex]?.notes || {};
174+
if (notes[pitch]) {
175+
delete notes[pitch]; // Remove the note from the notes object
176+
grid.beats[beatIndex].notes = { ...notes }; // Update the notes of the specific beat
177+
}
178+
}
179+
180+
return { grids: newGrids };
181+
}),
182+
166183
mergedBeats: [],
167184
mergeGrids: () => set((state) => {
168185
pushToUndoStack();
@@ -202,6 +219,7 @@ const useMusicStore = create<MusicState>((set, get) => ({
202219

203220
undoStack: [],
204221
undo: () => {
222+
return; // noop
205223
const { undoStack } = get();
206224

207225
if (undoStack.length === 0) {
@@ -234,6 +252,7 @@ const useMusicStore = create<MusicState>((set, get) => ({
234252

235253

236254
function pushToUndoStack() {
255+
return; // noop
237256
const currentState = useMusicStore.getState();
238257

239258
const stateToStore = Object.keys(currentState).reduce((acc, key) => {

0 commit comments

Comments
 (0)