From bc18d60883f0908d4f2bdcdbce0079fb4d94a710 Mon Sep 17 00:00:00 2001 From: Chris Duarte Date: Tue, 28 Mar 2017 19:59:01 -0700 Subject: [PATCH] Fix login transition (#410) * Fix login transition * Add instant transition to modal * Fix transition to show loader on first login * Add loader to load_team * Remove back button --- app/actions/views/channel.js | 5 +-- app/actions/views/load_team.js | 32 ++++++++++++++++--- app/actions/views/root.js | 5 ++- app/constants/navigation.js | 1 + app/constants/view.js | 2 ++ app/navigation/navigation_modal.js | 19 +++++++---- app/navigation/router.js | 8 ++++- app/navigation/routes.js | 4 ++- app/reducers/navigation/index.js | 5 ++- app/reducers/views/channel.js | 12 ++++++- .../channel_post_list/channel_post_list.js | 9 ++++-- .../channel_post_list_container.js | 1 + app/scenes/load_team/load_team.js | 18 +++++++++-- app/scenes/load_team/load_team_container.js | 10 ++++-- app/scenes/select_server/select_server.js | 3 +- 15 files changed, 103 insertions(+), 31 deletions(-) diff --git a/app/actions/views/channel.js b/app/actions/views/channel.js index 7dd701f35..31925508d 100644 --- a/app/actions/views/channel.js +++ b/app/actions/views/channel.js @@ -303,8 +303,9 @@ export function leaveChannel(channel, reset = false) { }; } -export function setChannelLoading() { +export function setChannelLoading(loading = true) { return { - type: ViewTypes.SET_CHANNEL_LOADER + type: ViewTypes.SET_CHANNEL_LOADER, + loading }; } diff --git a/app/actions/views/load_team.js b/app/actions/views/load_team.js index f22034118..04d09672b 100644 --- a/app/actions/views/load_team.js +++ b/app/actions/views/load_team.js @@ -1,14 +1,36 @@ // Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import {NavigationTypes} from 'app/constants'; +import {NavigationTypes, ViewTypes} from 'app/constants'; import Routes from 'app/navigation/routes'; export function goToChannelView() { return async (dispatch, getState) => { - dispatch({ - type: NavigationTypes.NAVIGATION_RESET, - routes: [Routes.ChannelView] - }, getState); + const state = getState(); + if (state.views.login.loginId) { + dispatch({ + type: NavigationTypes.NAVIGATION_REPLACE_AT_ROOT, + route: Routes.ChannelView + }, getState); + + dispatch({ + type: NavigationTypes.NAVIGATION_CLOSE_MODAL + }, getState); + + setTimeout(() => { + dispatch({ + type: ViewTypes.APPLICATION_INITIALIZED + }, getState); + }, 800); // modal close takes 400ms + } else { + dispatch({ + type: NavigationTypes.NAVIGATION_RESET, + routes: [Routes.ChannelView] + }, getState); + + dispatch({ + type: ViewTypes.APPLICATION_INITIALIZED + }, getState); + } }; } diff --git a/app/actions/views/root.js b/app/actions/views/root.js index 05c5edda0..c445159f9 100644 --- a/app/actions/views/root.js +++ b/app/actions/views/root.js @@ -18,9 +18,8 @@ import {markChannelAsRead, viewChannel} from 'mattermost-redux/actions/channels' export function goToSelectServer() { return async (dispatch, getState) => { dispatch({ - type: NavigationTypes.NAVIGATION_RESET, - routes: [Routes.SelectServer], - index: 0 + type: NavigationTypes.NAVIGATION_MODAL, + route: Routes.SelectServer }, getState); }; } diff --git a/app/constants/navigation.js b/app/constants/navigation.js index 72781a717..8dec80095 100644 --- a/app/constants/navigation.js +++ b/app/constants/navigation.js @@ -14,6 +14,7 @@ const NavigationTypes = keyMirror({ NAVIGATION_JUMP: null, NAVIGATION_JUMP_TO_INDEX: null, NAVIGATION_REPLACE: null, + NAVIGATION_REPLACE_AT_ROOT: null, NAVIGATION_RESET: null, NAVIGATION_MODAL: null, NAVIGATION_CLOSE_MODAL: null, diff --git a/app/constants/view.js b/app/constants/view.js index e5762c381..ad2345a33 100644 --- a/app/constants/view.js +++ b/app/constants/view.js @@ -4,6 +4,8 @@ import keyMirror from 'mattermost-redux/utils/key_mirror'; const ViewTypes = keyMirror({ + APPLICATION_INITIALIZED: null, + SERVER_URL_CHANGED: null, LOGIN_ID_CHANGED: null, diff --git a/app/navigation/navigation_modal.js b/app/navigation/navigation_modal.js index b00955725..b7533fa2c 100644 --- a/app/navigation/navigation_modal.js +++ b/app/navigation/navigation_modal.js @@ -3,7 +3,8 @@ import React, {PropTypes, PureComponent} from 'react'; import { - Animated + Animated, + InteractionManager } from 'react-native'; const {View: AnimatedView} = Animated; @@ -21,11 +22,13 @@ export default class NavigationModal extends PureComponent { ]), deviceHeight: PropTypes.number.isRequired, deviceWidth: PropTypes.number.isRequired, + duration: PropTypes.number, show: PropTypes.bool } static defaultProps = { animationType: ANIMATION_TYPES.SlideFromBottom, + duration: 400, show: false } @@ -62,9 +65,13 @@ export default class NavigationModal extends PureComponent { const animationType = nextProps.show ? nextProps.animationType : this.props.animationType; if (animationType === ANIMATION_TYPES.SlideFromBottom) { - this.slideFromBottomAnimationRunner(nextProps); + InteractionManager.runAfterInteractions(() => { + this.slideFromBottomAnimationRunner(nextProps); + }); } else if (animationType === ANIMATION_TYPES.Fade) { - this.fadeAnimationRunner(nextProps); + InteractionManager.runAfterInteractions(() => { + this.fadeAnimationRunner(nextProps); + }); } } } @@ -81,7 +88,7 @@ export default class NavigationModal extends PureComponent { }); const setOpacityToFull = Animated.timing(this.state.opacity, { toValue: 1, - duration: 400 + duration: nextProps.duration }); Animated.sequence([ setOpacityToZero, @@ -99,7 +106,7 @@ export default class NavigationModal extends PureComponent { } else { const setOpacityToZero = Animated.timing(this.state.opacity, { toValue: 0, - duration: 400 + duration: nextProps.duration }); const setTopToDeviceHeight = Animated.timing(this.state.top, { toValue: this.props.deviceHeight, @@ -130,7 +137,7 @@ export default class NavigationModal extends PureComponent { Animated.timing(this.state.top, { toValue: animateValue, - duration: 400 + duration: nextProps.duration }).start(() => { // Once the scene has finished sliding down we can release the child scene // which will unmount the scene correctly. diff --git a/app/navigation/router.js b/app/navigation/router.js index e4876d0ab..7f2b9088a 100644 --- a/app/navigation/router.js +++ b/app/navigation/router.js @@ -75,7 +75,12 @@ class Router extends Component { return {}; } - return Object.assign({}, route.navigationProps, route.component.navigationProps); + let component = route.component; + if (!component) { + component = {}; + } + + return Object.assign({}, route.navigationProps, component.navigationProps); }; renderTransition = (transitionProps) => { @@ -326,6 +331,7 @@ class Router extends Component { animationType={modalNavigationProps.modalAnimationType} deviceHeight={this.state.deviceHeight} deviceWidth={this.state.deviceWidth} + duration={modalNavigationProps.duration} show={modalVisible} > null + } + componentDidMount() { const {notification, currentTeam, myMembers, teams} = this.props; const {clearNotification, goToNotification} = this.props.actions; @@ -55,6 +63,10 @@ export default class LoadTeam extends PureComponent { } render() { - return null; + return ( + + + + ); } } diff --git a/app/scenes/load_team/load_team_container.js b/app/scenes/load_team/load_team_container.js index 8600a65b4..dc23859b3 100644 --- a/app/scenes/load_team/load_team_container.js +++ b/app/scenes/load_team/load_team_container.js @@ -2,18 +2,22 @@ // See License.txt for license information. import {bindActionCreators} from 'redux'; -import {connect} from 'react-redux'; + +import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams'; import {goToChannelView} from 'app/actions/views/load_team'; import {clearNotification, goToNotification} from 'app/actions/views/root'; import {handleTeamChange} from 'app/actions/views/select_team'; -import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams'; +import {getTheme} from 'app/selectors/preferences'; + +import navigationSceneConnect from '../navigationSceneConnect'; import LoadTeam from './load_team.js'; function mapStateToProps(state) { return { config: state.entities.general.config, + theme: getTheme(state), teamsRequest: state.requests.teams.allTeams, teams: state.entities.teams.teams, currentTeam: getCurrentTeam(state), @@ -33,4 +37,4 @@ function mapDispatchToProps(dispatch) { }; } -export default connect(mapStateToProps, mapDispatchToProps)(LoadTeam); +export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(LoadTeam); diff --git a/app/scenes/select_server/select_server.js b/app/scenes/select_server/select_server.js index 17879f273..b6b499b66 100644 --- a/app/scenes/select_server/select_server.js +++ b/app/scenes/select_server/select_server.js @@ -21,7 +21,6 @@ import {SplashScreenTypes} from 'app/constants'; import ErrorText from 'app/components/error_text'; import FormattedText from 'app/components/formatted_text'; import KeyboardLayout from 'app/components/layout/keyboard_layout'; -import Loading from 'app/components/loading'; import TextInputWithLocalizedPlaceholder from 'app/components/text_input_with_localized_placeholder'; import {GlobalStyles} from 'app/styles'; import {isValidUrl, stripTrailingSlashes} from 'app/utils/url'; @@ -116,7 +115,7 @@ export default class SelectServer extends PureComponent { licenseRequest.status === RequestStatus.STARTED; if (isLoading) { - return ; + return null; } const error = pingRequest.error || configRequest.error || licenseRequest.error;