diff --git a/app/actions/navigation/index.js b/app/actions/navigation/index.js index 2a24a6c7d..4c1f27971 100644 --- a/app/actions/navigation/index.js +++ b/app/actions/navigation/index.js @@ -47,10 +47,10 @@ export function goToLoadTeam() { }; } -export function goToSelectTeam() { +export function goToModalSelectTeam() { return async (dispatch, getState) => { dispatch({ - type: NavigationTypes.NAVIGATION_PUSH, + type: NavigationTypes.NAVIGATION_MODAL, route: Routes.SelectTeam }, getState); }; @@ -100,3 +100,24 @@ export function openRightMenuDrawer() { }, getState); }; } + +export function showOptionsModal(title, options) { + return async (dispatch, getState) => { + dispatch({ + type: NavigationTypes.NAVIGATION_MODAL, + route: Routes.OptionsModal, + props: { + title, + options + } + }, getState); + }; +} + +export function closeModal() { + return async (dispatch, getState) => { + dispatch({ + type: NavigationTypes.NAVIGATION_CLOSE_MODAL + }, getState); + }; +} diff --git a/app/actions/views/channel.js b/app/actions/views/channel.js index 92493842e..396abb35a 100644 --- a/app/actions/views/channel.js +++ b/app/actions/views/channel.js @@ -4,6 +4,7 @@ import {batchActions} from 'redux-batched-actions'; import {ViewTypes} from 'app/constants'; import {updateStorage} from 'app/actions/storage'; +import {closeDrawers} from 'app/actions/navigation'; import { fetchMyChannelsAndMembers, @@ -125,8 +126,12 @@ export function selectInitialChannel(teamId) { export function handleSelectChannel(channelId) { return async (dispatch, getState) => { const currentTeamId = getState().entities.teams.currentId; + await updateStorage(currentTeamId, {currentChannelId: channelId}); await selectChannel(channelId)(dispatch, getState); + setTimeout(async () => { + await closeDrawers()(dispatch, getState); // trying to smooth out channel switch transitions + }, 200); }; } diff --git a/app/actions/views/right_menu_drawer.js b/app/actions/views/right_menu_drawer.js index d9e60e868..3c8843ca3 100644 --- a/app/actions/views/right_menu_drawer.js +++ b/app/actions/views/right_menu_drawer.js @@ -6,17 +6,6 @@ import {batchActions} from 'redux-batched-actions'; import {NavigationTypes} from 'app/constants'; import Routes from 'app/navigation/routes'; -export function goToSelectTeam() { - return async (dispatch, getState) => { - dispatch(batchActions([{ - type: NavigationTypes.NAVIGATION_CLOSE_DRAWERS - }, { - type: NavigationTypes.NAVIGATION_PUSH, - route: Routes.SelectTeam - }]), getState); - }; -} - export function goToRecentMentions() { return async (dispatch, getState) => { dispatch(batchActions([{ diff --git a/app/components/channel_list/channel_list.js b/app/components/channel_list/channel_list.js index 04186fff6..a9f65de2d 100644 --- a/app/components/channel_list/channel_list.js +++ b/app/components/channel_list/channel_list.js @@ -73,8 +73,8 @@ class ChannelList extends React.Component { leaveChannel: React.PropTypes.func.isRequired, markFavorite: React.PropTypes.func.isRequired, unmarkFavorite: React.PropTypes.func.isRequired, - openModal: React.PropTypes.func.isRequired, - closeModal: React.PropTypes.func.isRequired + showOptionsModal: React.PropTypes.func.isRequired, + closeOptionsModal: React.PropTypes.func.isRequired }).isRequired }; @@ -176,7 +176,7 @@ class ChannelList extends React.Component { }, { text: formatMessage({id: 'mobile.channel_list.alertYes', defaultMessage: 'Yes'}), onPress: () => { - this.setState({showOptions: false}); + this.props.actions.closeOptionsModal(); this.props.actions.leaveChannel(channel); } }] @@ -201,7 +201,7 @@ class ChannelList extends React.Component { open = { action: () => { - this.props.actions.closeModal(); + this.props.actions.closeOptionsModal(); this.onSelectChannel(channel); }, text: formatMessage({id: 'mobile.channel_list.openDM', defaultMessage: 'Open Direct Message'}) @@ -231,7 +231,7 @@ class ChannelList extends React.Component { open = { action: () => { - this.props.actions.closeModal(); + this.props.actions.closeOptionsModal(); this.onSelectChannel(channel); }, text: formatMessage({id: 'mobile.channel_list.openChannel', defaultMessage: 'Open {term}'}, { @@ -257,7 +257,7 @@ class ChannelList extends React.Component { if (channel.isFavorite) { favorite = { action: () => { - this.props.actions.closeModal(); + this.props.actions.closeOptionsModal(); this.props.actions.unmarkFavorite(channel.id); }, text: formatMessage({id: 'channelHeader.removeFromFavorites', defaultMessage: 'Remove from Favorites'}) @@ -265,7 +265,7 @@ class ChannelList extends React.Component { } else { favorite = { action: () => { - this.props.actions.closeModal(); + this.props.actions.closeOptionsModal(); this.props.actions.markFavorite(channel.id); }, text: formatMessage({id: 'channelHeader.addToFavorites', defaultMessage: 'Add to Favorites'}) @@ -276,7 +276,7 @@ class ChannelList extends React.Component { if (close) { options.push(close); } - this.props.actions.openModal(title, options); + this.props.actions.showOptionsModal(title, options); }; getUnreadMessages = (channel) => { diff --git a/app/components/channel_list/channel_list_container.js b/app/components/channel_list/channel_list_container.js index 97b61ec2d..9f55f96a9 100644 --- a/app/components/channel_list/channel_list_container.js +++ b/app/components/channel_list/channel_list_container.js @@ -4,7 +4,7 @@ import {bindActionCreators} from 'redux'; import {connect} from 'react-redux'; -import {openModal, closeModal} from 'app/actions/views/options_modal'; +import {showOptionsModal, closeModal} from 'app/actions/navigation'; import {closeDMChannel, leaveChannel, markFavorite, unmarkFavorite} from 'app/actions/views/channel'; import {viewChannel} from 'service/actions/channels'; @@ -24,8 +24,8 @@ function mapDispatchToProps(dispatch) { leaveChannel, markFavorite, unmarkFavorite, - openModal, - closeModal + showOptionsModal, + closeOptionsModal: closeModal }, dispatch) }; } diff --git a/app/components/post_list/post_list.js b/app/components/post_list/post_list.js index 9342f10d6..f4f2a6bfb 100644 --- a/app/components/post_list/post_list.js +++ b/app/components/post_list/post_list.js @@ -2,7 +2,10 @@ // See License.txt for license information. import React from 'react'; -import {ListView, StyleSheet} from 'react-native'; +import { + ListView, + StyleSheet +} from 'react-native'; import Post from 'app/components/post'; diff --git a/app/components/post_list/post_list_container.js b/app/components/post_list/post_list_container.js index ab832e4f7..9557e384c 100644 --- a/app/components/post_list/post_list_container.js +++ b/app/components/post_list/post_list_container.js @@ -15,4 +15,3 @@ function mapStateToProps(state, ownProps) { } export default connect(mapStateToProps)(PostList); - diff --git a/app/constants/navigation.js b/app/constants/navigation.js index 90d3ee7e1..d0a28f2c1 100644 --- a/app/constants/navigation.js +++ b/app/constants/navigation.js @@ -12,7 +12,9 @@ const NavigationTypes = keyMirror({ NAVIGATION_JUMP: null, NAVIGATION_JUMP_TO_INDEX: null, NAVIGATION_REPLACE: null, - NAVIGATION_RESET: null + NAVIGATION_RESET: null, + NAVIGATION_MODAL: null, + NAVIGATION_CLOSE_MODAL: null }); export default NavigationTypes; diff --git a/app/initial_state.js b/app/initial_state.js index fdf740d41..251c37e24 100644 --- a/app/initial_state.js +++ b/app/initial_state.js @@ -258,8 +258,13 @@ const state = { routes: [ Routes.Root ], + modal: { + index: 0, + routes: [] + }, + isModal: false, leftDrawerOpen: false, - leftDrawerRoute: null, + leftDrawerRoute: Routes.ChannelDrawer, rightDrawerOpen: false, rightDrawerRoute: null }, diff --git a/app/navigation/navigation_modal.js b/app/navigation/navigation_modal.js new file mode 100644 index 000000000..4a68aa1c2 --- /dev/null +++ b/app/navigation/navigation_modal.js @@ -0,0 +1,63 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import React, {PropTypes, PureComponent} from 'react'; +import { + Animated, + Dimensions +} from 'react-native'; + +const {View: AnimatedView} = Animated; +const {width: deviceWidth, height: deviceHeight} = Dimensions.get('window'); + +export default class NavigationModal extends PureComponent { + static propTypes = { + show: PropTypes.bool + } + + static defaultProps = { + show: false + } + + state = { + top: new Animated.Value(deviceHeight) + } + + componentWillReceiveProps(nextProps) { + if (this.props.show === nextProps.show) { + return; + } + + // In order for the scene to be shown throughout the + // animated slide down we have to hang on to it by + // storing it in state + if (!this.state.children) { + this.setState({ + children: nextProps.children + }); + } + + const animateValue = nextProps.show ? 0 : deviceHeight; + + Animated.timing(this.state.top, { + toValue: animateValue, + duration: 400 + }).start(() => { + // Once the scene has finished sliding down we can release the child scene + // which will unmount the scene correctly. + if (!this.props.show && !nextProps.show) { + this.setState({ + children: null + }); + } + }); + } + + render() { + return ( + + {this.state.children} + + ); + } +} diff --git a/app/navigation/router.js b/app/navigation/router.js index 226021215..09213b878 100644 --- a/app/navigation/router.js +++ b/app/navigation/router.js @@ -13,15 +13,15 @@ import {bindActionCreators} from 'redux'; import {closeDrawers, goBack} from 'app/actions/navigation'; import Drawer from 'app/components/drawer'; import FormattedText from 'app/components/formatted_text'; -import OptionsModal from 'app/components/options_modal'; import {RouteTransitions} from 'app/navigation/routes'; import {getTheme} from 'service/selectors/entities/preferences'; +import NavigationModal from './navigation_modal'; + class Router extends React.Component { static propTypes = { navigation: React.PropTypes.object, theme: React.PropTypes.object, - modalVisible: React.PropTypes.bool.isRequired, actions: React.PropTypes.shape({ closeDrawers: React.PropTypes.func.isRequired, goBack: React.PropTypes.func.isRequired @@ -49,7 +49,7 @@ class Router extends React.Component { wrapHeaderComponent = (fx) => (props) => { if (fx && props.scene.isActive) { - return fx(props, this.emitHeaderEvent); + return fx(props, this.emitHeaderEvent, this.props.theme); } return null; @@ -74,10 +74,7 @@ class Router extends React.Component { renderLeftComponent={renderLeftComponent} renderTitleComponent={renderTitleComponent} renderRightComponent={renderRightComponent} - style={[ - navigationProps.headerStyle, - {backgroundColor: this.props.theme.sidebarHeaderBg} - ]} + style={[{backgroundColor: this.props.theme.sidebarHeaderBg}, navigationProps.headerStyle]} /> ); } @@ -94,7 +91,14 @@ class Router extends React.Component { ...cardProps }); } else { - style = {}; + // have to override shadow props for transparent modals + style = { + backgroundColor: 'transparent', + shadowColor: null, + shadowOffset: null, + shadowOpacity: null, + shadowRadius: null + }; } return ( @@ -154,7 +158,7 @@ class Router extends React.Component { configureTransition = () => { return { - duration: 500, + duration: 300, easing: Easing.inOut(Easing.ease) }; }; @@ -166,14 +170,13 @@ class Router extends React.Component { leftDrawerRoute, rightDrawerOpen, rightDrawerRoute, - routes + routes, + isModal: modalVisible } = this.props.navigation; const navigationProps = this.extractNavigationProps(routes[index]); let leftDrawerContent; if (leftDrawerRoute) { - // TODO: We should make it so that this is availabe once we login - // son when sliding it renders correctly without the neeed to open using the top-bar leftDrawerContent = this.renderRoute(leftDrawerRoute); } @@ -182,52 +185,58 @@ class Router extends React.Component { rightDrawerContent = this.renderRoute(rightDrawerRoute); } - const {modalVisible} = this.props; - return ( - + + + + + + - - - + + ); }; } function mapStateToProps(state) { - const modalVisible = state.views.optionsModal.visible; return { navigation: state.navigation, - theme: getTheme(state), - modalVisible + theme: getTheme(state) }; } diff --git a/app/navigation/routes.js b/app/navigation/routes.js index 09189704d..0c4a5e558 100644 --- a/app/navigation/routes.js +++ b/app/navigation/routes.js @@ -10,6 +10,7 @@ import { LoadTeam, Login, Mfa, + OptionsModal, RightMenuDrawer, Root, Search, @@ -77,6 +78,13 @@ export const Routes = { title: {id: 'mobile.routes.mfa', defaultMessage: 'Multi-factor Authentication'} } }, + OptionsModal: { + key: 'OptionsModal', + component: OptionsModal, + navigationProps: { + hideNavBar: true + } + }, RightMenuDrawer: { key: 'RightMenuDrawer', component: RightMenuDrawer diff --git a/app/reducers/navigation/index.js b/app/reducers/navigation/index.js index 7b14bd20d..979fd6eee 100644 --- a/app/reducers/navigation/index.js +++ b/app/reducers/navigation/index.js @@ -13,6 +13,11 @@ const initialState = { routes: [ Routes.Root ], + modal: { + index: 0, + routes: [] + }, + isModal: false, leftDrawerOpen: false, leftDrawerRoute: null, rightDrawerOpen: false, @@ -21,11 +26,19 @@ const initialState = { export default function(state = initialState, action) { switch (action.type) { - case NavigationTypes.NAVIGATION_PUSH: + case NavigationTypes.NAVIGATION_PUSH: { + if (state.isModal) { + const modalState = NavigationExperimental.StateUtils.push(state.modal, {props: action.props, ...action.route}); + return { + ...state, + modal: modalState + }; + } return NavigationExperimental.StateUtils.push(state, action.route); + } case NavigationTypes.NAVIGATION_POP: - if (state.leftDrawerOpen || state.rightDrawerOpen) { + if (!state.isModal && (state.leftDrawerOpen || state.rightDrawerOpen)) { return { ...state, leftDrawerOpen: false, @@ -33,6 +46,17 @@ export default function(state = initialState, action) { }; } + if (state.isModal) { + return { + ...state, + modal: { + index: 0, + routes: [] + }, + isModal: false + }; + } + return NavigationExperimental.StateUtils.pop(state); case NavigationTypes.NAVIGATION_OPEN_LEFT_DRAWER: @@ -56,22 +80,81 @@ export default function(state = initialState, action) { rightDrawerOpen: false }; - case NavigationTypes.NAVIGATION_JUMP: - return NavigationExperimental.StateUtils.jumpTo(state, action.key); + case NavigationTypes.NAVIGATION_JUMP: { + if (state.isModal) { + const modalState = NavigationExperimental.StateUtils.jumpTo(state.modal, action.key); + return { + ...state, + modal: modalState + }; + } + + return NavigationExperimental.StateUtils.jumpTo(state, action.key); + } + + case NavigationTypes.NAVIGATION_JUMP_TO_INDEX: { + if (state.isModal) { + const modalState = NavigationExperimental.StateUtils.jumpToIndex(state.modal, action.index); + return { + ...state, + modal: modalState + }; + } - case NavigationTypes.NAVIGATION_JUMP_TO_INDEX: return NavigationExperimental.StateUtils.jumpToIndex(state, action.index); + } case NavigationTypes.NAVIGATION_RESET: return { ...state, ...NavigationExperimental.StateUtils.reset(state, action.routes, action.index), + modal: { + index: 0, + routes: [] + }, + isModal: false, leftDrawerOpen: false, rightDrawerOpen: false }; - case NavigationTypes.NAVIGATION_REPLACE: + case NavigationTypes.NAVIGATION_REPLACE: { + if (state.isModal) { + const modalState = NavigationExperimental.StateUtils.replaceAtIndex(state.modal, state.modal.index, action.index); + return { + ...state, + modal: modalState + }; + } + return NavigationExperimental.StateUtils.replaceAtIndex(state, state.index, action.route); + } + + case NavigationTypes.NAVIGATION_MODAL: { + const modal = { + index: 0, + routes: [ + { + ...action.route, + props: action.props + } + ] + }; + return { + ...state, + modal, + isModal: true + }; + } + + case NavigationTypes.NAVIGATION_CLOSE_MODAL: + return { + ...state, + modal: { + index: 0, + routes: [] + }, + isModal: false + }; case UsersTypes.LOGOUT_SUCCESS: return NavigationExperimental.StateUtils.reset(state, initialState.routes, initialState.index); diff --git a/app/scenes/channel/channel_menu_button.js b/app/scenes/channel/channel_menu_button.js index e93714bb9..91bde8fed 100644 --- a/app/scenes/channel/channel_menu_button.js +++ b/app/scenes/channel/channel_menu_button.js @@ -14,14 +14,12 @@ import {getTheme} from 'service/selectors/entities/preferences'; function ChannelMenuButton(props) { return ( - props.emitter('open_right_menu')} - style={{height: 25, width: 25, marginLeft: 10, marginRight: 10}} - > + props.emitter('open_right_menu')}> diff --git a/app/scenes/channel_drawer/channel_drawer.js b/app/scenes/channel_drawer/channel_drawer.js index 557a5dc91..4eac8f498 100644 --- a/app/scenes/channel_drawer/channel_drawer.js +++ b/app/scenes/channel_drawer/channel_drawer.js @@ -18,9 +18,13 @@ export default class ChannelDrawer extends React.PureComponent { theme: React.PropTypes.object.isRequired }; + static defaultProps = { + currentTeam: {}, + currentChannel: {} + } + selectChannel = (id) => { this.props.actions.handleSelectChannel(id); - this.props.actions.closeDrawers(); }; render() { diff --git a/app/scenes/index.js b/app/scenes/index.js index f1812bad5..feb42961a 100644 --- a/app/scenes/index.js +++ b/app/scenes/index.js @@ -9,6 +9,7 @@ import ChannelAddMembers from './channel_add_members'; import LoadTeam from './load_team'; import Login from './login/login_container.js'; import Mfa from './mfa'; +import OptionsModal from './options_modal'; import RightMenuDrawer from './right_menu_drawer'; import Root from './root/root_container.js'; import Search from './search/search_container.js'; @@ -24,6 +25,7 @@ module.exports = { LoadTeam, Login, Mfa, + OptionsModal, RightMenuDrawer, Root, Search, diff --git a/app/scenes/navigationSceneConnect.js b/app/scenes/navigationSceneConnect.js index 4398d264d..b4b8728d9 100644 --- a/app/scenes/navigationSceneConnect.js +++ b/app/scenes/navigationSceneConnect.js @@ -15,7 +15,7 @@ import Icon from 'react-native-vector-icons/FontAwesome'; import FormattedText from 'app/components/formatted_text'; const defaults = { - renderBackButton: (props) => { + renderBackButton: (props, emitter, theme) => { return ( ); }, - renderTitleComponent: (props) => { + renderTitleComponent: (props, emitter, theme) => { const navProps = props.scene.route.navigationProps || {}; const title = navProps.title; if (title) { @@ -43,7 +43,7 @@ const defaults = { ); diff --git a/app/components/options_modal/index.js b/app/scenes/options_modal/index.js similarity index 100% rename from app/components/options_modal/index.js rename to app/scenes/options_modal/index.js diff --git a/app/components/options_modal/options_modal.js b/app/scenes/options_modal/options_modal.js similarity index 89% rename from app/components/options_modal/options_modal.js rename to app/scenes/options_modal/options_modal.js index dc40ba6eb..51f36f50b 100644 --- a/app/components/options_modal/options_modal.js +++ b/app/scenes/options_modal/options_modal.js @@ -7,7 +7,6 @@ import { View, StyleSheet, Dimensions, - Modal, Text, ScrollView, TouchableOpacity, @@ -84,7 +83,6 @@ export default class OptionsModal extends PureComponent { static propTypes = { title: PropTypes.string, options: PropTypes.array, - visible: PropTypes.bool, onOptionSelected: PropTypes.func, style: View.propTypes.style, titleStyle: View.propTypes.style, @@ -101,7 +99,6 @@ export default class OptionsModal extends PureComponent { static defaultProps = { title: '', options: [], - visible: false, style: {}, cancelStyle: {}, cancelTextStyle: {}, @@ -203,17 +200,10 @@ export default class OptionsModal extends PureComponent { render() { if (this.props.options.length) { return ( - - this.onOptionSelected(null)} - animationType={this.state.animationType} - > - this.onOptionSelected(null)}> - {this.renderOptionList()} - - + + this.onOptionSelected(null)}> + {this.renderOptionList()} + ); } diff --git a/app/components/options_modal/options_modal_container.js b/app/scenes/options_modal/options_modal_container.js similarity index 56% rename from app/components/options_modal/options_modal_container.js rename to app/scenes/options_modal/options_modal_container.js index 06b567d3a..25632b42e 100644 --- a/app/components/options_modal/options_modal_container.js +++ b/app/scenes/options_modal/options_modal_container.js @@ -2,24 +2,25 @@ // See License.txt for license information. import {bindActionCreators} from 'redux'; -import {connect} from 'react-redux'; -import {closeModal} from 'app/actions/views/options_modal'; +import navigationSceneConnect from '../navigationSceneConnect'; + +import {goBack} from 'app/actions/navigation'; import OptionsModal from './options_modal'; function mapStateToProps(state, ownProps) { return { - ...ownProps, - ...state.views.optionsModal + ...state.views.optionsModal, + ...ownProps }; } function mapDispatchToProps(dispatch) { return { actions: bindActionCreators({ - closeModal + closeModal: goBack }, dispatch) }; } -export default connect(mapStateToProps, mapDispatchToProps)(OptionsModal); +export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(OptionsModal); diff --git a/app/scenes/right_menu_drawer/right_menu_drawer.js b/app/scenes/right_menu_drawer/right_menu_drawer.js index c9e6818b9..48083b9b5 100644 --- a/app/scenes/right_menu_drawer/right_menu_drawer.js +++ b/app/scenes/right_menu_drawer/right_menu_drawer.js @@ -12,37 +12,40 @@ import { import Icon from 'react-native-vector-icons/FontAwesome'; import FormattedText from 'app/components/formatted_text'; +import {makeStyleSheetFromTheme} from 'app/utils/theme'; import RightMenuDrawerItem from './right_menu_drawer_item'; -const Styles = StyleSheet.create({ - container: { - backgroundColor: '#2071a7', - flex: 1, - ...Platform.select({ - ios: { - paddingTop: 20 - }, - android: { - paddingTop: 5 - } - }) - }, - itemText: { - color: 'white' - }, - icon: { - color: 'white', - width: 25 - }, - mentionIcon: { - fontSize: 17, - fontWeight: 'bold' - }, - divider: { - borderColor: 'rgba(255, 255, 255, 0.6)', - borderTopWidth: StyleSheet.hairlineWidth - } +const getStyleSheet = makeStyleSheetFromTheme((theme) => { + return StyleSheet.create({ + container: { + backgroundColor: theme.sidebarBg, + flex: 1, + ...Platform.select({ + ios: { + paddingTop: 20 + }, + android: { + paddingTop: 5 + } + }) + }, + itemText: { + color: 'white' + }, + icon: { + color: 'white', + width: 25 + }, + mentionIcon: { + fontSize: 17, + fontWeight: 'bold' + }, + divider: { + borderColor: 'rgba(255, 255, 255, 0.6)', + borderTopWidth: StyleSheet.hairlineWidth + } + }); }); export default class RightMenuDrawer extends React.Component { @@ -50,12 +53,15 @@ export default class RightMenuDrawer extends React.Component { actions: React.PropTypes.shape({ goToFlaggedPosts: React.PropTypes.func.isRequired, goToRecentMentions: React.PropTypes.func.isRequired, - goToSelectTeam: React.PropTypes.func.isRequired, + goToModalSelectTeam: React.PropTypes.func.isRequired, logout: React.PropTypes.func.isRequired - }).isRequired + }).isRequired, + theme: React.PropTypes.object } render() { + const Styles = getStyleSheet(this.props.theme); + return ( @@ -77,7 +83,7 @@ export default class RightMenuDrawer extends React.Component { defaultMessage='Flagged Posts' /> - + - + - + - + - + ; +function Divider(props) { + return ; } diff --git a/app/scenes/right_menu_drawer/right_menu_drawer_container.js b/app/scenes/right_menu_drawer/right_menu_drawer_container.js index 28c5dd489..66360967e 100644 --- a/app/scenes/right_menu_drawer/right_menu_drawer_container.js +++ b/app/scenes/right_menu_drawer/right_menu_drawer_container.js @@ -4,15 +4,19 @@ import {bindActionCreators} from 'redux'; import {connect} from 'react-redux'; -import {goBack} from 'app/actions/navigation'; -import {goToFlaggedPosts, goToRecentMentions, goToSelectTeam} from 'app/actions/views/right_menu_drawer'; +import {goBack, goToModalSelectTeam} from 'app/actions/navigation'; +import {goToFlaggedPosts, goToRecentMentions} from 'app/actions/views/right_menu_drawer'; import {logout} from 'service/actions/users'; +import {getTheme} from 'service/selectors/entities/preferences'; import RightMenuDrawer from './right_menu_drawer'; function mapStateToProps(state, ownProps) { - return ownProps; + return { + ...ownProps, + theme: getTheme(state) + }; } function mapDispatchToProps(dispatch) { @@ -21,7 +25,7 @@ function mapDispatchToProps(dispatch) { goBack, goToFlaggedPosts, goToRecentMentions, - goToSelectTeam, + goToModalSelectTeam, logout }, dispatch) }; diff --git a/app/scenes/select_team/select_team.js b/app/scenes/select_team/select_team.js index 5eb6ab50c..a9ef66b9f 100644 --- a/app/scenes/select_team/select_team.js +++ b/app/scenes/select_team/select_team.js @@ -2,7 +2,12 @@ // See License.txt for license information. import React from 'react'; -import {View, Image, Text} from 'react-native'; +import { + Image, + Text, + TouchableOpacity, + View +} from 'react-native'; import Button from 'react-native-button'; import Icon from 'react-native-vector-icons/MaterialIcons'; @@ -16,12 +21,39 @@ export default class SelectTeam extends React.Component { config: React.PropTypes.object.isRequired, teams: React.PropTypes.object.isRequired, myMembers: React.PropTypes.object.isRequired, + subscribeToHeaderEvent: React.PropTypes.func.isRequired, + unsubscribeFromHeaderEvent: React.PropTypes.func.isRequired, actions: React.PropTypes.shape({ goBackToChannelView: React.PropTypes.func.isRequired, handleTeamChange: React.PropTypes.func.isRequired }).isRequired }; + static navigationProps = { + renderLeftComponent: (props, emitter, theme) => { + return ( + emitter('close')} + > + + + ); + } + } + + componentWillMount() { + this.props.subscribeToHeaderEvent('close', this.props.actions.goBackToChannelView); + } + + componentWillUnmount() { + this.props.unsubscribeFromHeaderEvent('close'); + } + onSelectTeam(team) { this.props.actions.handleTeamChange(team).then(this.props.actions.goBackToChannelView); } diff --git a/test/app/reducers/navigation.test.js b/test/app/reducers/navigation.test.js index ab5395fc0..31fa8c5c3 100644 --- a/test/app/reducers/navigation.test.js +++ b/test/app/reducers/navigation.test.js @@ -23,6 +23,11 @@ describe('Reducers.Navigation', () => { assert.deepEqual(state, { index: 0, routes: [Routes.Root], + modal: { + index: 0, + routes: [] + }, + isModal: false, leftDrawerOpen: false, leftDrawerRoute: null, rightDrawerOpen: false,