Skip to content

Commit

Permalink
RN-458: Take scroll control when autocomplete in use (#3879)
Browse files Browse the repository at this point in the history
  • Loading branch information
edmofro authored May 23, 2022
1 parent 89fc9a5 commit c2ff891
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export class AutocompleteQuestionComponent extends React.Component {

render() {
const { optionList } = this.state;
const { answer, onChangeAnswer } = this.props;
const { answer, onChangeAnswer, scrollIntoFocus } = this.props;
return (
<View>
<Autocomplete
Expand All @@ -123,6 +123,7 @@ export class AutocompleteQuestionComponent extends React.Component {
options={optionList}
handleEndReached={this.fetchMoreResults}
handleChangeInput={this.filterOptionList}
scrollIntoFocus={scrollIntoFocus}
endReachedOffset={0.3}
/>
</View>
Expand All @@ -137,6 +138,7 @@ AutocompleteQuestionComponent.propTypes = {
onChangeAnswer: PropTypes.func.isRequired,
optionSetId: PropTypes.string.isRequired,
realmDatabase: PropTypes.any.isRequired,
scrollIntoFocus: PropTypes.func.isRequired,
};

AutocompleteQuestionComponent.defaultProps = {
Expand Down
68 changes: 50 additions & 18 deletions packages/meditrak-app/app/widgets/Autocomplete/Autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { View, StyleSheet, FlatList, TextInput, Platform, Text } from 'react-native';
import { Dimensions, View, StyleSheet, FlatList, TextInput, Platform, Text } from 'react-native';
import { takeScrollControl, releaseScrollControl } from '../../assessment/actions';
import {
THEME_FONT_FAMILY,
Expand All @@ -23,14 +23,31 @@ class AutocompleteComponent extends PureComponent {

this.state = {
isFocused: false,
isOpen: false,
searchTerm: '',
};
}

openResults = () => {
this.props.takeScrollControl();
this.props.scrollIntoFocus();
this.setState({
isOpen: true,
});
};

closeResults = () => {
this.props.releaseScrollControl();
this.setState({
isOpen: false,
});
};

handleFocus = () => {
this.setState({
isFocused: true,
});
this.openResults();
};

handleBlur = () => {
Expand All @@ -55,23 +72,39 @@ class AutocompleteComponent extends PureComponent {

onOptionPress = option => {
this.props.handleSelectOption(option);
this.closeResults();
};

onEndReached = () => {
const { handleEndReached } = this.props;
if (handleEndReached) handleEndReached();
};

getRightButtonProps = () => {
// use an "x" to represent clear if an option is selected or a search term entered
if (this.props.selectedOption || this.state.searchTerm) {
return {
name: 'times',
onPress: this.clearSelection,
};
}

// otherwise show up/down arrows to open/close the full set of results
if (this.state.isOpen) {
return {
name: 'caret-up',
onPress: this.closeResults,
};
}
return {
name: 'caret-down',
onPress: this.openResults,
};
};

render() {
const { searchTerm, isFocused } = this.state;
const {
placeholder,
selectedOption,
options,
endReachedOffset,
takeScrollControl,
releaseScrollControl,
} = this.props;
const { searchTerm, isFocused, isOpen } = this.state;
const { placeholder, selectedOption, options, endReachedOffset } = this.props;
return (
<View style={localStyles.wrapper}>
<Icon
Expand All @@ -85,11 +118,9 @@ class AutocompleteComponent extends PureComponent {
value={selectedOption || searchTerm}
selectTextOnFocus
onFocus={() => {
takeScrollControl();
this.handleFocus();
}}
onBlur={() => {
releaseScrollControl();
this.handleBlur();
}}
placeholder={placeholder}
Expand All @@ -101,8 +132,8 @@ class AutocompleteComponent extends PureComponent {
isFocused ? localStyles.textInputFocussed : {},
]}
/>
<Icon name="times" size={20} style={localStyles.clearIcon} onPress={this.clearSelection} />
{!selectedOption && options.length > 0 && (
<Icon size={20} style={localStyles.rightButton} {...this.getRightButtonProps()} />
{!selectedOption && options.length > 0 && isOpen && (
<View style={{ flex: 1 }}>
<FlatList
data={options}
Expand Down Expand Up @@ -136,8 +167,9 @@ Autocomplete.propTypes = {
handleSelectOption: PropTypes.func.isRequired,
handleChangeInput: PropTypes.func.isRequired,
handleEndReached: PropTypes.func,
takeScrollControl: PropTypes.func,
releaseScrollControl: PropTypes.func,
takeScrollControl: PropTypes.func.isRequired,
releaseScrollControl: PropTypes.func.isRequired,
scrollIntoFocus: PropTypes.func.isRequired,
endReachedOffset: PropTypes.number,
options: PropTypes.arrayOf(PropTypes.string).isRequired,
};
Expand Down Expand Up @@ -179,10 +211,10 @@ const localStyles = StyleSheet.create({
height: 40,
},
optionList: {
height: 200,
height: Dimensions.get('window').height, // fixed height so FlatList optimisations work within the outer ScrollView
flex: 1,
},
clearIcon: {
rightButton: {
position: 'absolute',
padding: 10,
right: 0,
Expand Down

0 comments on commit c2ff891

Please sign in to comment.