Gekidou about screen (#5591)

* Added about screen

* Remove TS error

* Needs clean up

* Testing login flow

* Converted About screen to functional component

* Improvements

* Sort imports

* Prevents double tapping

* Apply suggestions from code review

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>

* Code clean up

* Adding translation keys

* Added some keys

* Updated AppVersion component

* Missed translation key

Co-authored-by: Avinash Lingaloo <>
Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
Avinash Lingaloo 2021-08-05 08:48:36 +04:00 committed by GitHub
parent 7c5b3a1574
commit 0ef1dd44ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 742 additions and 38 deletions

View file

@ -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 = (
<FormattedText
id={t('mobile.about.appVersion')}
defaultMessage='App Version: {version} (Build {number})'
style={StyleSheet.flatten([style.version, textStyle])}
values={{
version: DeviceInfo.getVersion(),
number: DeviceInfo.getBuildNumber(),
}}
/>
);
if (!isWrapped) {
return appVersion;
}
return (
<View pointerEvents='none'>
<View style={style.info}>
<FormattedText
id='mobile.about.appVersion'
defaultMessage='App Version: {version} (Build {number})'
style={style.version}
values={{
version: DeviceInfo.getVersion(),
number: DeviceInfo.getBuildNumber(),
}}
/>
{appVersion}
</View>
</View>
);

View file

@ -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,

347
app/screens/about/index.tsx Normal file
View file

@ -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 (
<SafeAreaView
edges={['left', 'right']}
style={style.container}
testID='about.screen'
>
<StatusBar theme={theme}/>
<ScrollView
style={style.scrollView}
contentContainerStyle={style.scrollViewContent}
testID='about.scroll_view'
>
<View style={style.logoContainer}>
<CompassIcon
name='mattermost'
color={theme.centerChannelColor}
size={120}
testID='about.logo'
/>
</View>
<View style={style.infoContainer}>
<View style={style.titleContainer}>
<Text
style={style.title}
testID='about.site_name'
>
{`${config.value.SiteName} `}
</Text>
<Title
config={config}
license={license}
/>
</View>
<Subtitle config={config}/>
<AppVersion
isWrapped={false}
textStyle={style.info}
/>
<ServerVersion config={config}/>
<FormattedText
id={t('mobile.about.database')}
defaultMessage='Database: {type}'
style={style.info}
values={{
type: config.value.SQLDriverName,
}}
testID='about.database'
/>
{license.value.IsLicensed === 'true' && (
<View style={style.licenseContainer}>
<FormattedText
id={t('mobile.about.licensed')}
defaultMessage='Licensed to: {company}'
style={style.info}
values={{
company: license.value.Company,
}}
testID='about.licensee'
/>
</View>
)}
<LearnMore
config={config}
onHandleAboutEnterprise={handleAboutEnterprise}
onHandleAboutTeam={handleAboutTeam}
/>
{!MATTERMOST_BUNDLE_IDS.includes(DeviceInfo.getBundleId()) &&
<FormattedText
id={t('mobile.about.powered_by')}
defaultMessage='{site} is powered by Mattermost'
style={style.footerText}
values={{
site: config.value.SiteName,
}}
testID='about.powered_by'
/>
}
<FormattedText
id={t('mobile.about.copyright')}
defaultMessage='Copyright 2015-{currentYear} Mattermost, Inc. All rights reserved'
style={[style.footerText, style.copyrightText]}
values={{
currentYear: new Date().getFullYear(),
}}
testID='about.copyright'
/>
<View style={style.tosPrivacyContainer}>
<TosPrivacyContainer
config={config}
onPressTOS={handleTermsOfService}
onPressPrivacyPolicy={handlePrivacyPolicy}
/>
</View>
<View style={style.noticeContainer}>
<View style={style.footerGroup}>
<FormattedText
id={t('mobile.notice_text')}
defaultMessage='Mattermost is made possible by the open source software used in our {platform} and {mobile}.'
style={style.footerText}
values={{
platform: (
<FormattedText
id={t('mobile.notice_platform_link')}
defaultMessage='server'
style={style.noticeLink}
onPress={handlePlatformNotice}
/>
),
mobile: (
<FormattedText
id={t('mobile.notice_mobile_link')}
defaultMessage='mobile apps'
style={[style.noticeLink, {marginLeft: 5}]}
onPress={handleMobileNotice}
/>
),
}}
testID='about.notice_text'
/>
</View>
</View>
<View style={style.hashContainer}>
<View style={style.footerGroup}>
<FormattedText
id={t('about.hash')}
defaultMessage='Build Hash:'
style={style.footerTitleText}
testID='about.build_hash.title'
/>
<Text
style={style.footerText}
testID='about.build_hash.value'
>
{config.value.BuildHash}
</Text>
</View>
<View style={style.footerGroup}>
<FormattedText
id={t('about.hashee')}
defaultMessage='EE Build Hash:'
style={style.footerTitleText}
testID='about.build_hash_enterprise.title'
/>
<Text
style={style.footerText}
testID='about.build_hash_enterprise.value'
>
{config.value.BuildHashEnterprise}
</Text>
</View>
</View>
<View style={style.footerGroup}>
<FormattedText
id={t('about.date')}
defaultMessage='Build Date:'
style={style.footerTitleText}
testID='about.build_date.title'
/>
<Text
style={style.footerText}
testID='about.build_date.value'
>
{config.value.BuildDate}
</Text>
</View>
</View>
</ScrollView>
</SafeAreaView>
);
};
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));

View file

@ -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 (
<View style={style.learnContainer}>
<FormattedText
id={id}
defaultMessage={defaultMessage}
style={style.learn}
testID='about.learn_more'
/>
<TouchableOpacity onPress={onPress}>
<Text
style={style.learnLink}
testID='about.learn_more.url'
>
{url}
</Text>
</TouchableOpacity>
</View>
);
};
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;

View file

@ -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 (
<FormattedText
id={id}
defaultMessage={defaultMessage}
style={style.info}
values={values}
testID='about.server_version'
/>
);
};
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
info: {
color: theme.centerChannelColor,
fontSize: 16,
lineHeight: 19,
},
};
});
export default ServerVersion;

View file

@ -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 (
<FormattedText
id={id}
defaultMessage={defaultMessage}
style={style.subtitle}
testID='about.subtitle'
/>
);
};
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
subtitle: {
color: changeOpacity(theme.centerChannelColor, 0.5),
fontSize: 19,
marginBottom: 15,
},
};
});
export default Subtitle;

View file

@ -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 (
<FormattedText
id={id}
defaultMessage={defaultMessage}
style={style.title}
testID='about.title'
/>
);
};
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
title: {
fontSize: 22,
color: theme.centerChannelColor,
},
};
});
export default Title;

View file

@ -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 && (
<FormattedText
id={t('mobile.tos_link')}
defaultMessage='Terms of Service'
style={style.noticeLink}
onPress={onPressTOS}
testID='about.terms_of_service'
/>
)}
{hasTermsOfServiceLink && hasPrivacyPolicyLink && (
<Text style={[style.footerText, style.hyphenText]}>
{' - '}
</Text>
)}
{hasPrivacyPolicyLink && (
<FormattedText
id={t('mobile.privacy_link')}
defaultMessage='Privacy Policy'
style={style.noticeLink}
onPress={onPressPrivacyPolicy}
testID='about.privacy_policy'
/>
)}
</>
);
};
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;

View file

@ -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 = {

View file

@ -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 <FailedTeams/>;
@ -140,6 +147,14 @@ const Channel = ({currentChannelId, currentTeamId, time}: ChannelProps) => {
{`Loaded in: ${time || 0}ms. Logout from ${serverUrl}`}
</Text>
</View>
<View style={styles.sectionContainer}>
<Text
onPress={goToAbout}
style={styles.sectionTitle}
>
{'Go to About Screen'}
</Text>
</View>
</ScrollView>
</>
);
@ -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 (

View file

@ -51,9 +51,9 @@ Navigation.setLazyComponentRegistrator((screenName) => {
let screen: any|undefined;
let extraStyles: StyleProp<ViewStyle>;
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;

View file

@ -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';

View file

@ -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';

View file

@ -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 = {

View file

@ -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;
}

View file

@ -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",

View file

@ -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',

View file

@ -710,7 +710,7 @@ SPEC CHECKSUMS:
EXFileSystem: 0a04aba8da751b9ac954065911bcf166503f8267
ExpoModulesCore: 2734852616127a6c1fc23012197890a6f3763dc7
FBLazyVector: e686045572151edef46010a6f819ade377dfeb4b
FBReactNativeSpec: cef0cc6d50abc92e8cf52f140aa22b5371cfec0b
FBReactNativeSpec: d35931295aacfe996e833c01a3701d4aa7a80cb4
glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62
jail-monkey: 07b83767601a373db876e939b8dbf3f5eb15f073
libwebp: e90b9c01d99205d03b6bb8f2c8c415e5a4ef66f0