Skip to content

Commit

Permalink
Merge pull request #2346 from kidroca/kidroca/fix-url-not-updating-af…
Browse files Browse the repository at this point in the history
…ter-login-or-refresh

Fix: Address bar URL is not updated after login or landing on root
  • Loading branch information
marcaaron authored Apr 13, 2021
2 parents 94ba6da + e6ef81f commit 82a2898
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 97 deletions.
34 changes: 32 additions & 2 deletions src/libs/Navigation/AppNavigator/AuthScreens.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,16 @@ const propTypes = {
// Is the network currently offline or not
isOffline: PropTypes.bool,
}),

// The initial report for the home screen
initialReportID: PropTypes.string,

...windowDimensionsPropTypes,
};

const defaultProps = {
network: {isOffline: true},
initialReportID: null,
};

class AuthScreens extends React.Component {
Expand All @@ -94,6 +99,8 @@ class AuthScreens extends React.Component {

Timing.start(CONST.TIMING.HOMEPAGE_INITIAL_RENDER);
Timing.start(CONST.TIMING.HOMEPAGE_REPORTS_LOADED);

this.initialReportID = props.initialReportID;
}

componentDidMount() {
Expand Down Expand Up @@ -134,11 +141,20 @@ class AuthScreens extends React.Component {
}, ['meta'], true);
}

shouldComponentUpdate(prevProps) {
if (prevProps.isSmallScreenWidth !== this.props.isSmallScreenWidth) {
shouldComponentUpdate(nextProps) {
if (nextProps.isSmallScreenWidth !== this.props.isSmallScreenWidth) {
return true;
}

// Skip when `this.initialReportID` is already assigned. We no longer want to update it
if (!this.initialReportID) {
// Either we have a reportID or fetchAllReports resolved with no reports. Otherwise keep waiting
if (nextProps.initialReportID || nextProps.initialReportID === '') {
this.initialReportID = nextProps.initialReportID;
return true;
}
}

return false;
}

Expand All @@ -150,6 +166,11 @@ class AuthScreens extends React.Component {
}

render() {
// Wait to resolve initial Home route params.
if (!this.initialReportID) {
return null;
}

const modalScreenOptions = {
headerShown: false,
cardStyle: getNavigationModalCardStyle(this.props.isSmallScreenWidth),
Expand All @@ -172,6 +193,12 @@ class AuthScreens extends React.Component {
headerShown: false,
title: 'Expensify.cash',
}}
initialParams={{
screen: 'Report',
params: {
reportID: this.initialReportID,
},
}}
component={MainDrawerNavigator}
/>
<RootStack.Screen
Expand Down Expand Up @@ -243,5 +270,8 @@ export default compose(
network: {
key: ONYXKEYS.NETWORK,
},
initialReportID: {
key: ONYXKEYS.CURRENTLY_VIEWED_REPORTID,
},
}),
)(AuthScreens);
110 changes: 16 additions & 94 deletions src/libs/Navigation/NavigationRoot.js
Original file line number Diff line number Diff line change
@@ -1,115 +1,42 @@
import _ from 'underscore';
import React, {Component} from 'react';
import {ActivityIndicator, Linking, View} from 'react-native';
import PropTypes from 'prop-types';
import {
getStateFromPath,
getPathFromState,
NavigationContainer,
} from '@react-navigation/native';
import {withOnyx} from 'react-native-onyx';
import {getPathFromState, NavigationContainer} from '@react-navigation/native';
import {navigationRef} from './Navigation';
import linkingConfig from './linkingConfig';
import AppNavigator from './AppNavigator';
import getPathName from './getPathName';
import ONYXKEYS from '../../ONYXKEYS';
import ROUTES from '../../ROUTES';
import styles from '../../styles/styles';
import themeColors from '../../styles/themes/default';
import {updateCurrentlyViewedReportID} from '../actions/Report';
import {setCurrentURL} from '../actions/App';
import FullScreenLoadingIndicator from '../../components/FullscreenLoadingIndicator';

const propTypes = {
// Whether the current user is logged in with an authToken
authenticated: PropTypes.bool.isRequired,

// The current reportID that we are navigated to or should show in the ReportScreen
currentlyViewedReportID: PropTypes.string,
};

const defaultProps = {
currentlyViewedReportID: null,
};

class NavigationRoot extends Component {
constructor(props) {
super(props);

this.state = {
loading: true,
initialState: undefined,
};
this.parseAndStoreRoute = this.parseAndStoreRoute.bind(this);
}

componentDidMount() {
Linking.getInitialURL()
.then((initialUrl) => {
// On web we should be able to parse this. It will be null on native for now until deep links are
// hooked up
const path = getPathName(initialUrl);
let initialState = getStateFromPath(path, linkingConfig.config);
setCurrentURL(path);

// If we are landing on something other than the report screen or site root then we MUST set the
// initial route to the currently viewed report so there some history to navigate back from
if (path !== `/${ROUTES.HOME}` && !path.includes(`/${ROUTES.REPORT}`)) {
const homeRoute = {
name: 'Home',
};

if (this.props.currentlyViewedReportID) {
homeRoute.params = {
screen: 'Report',
params: {
reportID: this.props.currentlyViewedReportID,
},
};
}

if (!initialState) {
initialState = {
routes: [],
};
}

initialState.routes = [
homeRoute,
...initialState.routes,
];
}
/**
* Intercept state changes and perform different logic
* @param {NavigationState} state
*/
parseAndStoreRoute(state) {
if (!state) {
return;
}

this.setState({loading: false, initialState});
});
const path = getPathFromState(state, linkingConfig.config);
setCurrentURL(path);
}

render() {
if (this.state.loading) {
return (
<View style={[styles.flex1, styles.h100, styles.justifyContentCenter]}>
<ActivityIndicator size="large" color={themeColors.spinner} />
</View>
);
}

// If we are on web, desktop, or a widescreen width we will use our custom navigator to create the wider layout
return (
<NavigationContainer
initialState={this.state.initialState}
onStateChange={(state) => {
if (!state) {
return;
}

const path = getPathFromState(state, linkingConfig.config);
if (path.includes(ROUTES.REPORT)) {
const reportID = Number(_.last(path.split('/')));
if (reportID && !_.isNaN(reportID)) {
updateCurrentlyViewedReportID(reportID);
}
}

setCurrentURL(path);
}}
fallback={<FullScreenLoadingIndicator visible />}
onStateChange={this.parseAndStoreRoute}
ref={navigationRef}
linking={linkingConfig}
documentTitle={{
Expand All @@ -123,9 +50,4 @@ class NavigationRoot extends Component {
}

NavigationRoot.propTypes = propTypes;
NavigationRoot.defaultProps = defaultProps;
export default withOnyx({
currentlyViewedReportID: {
key: ONYXKEYS.CURRENTLY_VIEWED_REPORTID,
},
})(NavigationRoot);
export default NavigationRoot;
2 changes: 1 addition & 1 deletion src/libs/Navigation/linkingConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default {
config: {
screens: {
Home: {
path: '',
path: ROUTES.HOME,
initialRouteName: 'Report',
screens: {
// Report route
Expand Down
10 changes: 10 additions & 0 deletions src/pages/home/ReportScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import HeaderView from './HeaderView';
import Navigation from '../../libs/Navigation/Navigation';
import ROUTES from '../../ROUTES';
import FullScreenLoadingIndicator from '../../components/FullscreenLoadingIndicator';
import {updateCurrentlyViewedReportID} from '../../libs/actions/Report';

const propTypes = {
/* Navigation route context info provided by react navigation */
Expand Down Expand Up @@ -37,6 +38,7 @@ class ReportScreen extends React.Component {

if (reportChanged) {
this.prepareTransition();
this.storeCurrentlyViewedReport();
}
}

Expand Down Expand Up @@ -73,6 +75,14 @@ class ReportScreen extends React.Component {
this.loadingTimerId = setTimeout(() => this.setState({isLoading: false}), 300);
}

/**
* Persists the currently viewed report id
*/
storeCurrentlyViewedReport() {
const reportID = this.getReportID();
updateCurrentlyViewedReportID(reportID);
}

render() {
return (
<ScreenWrapper style={[styles.appContent, styles.flex1]}>
Expand Down

0 comments on commit 82a2898

Please sign in to comment.