refactor: don't use keyboardAwareNavigator The HOC currently forces us to expose some options in stack config which we don't want to. So we vendor this functionality for now to avoid this.

This commit is contained in:
satyajit.happy
2019-07-14 21:55:19 +02:00
parent 07b013ce49
commit 267d7c214f
5 changed files with 106 additions and 67 deletions

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import { StackRouter, createNavigator } from '@react-navigation/core';
import { createKeyboardAwareNavigator } from '@react-navigation/native';
import { Platform } from 'react-native';
import StackView from '../views/Stack/StackView';
import {
@@ -8,6 +8,7 @@ import {
NavigationProp,
Screen,
} from '../types';
import KeyboardManager from '../views/KeyboardManager';
function createStackNavigator(
routeConfigMap: {
@@ -26,13 +27,19 @@ function createStackNavigator(
) {
const router = StackRouter(routeConfigMap, stackConfig);
// Create a navigator with StackView as the view
let Navigator = createNavigator(StackView, router, stackConfig);
if (!stackConfig.disableKeyboardHandling && Platform.OS !== 'web') {
Navigator = createKeyboardAwareNavigator(Navigator, stackConfig);
if (stackConfig.disableKeyboardHandling || Platform.OS === 'web') {
return createNavigator(StackView, router, stackConfig);
}
return Navigator;
return createNavigator(
navigatorProps => (
<KeyboardManager>
{props => <StackView {...props} {...navigatorProps} />}
</KeyboardManager>
),
router,
stackConfig
);
}
export default createStackNavigator;

View File

@@ -0,0 +1,52 @@
import * as React from 'react';
import { TextInput, Keyboard } from 'react-native';
type Props = {
children: (props: {
onPageChangeStart: () => void;
onPageChangeConfirm: () => void;
onPageChangeCancel: () => void;
}) => React.ReactNode;
};
export default class KeyboardManager extends React.Component<Props> {
// 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 handlePageChangeStart = () => {
const input = TextInput.State.currentlyFocusedField();
// When a page change begins, blur the currently focused input
TextInput.State.blurTextInput(input);
// Store the id of this input so we can refocus it if change was cancelled
this.previouslyFocusedTextInput = input;
};
private handlePageChangeConfirm = () => {
Keyboard.dismiss();
// Cleanup the ID on successful page change
this.previouslyFocusedTextInput = null;
};
private handlePageChangeCancel = () => {
// The page didn't change, we should restore the focus of text input
const input = this.previouslyFocusedTextInput;
if (input) {
TextInput.State.focusTextInput(input);
}
this.previouslyFocusedTextInput = null;
};
render() {
return this.props.children({
onPageChangeStart: this.handlePageChangeStart,
onPageChangeConfirm: this.handlePageChangeConfirm,
onPageChangeCancel: this.handlePageChangeCancel,
});
}
}

View File

@@ -46,13 +46,9 @@ type Props = {
renderHeader: (props: HeaderContainerProps) => React.ReactNode;
renderScene: (props: { route: Route }) => React.ReactNode;
headerMode: HeaderMode;
onTransitionStart?: (
current: { index: number },
previous: { index: number }
) => void;
onGestureBegin?: () => void;
onGestureCanceled?: () => void;
onGestureEnd?: () => void;
onPageChangeStart?: () => void;
onPageChangeConfirm?: () => void;
onPageChangeCancel?: () => void;
};
type State = {
@@ -258,20 +254,10 @@ export default class Stack extends React.Component<Props, State> {
}));
};
private handleTransitionStart = ({
route,
current,
previous,
}: {
route: Route;
current: { index: number };
previous: { index: number };
}) => {
const { onTransitionStart, descriptors } = this.props;
private handleTransitionStart = ({ route }: { route: Route }) => {
const { descriptors } = this.props;
const descriptor = descriptors[route.key];
onTransitionStart && onTransitionStart(current, previous);
descriptor &&
descriptor.options.onTransitionStart &&
descriptor.options.onTransitionStart();
@@ -300,9 +286,9 @@ export default class Stack extends React.Component<Props, State> {
renderHeader,
renderScene,
headerMode,
onGestureBegin,
onGestureCanceled,
onGestureEnd,
onPageChangeStart,
onPageChangeConfirm,
onPageChangeCancel,
} = this.props;
const { scenes, layout, progress, floatingHeaderHeights } = this.state;
@@ -386,9 +372,9 @@ export default class Stack extends React.Component<Props, State> {
cardShadowEnabled={cardShadowEnabled}
cardStyle={cardStyle}
gesturesEnabled={index !== 0 && getGesturesEnabled({ route })}
onGestureBegin={onGestureBegin}
onGestureCanceled={onGestureCanceled}
onGestureEnd={onGestureEnd}
onPageChangeStart={onPageChangeStart}
onPageChangeConfirm={onPageChangeConfirm}
onPageChangeCancel={onPageChangeCancel}
gestureResponseDistance={gestureResponseDistance}
floatingHeaderHeight={floatingHeaderHeights[route.key]}
hasCustomHeader={header === null}

View File

@@ -33,15 +33,11 @@ type Props = TransitionPreset & {
onOpenRoute: (props: { route: Route }) => void;
onCloseRoute: (props: { route: Route }) => void;
onGoBack: (props: { route: Route }) => void;
onTransitionStart?: (props: {
route: Route;
current: { index: number };
previous: { index: number };
}) => void;
onTransitionStart?: (props: { route: Route }) => void;
onTransitionEnd?: (props: { route: Route }) => void;
onGestureBegin?: () => void;
onGestureCanceled?: () => void;
onGestureEnd?: () => void;
onPageChangeStart?: () => void;
onPageChangeConfirm?: () => void;
onPageChangeCancel?: () => void;
gestureResponseDistance?: {
vertical?: number;
horizontal?: number;
@@ -68,15 +64,21 @@ export default class StackItem extends React.PureComponent<Props> {
};
private handleTransitionStart = ({ closing }: { closing: boolean }) => {
const { index, scene, onTransitionStart, onGoBack } = this.props;
const {
scene,
onTransitionStart,
onPageChangeConfirm,
onPageChangeCancel,
onGoBack,
} = this.props;
onTransitionStart &&
onTransitionStart({
route: scene.route,
previous: { index: closing ? index - 1 : index },
current: { index },
});
if (closing) {
onPageChangeConfirm && onPageChangeConfirm();
} else {
onPageChangeCancel && onPageChangeCancel();
}
onTransitionStart && onTransitionStart({ route: scene.route });
closing && onGoBack({ route: scene.route });
};
@@ -96,9 +98,8 @@ export default class StackItem extends React.PureComponent<Props> {
cardShadowEnabled,
cardStyle,
gesturesEnabled,
onGestureBegin,
onGestureCanceled,
onGestureEnd,
onPageChangeStart,
onPageChangeCancel,
gestureResponseDistance,
floatingHeaderHeight,
hasCustomHeader,
@@ -129,9 +130,8 @@ export default class StackItem extends React.PureComponent<Props> {
shadowEnabled={cardShadowEnabled}
gesturesEnabled={gesturesEnabled}
onTransitionStart={this.handleTransitionStart}
onGestureBegin={onGestureBegin}
onGestureCanceled={onGestureCanceled}
onGestureEnd={onGestureEnd}
onGestureBegin={onPageChangeStart}
onGestureCanceled={onPageChangeCancel}
gestureResponseDistance={gestureResponseDistance}
transitionSpec={transitionSpec}
styleInterpolator={cardStyleInterpolator}

View File

@@ -16,13 +16,9 @@ type Props = {
navigation: NavigationProp;
descriptors: SceneDescriptorMap;
navigationConfig: NavigationStackConfig;
onTransitionStart?: (
current: { index: number },
previous: { index: number }
) => void;
onGestureBegin?: () => void;
onGestureCanceled?: () => void;
onGestureEnd?: () => void;
onPageChangeStart?: () => void;
onPageChangeConfirm?: () => void;
onPageChangeCancel?: () => void;
screenProps?: unknown;
};
@@ -275,10 +271,9 @@ class StackView extends React.Component<Props, State> {
const {
navigation,
navigationConfig,
onTransitionStart,
onGestureBegin,
onGestureCanceled,
onGestureEnd,
onPageChangeStart,
onPageChangeConfirm,
onPageChangeCancel,
} = this.props;
const { mode = 'card', ...config } = navigationConfig;
@@ -298,10 +293,9 @@ class StackView extends React.Component<Props, State> {
onGoBack={this.handleGoBack}
onOpenRoute={this.handleOpenRoute}
onCloseRoute={this.handleCloseRoute}
onTransitionStart={onTransitionStart}
onGestureBegin={onGestureBegin}
onGestureCanceled={onGestureCanceled}
onGestureEnd={onGestureEnd}
onPageChangeStart={onPageChangeStart}
onPageChangeConfirm={onPageChangeConfirm}
onPageChangeCancel={onPageChangeCancel}
renderHeader={this.renderHeader}
renderScene={this.renderScene}
headerMode={headerMode}