diff --git a/app/actions/navigation/index.js b/app/actions/navigation/index.js index 02b226ae5..b09f4b888 100644 --- a/app/actions/navigation/index.js +++ b/app/actions/navigation/index.js @@ -7,9 +7,11 @@ import merge from 'deepmerge'; import {Preferences} from '@mm-redux/constants'; import {getTheme} from '@mm-redux/selectors/entities/preferences'; +import EventEmmiter from '@mm-redux/utils/event_emitter'; import EphemeralStore from '@store/ephemeral_store'; import Store from '@store/store'; +import {NavigationTypes} from '@constants'; const CHANNEL_SCREEN = 'Channel'; @@ -223,6 +225,13 @@ export async function popToRoot() { } } +export async function dismissAllModalsAndPopToRoot() { + await dismissAllModals(); + await popToRoot(); + + EventEmmiter.emit(NavigationTypes.NAVIGATION_DISMISS_AND_POP_TO_ROOT); +} + export function showModal(name, title, passProps = {}, options = {}) { const theme = getThemeFromState(); const defaultOptions = { diff --git a/app/actions/navigation/index.test.js b/app/actions/navigation/index.test.js index 8f7b6664d..de94c3bcb 100644 --- a/app/actions/navigation/index.test.js +++ b/app/actions/navigation/index.test.js @@ -7,11 +7,14 @@ import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import merge from 'deepmerge'; +import EventEmitter from '@mm-redux/utils/event_emitter'; + import * as NavigationActions from '@actions/navigation'; import Preferences from '@mm-redux/constants/preferences'; import EphemeralStore from '@store/ephemeral_store'; import intitialState from '@store/initial_state'; import Store from '@store/store'; +import {NavigationTypes} from '@constants'; jest.unmock('@actions/navigation'); jest.mock('@store/ephemeral_store', () => ({ @@ -480,4 +483,15 @@ describe('@actions/navigation', () => { await NavigationActions.dismissOverlay(topComponentId); expect(dismissOverlay).toHaveBeenCalledWith(topComponentId); }); + + test('dismissAllModalsAndPopToRoot should call Navigation.dismissAllModals, Navigation.popToRoot, and emit event', async () => { + const dismissAllModals = jest.spyOn(Navigation, 'dismissAllModals'); + const popToRoot = jest.spyOn(Navigation, 'popToRoot'); + EventEmitter.emit = jest.fn(); + + await NavigationActions.dismissAllModalsAndPopToRoot(); + expect(dismissAllModals).toHaveBeenCalled(); + expect(popToRoot).toHaveBeenCalledWith(topComponentId); + expect(EventEmitter.emit).toHaveBeenCalledWith(NavigationTypes.NAVIGATION_DISMISS_AND_POP_TO_ROOT); + }); }); \ No newline at end of file diff --git a/app/components/post_list/post_list.js b/app/components/post_list/post_list.js index ab9fd3173..89c0ffe97 100644 --- a/app/components/post_list/post_list.js +++ b/app/components/post_list/post_list.js @@ -12,7 +12,7 @@ import * as PostListUtils from '@mm-redux/utils/post_list'; import CombinedUserActivityPost from 'app/components/combined_user_activity_post'; import Post from 'app/components/post'; -import {DeepLinkTypes, ListTypes} from 'app/constants'; +import {DeepLinkTypes, ListTypes, NavigationTypes} from '@constants'; import mattermostManaged from 'app/mattermost_managed'; import {makeExtraData} from 'app/utils/list_view'; import {changeOpacity} from 'app/utils/theme'; @@ -105,6 +105,7 @@ export default class PostList extends PureComponent { const {actions, deepLinkURL, highlightPostId, initialIndex} = this.props; EventEmitter.on('scroll-to-bottom', this.handleSetScrollToBottom); + EventEmitter.on(NavigationTypes.NAVIGATION_DISMISS_AND_POP_TO_ROOT, this.handleClosePermalink); // Invoked when hitting a deep link and app is not already running. if (deepLinkURL) { @@ -149,6 +150,7 @@ export default class PostList extends PureComponent { componentWillUnmount() { EventEmitter.off('scroll-to-bottom', this.handleSetScrollToBottom); + EventEmitter.off(NavigationTypes.NAVIGATION_DISMISS_AND_POP_TO_ROOT, this.handleClosePermalink); this.resetPostList(); } diff --git a/app/components/post_list/post_list.test.js b/app/components/post_list/post_list.test.js index ea303d261..aafd200b4 100644 --- a/app/components/post_list/post_list.test.js +++ b/app/components/post_list/post_list.test.js @@ -5,8 +5,10 @@ import React from 'react'; import {shallow} from 'enzyme'; import Preferences from '@mm-redux/constants/preferences'; +import EventEmitter from '@mm-redux/utils/event_emitter'; import * as NavigationActions from 'app/actions/navigation'; +import {NavigationTypes} from '@constants'; import PostList from './post_list'; jest.useFakeTimers(); @@ -121,4 +123,36 @@ describe('PostList', () => { expect(instance.loadToFillContent).toHaveBeenCalledTimes(1); }); + + test('should register listeners on componentDidMount', () => { + const wrapper = shallow( + , + ); + const instance = wrapper.instance(); + instance.handleSetScrollToBottom = jest.fn(); + instance.handleClosePermalink = jest.fn(); + EventEmitter.on = jest.fn(); + + expect(EventEmitter.on).not.toHaveBeenCalled(); + instance.componentDidMount(); + expect(EventEmitter.on).toHaveBeenCalledTimes(2); + expect(EventEmitter.on).toHaveBeenCalledWith('scroll-to-bottom', instance.handleSetScrollToBottom); + expect(EventEmitter.on).toHaveBeenCalledWith(NavigationTypes.NAVIGATION_DISMISS_AND_POP_TO_ROOT, instance.handleClosePermalink); + }); + + test('should remove listeners on componentWillUnmount', () => { + const wrapper = shallow( + , + ); + const instance = wrapper.instance(); + instance.handleSetScrollToBottom = jest.fn(); + instance.handleClosePermalink = jest.fn(); + EventEmitter.off = jest.fn(); + + expect(EventEmitter.off).not.toHaveBeenCalled(); + instance.componentWillUnmount(); + expect(EventEmitter.off).toHaveBeenCalledTimes(2); + expect(EventEmitter.off).toHaveBeenCalledWith('scroll-to-bottom', instance.handleSetScrollToBottom); + expect(EventEmitter.off).toHaveBeenCalledWith(NavigationTypes.NAVIGATION_DISMISS_AND_POP_TO_ROOT, instance.handleClosePermalink); + }); }); diff --git a/app/constants/navigation.js b/app/constants/navigation.js index a7226d2d4..7892bbd37 100644 --- a/app/constants/navigation.js +++ b/app/constants/navigation.js @@ -10,6 +10,7 @@ const NavigationTypes = keyMirror({ RESTART_APP: null, NAVIGATION_ERROR_TEAMS: null, NAVIGATION_SHOW_OVERLAY: null, + NAVIGATION_DISMISS_AND_POP_TO_ROOT: null, CLOSE_MAIN_SIDEBAR: null, MAIN_SIDEBAR_DID_CLOSE: null, MAIN_SIDEBAR_DID_OPEN: null, diff --git a/app/screens/user_profile/user_profile.js b/app/screens/user_profile/user_profile.js index ab2e2cf9d..cccaeca68 100644 --- a/app/screens/user_profile/user_profile.js +++ b/app/screens/user_profile/user_profile.js @@ -16,6 +16,7 @@ import { goToScreen, dismissModal, setButtons, + dismissAllModalsAndPopToRoot, } from '@actions/navigation'; import Config from '@assets/config'; import FormattedTime from '@components/formatted_time'; @@ -215,7 +216,7 @@ export default class UserProfile extends PureComponent { }, ); } else { - this.close(); + dismissAllModalsAndPopToRoot(); } };