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() {