diff --git a/package-lock.json b/package-lock.json
index 17e7e29..8a19fa8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17951,6 +17951,11 @@
"react-is": "^16.12.0 || ^17.0.0"
}
},
+ "react-simple-keyboard": {
+ "version": "3.4.65",
+ "resolved": "https://registry.npmjs.org/react-simple-keyboard/-/react-simple-keyboard-3.4.65.tgz",
+ "integrity": "sha512-SSxAXk/I6ry4oWi/Z2e1s21mtwBuNJLiMOJIprTf2OAniVxEf+PH5zupWu07wbNCMDsMv3uhdaJAR/W3kVMieg=="
+ },
"react-test-renderer": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-17.0.2.tgz",
@@ -18749,6 +18754,11 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
},
+ "simple-keyboard-layouts": {
+ "version": "3.1.54",
+ "resolved": "https://registry.npmjs.org/simple-keyboard-layouts/-/simple-keyboard-layouts-3.1.54.tgz",
+ "integrity": "sha512-JZ2zR0rq3rctFjmYo33YiXoZ535Y8m/LBk2qBWP/MZAOjRi2XpXaJnhQrWnVYQv6CP2kOlZZvEQAzn3DhZlQFA=="
+ },
"simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
diff --git a/package.json b/package.json
index fa4a485..fda0931 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "parandum",
- "version": "2.1.8",
+ "version": "2.1.9",
"private": true,
"dependencies": {
"@babel/core": "^7.16.0",
@@ -27,7 +27,9 @@
"react-router-dom": "^5.3.0",
"react-scripts": "^5.0.0-next.47",
"react-select": "^5.2.1",
+ "react-simple-keyboard": "^3.4.65",
"react-xarrows": "^2.0.2",
+ "simple-keyboard-layouts": "^3.1.54",
"styled-components": "^5.3.3",
"typescript": "^4.5.2",
"universal-cookie": "^4.0.4",
diff --git a/src/Progress.js b/src/Progress.js
index 76428cc..67e04dc 100644
--- a/src/Progress.js
+++ b/src/Progress.js
@@ -60,6 +60,10 @@ export default withRouter(class Progress extends React.Component {
sound: false,
ignoreCaps: false,
numberOfAnswers: null,
+ virtualKeyboardLanguage: "english",
+ virtualKeyboardLayoutName: "default",
+ showVirtualKeyboard: false,
+ showVirtualKeyboardOptions: false,
}
constructor(props) {
@@ -73,6 +77,12 @@ export default withRouter(class Progress extends React.Component {
createProgressWithIncorrect: props.functions.httpsCallable("createProgressWithIncorrect"),
},
navbarItems: [
+ {
+ type: "button",
+ onClick: this.showVirtualKeyboardOptions,
+ icon: ,
+ hideTextMobile: true,
+ },
{
type: "button",
onClick: this.showSettings,
@@ -88,6 +98,16 @@ export default withRouter(class Progress extends React.Component {
],
...this.changeableStateItems,
};
+
+ this.keyboardLayouts = new KeyboardLayouts();
+ this.keyboardLayoutsObj = this.keyboardLayouts.get();
+ this.keyboardLayoutNames = Object.keys(this.keyboardLayoutsObj).map(key =>
+ [
+ key,
+ // title case from camel case
+ key.charAt(0).toUpperCase() + key.slice(1).replace(/([A-Z])/g, " $1")
+ ]
+ );
let isMounted = true;
Object.defineProperty(this, "isMounted", {
@@ -300,15 +320,34 @@ export default withRouter(class Progress extends React.Component {
this.setState({
answerInput: event.target.value,
});
+ this.virtualKeyboard.setInput(event.target.value);
}
}
- proceed = () => {
+ onVirtualKeyboardChange = (answerInput) => {
+ this.setState({ answerInput });
+ };
+
+ onVirtualKeyboardKeyPress = (button) => {
+ if (button === "{shift}" || button === "{lock}") {
+ this.handleVirtualKeyboardShift();
+ } else if (button === "{enter}") {
+ this.proceed("virtual");
+ }
+ };
+
+ handleVirtualKeyboardShift = () => {
+ this.setState({
+ layoutName: this.state.virtualKeyboardLayoutName === "default" ? "shift" : "default",
+ });
+ }
+
+ proceed = (referrer="physical") => {
if (this.state.canProceed) {
if (this.state.currentAnswerStatus === null) {
- this.processAnswer();
+ this.processAnswer(referrer);
} else {
- this.nextQuestion();
+ this.nextQuestion(referrer);
}
}
}
@@ -325,7 +364,7 @@ export default withRouter(class Progress extends React.Component {
return newString;
}
- processAnswer = async () => {
+ processAnswer = async (referrer="physical") => {
if (this.state.canProceed) {
this.startLoading();
@@ -484,7 +523,7 @@ export default withRouter(class Progress extends React.Component {
await Promise.all(promises);
this.setState(newState, () => {
- if (!newState.duration) this.answerInput.focus()
+ if (!newState.duration && referrer === "physical") this.answerInput.focus();
});
}).catch((error) => {
console.log(`Couldn't process answer: ${error}`);
@@ -497,7 +536,11 @@ export default withRouter(class Progress extends React.Component {
}
showNextQuestion = (newState, currentState) => {
- if (currentState.nextPrompt === null) newState.setComplete = true;
+ if (currentState.nextPrompt === null) {
+ newState.setComplete = true;
+ this.virtualKeyboard.clearInput();
+ newState.showVirtualKeyboard = false;
+ }
newState.currentCorrect = [];
newState.currentPrompt = currentState.nextPrompt;
newState.currentSound = currentState.nextSound;
@@ -505,7 +548,7 @@ export default withRouter(class Progress extends React.Component {
return newState;
}
- nextQuestion = () => {
+ nextQuestion = (referrer="physical") => {
if (this.state.canProceed) {
this.startLoading();
@@ -520,7 +563,12 @@ export default withRouter(class Progress extends React.Component {
newState = this.showNextQuestion(newState, this.state);
}
- this.setState(newState, () => (this.isMounted && !this.state.setComplete) && this.answerInput.focus());
+ this.setState(newState, () => {
+ this.virtualKeyboard.clearInput();
+ if (this.isMounted && !this.state.setComplete && referrer === "physical") {
+ this.answerInput.focus();
+ }
+ });
}
}
@@ -634,6 +682,33 @@ export default withRouter(class Progress extends React.Component {
});
}
+ showVirtualKeyboardOptions = () => {
+ this.setState({
+ showVirtualKeyboardOptions: true,
+ })
+ }
+
+ hideVirtualKeyboardOptions = () => {
+ this.setState({
+ showVirtualKeyboardOptions: false,
+ })
+ }
+
+ showVirtualKeyboard = (language) => {
+ this.setState({
+ showVirtualKeyboard: true,
+ showVirtualKeyboardOptions: false,
+ virtualKeyboardLanguage: language,
+ });
+ }
+
+ hideVirtualKeyboard = () => {
+ this.setState({
+ showVirtualKeyboard: false,
+ showVirtualKeyboardOptions: false,
+ });
+ }
+
render() {
return (
@@ -665,7 +740,7 @@ export default withRouter(class Progress extends React.Component {
autoCorrect="off"
/>