UNPKG

3.52 kBJavaScriptView Raw
1import * as React from 'react';
2import { Keyboard, TextInput } from 'react-native';
3export default function useKeyboardManager(isEnabled) {
4 // Numeric id of the previously focused text input
5 // When a gesture didn't change the tab, we can restore the focused input with this
6 const previouslyFocusedTextInputRef = React.useRef(undefined);
7 const startTimestampRef = React.useRef(0);
8 const keyboardTimeoutRef = React.useRef();
9 const clearKeyboardTimeout = React.useCallback(() => {
10 if (keyboardTimeoutRef.current !== undefined) {
11 clearTimeout(keyboardTimeoutRef.current);
12 keyboardTimeoutRef.current = undefined;
13 }
14 }, []);
15 const onPageChangeStart = React.useCallback(() => {
16 if (!isEnabled()) {
17 return;
18 }
19
20 clearKeyboardTimeout();
21 const input = TextInput.State.currentlyFocusedInput(); // When a page change begins, blur the currently focused input
22
23 input === null || input === void 0 ? void 0 : input.blur(); // Store the id of this input so we can refocus it if change was cancelled
24
25 previouslyFocusedTextInputRef.current = input; // Store timestamp for touch start
26
27 startTimestampRef.current = Date.now();
28 }, [clearKeyboardTimeout, isEnabled]);
29 const onPageChangeConfirm = React.useCallback(force => {
30 if (!isEnabled()) {
31 return;
32 }
33
34 clearKeyboardTimeout();
35
36 if (force) {
37 // Always dismiss input, even if we don't have a ref to it
38 // We might not have the ref if onPageChangeStart was never called
39 // This can happen if page change was not from a gesture
40 Keyboard.dismiss();
41 } else {
42 const input = previouslyFocusedTextInputRef.current; // Dismiss the keyboard only if an input was a focused before
43 // This makes sure we don't dismiss input on going back and focusing an input
44
45 input === null || input === void 0 ? void 0 : input.blur();
46 } // Cleanup the ID on successful page change
47
48
49 previouslyFocusedTextInputRef.current = undefined;
50 }, [clearKeyboardTimeout, isEnabled]);
51 const onPageChangeCancel = React.useCallback(() => {
52 if (!isEnabled()) {
53 return;
54 }
55
56 clearKeyboardTimeout(); // The page didn't change, we should restore the focus of text input
57
58 const input = previouslyFocusedTextInputRef.current;
59
60 if (input) {
61 // If the interaction was super short we should make sure keyboard won't hide again.
62 // Too fast input refocus will result only in keyboard flashing on screen and hiding right away.
63 // During first ~100ms keyboard will be dismissed no matter what,
64 // so we have to make sure it won't interrupt input refocus logic.
65 // That's why when the interaction is shorter than 100ms we add delay so it won't hide once again.
66 // Subtracting timestamps makes us sure the delay is executed only when needed.
67 if (Date.now() - startTimestampRef.current < 100) {
68 keyboardTimeoutRef.current = setTimeout(() => {
69 input === null || input === void 0 ? void 0 : input.focus();
70 previouslyFocusedTextInputRef.current = undefined;
71 }, 100);
72 } else {
73 input === null || input === void 0 ? void 0 : input.focus();
74 previouslyFocusedTextInputRef.current = undefined;
75 }
76 }
77 }, [clearKeyboardTimeout, isEnabled]);
78 React.useEffect(() => {
79 return () => clearKeyboardTimeout();
80 }, [clearKeyboardTimeout]);
81 return {
82 onPageChangeStart,
83 onPageChangeConfirm,
84 onPageChangeCancel
85 };
86}
87//# sourceMappingURL=useKeyboardManager.js.map
\No newline at end of file