2020-05-01 05:54:12 +03:00
|
|
|
import React, { Component } from 'react';
|
2020-08-13 21:52:00 +03:00
|
|
|
import { cite } from '../../../../logic/lib/util';
|
2020-05-01 05:54:12 +03:00
|
|
|
import { Spinner } from '../../../components/Spinner';
|
|
|
|
|
|
|
|
export class Input extends Component {
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
|
|
|
awaiting: false,
|
|
|
|
type: 'Sending to Dojo'
|
|
|
|
};
|
|
|
|
this.keyPress = this.keyPress.bind(this);
|
|
|
|
this.inputRef = React.createRef();
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidUpdate() {
|
|
|
|
this.inputRef.current.setSelectionRange(this.props.cursor, this.props.cursor);
|
|
|
|
}
|
|
|
|
|
|
|
|
keyPress = (e) => {
|
|
|
|
if ((e.getModifierState('Control') || event.getModifierState('Meta'))
|
|
|
|
&& e.key === 'v') {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
const allowedKeys = [
|
|
|
|
'Enter', 'Backspace', 'ArrowLeft', 'ArrowRight', 'Tab'
|
|
|
|
];
|
|
|
|
|
|
|
|
if ((e.key.length > 1) && (!(allowedKeys.includes(e.key)))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// submit on enter
|
|
|
|
if (e.key === 'Enter') {
|
|
|
|
this.setState({ awaiting: true, type: 'Sending to Dojo' });
|
2020-05-12 00:58:13 +03:00
|
|
|
this.props.api.soto('ret').then(() => {
|
2020-05-01 05:54:12 +03:00
|
|
|
this.setState({ awaiting: false });
|
|
|
|
});
|
|
|
|
} else if ((e.key === 'Backspace') && (this.props.cursor > 0)) {
|
2020-05-12 00:58:13 +03:00
|
|
|
this.props.store.doEdit({ del: this.props.cursor - 1 });
|
|
|
|
return this.props.store.setState({ cursor: this.props.cursor - 1 });
|
2020-05-01 05:54:12 +03:00
|
|
|
} else if (e.key === 'Backspace') {
|
|
|
|
return;
|
|
|
|
} else if (e.key.startsWith('Arrow')) {
|
|
|
|
if (e.key === 'ArrowLeft') {
|
|
|
|
if (this.props.cursor > 0) {
|
2020-05-12 00:58:13 +03:00
|
|
|
this.props.store.setState({ cursor: this.props.cursor - 1 });
|
2020-05-01 05:54:12 +03:00
|
|
|
}
|
|
|
|
} else if (e.key === 'ArrowRight') {
|
|
|
|
if (this.props.cursor < this.props.input.length) {
|
2020-05-12 00:58:13 +03:00
|
|
|
this.props.store.setState({ cursor: this.props.cursor + 1 });
|
2020-05-01 05:54:12 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// tab completion
|
|
|
|
else if (e.key === 'Tab') {
|
|
|
|
this.setState({ awaiting: true, type: 'Getting suggestions' });
|
2020-05-12 00:58:13 +03:00
|
|
|
this.props.api.soto({ tab: this.props.cursor }).then(() => {
|
2020-05-01 05:54:12 +03:00
|
|
|
this.setState({ awaiting: false });
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// capture and transmit most characters
|
|
|
|
else {
|
2020-05-12 00:58:13 +03:00
|
|
|
this.props.store.doEdit({ ins: { cha: e.key, at: this.props.cursor } });
|
|
|
|
this.props.store.setState({ cursor: this.props.cursor + 1 });
|
2020-05-01 05:54:12 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
return (
|
|
|
|
<div className="flex flex-row flex-grow-1 relative">
|
|
|
|
<div className="flex-shrink-0">{cite(this.props.ship)}:dojo
|
|
|
|
</div>
|
|
|
|
<span id="prompt">
|
|
|
|
{this.props.prompt}
|
|
|
|
</span>
|
|
|
|
<input
|
|
|
|
autoCorrect="false"
|
|
|
|
autoFocus={true}
|
|
|
|
className="mono ml1 flex-auto dib w-100"
|
2020-05-07 06:21:03 +03:00
|
|
|
id="dojo"
|
2020-05-01 05:54:12 +03:00
|
|
|
cursor={this.props.cursor}
|
2020-05-12 00:58:13 +03:00
|
|
|
onClick={e => this.props.store.setState({ cursor: e.target.selectionEnd })}
|
2020-05-01 05:54:12 +03:00
|
|
|
onKeyDown={this.keyPress}
|
|
|
|
onPaste={(e) => {
|
|
|
|
const clipboardData = e.clipboardData || window.clipboardData;
|
|
|
|
const paste = Array.from(clipboardData.getData('Text'));
|
|
|
|
paste.reduce(async (previous, next) => {
|
|
|
|
await previous;
|
|
|
|
this.setState({ cursor: this.props.cursor + 1 });
|
2020-05-12 00:58:13 +03:00
|
|
|
return this.props.store.doEdit({ ins: { cha: next, at: this.props.cursor } });
|
2020-05-01 05:54:12 +03:00
|
|
|
}, Promise.resolve());
|
|
|
|
e.preventDefault();
|
|
|
|
}}
|
|
|
|
ref={this.inputRef}
|
|
|
|
defaultValue={this.props.input}
|
|
|
|
/>
|
|
|
|
<Spinner awaiting={this.state.awaiting} text={`${this.state.type}...`} classes="absolute right-0 bottom-0 inter pa ba pa2 b--gray1-d" />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Input;
|