Skip to content

Commit

Permalink
Merge pull request #10194 from rushatgabhane/delay-focus-for-android-…
Browse files Browse the repository at this point in the history
…only

OptionsSelector - delay input focus on android only
  • Loading branch information
Luke9389 authored Aug 5, 2022
2 parents 03aad3f + 47e4cd6 commit 90b5292
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 138 deletions.
1 change: 0 additions & 1 deletion src/components/IOUConfirmationList.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,6 @@ class IOUConfirmationList extends Component {
hideAdditionalOptionStates
forceTextUnreadStyle
autoFocus
shouldDelayFocus
shouldTextInputAppearBelowOptions
shouldShowOfflineMessage
optionHoveredStyle={canModifyParticipants ? styles.hoveredComponentBG : {}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,145 +4,34 @@ import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {View, findNodeHandle} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import Button from './Button';
import FixedFooter from './FixedFooter';
import OptionsList from './OptionsList';
import Text from './Text';
import compose from '../libs/compose';
import CONST from '../CONST';
import styles from '../styles/styles';
import optionPropTypes from './optionPropTypes';
import withLocalize, {withLocalizePropTypes} from './withLocalize';
import TextInput from './TextInput';
import ArrowKeyFocusManager from './ArrowKeyFocusManager';
import KeyboardShortcut from '../libs/KeyboardShortcut';
import ONYXKEYS from '../ONYXKEYS';
import FullScreenLoadingIndicator from './FullscreenLoadingIndicator';
import Button from '../Button';
import FixedFooter from '../FixedFooter';
import OptionsList from '../OptionsList';
import Text from '../Text';
import compose from '../../libs/compose';
import CONST from '../../CONST';
import styles from '../../styles/styles';
import withLocalize from '../withLocalize';
import TextInput from '../TextInput';
import ArrowKeyFocusManager from '../ArrowKeyFocusManager';
import KeyboardShortcut from '../../libs/KeyboardShortcut';
import ONYXKEYS from '../../ONYXKEYS';
import FullScreenLoadingIndicator from '../FullscreenLoadingIndicator';
import {propTypes as optionsSelectorPropTypes, defaultProps as optionsSelectorDefaultProps} from './optionsSelectorPropTypes';

const propTypes = {
/** Whether we should wait before focusing the TextInput, useful when using transitions */
/** Whether we should wait before focusing the TextInput, useful when using transitions on Android */
shouldDelayFocus: PropTypes.bool,

/** Callback to fire when a row is tapped */
onSelectRow: PropTypes.func,

/** Sections for the section list */
sections: PropTypes.arrayOf(PropTypes.shape({
/** Title of the section */
title: PropTypes.string,

/** The initial index of this section given the total number of options in each section's data array */
indexOffset: PropTypes.number,

/** Array of options */
data: PropTypes.arrayOf(optionPropTypes),

/** Whether this section should show or not */
shouldShow: PropTypes.bool,

/** Whether this section items disabled for selection */
isDisabled: PropTypes.bool,
})).isRequired,

/** Value in the search input field */
value: PropTypes.string.isRequired,

/** Callback fired when text changes */
onChangeText: PropTypes.func.isRequired,

/** Label to display for the text input */
textInputLabel: PropTypes.string,

/** Optional placeholder text for the selector */
placeholderText: PropTypes.string,

/** Options that have already been selected */
selectedOptions: PropTypes.arrayOf(optionPropTypes),

/** Optional header message */
headerMessage: PropTypes.string,

/** Whether we can select multiple options */
canSelectMultipleOptions: PropTypes.bool,

/** Whether any section headers should be visible */
hideSectionHeaders: PropTypes.bool,

/** Whether to allow arrow key actions on the list */
disableArrowKeysActions: PropTypes.bool,

/** Whether to disable interactivity of option rows */
isDisabled: PropTypes.bool,

/** A flag to indicate whether to show additional optional states, such as pin and draft icons */
hideAdditionalOptionStates: PropTypes.bool,

/** Force the text style to be the unread style on all rows */
forceTextUnreadStyle: PropTypes.bool,

/** Whether to show the title tooltip */
showTitleTooltip: PropTypes.bool,

/** Whether to focus the textinput after an option is selected */
shouldFocusOnSelectRow: PropTypes.bool,

/** Whether to autofocus the search input on mount */
autoFocus: PropTypes.bool,

/** Should a button be shown if a selection is made (only relevant if canSelectMultipleOptions is true) */
shouldShowConfirmButton: PropTypes.bool,

/** Text to show in the confirm button (only visible if multiple options are selected) */
confirmButtonText: PropTypes.string,

/** Function to execute if the confirm button is pressed */
onConfirmSelection: PropTypes.func,

/** If true, the text input will be below the options in the selector, not above. */
shouldTextInputAppearBelowOptions: PropTypes.bool,

/** If true, a message will display in the footer if the app is offline. */
shouldShowOfflineMessage: PropTypes.bool,

/** Custom content to display in the footer instead of the default button. */
footerContent: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),

/** Hover style for options in the OptionsList */
optionHoveredStyle: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),

/** Whether to show options list */
shouldShowOptions: PropTypes.bool,

...withLocalizePropTypes,
...optionsSelectorPropTypes,
};

const defaultProps = {
shouldDelayFocus: false,
onSelectRow: () => {},
textInputLabel: '',
placeholderText: '',
selectedOptions: [],
headerMessage: '',
canSelectMultipleOptions: false,
hideSectionHeaders: false,
hideAdditionalOptionStates: false,
forceTextUnreadStyle: false,
showTitleTooltip: false,
shouldFocusOnSelectRow: false,
autoFocus: true,
shouldShowConfirmButton: false,
confirmButtonText: undefined,
onConfirmSelection: () => {},
shouldTextInputAppearBelowOptions: false,
shouldShowOfflineMessage: false,
footerContent: undefined,
optionHoveredStyle: styles.hoveredComponentBG,
shouldShowOptions: true,
disableArrowKeysActions: false,
isDisabled: false,
...optionsSelectorDefaultProps,
};

class OptionsSelector extends Component {
class BaseOptionsSelector extends Component {
constructor(props) {
super(props);

Expand Down Expand Up @@ -427,13 +316,14 @@ class OptionsSelector extends Component {
}
}

OptionsSelector.defaultProps = defaultProps;
OptionsSelector.propTypes = propTypes;
BaseOptionsSelector.defaultProps = defaultProps;
BaseOptionsSelector.propTypes = propTypes;

export default compose(
withLocalize,
withOnyx({
network: {
key: ONYXKEYS.NETWORK,
},
}),
)(OptionsSelector);
)(BaseOptionsSelector);
18 changes: 18 additions & 0 deletions src/components/OptionsSelector/index.android.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React, {forwardRef} from 'react';
import BaseOptionsSelector from './BaseOptionsSelector';
import {propTypes, defaultProps} from './optionsSelectorPropTypes';

const OptionsSelector = forwardRef((props, ref) => (
<BaseOptionsSelector
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
ref={ref}
shouldDelayFocus
/>
));

OptionsSelector.propTypes = propTypes;
OptionsSelector.defaultProps = defaultProps;
OptionsSelector.displayName = 'OptionsSelector';

export default OptionsSelector;
17 changes: 17 additions & 0 deletions src/components/OptionsSelector/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React, {forwardRef} from 'react';
import BaseOptionsSelector from './BaseOptionsSelector';
import {propTypes, defaultProps} from './optionsSelectorPropTypes';

const OptionsSelector = forwardRef((props, ref) => (
<BaseOptionsSelector
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
ref={ref}
/>
));

OptionsSelector.propTypes = propTypes;
OptionsSelector.defaultProps = defaultProps;
OptionsSelector.displayName = 'OptionsSelector';

export default OptionsSelector;
125 changes: 125 additions & 0 deletions src/components/OptionsSelector/optionsSelectorPropTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import PropTypes from 'prop-types';
import optionPropTypes from '../optionPropTypes';
import {withLocalizePropTypes} from '../withLocalize';
import styles from '../../styles/styles';

const propTypes = {
/** Callback to fire when a row is tapped */
onSelectRow: PropTypes.func,

/** Sections for the section list */
sections: PropTypes.arrayOf(PropTypes.shape({
/** Title of the section */
title: PropTypes.string,

/** The initial index of this section given the total number of options in each section's data array */
indexOffset: PropTypes.number,

/** Array of options */
data: PropTypes.arrayOf(optionPropTypes),

/** Whether this section should show or not */
shouldShow: PropTypes.bool,

/** Whether this section items disabled for selection */
isDisabled: PropTypes.bool,
})).isRequired,

/** Value in the search input field */
value: PropTypes.string.isRequired,

/** Callback fired when text changes */
onChangeText: PropTypes.func.isRequired,

/** Label to display for the text input */
textInputLabel: PropTypes.string,

/** Optional placeholder text for the selector */
placeholderText: PropTypes.string,

/** Options that have already been selected */
selectedOptions: PropTypes.arrayOf(optionPropTypes),

/** Optional header message */
headerMessage: PropTypes.string,

/** Whether we can select multiple options */
canSelectMultipleOptions: PropTypes.bool,

/** Whether any section headers should be visible */
hideSectionHeaders: PropTypes.bool,

/** Whether to allow arrow key actions on the list */
disableArrowKeysActions: PropTypes.bool,

/** Whether to disable interactivity of option rows */
isDisabled: PropTypes.bool,

/** A flag to indicate whether to show additional optional states, such as pin and draft icons */
hideAdditionalOptionStates: PropTypes.bool,

/** Force the text style to be the unread style on all rows */
forceTextUnreadStyle: PropTypes.bool,

/** Whether to show the title tooltip */
showTitleTooltip: PropTypes.bool,

/** Whether to focus the textinput after an option is selected */
shouldFocusOnSelectRow: PropTypes.bool,

/** Whether to autofocus the search input on mount */
autoFocus: PropTypes.bool,

/** Should a button be shown if a selection is made (only relevant if canSelectMultipleOptions is true) */
shouldShowConfirmButton: PropTypes.bool,

/** Text to show in the confirm button (only visible if multiple options are selected) */
confirmButtonText: PropTypes.string,

/** Function to execute if the confirm button is pressed */
onConfirmSelection: PropTypes.func,

/** If true, the text input will be below the options in the selector, not above. */
shouldTextInputAppearBelowOptions: PropTypes.bool,

/** If true, a message will display in the footer if the app is offline. */
shouldShowOfflineMessage: PropTypes.bool,

/** Custom content to display in the footer instead of the default button. */
footerContent: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),

/** Hover style for options in the OptionsList */
optionHoveredStyle: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),

/** Whether to show options list */
shouldShowOptions: PropTypes.bool,

...withLocalizePropTypes,
};

const defaultProps = {
onSelectRow: () => {},
textInputLabel: '',
placeholderText: '',
selectedOptions: [],
headerMessage: '',
canSelectMultipleOptions: false,
hideSectionHeaders: false,
hideAdditionalOptionStates: false,
forceTextUnreadStyle: false,
showTitleTooltip: false,
shouldFocusOnSelectRow: false,
autoFocus: true,
shouldShowConfirmButton: false,
confirmButtonText: undefined,
onConfirmSelection: () => {},
shouldTextInputAppearBelowOptions: false,
shouldShowOfflineMessage: false,
footerContent: undefined,
optionHoveredStyle: styles.hoveredComponentBG,
shouldShowOptions: true,
disableArrowKeysActions: false,
isDisabled: false,
};

export {propTypes, defaultProps};
1 change: 0 additions & 1 deletion src/pages/NewChatPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,6 @@ class NewChatPage extends Component {
{!didScreenTransitionEnd && <FullScreenLoadingIndicator />}
{didScreenTransitionEnd && (
<OptionsSelector
shouldDelayFocus
canSelectMultipleOptions={this.props.isGroupChat}
sections={sections}
selectedOptions={this.state.selectedOptions}
Expand Down
1 change: 0 additions & 1 deletion src/pages/SearchPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ class SearchPage extends Component {
/>
<View style={[styles.flex1, styles.w100, styles.pRelative]}>
<OptionsSelector
shouldDelayFocus
sections={sections}
value={this.state.searchValue}
onSelectRow={this.selectReport}
Expand Down
1 change: 0 additions & 1 deletion src/pages/iou/IOUCurrencySelection.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ class IOUCurrencySelection extends Component {
onSelectRow={this.confirmCurrencySelection}
value={this.state.searchValue}
onChangeText={this.changeSearchValue}
shouldDelayFocus
placeholderText={this.props.translate('common.search')}
headerMessage={headerMessage}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ class IOUParticipantsRequest extends Component {
headerMessage={headerMessage}
hideAdditionalOptionStates
forceTextUnreadStyle
shouldDelayFocus
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,6 @@ class IOUParticipantsSplit extends Component {
headerMessage={headerMessage}
hideAdditionalOptionStates
forceTextUnreadStyle
shouldDelayFocus
shouldShowConfirmButton
confirmButtonText={this.props.translate('common.next')}
onConfirmSelection={this.finalizeParticipants}
Expand Down

0 comments on commit 90b5292

Please sign in to comment.