From 0ad62ced40c66d3454fec758b4442eed65d116ea Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Wed, 15 Jul 2020 11:17:55 -0400 Subject: [PATCH] MM-26744 in-prompt for end users if server is unsupported (#4565) --- app/screens/channel/channel_base.js | 45 +++---------- app/screens/channel/index.js | 17 ++--- .../terms_of_service/terms_of_service.js | 17 +++-- app/utils/supported_server.test.js | 22 +++++++ app/utils/supported_server.ts | 65 +++++++++++++++++++ assets/base/i18n/en.json | 3 + 6 files changed, 113 insertions(+), 56 deletions(-) create mode 100644 app/utils/supported_server.test.js create mode 100644 app/utils/supported_server.ts diff --git a/app/screens/channel/channel_base.js b/app/screens/channel/channel_base.js index f76f20ab6..4593f0684 100644 --- a/app/screens/channel/channel_base.js +++ b/app/screens/channel/channel_base.js @@ -4,19 +4,15 @@ import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import {intlShape} from 'react-intl'; -import { - Alert, - Keyboard, - Linking, - StyleSheet, -} from 'react-native'; +import {Keyboard, StyleSheet} from 'react-native'; import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; import {showModal, showModalOverCurrentContext} from '@actions/navigation'; import LocalConfig from '@assets/config'; -import {NavigationTypes, ViewTypes} from '@constants'; +import {NavigationTypes} from '@constants'; import EventEmitter from '@mm-redux/utils/event_emitter'; import EphemeralStore from '@store/ephemeral_store'; +import {unsupportedServer} from '@utils/supported_server'; import {preventDoubleTap} from '@utils/tap'; import {setNavigatorStyles} from '@utils/theme'; import tracker from '@utils/time_tracker'; @@ -41,6 +37,7 @@ export default class ChannelBase extends PureComponent { currentTeamId: PropTypes.string, disableTermsModal: PropTypes.bool, isSupportedServer: PropTypes.bool, + isSystemAdmin: PropTypes.bool, teamName: PropTypes.string, theme: PropTypes.object.isRequired, showTermsOfService: PropTypes.bool, @@ -77,6 +74,7 @@ export default class ChannelBase extends PureComponent { currentTeamId, disableTermsModal, isSupportedServer, + isSystemAdmin, showTermsOfService, skipMetrics, } = this.props; @@ -105,7 +103,7 @@ export default class ChannelBase extends PureComponent { this.showTermsOfServiceModal(); } else if (!isSupportedServer) { // Only display the Alert if the TOS does not need to show first - this.showUnsupportedServer(); + unsupportedServer(isSystemAdmin, this.context.intl.formatMessage); } if (!skipMetrics) { @@ -247,14 +245,14 @@ export default class ChannelBase extends PureComponent { showTermsOfServiceModal = async () => { const {intl} = this.context; - const {isSupportedServer, theme} = this.props; + const {isSupportedServer, isSystemAdmin, theme} = this.props; const screen = 'TermsOfService'; const title = intl.formatMessage({id: 'mobile.tos_link', defaultMessage: 'Terms of Service'}); MaterialIcon.getImageSource('close', 20, theme.sidebarHeaderTextColor).then((closeButton) => { const passProps = { closeButton, isSupportedServer, - showUnsupportedServer: this.showUnsupportedServer, + isSystemAdmin, }; const options = { layout: { @@ -274,33 +272,6 @@ export default class ChannelBase extends PureComponent { }); }; - showUnsupportedServer = () => { - const {formatMessage} = this.context.intl; - const title = formatMessage({id: 'mobile.server_upgrade.title', defaultMessage: 'Server upgrade required'}); - const message = formatMessage({ - id: 'mobile.server_upgrade.alert_description', - defaultMessage: 'This server version is unsupported and users will be exposed to compatibility issues that cause crashes or severe bugs breaking core functionality of the app. Upgrading to server version {serverVersion} or later is required.', - }, {serverVersion: ViewTypes.RequiredServer.FULL_VERSION}); - const cancel = { - text: formatMessage({id: 'mobile.server_upgrade.dismiss', defaultMessage: 'Dismiss'}), - style: 'default', - }; - const learnMore = { - text: formatMessage({id: 'mobile.server_upgrade.learn_more', defaultMessage: 'Learn More'}), - style: 'cancel', - onPress: () => { - const url = 'https://mattermost.com/blog/support-for-esr-5-9-has-ended/'; - if (Linking.canOpenURL(url)) { - Linking.openURL(url); - } - }, - }; - const buttons = [cancel, learnMore]; - const options = {cancelable: false}; - - Alert.alert(title, message, buttons, options); - }; - updateNativeScrollView = () => { if (this.keyboardTracker?.current) { this.keyboardTracker.current.resetScrollView(this.props.currentChannelId); diff --git a/app/screens/channel/index.js b/app/screens/channel/index.js index d55ae8660..81b5ed39d 100644 --- a/app/screens/channel/index.js +++ b/app/screens/channel/index.js @@ -23,21 +23,18 @@ function mapStateToProps(state) { const currentTeam = getCurrentTeam(state); const roles = getCurrentUserId(state) ? getCurrentUserRoles(state) : ''; const isSystemAdmin = checkIsSystemAdmin(roles); - let isSupportedServer = true; - - if (isSystemAdmin) { - isSupportedServer = isMinimumServerVersion( - getServerVersion(state), - ViewTypes.RequiredServer.MAJOR_VERSION, - ViewTypes.RequiredServer.MIN_VERSION, - ViewTypes.RequiredServer.PATCH_VERSION, - ); - } + const isSupportedServer = isMinimumServerVersion( + getServerVersion(state), + ViewTypes.RequiredServer.MAJOR_VERSION, + ViewTypes.RequiredServer.MIN_VERSION, + ViewTypes.RequiredServer.PATCH_VERSION, + ); return { currentTeamId: currentTeam?.id, currentChannelId: getCurrentChannelId(state), isSupportedServer, + isSystemAdmin, teamName: currentTeam?.display_name, theme: getTheme(state), showTermsOfService: shouldShowTermsOfService(state), diff --git a/app/screens/terms_of_service/terms_of_service.js b/app/screens/terms_of_service/terms_of_service.js index 541aa928c..e50c22489 100644 --- a/app/screens/terms_of_service/terms_of_service.js +++ b/app/screens/terms_of_service/terms_of_service.js @@ -11,15 +11,14 @@ import { import {intlShape} from 'react-intl'; import {Navigation} from 'react-native-navigation'; -import FailedNetworkAction from 'app/components/failed_network_action'; +import {dismissModal, setButtons} from '@actions/navigation'; +import FailedNetworkAction from '@components/failed_network_action'; import Loading from 'app/components/loading'; import Markdown from 'app/components/markdown'; import StatusBar from 'app/components/status_bar'; - -import {getMarkdownTextStyles, getMarkdownBlockStyles} from 'app/utils/markdown'; -import {makeStyleSheetFromTheme} from 'app/utils/theme'; - -import {dismissModal, setButtons} from 'app/actions/navigation'; +import {getMarkdownTextStyles, getMarkdownBlockStyles} from '@utils/markdown'; +import {unsupportedServer} from '@utils/supported_server'; +import {makeStyleSheetFromTheme} from '@utils/theme'; export default class TermsOfService extends PureComponent { static propTypes = { @@ -31,7 +30,7 @@ export default class TermsOfService extends PureComponent { componentId: PropTypes.string, closeButton: PropTypes.object, isSupportedServer: PropTypes.bool, - showUnsupportedServer: PropTypes.func, + isSystemAdmin: PropTypes.bool, siteName: PropTypes.string, theme: PropTypes.object, }; @@ -148,11 +147,11 @@ export default class TermsOfService extends PureComponent { handleAcceptTerms = () => { const onSuccess = () => { - const {isSupportedServer, showUnsupportedServer} = this.props; + const {isSupportedServer, isSystemAdmin} = this.props; dismissModal(); if (!isSupportedServer) { - showUnsupportedServer(); + unsupportedServer(isSystemAdmin, this.context.intl.formatMessage); } }; diff --git a/app/utils/supported_server.test.js b/app/utils/supported_server.test.js new file mode 100644 index 000000000..46bca9544 --- /dev/null +++ b/app/utils/supported_server.test.js @@ -0,0 +1,22 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {Alert} from 'react-native'; + +import {unsupportedServer} from './supported_server'; + +describe('Unsupported Server Alert', () => { + const formatMessage = ({defaultMessage}) => jest.fn().mockReturnValue(defaultMessage); + + it('should show the alert for sysadmin', () => { + const alert = jest.spyOn(Alert, 'alert'); + unsupportedServer(true, formatMessage); + expect(alert.mock.calls[0][2].length).toBe(2); + }); + + it('should show the alert for team admin / user', () => { + const alert = jest.spyOn(Alert, 'alert'); + unsupportedServer(false, formatMessage); + expect(alert.mock.calls[0][2].length).toBe(1); + }); +}); diff --git a/app/utils/supported_server.ts b/app/utils/supported_server.ts new file mode 100644 index 000000000..36bea7c84 --- /dev/null +++ b/app/utils/supported_server.ts @@ -0,0 +1,65 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {Alert, Linking, AlertButton} from 'react-native'; +import {ViewTypes} from '@constants'; + +interface FormatObjectType { + id: string; + defaultMessage: string; +} + +interface FormatMessageType { + (obj: FormatObjectType, values?: any): string; +} + +export function unsupportedServer(isSystemAdmin: boolean, formatMessage: FormatMessageType) { + if (isSystemAdmin) { + unsupportedServerAdminAlert(formatMessage); + } else { + unsupportedServerAlert(formatMessage); + } +} + +function unsupportedServerAdminAlert(formatMessage: FormatMessageType) { + const title = formatMessage({id: 'mobile.server_upgrade.title', defaultMessage: 'Server upgrade required'}); + const message = formatMessage({ + id: 'mobile.server_upgrade.alert_description', + defaultMessage: 'This server version is unsupported and users will be exposed to compatibility issues that cause crashes or severe bugs breaking core functionality of the app. Upgrading to server version {serverVersion} or later is required.', + }, {serverVersion: ViewTypes.RequiredServer.FULL_VERSION}); + const cancel: AlertButton = { + text: formatMessage({id: 'mobile.server_upgrade.dismiss', defaultMessage: 'Dismiss'}), + style: 'default', + }; + const learnMore: AlertButton = { + text: formatMessage({id: 'mobile.server_upgrade.learn_more', defaultMessage: 'Learn More'}), + style: 'cancel', + onPress: () => { + const url = 'https://mattermost.com/blog/support-for-esr-5-9-has-ended/'; + if (Linking.canOpenURL(url)) { + Linking.openURL(url); + } + }, + }; + const buttons: AlertButton[] = [cancel, learnMore]; + const options = {cancelable: false}; + + Alert.alert(title, message, buttons, options); +} + +function unsupportedServerAlert(formatMessage: FormatMessageType) { + const title = formatMessage({id: 'mobile.unsupported_server.title', defaultMessage: 'Unsupported server version'}); + const message = formatMessage({ + id: 'mobile.unsupported_server.message', + defaultMessage: 'Attachments, link previews, reactions and embed data may not be displayed correctly. If this issue persists contact your System Administrator to upgrade your Mattermost server.', + }); + const okButton: AlertButton = { + text: formatMessage({id: 'mobile.unsupported_server.ok', defaultMessage: 'OK'}), + style: 'default', + }; + + const buttons: AlertButton[] = [okButton]; + const options = {cancelable: false}; + + Alert.alert(title, message, buttons, options); +} \ No newline at end of file diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json index f9ffce2af..2e9bf0c28 100644 --- a/assets/base/i18n/en.json +++ b/assets/base/i18n/en.json @@ -497,6 +497,9 @@ "mobile.timezone_settings.manual": "Change timezone", "mobile.timezone_settings.select": "Select Timezone", "mobile.tos_link": "Terms of Service", + "mobile.unsupported_server.message": "Attachments, link previews, reactions and embed data may not be displayed correctly. If this issue persists contact your System Administrator to upgrade your Mattermost server.", + "mobile.unsupported_server.ok": "OK", + "mobile.unsupported_server.title": "Unsupported server version", "mobile.user_list.deactivated": "Deactivated", "mobile.user.settings.notifications.email.fifteenMinutes": "Every 15 minutes", "mobile.video_playback.failed_description": "An error occurred while trying to play the video.\n",