From 29054346c62ea4b6be5c8f1a0252a043e929d42b Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Tue, 4 May 2021 15:02:58 +0530 Subject: [PATCH 1/6] fix: modal animations --- src/components/OptionsSelector.js | 18 ++++++++++++++++-- .../Navigation/AppNavigator/AuthScreens.js | 2 +- .../AppNavigator/modalCardStyleInterpolator.js | 18 +++++++++++------- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/components/OptionsSelector.js b/src/components/OptionsSelector.js index 8e976eab31c7..3b2bb02dc2c7 100644 --- a/src/components/OptionsSelector.js +++ b/src/components/OptionsSelector.js @@ -2,6 +2,7 @@ import _ from 'underscore'; import React, {Component} from 'react'; import PropTypes from 'prop-types'; import {View} from 'react-native'; +import {withNavigation} from '@react-navigation/compat'; import TextInputWithFocusStyles from './TextInputWithFocusStyles'; import OptionsList from './OptionsList'; import styles from '../styles/styles'; @@ -59,6 +60,13 @@ const propTypes = { // Whether to show the title tooltip showTitleTooltip: PropTypes.bool, + + // Navigation prop from naviagtion lib + navigation: PropTypes.shape({ + + // Method to attach listner to Navigaton state. + addListener: PropTypes.func.isRequired, + }).isRequired, }; const defaultProps = { @@ -87,7 +95,13 @@ class OptionsSelector extends Component { } componentDidMount() { - this.textInput.focus(); + this.unsubscribeTransitionEnd = this.props.navigation.addListener('transitionEnd', () => { + this.textInput.focus(); + }); + } + + componentWillUnmount() { + this.unsubscribeTransitionEnd(); } /** @@ -204,4 +218,4 @@ class OptionsSelector extends Component { OptionsSelector.defaultProps = defaultProps; OptionsSelector.propTypes = propTypes; -export default OptionsSelector; +export default withNavigation(OptionsSelector); diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 2f202da5ba83..be0e64564ece 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -157,7 +157,7 @@ class AuthScreens extends React.Component { const modalScreenOptions = { headerShown: false, cardStyle: getNavigationModalCardStyle(this.props.isSmallScreenWidth), - cardStyleInterpolator: modalCardStyleInterpolator, + cardStyleInterpolator: (...props) => modalCardStyleInterpolator(this.props.isSmallScreenWidth, ...props), animationEnabled: true, gestureDirection: 'horizontal', cardOverlayEnabled: true, diff --git a/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.js b/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.js index 28b85c68b7ec..8ad5b1603cdd 100644 --- a/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.js +++ b/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.js @@ -1,15 +1,19 @@ import {Animated} from 'react-native'; +import variables from '../../../styles/variables'; -export default ({ - current: {progress}, - inverted, - layouts: { - screen, +export default ( + isSmallScreen, + { + current: {progress}, + inverted, + layouts: { + screen, + }, }, -}) => { +) => { const translateX = Animated.multiply(progress.interpolate({ inputRange: [0, 1], - outputRange: [screen.width, 0], + outputRange: [isSmallScreen ? screen.width : variables.sideBarWidth, 0], extrapolate: 'clamp', }), inverted); From 8a613ccf69a908119f7f6e2db2be5e49ca55f669 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Fri, 7 May 2021 17:11:26 +0530 Subject: [PATCH 2/6] added loader for searhPage --- src/components/OptionsSelector.js | 17 +------- src/components/ScreenWrapper.js | 22 +++++++--- src/pages/SearchPage.js | 67 ++++++++++++++++++------------- 3 files changed, 57 insertions(+), 49 deletions(-) diff --git a/src/components/OptionsSelector.js b/src/components/OptionsSelector.js index 4563fabcea75..addcaeb6fdbe 100644 --- a/src/components/OptionsSelector.js +++ b/src/components/OptionsSelector.js @@ -61,13 +61,6 @@ const propTypes = { // Whether to show the title tooltip showTitleTooltip: PropTypes.bool, - // Navigation prop from naviagtion lib - navigation: PropTypes.shape({ - - // Method to attach listner to Navigaton state. - addListener: PropTypes.func.isRequired, - }).isRequired, - // Whether to focus the textinput after an option is selected shouldFocusOnSelectRow: PropTypes.bool, }; @@ -100,13 +93,7 @@ class OptionsSelector extends Component { } componentDidMount() { - this.unsubscribeTransitionEnd = this.props.navigation.addListener('transitionEnd', () => { - this.textInput.focus(); - }); - } - - componentWillUnmount() { - this.unsubscribeTransitionEnd(); + this.textInput.focus(); } /** @@ -235,4 +222,4 @@ class OptionsSelector extends Component { OptionsSelector.defaultProps = defaultProps; OptionsSelector.propTypes = propTypes; -export default withNavigation(OptionsSelector); +export default OptionsSelector; diff --git a/src/components/ScreenWrapper.js b/src/components/ScreenWrapper.js index 3e141b3b2379..0493504c790e 100644 --- a/src/components/ScreenWrapper.js +++ b/src/components/ScreenWrapper.js @@ -24,8 +24,13 @@ const propTypes = { // Whether to include padding top includePaddingTop: PropTypes.bool, - // react-navigation object that will allow us to goBack() + // Called when navigated Screen's transition is finished. + onTransitionEnd: PropTypes.func, + + // react-navigation navigation object available to screen components navigation: PropTypes.shape({ + // Method to attach listner to Navigaton state. + addListener: PropTypes.func.isRequired, // Returns to the previous navigation state e.g. if this is inside a Modal we will dismiss it goBack: PropTypes.func, @@ -36,7 +41,9 @@ const defaultProps = { style: [], includePaddingBottom: true, includePaddingTop: true, + onTransitionEnd: () => {}, navigation: { + addListener: () => {}, goBack: () => {}, }, }; @@ -46,14 +53,19 @@ class ScreenWrapper extends React.Component { this.unsubscribe = KeyboardShortcut.subscribe('Escape', () => { this.props.navigation.goBack(); }, [], true); + + this.unsubscribeTransitionEnd = this.props.navigation.addListener('transitionEnd', () => { + this.props.onTransitionEnd(); + }); } componentWillUnmount() { - if (!this.unsubscribe) { - return; + if (this.unsubscribe) { + this.unsubscribe(); + } + if (this.unsubscribeTransitionEnd) { + this.unsubscribeTransitionEnd(); } - - this.unsubscribe(); } render() { diff --git a/src/pages/SearchPage.js b/src/pages/SearchPage.js index 339b4cfe28bf..5e56e76011cc 100644 --- a/src/pages/SearchPage.js +++ b/src/pages/SearchPage.js @@ -15,6 +15,7 @@ import HeaderWithCloseButton from '../components/HeaderWithCloseButton'; import ScreenWrapper from '../components/ScreenWrapper'; import Timing from '../libs/actions/Timing'; import CONST from '../CONST'; +import FullScreenLoadingIndicator from '../components/FullscreenLoadingIndicator'; const personalDetailsPropTypes = PropTypes.shape({ // The login of the person (either email or phone number) @@ -56,7 +57,7 @@ class SearchPage extends Component { Timing.start(CONST.TIMING.SEARCH_RENDER); this.selectReport = this.selectReport.bind(this); - + this.activateOptionsList = this.activateOptionsList.bind(this); const { recentReports, personalDetails, @@ -72,6 +73,7 @@ class SearchPage extends Component { recentReports, personalDetails, userToInvite, + isReady: false, }; } @@ -128,6 +130,10 @@ class SearchPage extends Component { } } + activateOptionsList() { + this.setState({isReady: true}); + } + render() { const sections = this.getSections(); const headerMessage = getHeaderMessage( @@ -136,38 +142,41 @@ class SearchPage extends Component { this.state.searchValue, ); return ( - + Navigation.dismissModal(true)} /> - - { - const { - recentReports, - personalDetails, - userToInvite, - } = getSearchOptions( - this.props.reports, - this.props.personalDetails, - searchValue, - ); - this.setState({ - searchValue, - userToInvite, - recentReports, - personalDetails, - }); - }} - headerMessage={headerMessage} - hideSectionHeaders - hideAdditionalOptionStates - showTitleTooltip - /> + + + {this.state.isReady && ( + { + const { + recentReports, + personalDetails, + userToInvite, + } = getSearchOptions( + this.props.reports, + this.props.personalDetails, + searchValue, + ); + this.setState({ + searchValue, + userToInvite, + recentReports, + personalDetails, + }); + }} + headerMessage={headerMessage} + hideSectionHeaders + hideAdditionalOptionStates + showTitleTooltip + /> + )} From 424fa46f413c6ce16d25a5ff494d98d1c5737d96 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Fri, 7 May 2021 17:29:40 +0530 Subject: [PATCH 3/6] added loader on new chat and new group page --- src/pages/NewChatPage.js | 14 ++++- src/pages/NewGroupPage.js | 108 +++++++++++++++++++++----------------- 2 files changed, 72 insertions(+), 50 deletions(-) diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index f0aa0160c889..9347d31545a6 100644 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -12,6 +12,7 @@ import withWindowDimensions, {windowDimensionsPropTypes} from '../components/wit import HeaderWithCloseButton from '../components/HeaderWithCloseButton'; import Navigation from '../libs/Navigation/Navigation'; import ScreenWrapper from '../components/ScreenWrapper'; +import FullScreenLoadingIndicator from '../components/FullscreenLoadingIndicator'; const personalDetailsPropTypes = PropTypes.shape({ // The login of the person (either email or phone number) @@ -48,6 +49,7 @@ class NewChatPage extends Component { super(props); this.createNewChat = this.createNewChat.bind(this); + this.activateOptionsList = this.activateOptionsList.bind(this); const { personalDetails, @@ -62,6 +64,7 @@ class NewChatPage extends Component { searchValue: '', personalDetails, userToInvite, + isReady: false, }; } @@ -92,6 +95,10 @@ class NewChatPage extends Component { return sections; } + activateOptionsList() { + this.setState({isReady: true}); + } + /** * Creates a new chat with the option * @param {Object} option @@ -112,12 +119,14 @@ class NewChatPage extends Component { ); return ( - + Navigation.dismissModal(true)} /> - + + + {this.state.isReady && ( + )} diff --git a/src/pages/NewGroupPage.js b/src/pages/NewGroupPage.js index 3b3d6cad19ae..034138d23c29 100644 --- a/src/pages/NewGroupPage.js +++ b/src/pages/NewGroupPage.js @@ -14,6 +14,7 @@ import withWindowDimensions, {windowDimensionsPropTypes} from '../components/wit import HeaderWithCloseButton from '../components/HeaderWithCloseButton'; import ScreenWrapper from '../components/ScreenWrapper'; import Navigation from '../libs/Navigation/Navigation'; +import FullScreenLoadingIndicator from '../components/FullscreenLoadingIndicator'; const personalDetailsPropTypes = PropTypes.shape({ // The login of the person (either email or phone number) @@ -51,6 +52,7 @@ class NewGroupPage extends Component { this.toggleOption = this.toggleOption.bind(this); this.createGroup = this.createGroup.bind(this); + this.activateOptionsList = this.activateOptionsList.bind(this); const { recentReports, @@ -69,6 +71,7 @@ class NewGroupPage extends Component { personalDetails, selectedOptions: [], userToInvite, + isReady: false, }; } @@ -117,6 +120,10 @@ class NewGroupPage extends Component { return sections; } + activateOptionsList() { + this.setState({isReady: true}); + } + /** * Once all our options are selected this method will call the API and create new chat between all selected users * and the currently logged in user @@ -180,58 +187,63 @@ class NewGroupPage extends Component { maxParticipantsReached, ); return ( - + Navigation.dismissModal(true)} /> - - { - const { - recentReports, - personalDetails, - userToInvite, - } = getNewGroupOptions( - this.props.reports, - this.props.personalDetails, - searchValue, - [], - ); - this.setState({ - searchValue, - userToInvite, - recentReports, - personalDetails, - }); - }} - headerMessage={headerMessage} - disableArrowKeysActions - hideAdditionalOptionStates - forceTextUnreadStyle - shouldFocusOnSelectRow - /> - {this.state.selectedOptions?.length > 0 && ( - - [ - styles.button, - styles.buttonSuccess, - styles.w100, - hovered && styles.buttonSuccessHovered, - ]} - > - - Create Group - - - + + + {this.state.isReady && ( + <> + { + const { + recentReports, + personalDetails, + userToInvite, + } = getNewGroupOptions( + this.props.reports, + this.props.personalDetails, + searchValue, + [], + ); + this.setState({ + searchValue, + userToInvite, + recentReports, + personalDetails, + }); + }} + headerMessage={headerMessage} + disableArrowKeysActions + hideAdditionalOptionStates + forceTextUnreadStyle + shouldFocusOnSelectRow + /> + {this.state.selectedOptions?.length > 0 && ( + + [ + styles.button, + styles.buttonSuccess, + styles.w100, + hovered && styles.buttonSuccessHovered, + ]} + > + + Create Group + + + + )} + )} From 0c617aeb86491b2858aa6694d767aca654a341f4 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Fri, 7 May 2021 22:58:57 +0530 Subject: [PATCH 4/6] chg: animation for IOUModals --- .../Navigation/AppNavigator/AuthScreens.js | 2 +- src/pages/iou/IOUBillPage.js | 11 +- src/pages/iou/IOUModal.js | 103 ++++++++++-------- src/pages/iou/IOURequestPage.js | 11 +- 4 files changed, 65 insertions(+), 62 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 794a8fedbd57..40a7111a54f0 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -71,7 +71,7 @@ const RootStack = createCustomModalStackNavigator(); // When modal screen gets focused, update modal visibility in Onyx // https://reactnavigation.org/docs/navigation-events/ const modalScreenListeners = { - focus: () => { + transitionEnd: () => { setModalVisibility(true); }, beforeRemove: () => { diff --git a/src/pages/iou/IOUBillPage.js b/src/pages/iou/IOUBillPage.js index 065f00165775..cda451e21360 100644 --- a/src/pages/iou/IOUBillPage.js +++ b/src/pages/iou/IOUBillPage.js @@ -1,12 +1,5 @@ import React from 'react'; import IOUModal from './IOUModal'; -import ScreenWrapper from '../../components/ScreenWrapper'; -export default props => ( - - {() => ( - // eslint-disable-next-line react/jsx-props-no-spreading - - )} - -); +// eslint-disable-next-line react/jsx-props-no-spreading +export default props => ; diff --git a/src/pages/iou/IOUModal.js b/src/pages/iou/IOUModal.js index f3fe5f198afc..11b86b133ec1 100644 --- a/src/pages/iou/IOUModal.js +++ b/src/pages/iou/IOUModal.js @@ -14,6 +14,8 @@ import {Close, BackArrow} from '../../components/Icon/Expensicons'; import Navigation from '../../libs/Navigation/Navigation'; import ONYXKEYS from '../../ONYXKEYS'; import {getPersonalDetailsForLogins} from '../../libs/OptionsListUtils'; +import FullScreenLoadingIndicator from '../../components/FullscreenLoadingIndicator'; +import ScreenWrapper from '../../components/ScreenWrapper'; /** * IOU modal for requesting money and splitting bills. @@ -35,6 +37,9 @@ const propTypes = { // Whether or not transaction creation has resulted to error error: PropTypes.bool, + + // is loading + loading: PropTypes.bool, }).isRequired, // Personal details of all the users @@ -74,6 +79,7 @@ class IOUModal extends Component { this.createTransaction = this.createTransaction.bind(this); this.updateComment = this.updateComment.bind(this); this.addParticipants = this.addParticipants.bind(this); + this.getReady = this.getReady.bind(this); const participants = lodashGet(props, 'report.participants', []); const participantsWithDetails = getPersonalDetailsForLogins(participants, props.personalDetails) .map(personalDetails => ({ @@ -92,6 +98,7 @@ class IOUModal extends Component { amount: '', selectedCurrency: 'USD', comment: '', + isReady: false, }; // Skip IOUParticipants step if participants are passed in @@ -103,10 +110,6 @@ class IOUModal extends Component { } } - componentDidMount() { - getPreferredCurrency(); - } - componentDidUpdate(prevProps) { // Successfully close the modal if transaction creation has ended and there is no error if (prevProps.iou.creatingIOUTransaction && !this.props.iou.creatingIOUTransaction && !this.props.iou.error) { @@ -114,6 +117,13 @@ class IOUModal extends Component { } } + + getReady() { + getPreferredCurrency(); + this.setState({isReady: true}); + } + + /** * Retrieve title for current step, based upon current step and type of IOU * @@ -209,7 +219,7 @@ class IOUModal extends Component { render() { const currentStep = this.steps[this.state.currentStepIndex]; return ( - <> + {this.state.currentStepIndex > 0 - && ( - - - - )} + && ( + + + + )}
- {currentStep === Steps.IOUAmount && ( - { - this.setState({amount}); - this.navigateToNextStep(); - }} - currencySelected={this.currencySelected} - selectedCurrency={this.state.selectedCurrency} - /> - )} - {currentStep === Steps.IOUParticipants && ( - - )} - {currentStep === Steps.IOUConfirm && ( - - )} - + + + {this.state.isReady && ( + <> + {currentStep === Steps.IOUAmount && ( + { + this.setState({amount}); + this.navigateToNextStep(); + }} + currencySelected={this.currencySelected} + selectedCurrency={this.state.selectedCurrency} + /> + )} + {currentStep === Steps.IOUParticipants && ( + + )} + {currentStep === Steps.IOUConfirm && ( + + )} + + )} + + ); } } diff --git a/src/pages/iou/IOURequestPage.js b/src/pages/iou/IOURequestPage.js index 67ee9d0f4dd4..6cacd162c105 100644 --- a/src/pages/iou/IOURequestPage.js +++ b/src/pages/iou/IOURequestPage.js @@ -1,12 +1,5 @@ import React from 'react'; import IOUModal from './IOUModal'; -import ScreenWrapper from '../../components/ScreenWrapper'; -export default props => ( - - {() => ( - // eslint-disable-next-line react/jsx-props-no-spreading - - )} - -); +// eslint-disable-next-line react/jsx-props-no-spreading +export default props => ; From b2ad5da500b3e4e988ca5be50130098a7373a063 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Fri, 7 May 2021 23:03:06 +0530 Subject: [PATCH 5/6] fix linting --- src/components/OptionsSelector.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/OptionsSelector.js b/src/components/OptionsSelector.js index addcaeb6fdbe..422b7d72855d 100644 --- a/src/components/OptionsSelector.js +++ b/src/components/OptionsSelector.js @@ -2,7 +2,6 @@ import _ from 'underscore'; import React, {Component} from 'react'; import PropTypes from 'prop-types'; import {View} from 'react-native'; -import {withNavigation} from '@react-navigation/compat'; import TextInputWithFocusStyles from './TextInputWithFocusStyles'; import OptionsList from './OptionsList'; import styles from '../styles/styles'; From 5517db8992235ae3290067a5a51638a4f1061d6b Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Sat, 8 May 2021 02:45:17 +0530 Subject: [PATCH 6/6] dried up duplicate logic to parent --- src/components/ScreenWrapper.js | 19 ++- .../Navigation/AppNavigator/AuthScreens.js | 6 +- src/pages/NewChatPage.js | 83 ++++++----- src/pages/NewGroupPage.js | 129 +++++++++-------- src/pages/SearchPage.js | 82 ++++++----- src/pages/home/sidebar/SidebarScreen.js | 2 +- src/pages/iou/IOUModal.js | 133 +++++++++--------- 7 files changed, 231 insertions(+), 223 deletions(-) diff --git a/src/components/ScreenWrapper.js b/src/components/ScreenWrapper.js index 0493504c790e..58e95b1b42e4 100644 --- a/src/components/ScreenWrapper.js +++ b/src/components/ScreenWrapper.js @@ -49,19 +49,27 @@ const defaultProps = { }; class ScreenWrapper extends React.Component { + constructor(props) { + super(props); + this.state = { + didScreenTransitionEnd: false, + }; + } + componentDidMount() { - this.unsubscribe = KeyboardShortcut.subscribe('Escape', () => { + this.unsubscribeEscapeKey = KeyboardShortcut.subscribe('Escape', () => { this.props.navigation.goBack(); }, [], true); this.unsubscribeTransitionEnd = this.props.navigation.addListener('transitionEnd', () => { + this.setState({didScreenTransitionEnd: true}); this.props.onTransitionEnd(); }); } componentWillUnmount() { - if (this.unsubscribe) { - this.unsubscribe(); + if (this.unsubscribeEscapeKey) { + this.unsubscribeEscapeKey(); } if (this.unsubscribeTransitionEnd) { this.unsubscribeTransitionEnd(); @@ -93,7 +101,10 @@ class ScreenWrapper extends React.Component { {// If props.children is a function, call it to provide the insets to the children. _.isFunction(this.props.children) - ? this.props.children(insets) + ? this.props.children({ + insets, + didScreenTransitionEnd: this.state.didScreenTransitionEnd, + }) : this.props.children } diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 40a7111a54f0..1f244fabec95 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -68,7 +68,9 @@ Onyx.connect({ const RootStack = createCustomModalStackNavigator(); -// When modal screen gets focused, update modal visibility in Onyx +// We want to delay the re-rendering for components(e.g. ReportActionCompose) +// that depends on modal visibility until Modal is completely closed or its transition has ended +// When modal screen is focused and animation transition is ended, update modal visibility in Onyx // https://reactnavigation.org/docs/navigation-events/ const modalScreenListeners = { transitionEnd: () => { @@ -159,7 +161,7 @@ class AuthScreens extends React.Component { const modalScreenOptions = { headerShown: false, cardStyle: getNavigationModalCardStyle(this.props.isSmallScreenWidth), - cardStyleInterpolator: (...props) => modalCardStyleInterpolator(this.props.isSmallScreenWidth, ...props), + cardStyleInterpolator: props => modalCardStyleInterpolator(this.props.isSmallScreenWidth, props), animationEnabled: true, gestureDirection: 'horizontal', cardOverlayEnabled: true, diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index 9347d31545a6..ed65470548de 100644 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -49,8 +49,6 @@ class NewChatPage extends Component { super(props); this.createNewChat = this.createNewChat.bind(this); - this.activateOptionsList = this.activateOptionsList.bind(this); - const { personalDetails, userToInvite, @@ -64,7 +62,6 @@ class NewChatPage extends Component { searchValue: '', personalDetails, userToInvite, - isReady: false, }; } @@ -95,10 +92,6 @@ class NewChatPage extends Component { return sections; } - activateOptionsList() { - this.setState({isReady: true}); - } - /** * Creates a new chat with the option * @param {Object} option @@ -119,42 +112,46 @@ class NewChatPage extends Component { ); return ( - - Navigation.dismissModal(true)} - /> - - - {this.state.isReady && ( - { - const { - personalDetails, - userToInvite, - } = getNewChatOptions( - this.props.reports, - this.props.personalDetails, - searchValue, - ); - this.setState({ - searchValue, - userToInvite, - personalDetails, - }); - }} - headerMessage={headerMessage} - hideSectionHeaders - disableArrowKeysActions - hideAdditionalOptionStates - forceTextUnreadStyle - /> - )} - - + + {({didScreenTransitionEnd}) => ( + <> + Navigation.dismissModal(true)} + /> + + + {didScreenTransitionEnd && ( + { + const { + personalDetails, + userToInvite, + } = getNewChatOptions( + this.props.reports, + this.props.personalDetails, + searchValue, + ); + this.setState({ + searchValue, + userToInvite, + personalDetails, + }); + }} + headerMessage={headerMessage} + hideSectionHeaders + disableArrowKeysActions + hideAdditionalOptionStates + forceTextUnreadStyle + /> + )} + + + + )} ); } diff --git a/src/pages/NewGroupPage.js b/src/pages/NewGroupPage.js index 034138d23c29..2d8b0eee51e0 100644 --- a/src/pages/NewGroupPage.js +++ b/src/pages/NewGroupPage.js @@ -52,8 +52,6 @@ class NewGroupPage extends Component { this.toggleOption = this.toggleOption.bind(this); this.createGroup = this.createGroup.bind(this); - this.activateOptionsList = this.activateOptionsList.bind(this); - const { recentReports, personalDetails, @@ -71,7 +69,6 @@ class NewGroupPage extends Component { personalDetails, selectedOptions: [], userToInvite, - isReady: false, }; } @@ -120,10 +117,6 @@ class NewGroupPage extends Component { return sections; } - activateOptionsList() { - this.setState({isReady: true}); - } - /** * Once all our options are selected this method will call the API and create new chat between all selected users * and the currently logged in user @@ -187,66 +180,70 @@ class NewGroupPage extends Component { maxParticipantsReached, ); return ( - - Navigation.dismissModal(true)} - /> - - - {this.state.isReady && ( - <> - { - const { - recentReports, - personalDetails, - userToInvite, - } = getNewGroupOptions( - this.props.reports, - this.props.personalDetails, - searchValue, - [], - ); - this.setState({ - searchValue, - userToInvite, - recentReports, - personalDetails, - }); - }} - headerMessage={headerMessage} - disableArrowKeysActions - hideAdditionalOptionStates - forceTextUnreadStyle - shouldFocusOnSelectRow - /> - {this.state.selectedOptions?.length > 0 && ( - - [ - styles.button, - styles.buttonSuccess, - styles.w100, - hovered && styles.buttonSuccessHovered, - ]} - > - - Create Group - - - + + {({didScreenTransitionEnd}) => ( + <> + Navigation.dismissModal(true)} + /> + + + {didScreenTransitionEnd && ( + <> + { + const { + recentReports, + personalDetails, + userToInvite, + } = getNewGroupOptions( + this.props.reports, + this.props.personalDetails, + searchValue, + [], + ); + this.setState({ + searchValue, + userToInvite, + recentReports, + personalDetails, + }); + }} + headerMessage={headerMessage} + disableArrowKeysActions + hideAdditionalOptionStates + forceTextUnreadStyle + shouldFocusOnSelectRow + /> + {this.state.selectedOptions?.length > 0 && ( + + [ + styles.button, + styles.buttonSuccess, + styles.w100, + hovered && styles.buttonSuccessHovered, + ]} + > + + Create Group + + + + )} + )} - - )} - - + + + + )} ); } diff --git a/src/pages/SearchPage.js b/src/pages/SearchPage.js index 5e56e76011cc..61b514f9c867 100644 --- a/src/pages/SearchPage.js +++ b/src/pages/SearchPage.js @@ -57,7 +57,6 @@ class SearchPage extends Component { Timing.start(CONST.TIMING.SEARCH_RENDER); this.selectReport = this.selectReport.bind(this); - this.activateOptionsList = this.activateOptionsList.bind(this); const { recentReports, personalDetails, @@ -73,7 +72,6 @@ class SearchPage extends Component { recentReports, personalDetails, userToInvite, - isReady: false, }; } @@ -130,10 +128,6 @@ class SearchPage extends Component { } } - activateOptionsList() { - this.setState({isReady: true}); - } - render() { const sections = this.getSections(); const headerMessage = getHeaderMessage( @@ -142,43 +136,47 @@ class SearchPage extends Component { this.state.searchValue, ); return ( - - Navigation.dismissModal(true)} - /> - - - {this.state.isReady && ( - { - const { - recentReports, - personalDetails, - userToInvite, - } = getSearchOptions( - this.props.reports, - this.props.personalDetails, - searchValue, - ); - this.setState({ - searchValue, - userToInvite, - recentReports, - personalDetails, - }); - }} - headerMessage={headerMessage} - hideSectionHeaders - hideAdditionalOptionStates - showTitleTooltip + + {({didScreenTransitionEnd}) => ( + <> + Navigation.dismissModal(true)} /> - )} - - + + + {didScreenTransitionEnd && ( + { + const { + recentReports, + personalDetails, + userToInvite, + } = getSearchOptions( + this.props.reports, + this.props.personalDetails, + searchValue, + ); + this.setState({ + searchValue, + userToInvite, + recentReports, + personalDetails, + }); + }} + headerMessage={headerMessage} + hideSectionHeaders + hideAdditionalOptionStates + showTitleTooltip + /> + )} + + + + )} ); } diff --git a/src/pages/home/sidebar/SidebarScreen.js b/src/pages/home/sidebar/SidebarScreen.js index ff4ef2ee630c..f6ffaed89b3c 100644 --- a/src/pages/home/sidebar/SidebarScreen.js +++ b/src/pages/home/sidebar/SidebarScreen.js @@ -77,7 +77,7 @@ class SidebarScreen extends Component { includePaddingBottom={false} style={[styles.sidebar]} > - {insets => ( + {({insets}) => ( <> - - - {this.state.currentStepIndex > 0 - && ( - - - - )} -
- - Navigation.dismissModal()} - style={[styles.touchableButtonImage]} + {({didScreenTransitionEnd}) => ( + <> + + - - + {this.state.currentStepIndex > 0 + && ( + + + + )} +
+ + Navigation.dismissModal()} + style={[styles.touchableButtonImage]} + > + + + + - - - - - {this.state.isReady && ( - <> - {currentStep === Steps.IOUAmount && ( - { - this.setState({amount}); - this.navigateToNextStep(); - }} - currencySelected={this.currencySelected} - selectedCurrency={this.state.selectedCurrency} - /> - )} - {currentStep === Steps.IOUParticipants && ( - - )} - {currentStep === Steps.IOUConfirm && ( - + + + {didScreenTransitionEnd && ( + <> + {currentStep === Steps.IOUAmount && ( + { + this.setState({amount}); + this.navigateToNextStep(); + }} + currencySelected={this.currencySelected} + selectedCurrency={this.state.selectedCurrency} + /> + )} + {currentStep === Steps.IOUParticipants && ( + + )} + {currentStep === Steps.IOUConfirm && ( + + )} + )} - - )} - + + + + )} ); }