diff --git a/app/components/app_version/index.tsx b/app/components/app_version/index.tsx
index 98138a8e4..21b29e595 100644
--- a/app/components/app_version/index.tsx
+++ b/app/components/app_version/index.tsx
@@ -2,9 +2,10 @@
// See LICENSE.txt for license information.
import React from 'react';
-import {StyleSheet, View} from 'react-native';
+import {StyleSheet, TextStyle, View} from 'react-native';
import DeviceInfo from 'react-native-device-info';
+import {t} from '@i18n';
import FormattedText from '@components/formatted_text';
const style = StyleSheet.create({
@@ -17,19 +18,32 @@ const style = StyleSheet.create({
},
});
-const AppVersion = () => {
+type AppVersionProps = {
+ isWrapped?: boolean;
+ textStyle?: TextStyle;
+}
+
+const AppVersion = ({isWrapped = true, textStyle = {}}: AppVersionProps) => {
+ const appVersion = (
+
+ );
+
+ if (!isWrapped) {
+ return appVersion;
+ }
+
return (
-
+ {appVersion}
);
diff --git a/app/constants/screens.ts b/app/constants/screens.ts
index 4959165f1..f7995d0a3 100644
--- a/app/constants/screens.ts
+++ b/app/constants/screens.ts
@@ -1,6 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
+export const ABOUT = 'About';
export const CHANNEL = 'Channel';
export const FORGOT_PASSWORD = 'ForgotPassword';
export const LOGIN = 'Login';
@@ -13,6 +14,7 @@ export const SSO = 'SSO';
export const THREAD = 'Thread';
export default {
+ ABOUT,
CHANNEL,
FORGOT_PASSWORD,
LOGIN,
diff --git a/app/screens/about/index.tsx b/app/screens/about/index.tsx
new file mode 100644
index 000000000..00e9dee47
--- /dev/null
+++ b/app/screens/about/index.tsx
@@ -0,0 +1,347 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
+import withObservables from '@nozbe/with-observables';
+import React, {useCallback} from 'react';
+import {useIntl} from 'react-intl';
+import {Alert, ScrollView, Text, View} from 'react-native';
+import DeviceInfo from 'react-native-device-info';
+import {SafeAreaView} from 'react-native-safe-area-context';
+
+import Config from '@assets/config.json';
+import AppVersion from '@components/app_version';
+import CompassIcon from '@components/compass_icon';
+import FormattedText from '@components/formatted_text';
+import StatusBar from '@components/status_bar';
+import AboutLinks from '@constants/about_links';
+import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
+import {useTheme} from '@context/theme';
+import {t} from '@i18n';
+import {preventDoubleTap} from '@utils/tap';
+import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
+import {tryOpenURL} from '@utils/url';
+
+import LearnMore from './learn_more';
+import ServerVersion from './server_version';
+import Subtitle from './subtitle';
+import Title from './title';
+import TosPrivacyContainer from './tos_privacy';
+
+import type {WithDatabaseArgs} from '@typings/database/database';
+import type SystemModel from '@typings/database/models/servers/system';
+
+const MATTERMOST_BUNDLE_IDS = ['com.mattermost.rnbeta', 'com.mattermost.rn'];
+
+type ConnectedAboutProps = {
+ config: SystemModel;
+ license: SystemModel;
+}
+
+const ConnectedAbout = ({config, license}: ConnectedAboutProps) => {
+ const intl = useIntl();
+ const theme = useTheme();
+ const style = getStyleSheet(theme);
+
+ const openURL = useCallback((url: string) => {
+ const onError = () => {
+ Alert.alert(
+ intl.formatMessage({
+ id: 'mobile.link.error.title',
+ defaultMessage: 'Error',
+ }),
+ intl.formatMessage({
+ id: 'mobile.link.error.text',
+ defaultMessage: 'Unable to open the link.',
+ }),
+ );
+ };
+
+ tryOpenURL(url, onError);
+ }, []);
+
+ const handleAboutTeam = useCallback(preventDoubleTap(() => {
+ return openURL(Config.AboutTeamURL);
+ }), []);
+
+ const handleAboutEnterprise = useCallback(preventDoubleTap(() => {
+ return openURL(Config.AboutEnterpriseURL);
+ }), []);
+
+ const handlePlatformNotice = useCallback(preventDoubleTap(() => {
+ return openURL(Config.PlatformNoticeURL);
+ }), []);
+
+ const handleMobileNotice = useCallback(preventDoubleTap(() => {
+ return openURL(Config.MobileNoticeURL);
+ }), []);
+
+ const handleTermsOfService = useCallback(preventDoubleTap(() => {
+ return openURL(AboutLinks.TERMS_OF_SERVICE);
+ }), []);
+
+ const handlePrivacyPolicy = useCallback(preventDoubleTap(() => {
+ return openURL(AboutLinks.PRIVACY_POLICY);
+ }), []);
+
+ return (
+
+
+
+
+
+
+
+
+
+ {`${config.value.SiteName} `}
+
+
+
+
+
+
+
+ {license.value.IsLicensed === 'true' && (
+
+
+
+ )}
+
+ {!MATTERMOST_BUNDLE_IDS.includes(DeviceInfo.getBundleId()) &&
+
+ }
+
+
+
+
+
+
+
+ ),
+ mobile: (
+
+ ),
+ }}
+ testID='about.notice_text'
+ />
+
+
+
+
+
+
+ {config.value.BuildHash}
+
+
+
+
+
+ {config.value.BuildHashEnterprise}
+
+
+
+
+
+
+ {config.value.BuildDate}
+
+
+
+
+
+ );
+};
+
+const getStyleSheet = makeStyleSheetFromTheme((theme) => {
+ return {
+ container: {
+ flex: 1,
+ },
+ scrollView: {
+ flex: 1,
+ backgroundColor: changeOpacity(theme.centerChannelColor, 0.06),
+ },
+ scrollViewContent: {
+ paddingBottom: 30,
+ },
+ logoContainer: {
+ alignItems: 'center',
+ flex: 1,
+ height: 200,
+ paddingVertical: 40,
+ },
+ infoContainer: {
+ flex: 1,
+ flexDirection: 'column',
+ paddingHorizontal: 20,
+ },
+ titleContainer: {
+ flex: 1,
+ marginBottom: 20,
+ },
+ title: {
+ fontSize: 22,
+ color: theme.centerChannelColor,
+ },
+ subtitle: {
+ color: changeOpacity(theme.centerChannelColor, 0.5),
+ fontSize: 19,
+ marginBottom: 15,
+ },
+ info: {
+ color: theme.centerChannelColor,
+ fontSize: 16,
+ lineHeight: 19,
+ },
+ licenseContainer: {
+ flex: 1,
+ flexDirection: 'row',
+ marginTop: 20,
+ },
+ noticeContainer: {
+ flex: 1,
+ flexDirection: 'column',
+ },
+ noticeLink: {
+ color: theme.linkColor,
+ fontSize: 11,
+ lineHeight: 13,
+ },
+ hashContainer: {
+ flex: 1,
+ flexDirection: 'column',
+ },
+ footerGroup: {
+ flex: 1,
+ },
+ footerTitleText: {
+ color: changeOpacity(theme.centerChannelColor, 0.5),
+ fontSize: 11,
+ fontWeight: '600',
+ lineHeight: 13,
+ },
+ footerText: {
+ color: changeOpacity(theme.centerChannelColor, 0.5),
+ fontSize: 11,
+ lineHeight: 13,
+ marginBottom: 10,
+ },
+ copyrightText: {
+ marginBottom: 0,
+ },
+ tosPrivacyContainer: {
+ flex: 1,
+ flexDirection: 'row',
+ marginBottom: 10,
+ },
+ };
+});
+
+export default withDatabase(withObservables([], ({database}: WithDatabaseArgs) => ({
+ config: database.collections.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG),
+ license: database.collections.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE),
+}))(ConnectedAbout));
+
diff --git a/app/screens/about/learn_more.tsx b/app/screens/about/learn_more.tsx
new file mode 100644
index 000000000..31632f6b1
--- /dev/null
+++ b/app/screens/about/learn_more.tsx
@@ -0,0 +1,75 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {Text, TouchableOpacity, View} from 'react-native';
+
+import Config from '@assets/config.json';
+import FormattedText from '@components/formatted_text';
+import {useTheme} from '@context/theme';
+import {t} from '@i18n';
+import {makeStyleSheetFromTheme} from '@utils/theme';
+
+import type SystemModel from '@typings/database/models/servers/system';
+
+type LearnMoreProps = {
+ config: SystemModel;
+ onHandleAboutEnterprise: () => void;
+ onHandleAboutTeam: () => void;
+};
+
+const LearnMore = ({config, onHandleAboutEnterprise, onHandleAboutTeam}: LearnMoreProps) => {
+ const theme = useTheme();
+ const style = getStyleSheet(theme);
+
+ let id = t('about.teamEditionLearn');
+ let defaultMessage = 'Join the Mattermost community at ';
+ let onPress = onHandleAboutTeam;
+ let url = Config.TeamEditionLearnURL;
+
+ if (config.value?.BuildEnterpriseReady === 'true') {
+ id = t('about.enterpriseEditionLearn');
+ defaultMessage = 'Learn more about Enterprise Edition at ';
+ onPress = onHandleAboutEnterprise;
+ url = Config.EELearnURL;
+ }
+
+ return (
+
+
+
+
+ {url}
+
+
+
+ );
+};
+
+const getStyleSheet = makeStyleSheetFromTheme((theme) => {
+ return {
+ learnContainer: {
+ flex: 1,
+ flexDirection: 'column',
+ marginVertical: 20,
+ },
+ learn: {
+ color: theme.centerChannelColor,
+ fontSize: 16,
+ },
+ learnLink: {
+ color: theme.linkColor,
+ fontSize: 16,
+ },
+ };
+});
+
+export default LearnMore;
diff --git a/app/screens/about/server_version.tsx b/app/screens/about/server_version.tsx
new file mode 100644
index 000000000..b27d4f3d9
--- /dev/null
+++ b/app/screens/about/server_version.tsx
@@ -0,0 +1,59 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+
+import FormattedText from '@components/formatted_text';
+import {useTheme} from '@context/theme';
+import {t} from '@i18n';
+import {makeStyleSheetFromTheme} from '@utils/theme';
+
+import type SystemModel from '@typings/database/models/servers/system';
+
+type ServerVersionProps = {
+ config: SystemModel;
+}
+
+const ServerVersion = ({config}: ServerVersionProps) => {
+ const buildNumber = config.value.BuildNumber;
+ const version = config.value.Version;
+ const theme = useTheme();
+ const style = getStyleSheet(theme);
+
+ let id = t('mobile.about.serverVersion');
+ let defaultMessage = 'Server Version: {version} (Build {number})';
+ let values = {
+ version,
+ number: buildNumber,
+ };
+
+ if (buildNumber === version) {
+ id = t('mobile.about.serverVersionNoBuild');
+ defaultMessage = 'Server Version: {version}';
+ values = {
+ version,
+ number: undefined,
+ };
+ }
+ return (
+
+ );
+};
+
+const getStyleSheet = makeStyleSheetFromTheme((theme) => {
+ return {
+ info: {
+ color: theme.centerChannelColor,
+ fontSize: 16,
+ lineHeight: 19,
+ },
+ };
+});
+
+export default ServerVersion;
diff --git a/app/screens/about/subtitle.tsx b/app/screens/about/subtitle.tsx
new file mode 100644
index 000000000..7d02f7267
--- /dev/null
+++ b/app/screens/about/subtitle.tsx
@@ -0,0 +1,49 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+
+import FormattedText from '@components/formatted_text';
+import {useTheme} from '@context/theme';
+import {t} from '@i18n';
+import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
+
+import type SystemModel from '@typings/database/models/servers/system';
+
+type SubtitleProps = {
+ config: SystemModel;
+}
+
+const Subtitle = ({config}: SubtitleProps) => {
+ const theme = useTheme();
+ const style = getStyleSheet(theme);
+
+ let id = t('about.teamEditionSt');
+ let defaultMessage = 'All your team communication in one place, instantly searchable and accessible anywhere.';
+
+ if (config.value.BuildEnterpriseReady === 'true') {
+ id = t('about.enterpriseEditionSt');
+ defaultMessage = 'Modern communication from behind your firewall.';
+ }
+
+ return (
+
+ );
+};
+
+const getStyleSheet = makeStyleSheetFromTheme((theme) => {
+ return {
+ subtitle: {
+ color: changeOpacity(theme.centerChannelColor, 0.5),
+ fontSize: 19,
+ marginBottom: 15,
+ },
+ };
+});
+
+export default Subtitle;
diff --git a/app/screens/about/title.tsx b/app/screens/about/title.tsx
new file mode 100644
index 000000000..1ca879848
--- /dev/null
+++ b/app/screens/about/title.tsx
@@ -0,0 +1,53 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import FormattedText from '@components/formatted_text';
+import React from 'react';
+
+import {useTheme} from '@context/theme';
+import {t} from '@i18n';
+import {makeStyleSheetFromTheme} from '@utils/theme';
+
+import type SystemModel from '@typings/database/models/servers/system';
+
+type TitleProps = {
+ config: SystemModel;
+ license: SystemModel;
+}
+
+const Title = ({config, license}: TitleProps) => {
+ const theme = useTheme();
+ const style = getStyleSheet(theme);
+
+ let id = t('about.teamEditiont0');
+ let defaultMessage = 'Team Edition';
+
+ if (config.value.BuildEnterpriseReady === 'true') {
+ id = t('about.teamEditiont1');
+ defaultMessage = 'Enterprise Edition';
+
+ if (license.value.IsLicensed === 'true') {
+ id = t('about.enterpriseEditione1');
+ defaultMessage = 'Enterprise Edition';
+ }
+ }
+ return (
+
+ );
+};
+
+const getStyleSheet = makeStyleSheetFromTheme((theme) => {
+ return {
+ title: {
+ fontSize: 22,
+ color: theme.centerChannelColor,
+ },
+ };
+});
+
+export default Title;
diff --git a/app/screens/about/tos_privacy.tsx b/app/screens/about/tos_privacy.tsx
new file mode 100644
index 000000000..567ea8739
--- /dev/null
+++ b/app/screens/about/tos_privacy.tsx
@@ -0,0 +1,73 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {Text} from 'react-native';
+
+import FormattedText from '@components/formatted_text';
+import {useTheme} from '@context/theme';
+import {t} from '@i18n';
+import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
+
+import type SystemModel from '@typings/database/models/servers/system';
+
+type TosPrivacyContainerProps = {
+ config: SystemModel;
+ onPressTOS: () => void;
+ onPressPrivacyPolicy: () => void;
+}
+
+const TosPrivacyContainer = ({config, onPressTOS, onPressPrivacyPolicy}: TosPrivacyContainerProps) => {
+ const hasTermsOfServiceLink = config.value?.TermsOfServiceLink;
+ const hasPrivacyPolicyLink = config.value?.PrivacyPolicyLink;
+ const theme = useTheme();
+ const style = getStyleSheet(theme);
+ return (
+ <>
+ {hasTermsOfServiceLink && (
+
+ )}
+ {hasTermsOfServiceLink && hasPrivacyPolicyLink && (
+
+ {' - '}
+
+ )}
+ {hasPrivacyPolicyLink && (
+
+ )}
+ >
+ );
+};
+
+const getStyleSheet = makeStyleSheetFromTheme((theme) => {
+ return {
+ noticeLink: {
+ color: theme.linkColor,
+ fontSize: 11,
+ lineHeight: 13,
+ },
+ footerText: {
+ color: changeOpacity(theme.centerChannelColor, 0.5),
+ fontSize: 11,
+ lineHeight: 13,
+ marginBottom: 10,
+ },
+ hyphenText: {
+ marginBottom: 0,
+ },
+ };
+});
+
+export default TosPrivacyContainer;
diff --git a/app/screens/channel/channel_nav_bar/channel_title/channel_guest_label/index.tsx b/app/screens/channel/channel_nav_bar/channel_title/channel_guest_label/index.tsx
index a4ebc2b81..e43656262 100644
--- a/app/screens/channel/channel_nav_bar/channel_title/channel_guest_label/index.tsx
+++ b/app/screens/channel/channel_nav_bar/channel_title/channel_guest_label/index.tsx
@@ -6,7 +6,7 @@ import {View} from 'react-native';
import FormattedText from '@components/formatted_text';
import {General} from '@constants';
-import {t} from '@utils/i18n';
+import {t} from '@i18n';
import {makeStyleSheetFromTheme} from '@utils/theme';
type ChannelGuestLabelProps = {
diff --git a/app/screens/channel/index.tsx b/app/screens/channel/index.tsx
index 60e3085a3..c1703b2a8 100644
--- a/app/screens/channel/index.tsx
+++ b/app/screens/channel/index.tsx
@@ -3,32 +3,32 @@
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
+import {goToScreen} from '@screens/navigation';
import React, {useMemo, useState} from 'react';
+import {useIntl} from 'react-intl';
import {Text, View, ScrollView} from 'react-native';
import {SafeAreaView} from 'react-native-safe-area-context';
import {logout} from '@actions/remote/session';
+import Markdown from '@components/markdown';
+import JumboEmoji from '@components/jumbo_emoji';
+import ProgressiveImage from '@components/progressive_image';
import ServerVersion from '@components/server_version';
import StatusBar from '@components/status_bar';
-import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
+import {Screens, Database} from '@constants';
import {useServerUrl} from '@context/server_url';
import {useTheme} from '@context/theme';
import {makeStyleSheetFromTheme} from '@utils/theme';
+import {getMarkdownBlockStyles, getMarkdownTextStyles} from '@utils/markdown';
import ChannelNavBar from './channel_nav_bar';
-
-import type SystemModel from '@typings/database/models/servers/system';
-import type {LaunchProps} from '@typings/launch';
-import type {WithDatabaseArgs} from '@typings/database/database';
-
import FailedChannels from './failed_channels';
import FailedTeams from './failed_teams';
-
-import Markdown from '@components/markdown';
-import {getMarkdownBlockStyles, getMarkdownTextStyles} from '@utils/markdown';
import md from './md.json';
-import ProgressiveImage from '@components/progressive_image';
-import JumboEmoji from '@components/jumbo_emoji';
+
+import type {WithDatabaseArgs} from '@typings/database/database';
+import type SystemModel from '@typings/database/models/servers/system';
+import type {LaunchProps} from '@typings/launch';
type ChannelProps = WithDatabaseArgs & LaunchProps & {
currentChannelId: SystemModel;
@@ -36,6 +36,7 @@ type ChannelProps = WithDatabaseArgs & LaunchProps & {
time?: number;
};
+const {MM_TABLES, SYSTEM_IDENTIFIERS} = Database;
const {SERVER: {SYSTEM}} = MM_TABLES;
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
@@ -69,6 +70,7 @@ const Channel = ({currentChannelId, currentTeamId, time}: ChannelProps) => {
//todo: https://mattermost.atlassian.net/browse/MM-37266
const theme = useTheme();
+ const intl = useIntl();
const styles = getStyleSheet(theme);
const serverUrl = useServerUrl();
@@ -77,6 +79,11 @@ const Channel = ({currentChannelId, currentTeamId, time}: ChannelProps) => {
logout(serverUrl!);
};
+ const goToAbout = () => {
+ const title = intl.formatMessage({id: 'about.title', defaultMessage: 'About {appTitle}'}, {appTitle: 'Mattermost'});
+ goToScreen(Screens.ABOUT, title);
+ };
+
const renderComponent = useMemo(() => {
if (!currentTeamId.value) {
return ;
@@ -140,6 +147,14 @@ const Channel = ({currentChannelId, currentTeamId, time}: ChannelProps) => {
{`Loaded in: ${time || 0}ms. Logout from ${serverUrl}`}
+
+
+ {'Go to About Screen'}
+
+
>
);
@@ -147,8 +162,9 @@ const Channel = ({currentChannelId, currentTeamId, time}: ChannelProps) => {
const [inViewport, setInViewport] = useState(false);
- setTimeout(async () => {
+ const viewPortTimer = setTimeout(async () => {
setInViewport(true);
+ clearTimeout(viewPortTimer);
}, 3000);
return (
diff --git a/app/screens/index.tsx b/app/screens/index.tsx
index 73b858807..e07ad9469 100644
--- a/app/screens/index.tsx
+++ b/app/screens/index.tsx
@@ -51,9 +51,9 @@ Navigation.setLazyComponentRegistrator((screenName) => {
let screen: any|undefined;
let extraStyles: StyleProp;
switch (screenName) {
- // case 'About':
- // screen = require('@screens/about').default;
- // break;
+ case 'About':
+ screen = withServerDatabase(require('@screens/about').default);
+ break;
// case 'AddReaction':
// screen = require('@screens/add_reaction').default;
// break;
diff --git a/app/screens/login/index.tsx b/app/screens/login/index.tsx
index 063ec336c..f657caa5c 100644
--- a/app/screens/login/index.tsx
+++ b/app/screens/login/index.tsx
@@ -26,8 +26,8 @@ import {FORGOT_PASSWORD, MFA} from '@constants/screens';
import FormattedText from '@components/formatted_text';
import {useManagedConfig} from '@mattermost/react-native-emm';
import {login} from '@actions/remote/session';
+import {t} from '@i18n';
import {goToScreen, resetToChannel} from '@screens/navigation';
-import {t} from '@utils/i18n';
import {preventDoubleTap} from '@utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
diff --git a/app/screens/mfa/index.tsx b/app/screens/mfa/index.tsx
index 1156f9fbb..043f9d163 100644
--- a/app/screens/mfa/index.tsx
+++ b/app/screens/mfa/index.tsx
@@ -19,7 +19,7 @@ import {SafeAreaView} from 'react-native-safe-area-context';
import ErrorText from '@components/error_text';
import FormattedText from '@components/formatted_text';
import {login} from '@actions/remote/session';
-import {t} from '@utils/i18n';
+import {t} from '@i18n';
import {preventDoubleTap} from '@utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
diff --git a/app/utils/draft/index.ts b/app/utils/draft/index.ts
index 9c1c64836..b08d4bbd2 100644
--- a/app/utils/draft/index.ts
+++ b/app/utils/draft/index.ts
@@ -6,7 +6,7 @@ import {Alert, AlertButton} from 'react-native';
import type {IntlShape} from 'react-intl';
-import {t} from '@utils/i18n';
+import {t} from '@i18n';
export function errorBadChannel(intl: IntlShape) {
const message = {
diff --git a/app/utils/i18n.ts b/app/utils/i18n.ts
deleted file mode 100644
index b8d23d715..000000000
--- a/app/utils/i18n.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-export function t(v: string) {
- return v;
-}
diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json
index ff0ac1e1b..90ccfaeb3 100644
--- a/assets/base/i18n/en.json
+++ b/assets/base/i18n/en.json
@@ -1,4 +1,15 @@
{
+ "about.date": "Build Date:",
+ "about.enterpriseEditione1": "Enterprise Edition",
+ "about.enterpriseEditionLearn": "Learn more about Enterprise Edition at ",
+ "about.enterpriseEditionSt": "Modern communication from behind your firewall.",
+ "about.hash": "Build Hash:",
+ "about.hashee": "EE Build Hash:",
+ "about.teamEditionLearn": "Join the Mattermost community at ",
+ "about.teamEditionSt": "All your team communication in one place, instantly searchable and accessible anywhere.",
+ "about.teamEditiont0": "Team Edition",
+ "about.teamEditiont1": "Enterprise Edition",
+ "about.title": "About {appTitle}",
"channel_header.directchannel.you": "{displayname} (you)",
"channel_loader.someone": "Someone",
"channel.channelHasGuests": "This channel has guests",
@@ -48,6 +59,12 @@
"login.username": "Username",
"login.userNotFound": "We couldn't find an account matching your login credentials.",
"mobile.about.appVersion": "App Version: {version} (Build {number})",
+ "mobile.about.copyright": "Copyright 2015-{currentYear} Mattermost, Inc. All rights reserved",
+ "mobile.about.database": "Database: {type}",
+ "mobile.about.licensed": "Licensed to: {company}",
+ "mobile.about.powered_by": "{site} is powered by Mattermost",
+ "mobile.about.serverVersion": "Server Version: {version} (Build {number})",
+ "mobile.about.serverVersionNoBuild": "Server Version: {version}",
"mobile.components.select_server_view.connect": "Connect",
"mobile.components.select_server_view.connecting": "Connecting...",
"mobile.components.select_server_view.enterServerUrl": "Enter Server URL",
@@ -74,6 +91,9 @@
"mobile.markdown.image.too_large": "Image exceeds max dimensions of {maxWidth} by {maxHeight}:",
"mobile.markdown.link.copy_url": "Copy URL",
"mobile.mention.copy_mention": "Copy Mention",
+ "mobile.notice_mobile_link": "mobile apps",
+ "mobile.notice_platform_link": "server",
+ "mobile.notice_text": "Mattermost is made possible by the open source software used in our {platform} and {mobile}.",
"mobile.oauth.failed_to_login": "Your login attempt failed. Please try again.",
"mobile.oauth.failed_to_open_link": "The link failed to open. Please try again.",
"mobile.oauth.failed_to_open_link_no_browser": "The link failed to open. Please verify if a browser is installed in the current space.",
@@ -82,6 +102,7 @@
"mobile.oauth.switch_to_browser": "Please use your browser to complete the login",
"mobile.oauth.try_again": "Try again",
"mobile.post.cancel": "Cancel",
+ "mobile.privacy_link": "Privacy Policy",
"mobile.push_notification_reply.button": "Send",
"mobile.push_notification_reply.placeholder": "Write a reply...",
"mobile.push_notification_reply.title": "Reply",
@@ -107,6 +128,7 @@
"mobile.server_url.empty": "Please enter a valid server URL",
"mobile.server_url.invalid_format": "URL must start with http:// or https://",
"mobile.session_expired": "Session Expired: Please log in to continue receiving notifications. Sessions for {siteName} are configured to expire every {daysCount, number} {daysCount, plural, one {day} other {days}}.",
+ "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",
diff --git a/babel.config.js b/babel.config.js
index 2b647a29a..90566e9c7 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -21,7 +21,7 @@ module.exports = {
alias: {
'@actions': './app/actions',
'@app': './app/',
- '@assets': './dist/assets',
+ '@assets': './dist/assets/',
'@client': './app/client',
'@components': './app/components',
'@constants': './app/constants',
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 5edb4a92c..f467a3c93 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -710,7 +710,7 @@ SPEC CHECKSUMS:
EXFileSystem: 0a04aba8da751b9ac954065911bcf166503f8267
ExpoModulesCore: 2734852616127a6c1fc23012197890a6f3763dc7
FBLazyVector: e686045572151edef46010a6f819ade377dfeb4b
- FBReactNativeSpec: cef0cc6d50abc92e8cf52f140aa22b5371cfec0b
+ FBReactNativeSpec: d35931295aacfe996e833c01a3701d4aa7a80cb4
glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62
jail-monkey: 07b83767601a373db876e939b8dbf3f5eb15f073
libwebp: e90b9c01d99205d03b6bb8f2c8c415e5a4ef66f0