diff --git a/package-lock.json b/package-lock.json index a94a342..d41ecd6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4677,6 +4677,11 @@ } } }, + "compute-scroll-into-view": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.14.tgz", + "integrity": "sha512-mKDjINe3tc6hGelUMNDzuhorIUZ7kS7BwyY0r2wQd2HOH2tRuJykiC06iSEX8y1TuhNzvz4GcJnK16mM2J1NMQ==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -14316,6 +14321,14 @@ "ajv-keywords": "^3.4.1" } }, + "scroll-into-view-if-needed": { + "version": "2.2.25", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.25.tgz", + "integrity": "sha512-C8RKJPq9lK7eubwGpLbUkw3lklcG3Ndjmea2PyauzrA0i4DPlzAmVMGxaZrBFqCrVLfvJmP80IyHnv4jxvg1OQ==", + "requires": { + "compute-scroll-into-view": "^1.0.14" + } + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -14667,6 +14680,14 @@ } } }, + "smooth-scroll-into-view-if-needed": { + "version": "1.1.28", + "resolved": "https://registry.npmjs.org/smooth-scroll-into-view-if-needed/-/smooth-scroll-into-view-if-needed-1.1.28.tgz", + "integrity": "sha512-VBxjAYySCfPix8JaiYKB+Rr4+1tFJ+aJ80caiVmsEA1cgQ3G/aFEfIRSpabJfX5o3FGm3IEttBLebe0uNtgURw==", + "requires": { + "scroll-into-view-if-needed": "^2.2.25" + } + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", diff --git a/package.json b/package.json index f217681..0134415 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "react-dom": "^16.13.1", "react-scripts": "3.4.1", "robotjs": "git+https://github.com/octalmage/robotjs.git#master", + "smooth-scroll-into-view-if-needed": "^1.1.28", "webmidi": "^2.5.1" }, "build": { diff --git a/roadmap.txt b/roadmap.md similarity index 55% rename from roadmap.txt rename to roadmap.md index 64652c9..92a15da 100644 --- a/roadmap.txt +++ b/roadmap.md @@ -1,19 +1,20 @@ - Current "roadmap" of upcoming changes -v0.1 release -- checkbox to turn off sending notes (for practicing without it playing) -- checkbox to turn off auto octave swap +v0.2 -v0.2 release +- key switches for octaves (when in not auto octave mode) - buttons for manually shifting the internal octave -- keymap selector +- keymap selector with a few options + +v0.3 + - Better ui for configuring note->key map future ideas + - UI that shows a piano and keypresses - Automatically play through a song - Mac build - Send different note ranges to different game clients? --- Like if multiboxing multiple instruments --- May be against terms of service :( \ No newline at end of file + -- Like if multiboxing multiple instruments + -- May be against terms of service :( diff --git a/src/react/App.module.css b/src/react/App.module.css index c7dfb88..b682a4f 100644 --- a/src/react/App.module.css +++ b/src/react/App.module.css @@ -4,6 +4,7 @@ .app { height: 100vh; + overflow: hidden; display: flex; flex-direction: column; align-items: center; diff --git a/src/react/components/InstrumentSelector.js b/src/react/components/InstrumentSelector.js new file mode 100644 index 0000000..9a479c6 --- /dev/null +++ b/src/react/components/InstrumentSelector.js @@ -0,0 +1,7 @@ +import React from 'react'; + +export default InstrumentSelector; + +function InstrumentSelector(props) { + return
Instrument: The Minstrel
; +} diff --git a/src/react/components/MIDIDisplay.js b/src/react/components/MIDIDisplay.js deleted file mode 100644 index ebbe17c..0000000 --- a/src/react/components/MIDIDisplay.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import { useKeySender } from '../hooks/useKeySender'; - -export default MIDIDisplay; - -function MIDIDisplay(props) { - const { sentMessages, octave } = useKeySender(); - return ( -
-

Messages

-
Octave {octave}
-
- {sentMessages.map((message, i) => ( -
{message}
- ))} -
-
- ); -} diff --git a/src/react/components/MIDIMessageDisplay.js b/src/react/components/MIDIMessageDisplay.js new file mode 100644 index 0000000..a0b7992 --- /dev/null +++ b/src/react/components/MIDIMessageDisplay.js @@ -0,0 +1,31 @@ +import React, { useEffect, useRef } from 'react'; +import scrollIntoView from 'smooth-scroll-into-view-if-needed'; + +import { useKeySender } from '../hooks/useKeySender'; + +import styles from './MIDIMessageDisplay.module.css'; + +export default MIDIMessageDisplay; + +function MIDIMessageDisplay(props) { + const { sentMessages } = useKeySender(); + const messagesEndRef = useRef(null); + + const scrollToBottom = () => { + scrollIntoView(messagesEndRef.current); + }; + + useEffect(scrollToBottom, [sentMessages]); + + return ( +
+

Messages

+
+ {sentMessages.map((message, i) => ( +
{message}
+ ))} +
+
+
+ ); +} diff --git a/src/react/components/MIDIMessageDisplay.module.css b/src/react/components/MIDIMessageDisplay.module.css new file mode 100644 index 0000000..2b0e6b2 --- /dev/null +++ b/src/react/components/MIDIMessageDisplay.module.css @@ -0,0 +1,16 @@ +.MIDIMessageDisplay { + display: flex; + flex-direction: column; + height: 100%; + width: 100%; +} + +.header { + flex: 0; +} + +.messages { + flex: 1; + overflow-y: auto; + width: 100%; +} diff --git a/src/react/components/PianoDisplay.js b/src/react/components/PianoDisplay.js new file mode 100644 index 0000000..3bdeaf3 --- /dev/null +++ b/src/react/components/PianoDisplay.js @@ -0,0 +1,9 @@ +import React from 'react'; +import { useKeySender } from '../hooks/useKeySender'; + +export default PianoDisplay; + +function PianoDisplay(props) { + const { octave } = useKeySender(); + return
Octave {octave}
; +} diff --git a/src/react/hooks/useKeySender.js b/src/react/hooks/useKeySender.js index b8efcf1..8cf2a3a 100644 --- a/src/react/hooks/useKeySender.js +++ b/src/react/hooks/useKeySender.js @@ -51,6 +51,8 @@ const keyMap = { // TODO: Move to config since the sweet spot may be different per game/person? const MULTIPLE_OCTAVE_SHIFT_DELAY = 75; +const MESSAGE_LIMIT = 100; + function KeySenderProvider(props) { const { children } = props; const { isLoading: configIsLoading, config } = useConfig(); @@ -211,7 +213,10 @@ function KeySenderProvider(props) { function _addMessage(message) { setState((curr) => ({ ...curr, - sentMessages: [message, ...curr.sentMessages].slice(0, 10), + sentMessages: [...curr.sentMessages, message].slice( + curr.sentMessages.length - MESSAGE_LIMIT, + MESSAGE_LIMIT + ), })); } diff --git a/src/react/scenes/MainContent/index.js b/src/react/scenes/MainContent/index.js index 2331e3f..a0ae685 100644 --- a/src/react/scenes/MainContent/index.js +++ b/src/react/scenes/MainContent/index.js @@ -1,9 +1,12 @@ import React from 'react'; -import MIDIDisplay from '../../components/MIDIDisplay'; -import MIDIControls from '../../components/MIDIControls'; import { useConfig } from '../../hooks/useConfig'; +import MIDIControls from '../../components/MIDIControls'; +import InstrumentSelector from '../../components/InstrumentSelector'; +import PianoDisplay from '../../components/PianoDisplay'; +import MIDIMessageDisplay from '../../components/MIDIMessageDisplay'; + import styles from './styles.module.css'; export default MainContent; @@ -18,10 +21,15 @@ function MainContent() {
- Input used for testing key press + + +
+ Input used for testing key press +
+
- +