Skip to content
This repository has been archived by the owner on Feb 8, 2020. It is now read-only.

Commit

Permalink
fix: keyboard manager in stack for fast swipe
Browse files Browse the repository at this point in the history
osdnk committed Oct 24, 2019
1 parent e54d87c commit 07bfc86
Showing 1 changed file with 34 additions and 3 deletions.
37 changes: 34 additions & 3 deletions packages/stack/src/views/KeyboardManager.tsx
Original file line number Diff line number Diff line change
@@ -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() {

0 comments on commit 07bfc86

Please sign in to comment.