diff --git a/app/components/at_mention/at_mention.js b/app/components/at_mention/at_mention.js index dc1d54798..0193171ac 100644 --- a/app/components/at_mention/at_mention.js +++ b/app/components/at_mention/at_mention.js @@ -5,13 +5,14 @@ import React from 'react'; import PropTypes from 'prop-types'; import {Clipboard, Text} from 'react-native'; import {intlShape} from 'react-intl'; +import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; import {displayUsername} from '@mm-redux/utils/user_utils'; import CustomPropTypes from 'app/constants/custom_prop_types'; import mattermostManaged from 'app/mattermost_managed'; import BottomSheet from 'app/utils/bottom_sheet'; -import {goToScreen} from 'app/actions/navigation'; +import {showModal} from 'app/actions/navigation'; export default class AtMention extends React.PureComponent { static propTypes = { @@ -45,15 +46,29 @@ export default class AtMention extends React.PureComponent { } } - goToUserProfile = () => { + goToUserProfile = async () => { const {intl} = this.context; + const {theme} = this.props; const screen = 'UserProfile'; const title = intl.formatMessage({id: 'mobile.routes.user_profile', defaultMessage: 'Profile'}); const passProps = { userId: this.state.user.id, }; - goToScreen(screen, title, passProps); + if (!this.closeButton) { + this.closeButton = await MaterialIcon.getImageSource('close', 20, theme.sidebarHeaderTextColor); + } + + const options = { + topBar: { + leftButtons: [{ + id: 'close-settings', + icon: this.closeButton, + }], + }, + }; + + showModal(screen, title, passProps, options); }; getUserDetailsFromMentionName() { diff --git a/app/components/channel_intro/channel_intro.js b/app/components/channel_intro/channel_intro.js index a3729bc90..0ceb3a0a9 100644 --- a/app/components/channel_intro/channel_intro.js +++ b/app/components/channel_intro/channel_intro.js @@ -8,11 +8,12 @@ import { View, } from 'react-native'; import {injectIntl, intlShape} from 'react-intl'; +import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; import {displayUsername} from '@mm-redux/utils/user_utils'; import {General} from '@mm-redux/constants'; -import {goToScreen} from 'app/actions/navigation'; +import {showModal} from 'app/actions/navigation'; import ProfilePicture from 'app/components/profile_picture'; import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing'; import {BotTag, GuestTag} from 'app/components/tag'; @@ -37,15 +38,28 @@ class ChannelIntro extends PureComponent { currentChannelMembers: [], }; - goToUserProfile = (userId) => { - const {intl} = this.props; + goToUserProfile = async (userId) => { + const {intl, theme} = this.props; const screen = 'UserProfile'; const title = intl.formatMessage({id: 'mobile.routes.user_profile', defaultMessage: 'Profile'}); const passProps = { userId, }; - goToScreen(screen, title, passProps); + if (!this.closeButton) { + this.closeButton = await MaterialIcon.getImageSource('close', 20, theme.sidebarHeaderTextColor); + } + + const options = { + topBar: { + leftButtons: [{ + id: 'close-settings', + icon: this.closeButton, + }], + }, + }; + + showModal(screen, title, passProps, options); }; getDisplayName = (member) => { diff --git a/app/components/post/post.js b/app/components/post/post.js index a97f9efe2..c435371be 100644 --- a/app/components/post/post.js +++ b/app/components/post/post.js @@ -10,23 +10,27 @@ import { ViewPropTypes, } from 'react-native'; import {intlShape} from 'react-intl'; +import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; import {Posts} from '@mm-redux/constants'; import EventEmitter from '@mm-redux/utils/event_emitter'; import {isPostEphemeral, isPostPendingOrFailed, isSystemMessage} from '@mm-redux/utils/post_utils'; -import PostBody from 'app/components/post_body'; -import PostHeader from 'app/components/post_header'; -import PostPreHeader from 'app/components/post_header/post_pre_header'; -import PostProfilePicture from 'app/components/post_profile_picture'; -import TouchableWithFeedback from 'app/components/touchable_with_feedback'; -import {NavigationTypes} from 'app/constants'; -import {fromAutoResponder} from 'app/utils/general'; -import {preventDoubleTap} from 'app/utils/tap'; -import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme'; -import {t} from 'app/utils/i18n'; -import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing'; -import {goToScreen, showModalOverCurrentContext} from 'app/actions/navigation'; +import {showModalOverCurrentContext, showModal} from '@actions/navigation'; + +import PostBody from '@components/post_body'; +import PostHeader from '@components/post_header'; +import PostProfilePicture from '@components/post_profile_picture'; +import PostPreHeader from '@components/post_header/post_pre_header'; +import TouchableWithFeedback from '@components/touchable_with_feedback'; +import {paddingHorizontal as padding} from '@components/safe_area_view/iphone_x_spacing'; + +import {NavigationTypes} from '@constants'; + +import {t} from '@utils/i18n'; +import {preventDoubleTap} from '@utils/tap'; +import {fromAutoResponder} from '@utils/general'; +import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; export default class Post extends PureComponent { static propTypes = { @@ -88,19 +92,30 @@ export default class Post extends PureComponent { this.postBodyRef = React.createRef(); } - goToUserProfile = () => { + goToUserProfile = async () => { const {intl} = this.context; - const {post} = this.props; + const {post, theme} = this.props; const screen = 'UserProfile'; const title = intl.formatMessage({id: 'mobile.routes.user_profile', defaultMessage: 'Profile'}); const passProps = { userId: post.user_id, }; + if (!this.closeButton) { + this.closeButton = await MaterialIcon.getImageSource('close', 20, theme.sidebarHeaderTextColor); + } + + const options = { + topBar: { + leftButtons: [{ + id: 'close-settings', + icon: this.closeButton, + }], + }, + }; + Keyboard.dismiss(); - requestAnimationFrame(() => { - goToScreen(screen, title, passProps); - }); + showModal(screen, title, passProps, options); }; autofillUserMention = (username) => { diff --git a/app/components/sidebars/settings/settings_sidebar_base.js b/app/components/sidebars/settings/settings_sidebar_base.js index 538cc0f34..a311e0e69 100644 --- a/app/components/sidebars/settings/settings_sidebar_base.js +++ b/app/components/sidebars/settings/settings_sidebar_base.js @@ -112,7 +112,7 @@ export default class SettingsSidebarBase extends PureComponent { this.openModal( 'UserProfile', intl.formatMessage({id: 'mobile.routes.user_profile', defaultMessage: 'Profile'}), - {userId, fromSettings: true}, + {userId}, ); }; diff --git a/app/screens/channel/channel_base.js b/app/screens/channel/channel_base.js index 0675744dd..19f68da4b 100644 --- a/app/screens/channel/channel_base.js +++ b/app/screens/channel/channel_base.js @@ -9,7 +9,6 @@ import { Keyboard, Linking, StyleSheet, - Platform, } from 'react-native'; import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; @@ -169,11 +168,6 @@ export default class ChannelBase extends PureComponent { icon: source, }], }, - ...Platform.select({ - ios: { - modalPresentationStyle: 'pageSheet', - }, - }), }; Keyboard.dismiss(); diff --git a/app/screens/reaction_list/reaction_row/reaction_row.js b/app/screens/reaction_list/reaction_row/reaction_row.js index 285cd3cc6..72be6f270 100644 --- a/app/screens/reaction_list/reaction_row/reaction_row.js +++ b/app/screens/reaction_list/reaction_row/reaction_row.js @@ -9,6 +9,7 @@ import { TouchableOpacity, View, } from 'react-native'; +import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; import {displayUsername} from '@mm-redux/utils/user_utils'; @@ -16,7 +17,7 @@ import ProfilePicture from 'app/components/profile_picture'; import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing'; import {preventDoubleTap} from 'app/utils/tap'; import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme'; -import {goToScreen} from 'app/actions/navigation'; +import {showModal} from 'app/actions/navigation'; import Emoji from 'app/components/emoji'; @@ -37,8 +38,8 @@ export default class ReactionRow extends React.PureComponent { intl: intlShape, }; - goToUserProfile = () => { - const {user} = this.props; + goToUserProfile = async () => { + const {user, theme} = this.props; const {formatMessage} = this.context.intl; const screen = 'UserProfile'; const title = formatMessage({id: 'mobile.routes.user_profile', defaultMessage: 'Profile'}); @@ -46,7 +47,20 @@ export default class ReactionRow extends React.PureComponent { userId: user.id, }; - goToScreen(screen, title, passProps); + if (!this.closeButton) { + this.closeButton = await MaterialIcon.getImageSource('close', 20, theme.sidebarHeaderTextColor); + } + + const options = { + topBar: { + leftButtons: [{ + id: 'close-settings', + icon: this.closeButton, + }], + }, + }; + + showModal(screen, title, passProps, options); }; render() { diff --git a/app/screens/user_profile/user_profile.js b/app/screens/user_profile/user_profile.js index 02ca131d4..5d1cb2968 100644 --- a/app/screens/user_profile/user_profile.js +++ b/app/screens/user_profile/user_profile.js @@ -14,7 +14,6 @@ import {Navigation} from 'react-native-navigation'; import { goToScreen, - popToRoot, dismissModal, setButtons, } from '@actions/navigation'; @@ -51,7 +50,6 @@ export default class UserProfile extends PureComponent { militaryTime: PropTypes.bool.isRequired, enableTimezone: PropTypes.bool.isRequired, isMyUser: PropTypes.bool.isRequired, - fromSettings: PropTypes.bool, isLandscape: PropTypes.bool.isRequired, }; @@ -99,14 +97,7 @@ export default class UserProfile extends PureComponent { } close = async () => { - const {fromSettings} = this.props; - - if (fromSettings) { - dismissModal(); - return; - } - - await popToRoot(); + dismissModal(); }; getDisplayName = () => { diff --git a/app/screens/user_profile/user_profile.test.js b/app/screens/user_profile/user_profile.test.js index 689aadf4a..18a55e027 100644 --- a/app/screens/user_profile/user_profile.test.js +++ b/app/screens/user_profile/user_profile.test.js @@ -145,47 +145,8 @@ describe('user_profile', () => { expect(goToScreen).toHaveBeenCalledTimes(1); }); - test('close should dismiss modal when fromSettings is true', async () => { - const dismissModal = jest.spyOn(NavigationActions, 'dismissModal'); - const dismissAllModals = jest.spyOn(NavigationActions, 'dismissAllModals'); - const popToRoot = jest.spyOn(NavigationActions, 'popToRoot'); - - const props = {...baseProps, fromSettings: true}; - - const wrapper = shallow( - , - {context: {intl: {formatMessage: jest.fn()}}}, - ); - - await wrapper.instance().close(); - expect(dismissModal).toHaveBeenCalledTimes(1); - expect(dismissAllModals).toHaveBeenCalledTimes(0); - expect(popToRoot).toHaveBeenCalledTimes(0); - }); - - test('close should dismiss all modals and pop to root when fromSettings is false', async () => { - const dismissModal = jest.spyOn(NavigationActions, 'dismissModal'); - const popToRoot = jest.spyOn(NavigationActions, 'popToRoot'); - - const props = {...baseProps, fromSettings: false}; - - const wrapper = shallow( - , - {context: {intl: {formatMessage: jest.fn()}}}, - ); - - await wrapper.instance().close(); - expect(dismissModal).toHaveBeenCalledTimes(0); - expect(popToRoot).toHaveBeenCalledTimes(1); - }); - test('should call close', () => { + const dismissModal = jest.spyOn(NavigationActions, 'dismissModal'); const wrapper = shallow( { const event = {buttonId: 'close-settings'}; wrapper.instance().navigationButtonPressed(event); expect(close).toHaveBeenCalledTimes(1); + expect(dismissModal).toHaveBeenCalledTimes(1); }); });