-
Notifications
You must be signed in to change notification settings - Fork 5
/
index.js
145 lines (131 loc) · 4.75 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import React from 'react';
import PropTypes from 'prop-types';
// import { connect } from 'react-redux';
// import { createStructuredSelector } from 'reselect';
import bind from 'wanakana/bind';
import unbind from 'wanakana/unbind';
import { SRS_RANKS, KEYCODES } from 'shared/constants';
import blockEvent from 'utils/blockEvent';
import ReviewAnswer from 'components/ReviewAnswer';
// import actions from 'containers/App/actions';
// import reviewActions from 'containers/ReviewSession/actions';
// import { selectAnswer, selectCurrentStreakName } from 'containers/ReviewSession/selectors';
// props from selectors
export class ReviewAnswerContainer extends React.Component {
static propTypes = {
streakName: PropTypes.oneOf(Object.values(SRS_RANKS)).isRequired,
answer: PropTypes.shape({
value: PropTypes.string,
marked: PropTypes.bool,
disabled: PropTypes.bool,
focus: PropTypes.bool,
correct: PropTypes.bool,
incorrect: PropTypes.bool,
valid: PropTypes.bool,
}),
checkAnswer: PropTypes.func.isRequired,
updateAnswer: PropTypes.func.isRequired,
recordAnswer: PropTypes.func.isRequired,
ignoreAnswer: PropTypes.func.isRequired,
showPanel: PropTypes.func.isRequired,
cycleInfoDetail: PropTypes.func.isRequired,
}
// TODO: these could potentially be state
// have to check sagas carefully though for any hooks
// passing the state in dispatched actions should be fine though
// though only interesting one is resetAnswer() when rotating
static defaultProps = {
// TODO: proper bool state naming isDisabled, isCorrect etc
answer: {
value: '',
marked: false,
disabled: false,
focus: false,
correct: false,
incorrect: false,
valid: true,
},
}
componentDidMount() {
// could probably use toKana() in handleKeyDown instead?
// depends on any quirks of IMEMode handling selection and 3char chunks
bind(this.inputFieldRef);
this.inputFieldRef.addEventListener('keydown', this.handleKeyDown);
}
componentDidUpdate() {
if (this.props.answer.focus) {
this.inputFieldRef.focus();
}
}
componentWillUnmount() {
this.inputFieldRef.removeEventListener('keydown', this.handleKeyDown);
unbind(this.inputFieldRef);
}
// move up to parent ReviewsPage/Page level?
// check target isn't synonym form?
getKeyHandler = (keycode) => ({
[KEYCODES.ENTER]: this.props.recordAnswer,
[KEYCODES.SPACE]: this.props.cycleInfoDetail,
[KEYCODES.N_LOWERCASE]: () => this.props.showPanel('notes'),
[KEYCODES.F_LOWERCASE]: () => this.props.showPanel('info'),
[KEYCODES.S_LOWERCASE]: () => this.props.showPanel('synonym'),
[KEYCODES.I_LOWERCASE]: this.handleIgnore,
[KEYCODES.BACKSPACE]: this.handleIgnore,
[KEYCODES.FORWARD_SLASH]: this.handleIgnore,
}[keycode])
handleKeyDown = (event) => {
const action = this.getKeyHandler(event.keyCode);
if (this.props.answer.disabled && action) {
blockEvent(event);
action();
}
}
handleInput = (event) => {
this.props.updateAnswer(event.target.value);
}
handleIgnore = () => {
// should really be passing these kinda details from state to sagas in the other handleFuncs
this.props.ignoreAnswer(this.props.answer.correct);
}
handleSubmit = (event) => {
blockEvent(event);
if (this.props.answer.disabled) {
this.props.recordAnswer();
} else if (!this.props.answer.valid || !this.props.answer.marked) {
this.props.checkAnswer();
}
}
render() {
const { answer, streakName } = this.props;
return (
<ReviewAnswer
isMarked={answer.marked}
isFocused={answer.focus}
isValid={answer.valid}
isCorrect={answer.correct}
isIncorrect={answer.incorrect}
isDisabled={answer.disabled}
streakName={streakName}
handleSubmit={this.handleSubmit}
handleIgnore={this.handleIgnore}
handleInput={this.handleInput}
inputFieldRef={(node) => { this.inputFieldRef = node; }}
inputFieldValue={answer.value}
/>
);
}
}
// const mapStateToProps = createStructuredSelector({
// answer: selectAnswer,
// streak: selectCurrentStreak,
// });
//
// const mapDispatchToProps = (dispatch) => ({
// updateAnswer: (value) => dispatch(reviewActions.updateAnswerInput({ input: value })),
// checkAnswer: () => dispatch(reviewActions.checkAnswer()),
// recordAnswer: () => dispatch(reviewActions.recordAnswerRequest()),
// ignoreAnswer: (correctness) => dispatch(reviewActions.markIgnored(correctness)),
// showPanel: (name) => dispatch(reviewActions.showPanel(name)),
// cycleInfoDetail: () => dispatch(globalActions.cycleInfoDetail()),
// });
export default /* connect(mapStateToProps, mapDispatchToProps)(*/ReviewAnswerContainer/* )*/;