fix: keyboard manager in stack for fast swipe

This commit is contained in:
osdnk
2019-10-24 18:50:16 +02:00
parent e54d87c41c
commit 07bfc86327

View File

@@ -11,14 +11,27 @@ type Props = {
};
export default class KeyboardManager extends React.Component<Props> {
componentWillUnmount = () => {
this.clearKeyboardTimeout();
};
// Numeric id of the previously focused text input
// When a gesture didn't change the tab, we can restore the focused input with this
private previouslyFocusedTextInput: number | null = null;
private startTimestamp: number = 0;
private keyboardTimeout: NodeJS.Timeout | undefined;
clearKeyboardTimeout = () => {
if (this.keyboardTimeout !== undefined) {
clearTimeout(this.keyboardTimeout);
this.keyboardTimeout = undefined;
}
};
private handlePageChangeStart = () => {
if (!this.props.enabled) {
return;
}
this.clearKeyboardTimeout();
const input = TextInput.State.currentlyFocusedField();
@@ -27,12 +40,16 @@ export default class KeyboardManager extends React.Component<Props> {
// Store the id of this input so we can refocus it if change was cancelled
this.previouslyFocusedTextInput = input;
// Store timestamp for touch start
this.startTimestamp = Date.now();
};
private handlePageChangeConfirm = () => {
if (!this.props.enabled) {
return;
}
this.clearKeyboardTimeout();
Keyboard.dismiss();
@@ -44,15 +61,29 @@ export default class KeyboardManager extends React.Component<Props> {
if (!this.props.enabled) {
return;
}
this.clearKeyboardTimeout();
// The page didn't change, we should restore the focus of text input
const input = this.previouslyFocusedTextInput;
if (input) {
TextInput.State.focusTextInput(input);
}
// If the interaction was super short we should make sure keyboard won't hide again.
this.previouslyFocusedTextInput = null;
// Too fast input refocus will result only in keyboard flashing on screen and hiding right away.
// During first ~100ms keyboard will be dismissed no matter what,
// so we have to make sure it won't interrupt input refocus logic.
// That's why when the interaction is shorter than 100ms we add delay so it won't hide once again.
// Subtracting timestamps makes us sure the delay is executed only when needed.
if (Date.now() - this.startTimestamp < 100) {
this.keyboardTimeout = setTimeout(() => {
TextInput.State.focusTextInput(input);
this.previouslyFocusedTextInput = null;
}, 100);
} else {
TextInput.State.focusTextInput(input);
this.previouslyFocusedTextInput = null;
}
}
};
render() {