diff --git a/app/actions/navigation.js b/app/actions/navigation.js
index ca261c905..f1e6852bb 100644
--- a/app/actions/navigation.js
+++ b/app/actions/navigation.js
@@ -178,7 +178,12 @@ export function popToRoot() {
return () => {
const componentId = EphemeralStore.getTopComponentId();
- Navigation.popToRoot(componentId);
+ Navigation.popToRoot(componentId).catch(() => {
+ // RNN returns a promise rejection if there are no screens
+ // atop the root screen to pop. We'll do nothing in this
+ // case but we will catch the rejection here so that the
+ // caller doesn't have to.
+ });
};
}
@@ -289,7 +294,11 @@ export function dismissModal(options = {}) {
export function dismissAllModals(options = {}) {
return () => {
- Navigation.dismissAllModals(options);
+ Navigation.dismissAllModals(options).catch(() => {
+ // RNN returns a promise rejection if there are no modals to
+ // dismiss. We'll do nothing in this case but we will catch
+ // the rejection here so that the caller doesn't have to.
+ });
};
}
@@ -321,3 +330,32 @@ export function setButtons(componentId, buttons = {leftButtons: [], rightButtons
});
};
}
+
+export function showOverlay(name, passProps, options = {}) {
+ return () => {
+ const defaultOptions = {
+ overlay: {
+ interceptTouchOutside: false,
+ },
+ };
+
+ Navigation.showOverlay({
+ component: {
+ name,
+ passProps,
+ options: merge(defaultOptions, options),
+ },
+ });
+ };
+}
+
+export function dismissOverlay(componentId) {
+ return () => {
+ return Navigation.dismissOverlay(componentId).catch(() => {
+ // RNN returns a promise rejection if there is no modal with
+ // this componentId to dismiss. We'll do nothing in this case
+ // but we will catch the rejection here so that the caller
+ // doesn't have to.
+ });
+ };
+}
diff --git a/app/actions/views/search.js b/app/actions/views/search.js
index 0e6f0c3a2..2ccd0060d 100644
--- a/app/actions/views/search.js
+++ b/app/actions/views/search.js
@@ -1,8 +1,6 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
-import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
-
import {ViewTypes} from 'app/constants';
export function handleSearchDraftChanged(text) {
@@ -13,27 +11,3 @@ export function handleSearchDraftChanged(text) {
}, getState);
};
}
-
-// TODO: Remove this once all screens/components call
-// app/actions/navigation's showSearchModal
-export function showSearchModal(navigator, initialValue = '') {
- return (dispatch, getState) => {
- const theme = getTheme(getState());
-
- const options = {
- screen: 'Search',
- animated: true,
- backButtonTitle: '',
- overrideBackPress: true,
- passProps: {
- initialValue,
- },
- navigatorStyle: {
- navBarHidden: true,
- screenBackgroundColor: theme.centerChannelBg,
- },
- };
-
- navigator.showModal(options);
- };
-}
diff --git a/app/components/__snapshots__/profile_picture_button.test.js.snap b/app/components/__snapshots__/profile_picture_button.test.js.snap
index 97f0ea52d..c4205e2cf 100644
--- a/app/components/__snapshots__/profile_picture_button.test.js.snap
+++ b/app/components/__snapshots__/profile_picture_button.test.js.snap
@@ -9,13 +9,6 @@ exports[`profile_picture_button should match snapshot 1`] = `
]
}
maxFileSize={20971520}
- navigator={
- Object {
- "dismissModal": [MockFunction],
- "push": [MockFunction],
- "setButtons": [MockFunction],
- }
- }
theme={
Object {
"awayIndicator": "#ffbc42",
diff --git a/app/components/client_upgrade_listener/client_upgrade_listener.js b/app/components/client_upgrade_listener/client_upgrade_listener.js
index 31631d8ca..b05b3f14f 100644
--- a/app/components/client_upgrade_listener/client_upgrade_listener.js
+++ b/app/components/client_upgrade_listener/client_upgrade_listener.js
@@ -27,6 +27,8 @@ export default class ClientUpgradeListener extends PureComponent {
actions: PropTypes.shape({
logError: PropTypes.func.isRequired,
setLastUpgradeCheck: PropTypes.func.isRequired,
+ showModal: PropTypes.func.isRequired,
+ dismissModal: PropTypes.func.isRequired,
}).isRequired,
currentVersion: PropTypes.string,
downloadLink: PropTypes.string,
@@ -35,7 +37,6 @@ export default class ClientUpgradeListener extends PureComponent {
lastUpgradeCheck: PropTypes.number,
latestVersion: PropTypes.string,
minVersion: PropTypes.string,
- navigator: PropTypes.object,
theme: PropTypes.object.isRequired,
};
@@ -140,27 +141,26 @@ export default class ClientUpgradeListener extends PureComponent {
};
handleLearnMore = () => {
+ const {actions} = this.props;
const {intl} = this.context;
- this.props.navigator.dismissModal({animationType: 'none'});
- this.props.navigator.showModal({
- screen: 'ClientUpgrade',
- title: intl.formatMessage({id: 'mobile.client_upgrade', defaultMessage: 'Upgrade App'}),
- navigatorStyle: {
- navBarHidden: false,
- statusBarHidden: false,
- statusBarHideWithNavBar: false,
- },
- navigatorButtons: {
+ actions.dismissModal();
+
+ const screen = 'ClientUpgrade';
+ const title = intl.formatMessage({id: 'mobile.client_upgrade', defaultMessage: 'Upgrade App'});
+ const passProps = {
+ upgradeType: this.state.upgradeType,
+ };
+ const options = {
+ topBar: {
leftButtons: [{
id: 'close-upgrade',
icon: this.closeButton,
}],
},
- passProps: {
- upgradeType: this.state.upgradeType,
- },
- });
+ };
+
+ actions.showModal(screen, title, passProps, options);
this.toggleUpgradeMessage(false);
};
diff --git a/app/components/client_upgrade_listener/index.js b/app/components/client_upgrade_listener/index.js
index 2e66b2377..173c14a50 100644
--- a/app/components/client_upgrade_listener/index.js
+++ b/app/components/client_upgrade_listener/index.js
@@ -4,11 +4,12 @@ import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {logError} from 'mattermost-redux/actions/errors';
+import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
+import {showModal, dismissModal} from 'app/actions/navigation';
import {setLastUpgradeCheck} from 'app/actions/views/client_upgrade';
import getClientUpgrade from 'app/selectors/client_upgrade';
import {isLandscape} from 'app/selectors/device';
-import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import ClientUpgradeListener from './client_upgrade_listener';
@@ -32,6 +33,8 @@ function mapDispatchToProps(dispatch) {
actions: bindActionCreators({
logError,
setLastUpgradeCheck,
+ showModal,
+ dismissModal,
}, dispatch),
};
}
diff --git a/app/components/message_attachments/index.js b/app/components/message_attachments/index.js
index e3b287545..7f3c126ce 100644
--- a/app/components/message_attachments/index.js
+++ b/app/components/message_attachments/index.js
@@ -18,7 +18,6 @@ export default class MessageAttachments extends PureComponent {
deviceWidth: PropTypes.number.isRequired,
postId: PropTypes.string.isRequired,
metadata: PropTypes.object,
- navigator: PropTypes.object.isRequired,
onHashtagPress: PropTypes.func,
onPermalinkPress: PropTypes.func,
theme: PropTypes.object,
@@ -33,7 +32,6 @@ export default class MessageAttachments extends PureComponent {
deviceHeight,
deviceWidth,
metadata,
- navigator,
onHashtagPress,
onPermalinkPress,
postId,
@@ -52,7 +50,6 @@ export default class MessageAttachments extends PureComponent {
deviceWidth={deviceWidth}
key={'att_' + i}
metadata={metadata}
- navigator={navigator}
onHashtagPress={onHashtagPress}
onPermalinkPress={onPermalinkPress}
postId={postId}
diff --git a/app/components/post_attachment_opengraph/post_attachment_opengraph.test.js b/app/components/post_attachment_opengraph/post_attachment_opengraph.test.js
index 4d03ae92d..dc1b926ff 100644
--- a/app/components/post_attachment_opengraph/post_attachment_opengraph.test.js
+++ b/app/components/post_attachment_opengraph/post_attachment_opengraph.test.js
@@ -37,7 +37,6 @@ describe('PostAttachmentOpenGraph', () => {
},
isReplyPost: false,
link: 'https://mattermost.com/',
- navigator: {},
theme: Preferences.THEMES.default,
};
diff --git a/app/components/post_textbox/__snapshots__/post_textbox.test.js.snap b/app/components/post_textbox/__snapshots__/post_textbox.test.js.snap
index ac7535189..ea489c424 100644
--- a/app/components/post_textbox/__snapshots__/post_textbox.test.js.snap
+++ b/app/components/post_textbox/__snapshots__/post_textbox.test.js.snap
@@ -16,23 +16,11 @@ exports[`PostTextBox should match, full snapshot 1`] = `
}
}
>
-
{
files: [],
maxFileSize: 1024,
maxMessageLength: 4000,
- navigator: {
- showModal: jest.fn(),
- },
rootId: '',
theme: Preferences.THEMES.default,
uploadFileRequestStatus: 'NOT_STARTED',
diff --git a/app/components/profile_picture_button.test.js b/app/components/profile_picture_button.test.js
index a46a1a09c..44237c1a0 100644
--- a/app/components/profile_picture_button.test.js
+++ b/app/components/profile_picture_button.test.js
@@ -10,15 +10,8 @@ import ProfilePictureButton from './profile_picture_button.js';
import {Client4} from 'mattermost-redux/client';
describe('profile_picture_button', () => {
- const navigator = {
- setButtons: jest.fn(),
- dismissModal: jest.fn(),
- push: jest.fn(),
- };
-
const baseProps = {
theme: Preferences.THEMES.default,
- navigator,
currentUser: {
first_name: 'Dwight',
last_name: 'Schrute',
diff --git a/app/components/root/index.js b/app/components/root/index.js
index 747bfdb9c..7f4b28031 100644
--- a/app/components/root/index.js
+++ b/app/components/root/index.js
@@ -4,7 +4,6 @@
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
-import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentUrl} from 'mattermost-redux/selectors/entities/general';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
@@ -19,7 +18,6 @@ function mapStateToProps(state) {
return {
theme: getTheme(state),
- currentChannelId: getCurrentChannelId(state),
currentUrl: removeProtocol(getCurrentUrl(state)),
locale,
};
diff --git a/app/components/root/root.js b/app/components/root/root.js
index 051c4c715..95e46af44 100644
--- a/app/components/root/root.js
+++ b/app/components/root/root.js
@@ -9,7 +9,7 @@ import {Platform} from 'react-native';
import {Client4} from 'mattermost-redux/client';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
-import {NavigationTypes, ViewTypes} from 'app/constants';
+import {NavigationTypes} from 'app/constants';
import {getTranslations} from 'app/i18n';
export default class Root extends PureComponent {
@@ -18,9 +18,7 @@ export default class Root extends PureComponent {
resetToTeams: PropTypes.func.isRequired,
}).isRequired,
children: PropTypes.node,
- navigator: PropTypes.object,
excludeEvents: PropTypes.bool,
- currentChannelId: PropTypes.string,
currentUrl: PropTypes.string,
locale: PropTypes.string.isRequired,
theme: PropTypes.object.isRequired,
@@ -30,8 +28,6 @@ export default class Root extends PureComponent {
Client4.setAcceptLanguage(this.props.locale);
if (!this.props.excludeEvents) {
- EventEmitter.on(ViewTypes.NOTIFICATION_IN_APP, this.handleInAppNotification);
- EventEmitter.on(ViewTypes.NOTIFICATION_TAPPED, this.handleNotificationTapped);
EventEmitter.on(NavigationTypes.NAVIGATION_NO_TEAMS, this.handleNoTeams);
EventEmitter.on(NavigationTypes.NAVIGATION_ERROR_TEAMS, this.errorTeamsList);
}
@@ -45,30 +41,11 @@ export default class Root extends PureComponent {
componentWillUnmount() {
if (!this.props.excludeEvents) {
- EventEmitter.off(ViewTypes.NOTIFICATION_IN_APP, this.handleInAppNotification);
- EventEmitter.off(ViewTypes.NOTIFICATION_TAPPED, this.handleNotificationTapped);
EventEmitter.off(NavigationTypes.NAVIGATION_NO_TEAMS, this.handleNoTeams);
EventEmitter.off(NavigationTypes.NAVIGATION_ERROR_TEAMS, this.errorTeamsList);
}
}
- handleInAppNotification = (notification) => {
- const {data} = notification;
- const {currentChannelId, navigator} = this.props;
-
- if (data && data.channel_id !== currentChannelId) {
- navigator.showInAppNotification({
- screen: 'Notification',
- position: 'top',
- autoDismissTimerSec: 5,
- dismissWithSwipe: true,
- passProps: {
- notification,
- },
- });
- }
- };
-
handleNoTeams = () => {
if (!this.refs.provider) {
setTimeout(this.handleNoTeams, 200);
@@ -119,18 +96,6 @@ export default class Root extends PureComponent {
actions.resetToTeams(screen, title, passProps, options);
}
- handleNotificationTapped = async () => {
- const {navigator} = this.props;
-
- if (Platform.OS === 'android') {
- navigator.dismissModal({animation: 'none'});
- }
-
- navigator.popToRoot({
- animated: false,
- });
- };
-
render() {
const locale = this.props.locale;
diff --git a/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js b/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js
index 38334340d..b9ced6211 100644
--- a/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js
+++ b/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js
@@ -31,7 +31,6 @@ describe('ChannelItem', () => {
isUnread: true,
hasDraft: false,
mentions: 0,
- navigator: {push: () => {}}, // eslint-disable-line no-empty-function
onSelectChannel: () => {}, // eslint-disable-line no-empty-function
shouldHideChannel: false,
showUnreadForMsgs: true,
diff --git a/app/components/sidebars/settings/settings_sidebar.js b/app/components/sidebars/settings/settings_sidebar.js
index 9a3fff5b3..41a76f970 100644
--- a/app/components/sidebars/settings/settings_sidebar.js
+++ b/app/components/sidebars/settings/settings_sidebar.js
@@ -68,10 +68,12 @@ export default class SettingsDrawer extends PureComponent {
}
componentDidMount() {
+ EventEmitter.on('close_settings_sidebar', this.closeSettingsSidebar);
BackHandler.addEventListener('hardwareBackPress', this.handleAndroidBack);
}
componentWillUnmount() {
+ EventEmitter.off('close_settings_sidebar', this.closeSettingsSidebar);
BackHandler.removeEventListener('hardwareBackPress', this.handleAndroidBack);
}
diff --git a/app/constants/navigation.js b/app/constants/navigation.js
index 809997da3..618dc5b3f 100644
--- a/app/constants/navigation.js
+++ b/app/constants/navigation.js
@@ -9,6 +9,7 @@ const NavigationTypes = keyMirror({
NAVIGATION_NO_TEAMS: null,
RESTART_APP: null,
NAVIGATION_ERROR_TEAMS: null,
+ NAVIGATION_SHOW_OVERLAY: null,
});
export default NavigationTypes;
diff --git a/app/constants/view.js b/app/constants/view.js
index 0c3dc6b37..010944a69 100644
--- a/app/constants/view.js
+++ b/app/constants/view.js
@@ -42,7 +42,6 @@ const ViewTypes = keyMirror({
COMMENT_DRAFT_SELECTION_CHANGED: null,
NOTIFICATION_IN_APP: null,
- NOTIFICATION_TAPPED: null,
SET_POST_DRAFT: null,
SET_COMMENT_DRAFT: null,
diff --git a/app/init/global_event_handler.js b/app/init/global_event_handler.js
index df17fb796..4eb258b93 100644
--- a/app/init/global_event_handler.js
+++ b/app/init/global_event_handler.js
@@ -11,11 +11,13 @@ import {close as closeWebSocket} from 'mattermost-redux/actions/websocket';
import {Client4} from 'mattermost-redux/client';
import {General} from 'mattermost-redux/constants';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
+import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
import {setDeviceDimensions, setDeviceOrientation, setDeviceAsTablet, setStatusBarHeight} from 'app/actions/device';
import {selectDefaultChannel} from 'app/actions/views/channel';
+import {showOverlay} from 'app/actions/navigation';
import {loadConfigAndLicense, setDeepLinkURL, startDataCleanup} from 'app/actions/views/root';
-import {NavigationTypes} from 'app/constants';
+import {NavigationTypes, ViewTypes} from 'app/constants';
import {getTranslations} from 'app/i18n';
import mattermostManaged from 'app/mattermost_managed';
import PushNotifications from 'app/push_notifications';
@@ -38,12 +40,15 @@ class GlobalEventHandler {
EventEmitter.on(General.SERVER_VERSION_CHANGED, this.onServerVersionChanged);
EventEmitter.on(General.CONFIG_CHANGED, this.onServerConfigChanged);
EventEmitter.on(General.SWITCH_TO_DEFAULT_CHANNEL, this.onSwitchToDefaultChannel);
+ this.turnOnInAppNotificationHandling();
Dimensions.addEventListener('change', this.onOrientationChange);
AppState.addEventListener('change', this.onAppStateChange);
Linking.addEventListener('url', this.onDeepLink);
}
appActive = async () => {
+ this.turnOnInAppNotificationHandling();
+
// if the app is being controlled by an EMM provider
if (emmProvider.enabled && emmProvider.inAppPinCode) {
const authExpired = (Date.now() - emmProvider.inBackgroundSince) >= PROMPT_IN_APP_PIN_CODE_AFTER;
@@ -57,6 +62,8 @@ class GlobalEventHandler {
};
appInactive = () => {
+ this.turnOffInAppNotificationHandling();
+
const {dispatch} = this.store;
// When the app is sent to the background we set the time when that happens
@@ -227,6 +234,31 @@ class GlobalEventHandler {
dispatch(logout());
}
};
+
+ turnOnInAppNotificationHandling = () => {
+ EventEmitter.on(ViewTypes.NOTIFICATION_IN_APP, this.handleInAppNotification);
+ }
+
+ turnOffInAppNotificationHandling = () => {
+ EventEmitter.off(ViewTypes.NOTIFICATION_IN_APP, this.handleInAppNotification);
+ }
+
+ handleInAppNotification = (notification) => {
+ const {data} = notification;
+ const {dispatch, getState} = this.store;
+ const state = getState();
+ const currentChannelId = getCurrentChannelId(state);
+
+ if (data && data.channel_id !== currentChannelId) {
+ const screen = 'Notification';
+ const passProps = {
+ notification,
+ };
+
+ EventEmitter.emit(NavigationTypes.NAVIGATION_SHOW_OVERLAY);
+ dispatch(showOverlay(screen, passProps));
+ }
+ };
}
export default new GlobalEventHandler();
diff --git a/app/screens/about/about.js b/app/screens/about/about.js
index dc056e9ec..2417768c1 100644
--- a/app/screens/about/about.js
+++ b/app/screens/about/about.js
@@ -26,7 +26,6 @@ export default class About extends PureComponent {
componentId: PropTypes.string,
config: PropTypes.object.isRequired,
license: PropTypes.object.isRequired,
- navigator: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
};
diff --git a/app/screens/add_reaction/add_reaction.js b/app/screens/add_reaction/add_reaction.js
index f24978bf5..e03ddbf85 100644
--- a/app/screens/add_reaction/add_reaction.js
+++ b/app/screens/add_reaction/add_reaction.js
@@ -15,9 +15,12 @@ import {setNavigatorStyles} from 'app/utils/theme';
export default class AddReaction extends PureComponent {
static propTypes = {
+ actions: PropTypes.shape({
+ dismissModal: PropTypes.func.isRequired,
+ setButtons: PropTypes.func.isRequired,
+ }).isRequired,
componentId: PropTypes.string,
closeButton: PropTypes.object,
- navigator: PropTypes.object.isRequired,
onEmojiPress: PropTypes.func,
theme: PropTypes.object.isRequired,
};
@@ -33,7 +36,7 @@ export default class AddReaction extends PureComponent {
constructor(props) {
super(props);
- props.navigator.setButtons({
+ props.actions.setButtons(props.componentId, {
leftButtons: [{...this.leftButton, icon: props.closeButton}],
});
}
@@ -55,9 +58,7 @@ export default class AddReaction extends PureComponent {
}
close = () => {
- this.props.navigator.dismissModal({
- animationType: 'slide-down',
- });
+ this.props.actions.dismissModal();
};
handleEmojiPress = (emoji) => {
diff --git a/app/screens/add_reaction/index.js b/app/screens/add_reaction/index.js
index 1c3d7556b..eb24346b2 100644
--- a/app/screens/add_reaction/index.js
+++ b/app/screens/add_reaction/index.js
@@ -1,10 +1,13 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
+import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
+import {dismissModal, setButtons} from 'app/actions/navigation';
+
import AddReaction from './add_reaction';
function mapStateToProps(state) {
@@ -13,4 +16,13 @@ function mapStateToProps(state) {
};
}
-export default connect(mapStateToProps)(AddReaction);
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ dismissModal,
+ setButtons,
+ }, dispatch),
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(AddReaction);
diff --git a/app/screens/channel/channel.android.js b/app/screens/channel/channel.android.js
index 14748150e..866911888 100644
--- a/app/screens/channel/channel.android.js
+++ b/app/screens/channel/channel.android.js
@@ -20,35 +20,30 @@ import ChannelBase, {ClientUpgradeListener, style} from './channel_base';
export default class ChannelAndroid extends ChannelBase {
render() {
const {height} = Dimensions.get('window');
- const {
- navigator,
- } = this.props;
const channelLoaderStyle = [style.channelLoader, {height}];
const drawerContent = (
-
+
-
+
- {LocalConfig.EnableMobileClientUpgrade && }
+ {LocalConfig.EnableMobileClientUpgrade && }
);
diff --git a/app/screens/channel/channel.ios.js b/app/screens/channel/channel.ios.js
index 700de6ab7..5e9189102 100644
--- a/app/screens/channel/channel.ios.js
+++ b/app/screens/channel/channel.ios.js
@@ -38,7 +38,6 @@ export default class ChannelIOS extends ChannelBase {
const {height} = Dimensions.get('window');
const {
currentChannelId,
- navigator,
} = this.props;
const channelLoaderStyle = [style.channelLoader, {height}];
@@ -48,17 +47,15 @@ export default class ChannelIOS extends ChannelBase {
const drawerContent = (
-
+
@@ -74,7 +71,7 @@ export default class ChannelIOS extends ChannelBase {
height={height}
style={channelLoaderStyle}
/>
- {LocalConfig.EnableMobileClientUpgrade && }
+ {LocalConfig.EnableMobileClientUpgrade && }
diff --git a/app/screens/code/code.js b/app/screens/code/code.js
index 831538c8a..019b3346b 100644
--- a/app/screens/code/code.js
+++ b/app/screens/code/code.js
@@ -18,8 +18,10 @@ import {changeOpacity, makeStyleSheetFromTheme, setNavigatorStyles} from 'app/ut
export default class Code extends React.PureComponent {
static propTypes = {
+ actions: PropTypes.shape({
+ popTopScreen: PropTypes.func.isRequired,
+ }).isRequired,
componentId: PropTypes.string,
- navigator: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
content: PropTypes.string.isRequired,
};
@@ -39,7 +41,7 @@ export default class Code extends React.PureComponent {
}
handleAndroidBack = () => {
- this.props.navigator.pop();
+ this.props.actions.popTopScreen();
return true;
};
diff --git a/app/screens/code/index.js b/app/screens/code/index.js
index 4b0abdcd9..c833020be 100644
--- a/app/screens/code/index.js
+++ b/app/screens/code/index.js
@@ -1,10 +1,13 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
+import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
+import {popTopScreen} from 'app/actions/navigation';
+
import Code from './code';
function mapStateToProps(state) {
@@ -13,4 +16,12 @@ function mapStateToProps(state) {
};
}
-export default connect(mapStateToProps)(Code);
\ No newline at end of file
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ popTopScreen,
+ }, dispatch),
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(Code);
\ No newline at end of file
diff --git a/app/screens/error_teams_list/error_teams_list.js b/app/screens/error_teams_list/error_teams_list.js
index a795920c8..a972997cd 100644
--- a/app/screens/error_teams_list/error_teams_list.js
+++ b/app/screens/error_teams_list/error_teams_list.js
@@ -32,9 +32,9 @@ export default class ErrorTeamsList extends PureComponent {
connection: PropTypes.func.isRequired,
logout: PropTypes.func.isRequired,
selectDefaultTeam: PropTypes.func.isRequired,
+ resetToChannel: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
- navigator: PropTypes.object,
theme: PropTypes.object,
};
@@ -64,21 +64,10 @@ export default class ErrorTeamsList extends PureComponent {
}
goToChannelView = () => {
- const {navigator, theme} = this.props;
-
- navigator.resetTo({
- screen: 'Channel',
- animated: false,
- navigatorStyle: {
- navBarHidden: true,
- statusBarHidden: false,
- statusBarHideWithNavBar: false,
- screenBackgroundColor: theme.centerChannelBg,
- },
- passProps: {
- disableTermsModal: true,
- },
- });
+ const passProps = {
+ disableTermsModal: true,
+ };
+ this.props.actions.resetToChannel(passProps);
};
getUserInfo = async () => {
diff --git a/app/screens/error_teams_list/error_teams_list.test.js b/app/screens/error_teams_list/error_teams_list.test.js
index 1a8c053dc..229ec1f42 100644
--- a/app/screens/error_teams_list/error_teams_list.test.js
+++ b/app/screens/error_teams_list/error_teams_list.test.js
@@ -22,6 +22,7 @@ describe('ErrorTeamsList', () => {
connection: () => {}, // eslint-disable-line no-empty-function
logout: () => {}, // eslint-disable-line no-empty-function
selectDefaultTeam: () => {}, // eslint-disable-line no-empty-function
+ resetToChannel: jest.fn(),
},
componentId: 'component-id',
theme: Preferences.THEMES.default,
@@ -39,6 +40,7 @@ describe('ErrorTeamsList', () => {
const selectDefaultTeam = jest.fn();
const logout = jest.fn();
const actions = {
+ ...baseProps.actions,
loadMe,
logout,
selectDefaultTeam,
diff --git a/app/screens/error_teams_list/index.js b/app/screens/error_teams_list/index.js
index 31424ed03..981e62733 100644
--- a/app/screens/error_teams_list/index.js
+++ b/app/screens/error_teams_list/index.js
@@ -8,6 +8,8 @@ import {logout, loadMe} from 'mattermost-redux/actions/users';
import {connection} from 'app/actions/device';
import {selectDefaultTeam} from 'app/actions/views/select_team';
+import {resetToChannel} from 'app/actions/navigation';
+
import ErrorTeamsList from './error_teams_list.js';
function mapDispatchToProps(dispatch) {
@@ -17,6 +19,7 @@ function mapDispatchToProps(dispatch) {
selectDefaultTeam,
connection,
loadMe,
+ resetToChannel,
}, dispatch),
};
}
diff --git a/app/screens/expanded_announcement_banner/expanded_announcement_banner.js b/app/screens/expanded_announcement_banner/expanded_announcement_banner.js
index 363105a53..3fb7a31ae 100644
--- a/app/screens/expanded_announcement_banner/expanded_announcement_banner.js
+++ b/app/screens/expanded_announcement_banner/expanded_announcement_banner.js
@@ -16,15 +16,15 @@ export default class ExpandedAnnouncementBanner extends React.PureComponent {
static propTypes = {
actions: PropTypes.shape({
dismissBanner: PropTypes.func.isRequired,
+ popTopScreen: PropTypes.func.isRequired,
}).isRequired,
allowDismissal: PropTypes.bool.isRequired,
bannerText: PropTypes.string.isRequired,
- navigator: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
}
close = () => {
- this.props.navigator.pop();
+ this.props.actions.popTopScreen();
};
dismissBanner = () => {
@@ -67,7 +67,6 @@ export default class ExpandedAnnouncementBanner extends React.PureComponent {
{
- const {getItemMeasures, navigator} = this.props;
+ const {actions, getItemMeasures, componentId} = this.props;
const {index} = this.state;
this.setState({animating: true});
- navigator.setStyle({
- screenBackgroundColor: 'transparent',
+ Navigation.mergeOptions(componentId, {
+ layout: {
+ backgroundColor: 'transparent',
+ },
});
getItemMeasures(index, (origin) => {
@@ -117,7 +126,7 @@ export default class ImagePreview extends PureComponent {
}
this.animateOpenAnimToValue(0, () => {
- navigator.dismissModal({animationType: 'none'});
+ actions.dismissModal();
});
});
};
@@ -177,7 +186,7 @@ export default class ImagePreview extends PureComponent {
};
renderAttachmentDocument = (file) => {
- const {canDownloadFiles, theme, navigator} = this.props;
+ const {canDownloadFiles, theme} = this.props;
return (
@@ -190,7 +199,6 @@ export default class ImagePreview extends PureComponent {
file={file}
iconHeight={100}
iconWidth={100}
- navigator={navigator}
theme={theme}
wrapperHeight={200}
wrapperWidth={200}
@@ -441,6 +449,7 @@ export default class ImagePreview extends PureComponent {
};
showDownloadOptionsIOS = async () => {
+ const {actions} = this.props;
const {formatMessage} = this.context.intl;
const file = this.getCurrentFile();
const items = [];
@@ -504,30 +513,17 @@ export default class ImagePreview extends PureComponent {
});
}
- const options = {
- title: file.caption,
- items,
- onCancelPress: () => this.setHeaderAndFooterVisible(true),
- };
-
if (items.length) {
this.setHeaderAndFooterVisible(false);
- this.props.navigator.showModal({
- screen: 'OptionsModal',
- title: '',
- animationType: 'none',
- passProps: {
- ...options,
- },
- navigatorStyle: {
- navBarHidden: true,
- statusBarHidden: false,
- statusBarHideWithNavBar: false,
- screenBackgroundColor: 'transparent',
- modalPresentationStyle: 'overCurrentContext',
- },
- });
+ const screen = 'OptionsModal';
+ const passProps = {
+ title: file.caption,
+ items,
+ onCancelPress: () => this.setHeaderAndFooterVisible(true),
+ };
+
+ actions.showModalOverCurrentContext(screen, passProps);
}
};
diff --git a/app/screens/image_preview/image_preview.test.js b/app/screens/image_preview/image_preview.test.js
index e4e31a0f6..922e26551 100644
--- a/app/screens/image_preview/image_preview.test.js
+++ b/app/screens/image_preview/image_preview.test.js
@@ -6,6 +6,7 @@ import {shallow} from 'enzyme';
import {
TouchableOpacity,
} from 'react-native';
+import {Navigation} from 'react-native-navigation';
import Preferences from 'mattermost-redux/constants/preferences';
@@ -18,6 +19,13 @@ jest.mock('react-native-doc-viewer', () => {
OpenFile: jest.fn(),
};
});
+jest.mock('react-native-navigation', () => ({
+ Navigation: {
+ mergeOptions: jest.fn(),
+ },
+}));
+
+Navigation.mergeOptions = jest.fn();
describe('ImagePreview', () => {
const baseProps = {
@@ -30,10 +38,14 @@ describe('ImagePreview', () => {
],
getItemMeasures: jest.fn(),
index: 0,
- navigator: {setStyle: jest.fn()},
origin: {},
target: {},
theme: Preferences.THEMES.default,
+ componentId: 'component-id',
+ actions: {
+ dismissModal: jest.fn(),
+ showModalOverCurrentContext: jest.fn(),
+ },
};
test('should match snapshot', () => {
@@ -67,21 +79,26 @@ describe('ImagePreview', () => {
expect(wrapper.state('index')).toEqual(1);
});
- test('should match call getItemMeasures & navigator.setStyle on close', () => {
+ test('should match call getItemMeasures & Navigation.mergeOptions on close', () => {
const getItemMeasures = jest.fn();
- const navigator = {setStyle: jest.fn()};
const wrapper = shallow(
,
{context: {intl: {formatMessage: jest.fn()}}},
);
wrapper.instance().close();
- expect(navigator.setStyle).toHaveBeenCalledTimes(2);
- expect(navigator.setStyle).toBeCalledWith({screenBackgroundColor: 'transparent'});
+ expect(Navigation.mergeOptions).toHaveBeenCalledTimes(2);
+ expect(Navigation.mergeOptions).toHaveBeenCalledWith(
+ baseProps.componentId,
+ {
+ layout: {
+ backgroundColor: 'transparent',
+ },
+ },
+ );
});
});
diff --git a/app/screens/image_preview/index.js b/app/screens/image_preview/index.js
index 425a1df99..e72f70bff 100644
--- a/app/screens/image_preview/index.js
+++ b/app/screens/image_preview/index.js
@@ -1,12 +1,15 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
+import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
-import {getDimensions} from 'app/selectors/device';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {canDownloadFilesOnMobile} from 'mattermost-redux/selectors/entities/general';
+import {dismissModal, showModalOverCurrentContext} from 'app/actions/navigation';
+import {getDimensions} from 'app/selectors/device';
+
import ImagePreview from './image_preview';
function mapStateToProps(state) {
@@ -17,4 +20,13 @@ function mapStateToProps(state) {
};
}
-export default connect(mapStateToProps)(ImagePreview);
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ dismissModal,
+ showModalOverCurrentContext,
+ }, dispatch),
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(ImagePreview);
diff --git a/app/screens/index.js b/app/screens/index.js
index 36d38b336..498e7171a 100644
--- a/app/screens/index.js
+++ b/app/screens/index.js
@@ -9,23 +9,12 @@ import Channel from 'app/screens/channel';
import Root from 'app/components/root';
import SelectServer from 'app/screens/select_server';
-// TODO remove dummy navigator object
-const navigator = {
- push: () => {}, // eslint-disable-line no-empty-function
- setOnNavigatorEvent: () => {}, // eslint-disable-line no-empty-function
- setStyle: () => {}, // eslint-disable-line no-empty-function
- setButtons: () => {}, // eslint-disable-line no-empty-function
-};
-
export function registerScreens(store, Provider) {
// TODO consolidate this with app/utils/wrap_context_provider
const wrapper = (Comp) => (props) => ( // eslint-disable-line react/display-name
-
-
+
+
);
diff --git a/app/screens/interactive_dialog/dialog_element.js b/app/screens/interactive_dialog/dialog_element.js
index e675bcf78..5003c12ea 100644
--- a/app/screens/interactive_dialog/dialog_element.js
+++ b/app/screens/interactive_dialog/dialog_element.js
@@ -25,7 +25,6 @@ export default class DialogElement extends PureComponent {
options: PropTypes.arrayOf(PropTypes.object),
value: PropTypes.any,
onChange: PropTypes.func,
- navigator: PropTypes.object,
theme: PropTypes.object,
};
@@ -71,7 +70,6 @@ export default class DialogElement extends PureComponent {
theme,
dataSource,
options,
- navigator,
} = this.props;
let {maxLength} = this.props;
@@ -128,7 +126,6 @@ export default class DialogElement extends PureComponent {
placeholder={placeholder}
showRequiredAsterisk={true}
selected={this.state.selected}
- navigator={navigator}
roundedBorders={false}
/>
);
diff --git a/app/screens/interactive_dialog/index.js b/app/screens/interactive_dialog/index.js
index e68b387ea..6170b7b6e 100644
--- a/app/screens/interactive_dialog/index.js
+++ b/app/screens/interactive_dialog/index.js
@@ -7,6 +7,8 @@ import {connect} from 'react-redux';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {submitInteractiveDialog} from 'mattermost-redux/actions/integrations';
+import {dismissModal} from 'app/actions/navigation';
+
import InteractiveDialog from './interactive_dialog';
function mapStateToProps(state) {
@@ -29,6 +31,7 @@ function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
submitInteractiveDialog,
+ dismissModal,
}, dispatch),
};
}
diff --git a/app/screens/interactive_dialog/interactive_dialog.js b/app/screens/interactive_dialog/interactive_dialog.js
index 94ace245b..e4888ee7e 100644
--- a/app/screens/interactive_dialog/interactive_dialog.js
+++ b/app/screens/interactive_dialog/interactive_dialog.js
@@ -22,10 +22,10 @@ export default class InteractiveDialog extends PureComponent {
elements: PropTypes.arrayOf(PropTypes.object).isRequired,
notifyOnCancel: PropTypes.bool,
state: PropTypes.string,
- navigator: PropTypes.object,
theme: PropTypes.object,
actions: PropTypes.shape({
submitInteractiveDialog: PropTypes.func.isRequired,
+ dismissModal: PropTypes.func.isRequired,
}).isRequired,
};
@@ -136,9 +136,7 @@ export default class InteractiveDialog extends PureComponent {
}
handleHide = () => {
- this.props.navigator.dismissModal({
- animationType: 'slide-down',
- });
+ this.props.actions.dismissModal();
}
onChange = (name, value) => {
@@ -147,7 +145,7 @@ export default class InteractiveDialog extends PureComponent {
}
render() {
- const {elements, theme, navigator} = this.props;
+ const {elements, theme} = this.props;
const style = getStyleFromTheme(theme);
return (
@@ -172,7 +170,6 @@ export default class InteractiveDialog extends PureComponent {
options={e.options}
value={this.state.values[e.name]}
onChange={this.onChange}
- navigator={navigator}
theme={theme}
/>
);
diff --git a/app/screens/interactive_dialog/interactive_dialog.test.js b/app/screens/interactive_dialog/interactive_dialog.test.js
index 4219edf33..9030af549 100644
--- a/app/screens/interactive_dialog/interactive_dialog.test.js
+++ b/app/screens/interactive_dialog/interactive_dialog.test.js
@@ -19,8 +19,6 @@ describe('InteractiveDialog', () => {
theme: Preferences.THEMES.default,
actions: {
submitInteractiveDialog: jest.fn(),
- },
- navigator: {
dismissModal: jest.fn(),
},
componentId: 'component-id',
@@ -37,11 +35,9 @@ describe('InteractiveDialog', () => {
});
test('should submit dialog', async () => {
- const submitInteractiveDialog = jest.fn();
const wrapper = shallow(
,
);
@@ -53,16 +49,14 @@ describe('InteractiveDialog', () => {
};
wrapper.instance().handleSubmit();
- expect(submitInteractiveDialog).toHaveBeenCalledTimes(1);
- expect(submitInteractiveDialog).toHaveBeenCalledWith(dialog);
+ expect(baseProps.actions.submitInteractiveDialog).toHaveBeenCalledTimes(1);
+ expect(baseProps.actions.submitInteractiveDialog).toHaveBeenCalledWith(dialog);
});
test('should submit dialog on cancel', async () => {
- const submitInteractiveDialog = jest.fn();
const wrapper = shallow(
,
);
@@ -75,21 +69,19 @@ describe('InteractiveDialog', () => {
};
wrapper.instance().navigationButtonPressed({buttonId: 'close-dialog'});
- expect(submitInteractiveDialog).toHaveBeenCalledTimes(1);
- expect(submitInteractiveDialog).toHaveBeenCalledWith(dialog);
+ expect(baseProps.actions.submitInteractiveDialog).toHaveBeenCalledTimes(1);
+ expect(baseProps.actions.submitInteractiveDialog).toHaveBeenCalledWith(dialog);
});
test('should not submit dialog on cancel', async () => {
- const submitInteractiveDialog = jest.fn();
const wrapper = shallow(
,
);
wrapper.instance().navigationButtonPressed({buttonId: 'close-dialog'});
- expect(submitInteractiveDialog).not.toHaveBeenCalled();
+ expect(baseProps.actions.submitInteractiveDialog).not.toHaveBeenCalled();
});
});
diff --git a/app/screens/more_dms/index.js b/app/screens/more_dms/index.js
index 3427eaff8..0f92b9b0a 100644
--- a/app/screens/more_dms/index.js
+++ b/app/screens/more_dms/index.js
@@ -14,6 +14,8 @@ import {getTeammateNameDisplaySetting, getTheme} from 'mattermost-redux/selector
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUserId, getUsers} from 'mattermost-redux/selectors/entities/users';
+import {dismissModal, setButtons} from 'app/actions/navigation';
+
import MoreDirectMessages from './more_dms';
function mapStateToProps(state) {
@@ -40,6 +42,8 @@ function mapDispatchToProps(dispatch) {
getProfilesInTeam,
searchProfiles,
setChannelDisplayName,
+ dismissModal,
+ setButtons,
}, dispatch),
};
}
diff --git a/app/screens/more_dms/more_dms.js b/app/screens/more_dms/more_dms.js
index 0d8723af3..3f1640020 100644
--- a/app/screens/more_dms/more_dms.js
+++ b/app/screens/more_dms/more_dms.js
@@ -39,13 +39,14 @@ export default class MoreDirectMessages extends PureComponent {
getProfilesInTeam: PropTypes.func.isRequired,
searchProfiles: PropTypes.func.isRequired,
setChannelDisplayName: PropTypes.func.isRequired,
+ dismissModal: PropTypes.func.isRequired,
+ setButtons: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
allProfiles: PropTypes.object.isRequired,
currentDisplayName: PropTypes.string,
currentTeamId: PropTypes.string.isRequired,
currentUserId: PropTypes.string.isRequired,
- navigator: PropTypes.object,
restrictDirectMessage: PropTypes.bool.isRequired,
teammateNameDisplay: PropTypes.string,
theme: PropTypes.object.isRequired,
@@ -108,7 +109,7 @@ export default class MoreDirectMessages extends PureComponent {
}
close = () => {
- this.props.navigator.dismissModal({animationType: 'slide-down'});
+ this.props.actions.dismissModal();
};
clearSearch = () => {
@@ -325,13 +326,14 @@ export default class MoreDirectMessages extends PureComponent {
};
updateNavigationButtons = (startEnabled, context = this.context) => {
+ const {actions, componentId} = this.props;
const {formatMessage} = context.intl;
- this.props.navigator.setButtons({
+ actions.setButtons(componentId, {
rightButtons: [{
id: START_BUTTON,
- title: formatMessage({id: 'mobile.more_dms.start', defaultMessage: 'Start'}),
+ text: formatMessage({id: 'mobile.more_dms.start', defaultMessage: 'Start'}),
showAsAction: 'always',
- disabled: !startEnabled,
+ enabled: startEnabled,
}],
});
};
diff --git a/app/screens/notification/index.js b/app/screens/notification/index.js
index 7674cf74a..47d22b173 100644
--- a/app/screens/notification/index.js
+++ b/app/screens/notification/index.js
@@ -12,6 +12,8 @@ import {getTeammateNameDisplaySetting, getTheme} from 'mattermost-redux/selector
import {getUser} from 'mattermost-redux/selectors/entities/users';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
+import {dismissOverlay, dismissAllModals, popToRoot} from 'app/actions/navigation';
+
import Notification from './notification';
function mapStateToProps(state, ownProps) {
@@ -42,6 +44,9 @@ function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
loadFromPushNotification,
+ dismissOverlay,
+ dismissAllModals,
+ popToRoot,
}, dispatch),
};
}
diff --git a/app/screens/notification/notification.js b/app/screens/notification/notification.js
index ff2225f00..732796e12 100644
--- a/app/screens/notification/notification.js
+++ b/app/screens/notification/notification.js
@@ -8,55 +8,149 @@ import {
InteractionManager,
Platform,
StyleSheet,
- Text,
TouchableOpacity,
+ Text,
View,
} from 'react-native';
-
-import FormattedText from 'app/components/formatted_text';
-import ProfilePicture from 'app/components/profile_picture';
-import {changeOpacity} from 'app/utils/theme';
+import {Navigation} from 'react-native-navigation';
+import * as Animatable from 'react-native-animatable';
+import {PanGestureHandler} from 'react-native-gesture-handler';
import {isDirectChannel} from 'mattermost-redux/utils/channel_utils';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
import {displayUsername} from 'mattermost-redux/utils/user_utils';
+import FormattedText from 'app/components/formatted_text';
+import ProfilePicture from 'app/components/profile_picture';
+import {changeOpacity} from 'app/utils/theme';
+import {NavigationTypes} from 'app/constants';
+
import logo from 'assets/images/icon.png';
import webhookIcon from 'assets/images/icons/webhook.jpg';
const IMAGE_SIZE = 33;
+const AUTO_DISMISS_TIME_MILLIS = 5000;
export default class Notification extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
loadFromPushNotification: PropTypes.func.isRequired,
+ dismissOverlay: PropTypes.func.isRequired,
+ dismissAllModals: PropTypes.func.isRequired,
+ popToRoot: PropTypes.func.isRequired,
}).isRequired,
+ componentId: PropTypes.string.isRequired,
channel: PropTypes.object,
config: PropTypes.object,
deviceWidth: PropTypes.number.isRequired,
notification: PropTypes.object.isRequired,
teammateNameDisplay: PropTypes.string,
- navigator: PropTypes.object,
theme: PropTypes.object.isRequired,
user: PropTypes.object,
};
+ state = {
+ keyFrames: {
+ from: {
+ translateY: -100,
+ },
+ to: {
+ translateY: 0,
+ },
+ },
+ }
+
+ tapped = false;
+
+ componentDidMount() {
+ this.setDismissTimer();
+ this.setDidDisappearListener();
+ this.setShowOverlayListener();
+ }
+
+ componentWillUnmount() {
+ this.clearDismissTimer();
+ this.clearDidDisappearListener();
+ this.clearShowOverlayListener();
+ }
+
+ setDismissTimer = () => {
+ this.dismissTimer = setTimeout(() => {
+ if (!this.tapped) {
+ this.animateDismissOverlay();
+ }
+ }, AUTO_DISMISS_TIME_MILLIS);
+ }
+
+ clearDismissTimer = () => {
+ if (this.dismissTimer) {
+ clearTimeout(this.dismissTimer);
+ this.dismissTimer = null;
+ }
+ }
+
+ setDidDisappearListener = () => {
+ this.didDismissListener = Navigation.events().registerComponentDidDisappearListener(({componentId}) => {
+ if (componentId === this.props.componentId && this.tapped) {
+ const {actions} = this.props;
+ actions.dismissAllModals();
+ actions.popToRoot();
+ }
+ });
+ }
+
+ clearDidDisappearListener = () => {
+ this.didDismissListener.remove();
+ }
+
+ setShowOverlayListener = () => {
+ EventEmitter.on(NavigationTypes.NAVIGATION_SHOW_OVERLAY, this.onNewOverlay);
+ }
+
+ clearShowOverlayListener = () => {
+ EventEmitter.off(NavigationTypes.NAVIGATION_SHOW_OVERLAY, this.onNewOverlay);
+ }
+
+ onNewOverlay = () => {
+ // Dismiss this overlay so that there is only ever one.
+ this.dismissOverlay();
+ }
+
+ dismissOverlay = () => {
+ this.clearDismissTimer();
+
+ const {actions, componentId} = this.props;
+ actions.dismissOverlay(componentId);
+ }
+
+ animateDismissOverlay = () => {
+ this.clearDismissTimer();
+
+ this.setState({
+ keyFrames: {
+ from: {
+ translateY: 0,
+ },
+ to: {
+ translateY: -100,
+ },
+ },
+ });
+ setTimeout(() => this.dismissOverlay(), 1000);
+ }
+
notificationTapped = () => {
- const {actions, navigator, notification} = this.props;
+ this.tapped = true;
+ this.clearDismissTimer();
+
+ const {actions, notification} = this.props;
EventEmitter.emit('close_channel_drawer');
+ EventEmitter.emit('close_settings_sidebar');
InteractionManager.runAfterInteractions(() => {
- navigator.dismissInAppNotification();
+ this.dismissOverlay();
if (!notification.localNotification) {
actions.loadFromPushNotification(notification);
-
- if (Platform.OS === 'android') {
- navigator.dismissModal({animation: 'none'});
- }
-
- navigator.popToRoot({
- animated: false,
- });
}
});
};
@@ -202,28 +296,39 @@ export default class Notification extends PureComponent {
const icon = this.getNotificationIcon();
return (
-
-
+
-
- {icon}
+
+
+
+ {icon}
+
+
+ {title}
+
+
+ {messageText}
+
+
+
+
-
- {title}
-
-
- {messageText}
-
-
-
-
-
+
+
);
}
diff --git a/app/screens/permalink/index.js b/app/screens/permalink/index.js
index 50d54399f..ef5f06525 100644
--- a/app/screens/permalink/index.js
+++ b/app/screens/permalink/index.js
@@ -16,13 +16,18 @@ import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
+import {
+ goToScreen,
+ dismissModal,
+ dismissAllModals,
+ resetToChannel,
+} from 'app/actions/navigation';
import {
handleSelectChannel,
loadThreadIfNecessary,
setChannelDisplayName,
setChannelLoading,
} from 'app/actions/views/channel';
-import {showSearchModal} from 'app/actions/views/search';
import {handleTeamChange} from 'app/actions/views/select_team';
import Permalink from './permalink';
@@ -74,7 +79,10 @@ function mapDispatchToProps(dispatch) {
selectPost,
setChannelDisplayName,
setChannelLoading,
- showSearchModal,
+ goToScreen,
+ dismissModal,
+ dismissAllModals,
+ resetToChannel,
}, dispatch),
};
}
diff --git a/app/screens/permalink/permalink.js b/app/screens/permalink/permalink.js
index d223b031b..3d59012b0 100644
--- a/app/screens/permalink/permalink.js
+++ b/app/screens/permalink/permalink.js
@@ -57,6 +57,10 @@ export default class Permalink extends PureComponent {
selectPost: PropTypes.func.isRequired,
setChannelDisplayName: PropTypes.func.isRequired,
setChannelLoading: PropTypes.func.isRequired,
+ goToScreen: PropTypes.func.isRequired,
+ dismissModal: PropTypes.func.isRequired,
+ dismissAllModals: PropTypes.func.isRequired,
+ resetToChannel: PropTypes.func.isRequired,
}).isRequired,
channelId: PropTypes.string,
channelIsArchived: PropTypes.bool,
@@ -67,7 +71,6 @@ export default class Permalink extends PureComponent {
focusedPostId: PropTypes.string.isRequired,
isPermalink: PropTypes.bool,
myMembers: PropTypes.object.isRequired,
- navigator: PropTypes.object,
onClose: PropTypes.func,
onPress: PropTypes.func,
postIds: PropTypes.array,
@@ -171,39 +174,29 @@ export default class Permalink extends PureComponent {
}
goToThread = preventDoubleTap((post) => {
- const {actions, navigator, theme} = this.props;
+ const {actions} = this.props;
const channelId = post.channel_id;
const rootId = (post.root_id || post.id);
+ const screen = 'Thread';
+ const title = '';
+ const passProps = {
+ channelId,
+ rootId,
+ };
actions.loadThreadIfNecessary(rootId);
actions.selectPost(rootId);
- const options = {
- screen: 'Thread',
- animated: true,
- backButtonTitle: '',
- navigatorStyle: {
- navBarTextColor: theme.sidebarHeaderTextColor,
- navBarBackgroundColor: theme.sidebarHeaderBg,
- navBarButtonColor: theme.sidebarHeaderTextColor,
- screenBackgroundColor: theme.centerChannelBg,
- },
- passProps: {
- channelId,
- rootId,
- },
- };
-
- navigator.push(options);
+ actions.goToScreen(screen, title, passProps);
});
handleClose = () => {
- const {actions, navigator, onClose} = this.props;
+ const {actions, onClose} = this.props;
if (this.refs.view) {
this.mounted = false;
this.refs.view.zoomOut().then(() => {
actions.selectPost('');
- navigator.dismissModal({animationType: 'none'});
+ actions.dismissModal();
if (onClose) {
onClose();
@@ -232,7 +225,7 @@ export default class Permalink extends PureComponent {
jumpToChannel = (channelId, channelDisplayName) => {
if (channelId) {
- const {actions, channelTeamId, currentTeamId, navigator, onClose, theme} = this.props;
+ const {actions, channelTeamId, currentTeamId, onClose} = this.props;
const currentChannelId = this.props.channelId;
const {
handleSelectChannel,
@@ -246,23 +239,13 @@ export default class Permalink extends PureComponent {
if (channelId === currentChannelId) {
EventEmitter.emit('reset_channel');
} else {
- navigator.resetTo({
- screen: 'Channel',
- animated: true,
- animationType: 'fade',
- navigatorStyle: {
- navBarHidden: true,
- statusBarHidden: false,
- statusBarHideWithNavBar: false,
- screenBackgroundColor: theme.centerChannelBg,
- },
- passProps: {
- disableTermsModal: true,
- },
- });
+ const passProps = {
+ disableTermsModal: true,
+ };
+ actions.resetToChannel(passProps);
}
- navigator.dismissAllModals({animationType: 'slide-down'});
+ actions.dismissAllModals();
if (onClose) {
onClose();
@@ -350,7 +333,6 @@ export default class Permalink extends PureComponent {
const {
currentUserId,
focusedPostId,
- navigator,
theme,
} = this.props;
const {
@@ -395,7 +377,6 @@ export default class Permalink extends PureComponent {
lastPostIndex={Platform.OS === 'android' ? getLastPostIndex(postIdsState) : -1}
currentUserId={currentUserId}
lastViewedAt={0}
- navigator={navigator}
highlightPinnedOrFlagged={false}
/>
);
diff --git a/app/screens/permalink/permalink.test.js b/app/screens/permalink/permalink.test.js
index 5cc33b09c..bd1147c5a 100644
--- a/app/screens/permalink/permalink.test.js
+++ b/app/screens/permalink/permalink.test.js
@@ -11,13 +11,6 @@ import Permalink from './permalink.js';
jest.mock('react-intl');
describe('Permalink', () => {
- const navigator = {
- dismissAllModals: jest.fn(),
- dismissModal: jest.fn(),
- push: jest.fn(),
- resetTo: jest.fn(),
- };
-
const actions = {
getPostsAround: jest.fn(),
getPostThread: jest.fn(),
@@ -29,6 +22,10 @@ describe('Permalink', () => {
selectPost: jest.fn(),
setChannelDisplayName: jest.fn(),
setChannelLoading: jest.fn(),
+ goToScreen: jest.fn(),
+ dismissModal: jest.fn(),
+ dismissAllModals: jest.fn(),
+ resetToChannel: jest.fn(),
};
const baseProps = {
@@ -42,7 +39,6 @@ describe('Permalink', () => {
focusedPostId: 'focused_post_id',
isPermalink: true,
myMembers: {},
- navigator,
onClose: jest.fn(),
onPress: jest.fn(),
postIds: ['post_id_1', 'focused_post_id', 'post_id_3'],
diff --git a/app/screens/reaction_list/__snapshots__/reaction_list.test.js.snap b/app/screens/reaction_list/__snapshots__/reaction_list.test.js.snap
index bb73b1098..bdfdeb767 100644
--- a/app/screens/reaction_list/__snapshots__/reaction_list.test.js.snap
+++ b/app/screens/reaction_list/__snapshots__/reaction_list.test.js.snap
@@ -22,7 +22,7 @@ exports[`ReactionList should match snapshot 1`] = `
}
}
>
-
-
-
- {
- this.props.navigator.dismissModal({
- animationType: 'none',
- });
+ this.props.actions.dismissModal();
};
getMissingProfiles = () => {
@@ -137,7 +135,6 @@ export default class ReactionList extends PureComponent {
renderReactionRows = () => {
const {
- navigator,
teammateNameDisplay,
theme,
} = this.props;
@@ -157,7 +154,6 @@ export default class ReactionList extends PureComponent {
>
{
const baseProps = {
actions: {
getMissingProfilesByIds: jest.fn(),
+ dismissModal: jest.fn(),
},
allUserIds: ['user_id_1', 'user_id_2'],
reactions: {'user_id_1-smile': {emoji_name: 'smile', user_id: 'user_id_1'}, 'user_id_2-+1': {emoji_name: '+1', user_id: 'user_id_2'}},
diff --git a/app/screens/reaction_list/__snapshots__/reaction_row.test.js.snap b/app/screens/reaction_list/reaction_row/__snapshots__/reaction_row.test.js.snap
similarity index 100%
rename from app/screens/reaction_list/__snapshots__/reaction_row.test.js.snap
rename to app/screens/reaction_list/reaction_row/__snapshots__/reaction_row.test.js.snap
diff --git a/app/screens/reaction_list/reaction_row/index.js b/app/screens/reaction_list/reaction_row/index.js
new file mode 100644
index 000000000..d91992b1f
--- /dev/null
+++ b/app/screens/reaction_list/reaction_row/index.js
@@ -0,0 +1,19 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {bindActionCreators} from 'redux';
+import {connect} from 'react-redux';
+
+import {goToScreen} from 'app/actions/navigation';
+
+import ReactionRow from './reaction_row';
+
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ goToScreen,
+ }, dispatch),
+ };
+}
+
+export default connect(null, mapDispatchToProps)(ReactionRow);
diff --git a/app/screens/reaction_list/reaction_row.js b/app/screens/reaction_list/reaction_row/reaction_row.js
similarity index 82%
rename from app/screens/reaction_list/reaction_row.js
rename to app/screens/reaction_list/reaction_row/reaction_row.js
index da33b73ff..8ad6e2e56 100644
--- a/app/screens/reaction_list/reaction_row.js
+++ b/app/screens/reaction_list/reaction_row/reaction_row.js
@@ -21,8 +21,10 @@ import Emoji from 'app/components/emoji';
export default class ReactionRow extends React.PureComponent {
static propTypes = {
+ actions: PropTypes.shape({
+ goToScreen: PropTypes.func.isRequired,
+ }).isRequired,
emojiName: PropTypes.string.isRequired,
- navigator: PropTypes.object,
teammateNameDisplay: PropTypes.string.isRequired,
theme: PropTypes.object.isRequired,
user: PropTypes.object.isRequired,
@@ -37,26 +39,15 @@ export default class ReactionRow extends React.PureComponent {
};
goToUserProfile = () => {
- const {navigator, theme, user} = this.props;
+ const {actions, user} = this.props;
const {formatMessage} = this.context.intl;
-
- const options = {
- screen: 'UserProfile',
- title: formatMessage({id: 'mobile.routes.user_profile', defaultMessage: 'Profile'}),
- animated: true,
- backButtonTitle: '',
- passProps: {
- userId: user.id,
- },
- navigatorStyle: {
- navBarTextColor: theme.sidebarHeaderTextColor,
- navBarBackgroundColor: theme.sidebarHeaderBg,
- navBarButtonColor: theme.sidebarHeaderTextColor,
- screenBackgroundColor: theme.centerChannelBg,
- },
+ const screen = 'UserProfile';
+ const title = formatMessage({id: 'mobile.routes.user_profile', defaultMessage: 'Profile'});
+ const passProps = {
+ userId: user.id,
};
- navigator.push(options);
+ actions.goToScreen(screen, title, passProps);
};
render() {
diff --git a/app/screens/reaction_list/reaction_row.test.js b/app/screens/reaction_list/reaction_row/reaction_row.test.js
similarity index 91%
rename from app/screens/reaction_list/reaction_row.test.js
rename to app/screens/reaction_list/reaction_row/reaction_row.test.js
index 471b67658..21e7fcd10 100644
--- a/app/screens/reaction_list/reaction_row.test.js
+++ b/app/screens/reaction_list/reaction_row/reaction_row.test.js
@@ -9,8 +9,10 @@ import ReactionRow from './reaction_row';
describe('ReactionRow', () => {
const baseProps = {
+ actions: {
+ goToScreen: jest.fn(),
+ },
emojiName: 'smile',
- navigator: {},
teammateNameDisplay: 'username',
theme: Preferences.THEMES.default,
user: {id: 'user_id', username: 'username'},
diff --git a/app/screens/search/index.js b/app/screens/search/index.js
index a8751a9f6..7f6918eae 100644
--- a/app/screens/search/index.js
+++ b/app/screens/search/index.js
@@ -15,7 +15,7 @@ import {isMinimumServerVersion} from 'mattermost-redux/utils/helpers';
import {getUserCurrentTimezone} from 'mattermost-redux/utils/timezone_utils';
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
-import {dismissModal} from 'app/actions/navigation';
+import {dismissModal, goToScreen, showModalOverCurrentContext} from 'app/actions/navigation';
import {loadChannelsByTeamName, loadThreadIfNecessary} from 'app/actions/views/channel';
import {handleSearchDraftChanged} from 'app/actions/views/search';
import {isLandscape} from 'app/selectors/device';
@@ -86,6 +86,8 @@ function mapDispatchToProps(dispatch) {
getMorePostsForSearch,
selectPost,
dismissModal,
+ goToScreen,
+ showModalOverCurrentContext,
}, dispatch),
};
}
diff --git a/app/screens/search/search.js b/app/screens/search/search.js
index 82acb7e3e..d8d32a2f7 100644
--- a/app/screens/search/search.js
+++ b/app/screens/search/search.js
@@ -57,12 +57,13 @@ export default class Search extends PureComponent {
selectFocusedPostId: PropTypes.func.isRequired,
selectPost: PropTypes.func.isRequired,
dismissModal: PropTypes.func.isRequired,
+ goToScreen: PropTypes.func.isRequired,
+ showModalOverCurrentContext: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string.isRequired,
currentTeamId: PropTypes.string.isRequired,
initialValue: PropTypes.string,
isLandscape: PropTypes.bool.isRequired,
- navigator: PropTypes.object,
postIds: PropTypes.array,
archivedPostIds: PropTypes.arrayOf(PropTypes.string),
recent: PropTypes.array.isRequired,
@@ -183,7 +184,7 @@ export default class Search extends PureComponent {
});
goToThread = (post) => {
- const {actions, navigator, theme} = this.props;
+ const {actions} = this.props;
const channelId = post.channel_id;
const rootId = (post.root_id || post.id);
@@ -191,23 +192,14 @@ export default class Search extends PureComponent {
actions.loadThreadIfNecessary(rootId);
actions.selectPost(rootId);
- const options = {
- screen: 'Thread',
- animated: true,
- backButtonTitle: '',
- navigatorStyle: {
- navBarTextColor: theme.sidebarHeaderTextColor,
- navBarBackgroundColor: theme.sidebarHeaderBg,
- navBarButtonColor: theme.sidebarHeaderTextColor,
- screenBackgroundColor: theme.centerChannelBg,
- },
- passProps: {
- channelId,
- rootId,
- },
+ const screen = 'Thread';
+ const title = '';
+ const passProps = {
+ channelId,
+ rootId,
};
- navigator.push(options);
+ actions.goToScreen(screen, title, passProps);
};
handleHashtagPress = (hashtag) => {
@@ -389,7 +381,6 @@ export default class Search extends PureComponent {
postId={item}
previewPost={this.previewPost}
goToThread={this.goToThread}
- navigator={this.props.navigator}
onHashtagPress={this.handleHashtagPress}
onPermalinkPress={this.handlePermalinkPress}
managedConfig={mattermostManaged.getCachedConfig()}
@@ -449,29 +440,24 @@ export default class Search extends PureComponent {
};
showPermalinkView = (postId, isPermalink) => {
- const {actions, navigator} = this.props;
+ const {actions} = this.props;
actions.selectFocusedPostId(postId);
if (!this.showingPermalink) {
+ const screen = 'Permalink';
+ const passProps = {
+ isPermalink,
+ onClose: this.handleClosePermalink,
+ };
const options = {
- screen: 'Permalink',
- animationType: 'none',
- backButtonTitle: '',
- overrideBackPress: true,
- navigatorStyle: {
- navBarHidden: true,
- screenBackgroundColor: changeOpacity('#000', 0.2),
- modalPresentationStyle: 'overCurrentContext',
- },
- passProps: {
- isPermalink,
- onClose: this.handleClosePermalink,
+ layout: {
+ backgroundColor: changeOpacity('#000', 0.2),
},
};
this.showingPermalink = true;
- navigator.showModal(options);
+ actions.showModalOverCurrentContext(screen, passProps, options);
}
};
diff --git a/app/screens/selector_screen/index.js b/app/screens/selector_screen/index.js
index e5f69d1fd..1bd00b4ac 100644
--- a/app/screens/selector_screen/index.js
+++ b/app/screens/selector_screen/index.js
@@ -9,6 +9,8 @@ import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {getProfiles, searchProfiles} from 'mattermost-redux/actions/users';
import {getChannels, searchChannels} from 'mattermost-redux/actions/channels';
+import {popTopScreen} from 'app/actions/navigation';
+
import SelectorScreen from './selector_screen';
function mapStateToProps(state) {
@@ -32,6 +34,7 @@ function mapDispatchToProps(dispatch) {
getChannels,
searchProfiles,
searchChannels,
+ popTopScreen,
}, dispatch),
};
}
diff --git a/app/screens/selector_screen/selector_screen.js b/app/screens/selector_screen/selector_screen.js
index 2694641e7..9db461989 100644
--- a/app/screens/selector_screen/selector_screen.js
+++ b/app/screens/selector_screen/selector_screen.js
@@ -34,12 +34,12 @@ export default class SelectorScreen extends PureComponent {
getChannels: PropTypes.func.isRequired,
searchProfiles: PropTypes.func.isRequired,
searchChannels: PropTypes.func.isRequired,
+ popTopScreen: PropTypes.func.isRequired,
}),
componentId: PropTypes.string,
currentTeamId: PropTypes.string.isRequired,
data: PropTypes.arrayOf(PropTypes.object),
dataSource: PropTypes.string,
- navigator: PropTypes.object,
onSelect: PropTypes.func.isRequired,
theme: PropTypes.object.isRequired,
};
@@ -93,7 +93,7 @@ export default class SelectorScreen extends PureComponent {
};
close = () => {
- this.props.navigator.pop({animated: true});
+ this.props.actions.popTopScreen();
};
handleSelectItem = (id, item) => {
diff --git a/app/screens/selector_screen/selector_screen.test.js b/app/screens/selector_screen/selector_screen.test.js
index b017809f9..eb6d311cb 100644
--- a/app/screens/selector_screen/selector_screen.test.js
+++ b/app/screens/selector_screen/selector_screen.test.js
@@ -67,6 +67,7 @@ describe('SelectorScreen', () => {
getChannels,
searchProfiles,
searchChannels,
+ popTopScreen: jest.fn(),
};
const baseProps = {
diff --git a/app/screens/terms_of_service/__snapshots__/terms_of_service.test.js.snap b/app/screens/terms_of_service/__snapshots__/terms_of_service.test.js.snap
index f323d4cbd..313792907 100644
--- a/app/screens/terms_of_service/__snapshots__/terms_of_service.test.js.snap
+++ b/app/screens/terms_of_service/__snapshots__/terms_of_service.test.js.snap
@@ -45,87 +45,6 @@ exports[`TermsOfService should enable/disable navigator buttons on setNavigatorB
disableAtMentions={true}
disableChannelLink={true}
disableHashtags={true}
- navigator={
- Object {
- "dismissAllModals": [MockFunction],
- "dismissModal": [MockFunction],
- "setButtons": [MockFunction] {
- "calls": Array [
- Array [
- Object {
- "leftButtons": Array [
- Object {
- "disabled": true,
- "icon": Object {},
- "id": "reject-terms-of-service",
- },
- ],
- "rightButtons": Array [
- Object {
- "disabled": true,
- "id": "accept-terms-of-service",
- "showAsAction": "always",
- "title": undefined,
- },
- ],
- },
- ],
- Array [
- Object {
- "leftButtons": Array [
- Object {
- "disabled": true,
- "icon": Object {},
- "id": "reject-terms-of-service",
- },
- ],
- "rightButtons": Array [
- Object {
- "disabled": true,
- "id": "accept-terms-of-service",
- "showAsAction": "always",
- "title": undefined,
- },
- ],
- },
- ],
- Array [
- Object {
- "leftButtons": Array [
- Object {
- "disabled": false,
- "icon": Object {},
- "id": "reject-terms-of-service",
- },
- ],
- "rightButtons": Array [
- Object {
- "disabled": false,
- "id": "accept-terms-of-service",
- "showAsAction": "always",
- "title": undefined,
- },
- ],
- },
- ],
- ],
- "results": Array [
- Object {
- "type": "return",
- "value": undefined,
- },
- Object {
- "type": "return",
- "value": undefined,
- },
- Object {
- "type": "return",
- "value": undefined,
- },
- ],
- },
- }
- }
textStyles={
Object {
"code": Object {
@@ -261,110 +180,6 @@ exports[`TermsOfService should enable/disable navigator buttons on setNavigatorB
disableAtMentions={true}
disableChannelLink={true}
disableHashtags={true}
- navigator={
- Object {
- "dismissAllModals": [MockFunction],
- "dismissModal": [MockFunction],
- "setButtons": [MockFunction] {
- "calls": Array [
- Array [
- Object {
- "leftButtons": Array [
- Object {
- "disabled": true,
- "icon": Object {},
- "id": "reject-terms-of-service",
- },
- ],
- "rightButtons": Array [
- Object {
- "disabled": true,
- "id": "accept-terms-of-service",
- "showAsAction": "always",
- "title": undefined,
- },
- ],
- },
- ],
- Array [
- Object {
- "leftButtons": Array [
- Object {
- "disabled": true,
- "icon": Object {},
- "id": "reject-terms-of-service",
- },
- ],
- "rightButtons": Array [
- Object {
- "disabled": true,
- "id": "accept-terms-of-service",
- "showAsAction": "always",
- "title": undefined,
- },
- ],
- },
- ],
- Array [
- Object {
- "leftButtons": Array [
- Object {
- "disabled": false,
- "icon": Object {},
- "id": "reject-terms-of-service",
- },
- ],
- "rightButtons": Array [
- Object {
- "disabled": false,
- "id": "accept-terms-of-service",
- "showAsAction": "always",
- "title": undefined,
- },
- ],
- },
- ],
- Array [
- Object {
- "leftButtons": Array [
- Object {
- "disabled": true,
- "icon": Object {},
- "id": "reject-terms-of-service",
- },
- ],
- "rightButtons": Array [
- Object {
- "disabled": true,
- "id": "accept-terms-of-service",
- "showAsAction": "always",
- "title": undefined,
- },
- ],
- },
- ],
- ],
- "results": Array [
- Object {
- "type": "return",
- "value": undefined,
- },
- Object {
- "type": "return",
- "value": undefined,
- },
- Object {
- "type": "return",
- "value": undefined,
- },
- Object {
- "type": "return",
- "value": undefined,
- },
- ],
- },
- }
- }
textStyles={
Object {
"code": Object {
@@ -572,87 +387,6 @@ exports[`TermsOfService should match snapshot on enableNavigatorLogout 1`] = `
disableAtMentions={true}
disableChannelLink={true}
disableHashtags={true}
- navigator={
- Object {
- "dismissAllModals": [MockFunction],
- "dismissModal": [MockFunction],
- "setButtons": [MockFunction] {
- "calls": Array [
- Array [
- Object {
- "leftButtons": Array [
- Object {
- "disabled": true,
- "icon": Object {},
- "id": "reject-terms-of-service",
- },
- ],
- "rightButtons": Array [
- Object {
- "disabled": true,
- "id": "accept-terms-of-service",
- "showAsAction": "always",
- "title": undefined,
- },
- ],
- },
- ],
- Array [
- Object {
- "leftButtons": Array [
- Object {
- "disabled": true,
- "icon": Object {},
- "id": "reject-terms-of-service",
- },
- ],
- "rightButtons": Array [
- Object {
- "disabled": true,
- "id": "accept-terms-of-service",
- "showAsAction": "always",
- "title": undefined,
- },
- ],
- },
- ],
- Array [
- Object {
- "leftButtons": Array [
- Object {
- "disabled": false,
- "icon": Object {},
- "id": "close-terms-of-service",
- },
- ],
- "rightButtons": Array [
- Object {
- "disabled": true,
- "id": "accept-terms-of-service",
- "showAsAction": "always",
- "title": undefined,
- },
- ],
- },
- ],
- ],
- "results": Array [
- Object {
- "type": "return",
- "value": undefined,
- },
- Object {
- "type": "return",
- "value": undefined,
- },
- Object {
- "type": "return",
- "value": undefined,
- },
- ],
- },
- }
- }
textStyles={
Object {
"code": Object {
diff --git a/app/screens/terms_of_service/index.js b/app/screens/terms_of_service/index.js
index a9c843bac..51519d733 100644
--- a/app/screens/terms_of_service/index.js
+++ b/app/screens/terms_of_service/index.js
@@ -8,6 +8,12 @@ import {getTermsOfService, logout, updateMyTermsOfServiceStatus} from 'mattermos
import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
+import {
+ setButtons,
+ dismissModal,
+ dismissAllModals,
+} from 'app/actions/navigation';
+
import TermsOfService from './terms_of_service.js';
function mapStateToProps(state) {
@@ -25,6 +31,9 @@ function mapDispatchToProps(dispatch) {
getTermsOfService,
logout,
updateMyTermsOfServiceStatus,
+ setButtons,
+ dismissModal,
+ dismissAllModals,
}, dispatch),
};
}
diff --git a/app/screens/terms_of_service/terms_of_service.js b/app/screens/terms_of_service/terms_of_service.js
index 850b36e57..14fb41968 100644
--- a/app/screens/terms_of_service/terms_of_service.js
+++ b/app/screens/terms_of_service/terms_of_service.js
@@ -36,10 +36,12 @@ export default class TermsOfService extends PureComponent {
logout: PropTypes.func.isRequired,
getTermsOfService: PropTypes.func.isRequired,
updateMyTermsOfServiceStatus: PropTypes.func.isRequired,
+ setButtons: PropTypes.func.isRequired,
+ dismissModal: PropTypes.func.isRequired,
+ dismissAllModals: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
closeButton: PropTypes.object,
- navigator: PropTypes.object,
siteName: PropTypes.string,
theme: PropTypes.object,
};
@@ -71,7 +73,7 @@ export default class TermsOfService extends PureComponent {
termsText: '',
};
- this.rightButton.title = context.intl.formatMessage({id: 'terms_of_service.agreeButton', defaultMessage: 'I Agree'});
+ this.rightButton.text = context.intl.formatMessage({id: 'terms_of_service.agreeButton', defaultMessage: 'I Agree'});
this.leftButton.icon = props.closeButton;
this.setNavigatorButtons(false);
@@ -106,27 +108,28 @@ export default class TermsOfService extends PureComponent {
}
setNavigatorButtons = (enabled = true) => {
+ const {actions, componentId} = this.props;
const buttons = {
- leftButtons: [{...this.leftButton, disabled: !enabled}],
- rightButtons: [{...this.rightButton, disabled: !enabled}],
+ leftButtons: [{...this.leftButton, enabled}],
+ rightButtons: [{...this.rightButton, enabled}],
};
- this.props.navigator.setButtons(buttons);
+ actions.setButtons(componentId, buttons);
};
enableNavigatorLogout = () => {
const buttons = {
- leftButtons: [{...this.leftButton, id: 'close-terms-of-service', disabled: false}],
- rightButtons: [{...this.rightButton, disabled: true}],
+ leftButtons: [{...this.leftButton, id: 'close-terms-of-service', enabled: true}],
+ rightButtons: [{...this.rightButton, enabled: false}],
};
- this.props.navigator.setButtons(buttons);
+ this.props.actions.setButtons(buttons);
};
closeTermsAndLogout = () => {
const {actions} = this.props;
- this.props.navigator.dismissAllModals();
+ actions.dismissAllModals();
actions.logout();
};
@@ -163,9 +166,7 @@ export default class TermsOfService extends PureComponent {
this.registerUserAction(
true,
() => {
- this.props.navigator.dismissModal({
- animationType: 'slide-down',
- });
+ this.props.actions.dismissModal();
},
this.handleAcceptTerms
);
@@ -234,7 +235,7 @@ export default class TermsOfService extends PureComponent {
};
render() {
- const {navigator, theme} = this.props;
+ const {theme} = this.props;
const styles = getStyleSheet(theme);
const blockStyles = getMarkdownBlockStyles(theme);
@@ -267,7 +268,6 @@ export default class TermsOfService extends PureComponent {
>
{
getTermsOfService: jest.fn(),
updateMyTermsOfServiceStatus: jest.fn(),
logout: jest.fn(),
+ setButtons: jest.fn(),
+ dismissModal: jest.fn(),
+ dismissAllModals: jest.fn(),
};
const baseProps = {
actions,
- navigator: {
- dismissAllModals: jest.fn(),
- dismissModal: jest.fn(),
- setButtons: jest.fn(),
- },
theme: Preferences.THEMES.default,
closeButton: {},
siteName: 'Mattermost',
@@ -83,18 +81,18 @@ describe('TermsOfService', () => {
expect(wrapper.getElement()).toMatchSnapshot();
});
- test('should call props.navigator.setButtons on setNavigatorButtons', async () => {
+ test('should call props.actions.setButtons on setNavigatorButtons', async () => {
const wrapper = shallow(
,
{context: {intl: {formatMessage: jest.fn()}}},
);
wrapper.setState({loading: false, termsId: 1, termsText: 'Terms Text'});
- expect(baseProps.navigator.setButtons).toHaveBeenCalledTimes(2);
+ expect(baseProps.actions.setButtons).toHaveBeenCalledTimes(2);
wrapper.instance().setNavigatorButtons(true);
- expect(baseProps.navigator.setButtons).toHaveBeenCalledTimes(3);
+ expect(baseProps.actions.setButtons).toHaveBeenCalledTimes(3);
wrapper.instance().setNavigatorButtons(false);
- expect(baseProps.navigator.setButtons).toHaveBeenCalledTimes(4);
+ expect(baseProps.actions.setButtons).toHaveBeenCalledTimes(4);
});
test('should enable/disable navigator buttons on setNavigatorButtons true/false', () => {
@@ -129,6 +127,6 @@ describe('TermsOfService', () => {
wrapper.setState({loading: false, termsId: 1, termsText: 'Terms Text'});
wrapper.instance().closeTermsAndLogout();
- expect(baseProps.navigator.dismissAllModals).toHaveBeenCalledTimes(1);
+ expect(baseProps.actions.dismissAllModals).toHaveBeenCalledTimes(1);
});
});
diff --git a/app/screens/text_preview/text_preview.js b/app/screens/text_preview/text_preview.js
index 68e7b214b..daa637fa7 100644
--- a/app/screens/text_preview/text_preview.js
+++ b/app/screens/text_preview/text_preview.js
@@ -18,7 +18,6 @@ import {changeOpacity, makeStyleSheetFromTheme, setNavigatorStyles} from 'app/ut
export default class TextPreview extends React.PureComponent {
static propTypes = {
componentId: PropTypes.string,
- navigator: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
content: PropTypes.string.isRequired,
};
diff --git a/app/screens/thread/__snapshots__/thread.ios.test.js.snap b/app/screens/thread/__snapshots__/thread.ios.test.js.snap
index ebef67766..897c3640e 100644
--- a/app/screens/thread/__snapshots__/thread.ios.test.js.snap
+++ b/app/screens/thread/__snapshots__/thread.ios.test.js.snap
@@ -13,28 +13,6 @@ exports[`thread should match snapshot, has root post 1`] = `
lastPostIndex={2}
lastViewedAt={0}
location="thread"
- navigator={
- Object {
- "dismissModal": [MockFunction],
- "pop": [MockFunction],
- "resetTo": [MockFunction],
- "setTitle": [MockFunction] {
- "calls": Array [
- Array [
- Object {
- "title": undefined,
- },
- ],
- ],
- "results": Array [
- Object {
- "type": "return",
- "value": undefined,
- },
- ],
- },
- }
- }
onPostPress={[Function]}
postIds={
Array [
@@ -76,28 +54,6 @@ exports[`thread should match snapshot, has root post 1`] = `
channelId="channel_id"
channelIsArchived={false}
cursorPositionEvent="onThreadTextBoxCursorChange"
- navigator={
- Object {
- "dismissModal": [MockFunction],
- "pop": [MockFunction],
- "resetTo": [MockFunction],
- "setTitle": [MockFunction] {
- "calls": Array [
- Array [
- Object {
- "title": undefined,
- },
- ],
- ],
- "results": Array [
- Object {
- "type": "return",
- "value": undefined,
- },
- ],
- },
- }
- }
onCloseChannel={[Function]}
rootId="root_id"
valueEvent="onThreadTextBoxValueChange"
@@ -128,28 +84,6 @@ exports[`thread should match snapshot, render footer 1`] = `
lastPostIndex={2}
lastViewedAt={0}
location="thread"
- navigator={
- Object {
- "dismissModal": [MockFunction],
- "pop": [MockFunction],
- "resetTo": [MockFunction],
- "setTitle": [MockFunction] {
- "calls": Array [
- Array [
- Object {
- "title": undefined,
- },
- ],
- ],
- "results": Array [
- Object {
- "type": "return",
- "value": undefined,
- },
- ],
- },
- }
- }
onPostPress={[Function]}
postIds={
Array [
@@ -176,28 +110,6 @@ exports[`thread should match snapshot, render footer 2`] = `
lastPostIndex={2}
lastViewedAt={0}
location="thread"
- navigator={
- Object {
- "dismissModal": [MockFunction],
- "pop": [MockFunction],
- "resetTo": [MockFunction],
- "setTitle": [MockFunction] {
- "calls": Array [
- Array [
- Object {
- "title": undefined,
- },
- ],
- ],
- "results": Array [
- Object {
- "type": "return",
- "value": undefined,
- },
- ],
- },
- }
- }
onPostPress={[Function]}
postIds={
Array [
diff --git a/app/screens/thread/index.js b/app/screens/thread/index.js
index 7f1573ab0..a089d7755 100644
--- a/app/screens/thread/index.js
+++ b/app/screens/thread/index.js
@@ -10,6 +10,8 @@ import {selectPost} from 'mattermost-redux/actions/posts';
import {makeGetChannel, getMyCurrentChannelMembership} from 'mattermost-redux/selectors/entities/channels';
import {makeGetPostIdsForThread} from 'mattermost-redux/selectors/entities/posts';
+import {popTopScreen, resetToChannel} from 'app/actions/navigation';
+
import Thread from './thread';
function makeMapStateToProps() {
@@ -37,6 +39,8 @@ function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
selectPost,
+ popTopScreen,
+ resetToChannel,
}, dispatch),
};
}
diff --git a/app/screens/thread/thread.android.js b/app/screens/thread/thread.android.js
index 2184e0d88..849c3a2fa 100644
--- a/app/screens/thread/thread.android.js
+++ b/app/screens/thread/thread.android.js
@@ -19,7 +19,6 @@ export default class ThreadAndroid extends ThreadBase {
const {
channelId,
myMember,
- navigator,
postIds,
rootId,
channelIsArchived,
@@ -36,7 +35,6 @@ export default class ThreadAndroid extends ThreadBase {
currentUserId={myMember && myMember.user_id}
lastViewedAt={this.state.lastViewedAt}
lastPostIndex={-1}
- navigator={navigator}
onPostPress={this.hideKeyboard}
location={THREAD}
/>
@@ -47,7 +45,6 @@ export default class ThreadAndroid extends ThreadBase {
channelIsArchived={channelIsArchived}
rootId={rootId}
channelId={channelId}
- navigator={navigator}
onCloseChannel={this.onCloseChannel}
/>
);
diff --git a/app/screens/thread/thread.ios.js b/app/screens/thread/thread.ios.js
index 7ba12e368..863717d26 100644
--- a/app/screens/thread/thread.ios.js
+++ b/app/screens/thread/thread.ios.js
@@ -29,7 +29,6 @@ export default class ThreadIOS extends ThreadBase {
const {
channelId,
myMember,
- navigator,
postIds,
rootId,
channelIsArchived,
@@ -47,7 +46,6 @@ export default class ThreadIOS extends ThreadBase {
lastPostIndex={getLastPostIndex(postIds)}
currentUserId={myMember && myMember.user_id}
lastViewedAt={this.state.lastViewedAt}
- navigator={navigator}
onPostPress={this.hideKeyboard}
location={THREAD}
scrollViewNativeID={SCROLLVIEW_NATIVE_ID}
@@ -77,7 +75,6 @@ export default class ThreadIOS extends ThreadBase {
channelIsArchived={channelIsArchived}
rootId={rootId}
channelId={channelId}
- navigator={navigator}
onCloseChannel={this.onCloseChannel}
cursorPositionEvent={THREAD_POST_TEXTBOX_CURSOR_CHANGE}
valueEvent={THREAD_POST_TEXTBOX_VALUE_CHANGE}
diff --git a/app/screens/thread/thread.ios.test.js b/app/screens/thread/thread.ios.test.js
index 309b71088..0478ed22d 100644
--- a/app/screens/thread/thread.ios.test.js
+++ b/app/screens/thread/thread.ios.test.js
@@ -11,22 +11,22 @@ import PostList from 'app/components/post_list';
import ThreadIOS from './thread.ios';
jest.mock('react-intl');
+jest.mock('react-native-navigation', () => ({
+ Navigation: {
+ mergeOptions: jest.fn(),
+ },
+}));
describe('thread', () => {
- const navigator = {
- dismissModal: jest.fn(),
- pop: jest.fn(),
- resetTo: jest.fn(),
- setTitle: jest.fn(),
- };
const baseProps = {
actions: {
selectPost: jest.fn(),
+ popTopScreen: jest.fn(),
+ resetToChannel: jest.fn(),
},
channelId: 'channel_id',
channelType: General.OPEN_CHANNEL,
displayName: 'channel_display_name',
- navigator,
myMember: {last_viewed_at: 0, user_id: 'member_user_id'},
rootId: 'root_id',
theme: Preferences.THEMES.default,
@@ -55,35 +55,19 @@ describe('thread', () => {
expect(wrapper.getElement()).toMatchSnapshot();
});
- test('should call props.navigator on onCloseChannel', () => {
- const channelScreen = {
- screen: 'Channel',
- title: '',
- animated: false,
- backButtonTitle: '',
- navigatorStyle: {
- animated: true,
- animationType: 'fade',
- navBarHidden: true,
- statusBarHidden: false,
- statusBarHideWithNavBar: false,
- screenBackgroundColor: 'transparent',
- },
- passProps: {
- disableTermsModal: true,
- },
+ test('should call props.actions.resetToChannel on onCloseChannel', () => {
+ const passProps = {
+ disableTermsModal: true,
};
- const newNavigator = {...navigator};
const wrapper = shallow(
,
{context: {intl: {formatMessage: jest.fn()}}},
);
wrapper.instance().onCloseChannel();
- expect(newNavigator.resetTo).toHaveBeenCalledTimes(1);
- expect(newNavigator.resetTo).toBeCalledWith(channelScreen);
+ expect(baseProps.actions.resetToChannel).toHaveBeenCalledTimes(1);
+ expect(baseProps.actions.resetToChannel).toBeCalledWith(passProps);
});
test('should match snapshot, render footer', () => {
diff --git a/app/screens/thread/thread_base.js b/app/screens/thread/thread_base.js
index 468142ebd..0b64e7e32 100644
--- a/app/screens/thread/thread_base.js
+++ b/app/screens/thread/thread_base.js
@@ -3,8 +3,9 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
-import {Keyboard, Platform} from 'react-native';
+import {Keyboard} from 'react-native';
import {intlShape} from 'react-intl';
+import {Navigation} from 'react-native-navigation';
import {General, RequestStatus} from 'mattermost-redux/constants';
@@ -16,12 +17,13 @@ export default class ThreadBase extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
selectPost: PropTypes.func.isRequired,
+ popTopScreen: PropTypes.func.isRequired,
+ resetToChannel: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
channelId: PropTypes.string.isRequired,
channelType: PropTypes.string,
displayName: PropTypes.string,
- navigator: PropTypes.object,
myMember: PropTypes.object.isRequired,
rootId: PropTypes.string.isRequired,
theme: PropTypes.object.isRequired,
@@ -53,8 +55,12 @@ export default class ThreadBase extends PureComponent {
this.postTextbox = React.createRef();
- this.props.navigator.setTitle({
- title,
+ Navigation.mergeOptions(props.componentId, {
+ topBar: {
+ title: {
+ text: title,
+ },
+ },
});
this.state = {
@@ -82,17 +88,7 @@ export default class ThreadBase extends PureComponent {
}
close = () => {
- const {navigator} = this.props;
-
- if (Platform.OS === 'ios') {
- navigator.pop({
- animated: true,
- });
- } else {
- navigator.dismissModal({
- animationType: 'slide-down',
- });
- }
+ this.props.actions.popTopScreen();
};
handleAutoComplete = (value) => {
@@ -124,22 +120,9 @@ export default class ThreadBase extends PureComponent {
};
onCloseChannel = () => {
- this.props.navigator.resetTo({
- screen: 'Channel',
- title: '',
- animated: false,
- backButtonTitle: '',
- navigatorStyle: {
- animated: true,
- animationType: 'fade',
- navBarHidden: true,
- statusBarHidden: false,
- statusBarHideWithNavBar: false,
- screenBackgroundColor: 'transparent',
- },
- passProps: {
- disableTermsModal: true,
- },
- });
+ const passProps = {
+ disableTermsModal: true,
+ };
+ this.props.actions.resetToChannel(passProps);
};
}
diff --git a/app/screens/user_profile/index.js b/app/screens/user_profile/index.js
index adeb16750..f4e926c61 100644
--- a/app/screens/user_profile/index.js
+++ b/app/screens/user_profile/index.js
@@ -15,6 +15,13 @@ import {loadBot} from 'mattermost-redux/actions/bots';
import {getBotAccounts} from 'mattermost-redux/selectors/entities/bots';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
+import {
+ setButtons,
+ dismissModal,
+ resetToChannel,
+ goToScreen,
+} from 'app/actions/navigation';
+
import UserProfile from './user_profile';
function mapStateToProps(state, ownProps) {
@@ -43,6 +50,10 @@ function mapDispatchToProps(dispatch) {
makeDirectChannel,
setChannelDisplayName,
loadBot,
+ setButtons,
+ dismissModal,
+ resetToChannel,
+ goToScreen,
}, dispatch),
};
}
diff --git a/app/screens/user_profile/user_profile.js b/app/screens/user_profile/user_profile.js
index 130ffd3a1..848e8332d 100644
--- a/app/screens/user_profile/user_profile.js
+++ b/app/screens/user_profile/user_profile.js
@@ -33,11 +33,14 @@ export default class UserProfile extends PureComponent {
makeDirectChannel: PropTypes.func.isRequired,
setChannelDisplayName: PropTypes.func.isRequired,
loadBot: PropTypes.func.isRequired,
+ setButtons: PropTypes.func.isRequired,
+ dismissModal: PropTypes.func.isRequired,
+ resetToChannel: PropTypes.func.isRequired,
+ goToScreen: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
config: PropTypes.object.isRequired,
currentDisplayName: PropTypes.string,
- navigator: PropTypes.object,
teammateNameDisplay: PropTypes.string,
theme: PropTypes.object.isRequired,
user: PropTypes.object.isRequired,
@@ -61,13 +64,13 @@ export default class UserProfile extends PureComponent {
super(props);
if (props.isMyUser) {
- this.rightButton.title = context.intl.formatMessage({id: 'mobile.routes.user_profile.edit', defaultMessage: 'Edit'});
+ this.rightButton.text = context.intl.formatMessage({id: 'mobile.routes.user_profile.edit', defaultMessage: 'Edit'});
const buttons = {
rightButtons: [this.rightButton],
};
- props.navigator.setButtons(buttons);
+ props.actions.setButtons(props.componentId, buttons);
}
}
@@ -97,30 +100,17 @@ export default class UserProfile extends PureComponent {
}
close = () => {
- const {navigator, theme} = this.props;
+ const {actions, fromSettings} = this.props;
- if (this.props.fromSettings) {
- navigator.dismissModal({
- animationType: 'slide-down',
- });
+ if (fromSettings) {
+ actions.dismissModal();
return;
}
- navigator.resetTo({
- screen: 'Channel',
- animated: true,
- navigatorStyle: {
- animated: true,
- animationType: 'fade',
- navBarHidden: true,
- statusBarHidden: false,
- statusBarHideWithNavBar: false,
- screenBackgroundColor: theme.centerChannelBg,
- },
- passProps: {
- disableTermsModal: true,
- },
- });
+ const passProps = {
+ disableTermsModal: true,
+ };
+ actions.resetToChannel(passProps);
};
getDisplayName = () => {
@@ -231,27 +221,15 @@ export default class UserProfile extends PureComponent {
};
goToEditProfile = () => {
- const {user: currentUser} = this.props;
+ const {actions, user: currentUser} = this.props;
const {formatMessage} = this.context.intl;
const commandType = 'Push';
-
- const {navigator, theme} = this.props;
- const options = {
- screen: 'EditProfile',
- title: formatMessage({id: 'mobile.routes.edit_profile', defaultMessage: 'Edit Profile'}),
- animated: true,
- backButtonTitle: '',
- passProps: {currentUser, commandType},
- navigatorStyle: {
- navBarTextColor: theme.sidebarHeaderTextColor,
- navBarBackgroundColor: theme.sidebarHeaderBg,
- navBarButtonColor: theme.sidebarHeaderTextColor,
- screenBackgroundColor: theme.centerChannelBg,
- },
- };
+ const screen = 'EditProfile';
+ const title = formatMessage({id: 'mobile.routes.edit_profile', defaultMessage: 'Edit Profile'});
+ const passProps = {currentUser, commandType};
requestAnimationFrame(() => {
- navigator.push(options);
+ actions.goToScreen(screen, title, passProps);
});
};
diff --git a/app/screens/user_profile/user_profile.test.js b/app/screens/user_profile/user_profile.test.js
index af4e8d903..5c425058f 100644
--- a/app/screens/user_profile/user_profile.test.js
+++ b/app/screens/user_profile/user_profile.test.js
@@ -22,6 +22,10 @@ describe('user_profile', () => {
setChannelDisplayName: jest.fn(),
makeDirectChannel: jest.fn(),
loadBot: jest.fn(),
+ setButtons: jest.fn(),
+ dismissModal: jest.fn(),
+ resetToChannel: jest.fn(),
+ goToScreen: jest.fn(),
};
const baseProps = {
actions,
@@ -29,11 +33,6 @@ describe('user_profile', () => {
ShowEmailAddress: true,
},
teammateNameDisplay: 'username',
- navigator: {
- resetTo: jest.fn(),
- push: jest.fn(),
- dismissModal: jest.fn(),
- },
teams: [],
theme: Preferences.THEMES.default,
enableTimezone: false,
@@ -90,16 +89,9 @@ describe('user_profile', () => {
});
test('should push EditProfile', async () => {
- const props = {
- ...baseProps,
- navigator: {
- push: jest.fn(),
- },
- };
-
const wrapper = shallow(
,
{context: {intl: {formatMessage: jest.fn()}}},
@@ -107,18 +99,18 @@ describe('user_profile', () => {
wrapper.instance().goToEditProfile();
setTimeout(() => {
- expect(props.navigator.push).toHaveBeenCalledTimes(1);
+ expect(baseProps.actions.goToScreen).toHaveBeenCalledTimes(1);
}, 16);
});
test('should call goToEditProfile', () => {
const props = {
...baseProps,
- navigator: {
- push: jest.fn(),
+ actions: {
+ ...baseProps.actions,
+ goToScreen: jest.fn(),
},
};
-
const wrapper = shallow(
{
const event = {buttonId: wrapper.instance().rightButton.id};
wrapper.instance().navigationButtonPressed(event);
setTimeout(() => {
- expect(props.navigator.push).toHaveBeenCalledTimes(1);
+ expect(baseProps.actions.goToScreen).toHaveBeenCalledTimes(1);
}, 0);
});
@@ -147,11 +139,11 @@ describe('user_profile', () => {
const event = {buttonId: 'close-settings'};
wrapper.instance().navigationButtonPressed(event);
- expect(props.navigator.dismissModal).toHaveBeenCalledTimes(1);
+ expect(props.actions.dismissModal).toHaveBeenCalledTimes(1);
props.fromSettings = false;
wrapper.setProps({...props});
wrapper.instance().navigationButtonPressed(event);
- expect(props.navigator.resetTo).toHaveBeenCalledTimes(1);
+ expect(props.actions.resetToChannel).toHaveBeenCalledTimes(1);
});
});
diff --git a/app/utils/push_notifications.js b/app/utils/push_notifications.js
index 97a46032e..0214bbdd8 100644
--- a/app/utils/push_notifications.js
+++ b/app/utils/push_notifications.js
@@ -15,6 +15,7 @@ import {
createPostForNotificationReply,
loadFromPushNotification,
} from 'app/actions/views/root';
+import {dismissAllModals, popToRoot} from 'app/actions/navigation';
import {ViewTypes} from 'app/constants';
import {getLocalizedMessage} from 'app/i18n';
import {getCurrentServerUrl, getAppCredentials} from 'app/init/credentials';
@@ -45,7 +46,13 @@ class PushNotificationUtils {
await this.store.dispatch(loadFromPushNotification(notification, true));
if (!EphemeralStore.appStartedFromPushNotification) {
- EventEmitter.emit(ViewTypes.NOTIFICATION_TAPPED);
+ EventEmitter.emit('close_channel_drawer');
+ EventEmitter.emit('close_settings_sidebar');
+
+ const {dispatch} = this.store;
+ dispatch(dismissAllModals());
+ dispatch(popToRoot());
+
PushNotifications.resetNotification();
}
};
diff --git a/app/utils/wrap_context_provider.js b/app/utils/wrap_context_provider.js
index 015d9378a..cea58cabb 100644
--- a/app/utils/wrap_context_provider.js
+++ b/app/utils/wrap_context_provider.js
@@ -6,10 +6,8 @@ import IntlWrapper from 'app/components/root';
export function wrapWithContextProvider(Comp, excludeEvents = true) {
return (props) => { //eslint-disable-line react/display-name
- const {navigator} = props; //eslint-disable-line react/prop-types
return (
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 0830f40fa..de555aa2b 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -13,4 +13,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 63cb0d0aef536c8cbf15bf664fcfe31852a13dd1
-COCOAPODS: 1.6.1
+COCOAPODS: 1.5.3