diff --git a/app/actions/navigation/index.js b/app/actions/navigation/index.js index 963552fc0..e2255f461 100644 --- a/app/actions/navigation/index.js +++ b/app/actions/navigation/index.js @@ -30,6 +30,15 @@ export function goBack() { }; } +export function goToAbout() { + return async (dispatch, getState) => { + dispatch({ + type: NavigationTypes.NAVIGATION_PUSH, + route: Routes.About + }, getState); + }; +} + export function goToAccountNotifications() { return async (dispatch, getState) => { dispatch({ diff --git a/app/navigation/routes.js b/app/navigation/routes.js index d710c0286..1cf6a01d5 100644 --- a/app/navigation/routes.js +++ b/app/navigation/routes.js @@ -2,6 +2,7 @@ // See License.txt for license information. import { + About, AccountNotifications, AccountSettings, ChannelView, @@ -36,8 +37,16 @@ export const RouteTransitions = keyMirror({ }); export const Routes = { + About: { + key: 'About', + transition: RouteTransitions.Horizontal, + component: About, + navigationProps: { + title: {id: 'about.titles', defaultMessage: 'About Mattermost'} + } + }, AccountNotifications: { - key: 'AccountNotifications', + key: 'About', transition: RouteTransitions.Horizontal, component: AccountNotifications, navigationProps: { diff --git a/app/scenes/about/about.js b/app/scenes/about/about.js new file mode 100644 index 000000000..ae463223a --- /dev/null +++ b/app/scenes/about/about.js @@ -0,0 +1,321 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import React, {PropTypes, PureComponent} from 'react'; +import { + Linking, + ScrollView, + StyleSheet, + Text, + TouchableOpacity, + View +} from 'react-native'; +import DeviceInfo from 'react-native-device-info'; + +import FormattedText from 'app/components/formatted_text'; +import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme'; + +import MattermostIcon from 'app/components/mattermost_icon'; + +export default class About extends PureComponent { + static propTypes = { + config: PropTypes.object.isRequired, + license: PropTypes.object.isRequired, + theme: PropTypes.object.isRequired + }; + + handleAboutTeam = () => { + Linking.openURL('http://www.mattermost.org/'); + }; + + handleAboutEnterprise = () => { + Linking.openURL('http://about.mattermost.com/'); + }; + + render() { + const {theme, config, license} = this.props; + const style = getStyleSheet(theme); + + let title = ( + + ); + + let subTitle = ( + + ); + + let learnMore = ( + + + + + {'mattermost.org'} + + + + ); + + let licensee; + if (config.BuildEnterpriseReady === 'true') { + title = ( + + ); + + subTitle = ( + + ); + + learnMore = ( + + + + + {'about.mattermost.com'} + + + + ); + + if (license.IsLicensed === 'true') { + title = ( + + ); + + licensee = ( + + + + {'\u00a0' + license.Company} + + + ); + } + } + + let serverVersion; + if (config.BuildNumber === config.Version) { + serverVersion = ( + + ); + } else { + serverVersion = ( + + ); + } + + return ( + + + + + + + + + {'Mattermost '} + + {title} + + {subTitle} + + {serverVersion} + + {licensee} + {learnMore} + + + + + + {'\u00a0' + config.BuildHash} + + + + + + {'\u00a0' + config.BuildHashEnterprise} + + + + + + + {'\u00a0' + config.BuildDate} + + + + + + ); + } +} + +const getStyleSheet = makeStyleSheetFromTheme((theme) => { + return StyleSheet.create({ + wrapper: { + flex: 1, + backgroundColor: theme.centerChannelBg + }, + scrollView: { + flex: 1, + backgroundColor: changeOpacity(theme.centerChannelColor, 0.03) + }, + scrollViewContent: { + paddingBottom: 30 + }, + logoContainer: { + alignItems: 'center', + flex: 1, + height: 200, + paddingVertical: 40 + }, + infoContainer: { + flex: 1, + flexDirection: 'column', + paddingHorizontal: 20 + }, + titleContainer: { + flex: 1, + flexDirection: 'row', + marginBottom: 20 + }, + title: { + fontSize: 22, + color: theme.centerChannelColor + }, + subtitle: { + color: changeOpacity(theme.centerChannelColor, 0.5), + fontSize: 19, + marginBottom: 15 + }, + learnContainer: { + flex: 1, + flexDirection: 'column', + marginVertical: 20 + }, + learn: { + color: theme.centerChannelColor, + fontSize: 16 + }, + learnLink: { + color: theme.linkColor, + fontSize: 16 + }, + info: { + color: theme.centerChannelColor, + fontSize: 16, + lineHeight: 19 + }, + licenseContainer: { + flex: 1, + flexDirection: 'row', + marginVertical: 20 + }, + hashContainer: { + flex: 1, + flexDirection: 'column', + marginVertical: 15 + }, + footerGroup: { + flex: 1, + flexDirection: 'row' + }, + footerText: { + color: changeOpacity(theme.centerChannelColor, 0.5), + fontSize: 11, + lineHeight: 13 + } + }); +}); diff --git a/app/scenes/about/index.js b/app/scenes/about/index.js new file mode 100644 index 000000000..a51a41175 --- /dev/null +++ b/app/scenes/about/index.js @@ -0,0 +1,19 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import {getTheme} from 'app/selectors/preferences'; +import navigationSceneConnect from 'app/scenes/navigationSceneConnect'; + +import About from './about'; + +function mapStateToProps(state) { + const {config, license} = state.entities.general; + + return { + config, + license, + theme: getTheme(state) + }; +} + +export default navigationSceneConnect(mapStateToProps)(About); diff --git a/app/scenes/index.js b/app/scenes/index.js index 2626e645d..e29902e96 100644 --- a/app/scenes/index.js +++ b/app/scenes/index.js @@ -1,6 +1,7 @@ // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. +import About from './about'; import AccountNotifications from './account_notifications'; import AccountSettings from './account_settings'; import Channel from './channel'; @@ -28,6 +29,7 @@ import UserProfile from './user_profile'; import Saml from './saml'; module.exports = { + About, AccountNotifications, AccountSettings, ChannelView: Channel, // Special case the name for this one to avoid ambiguity diff --git a/app/scenes/settings/index.js b/app/scenes/settings/index.js index 6640623e9..dc32d04ce 100644 --- a/app/scenes/settings/index.js +++ b/app/scenes/settings/index.js @@ -6,6 +6,7 @@ import {bindActionCreators} from 'redux'; import { closeDrawers, goBack, + goToAbout, goToAccountSettings, goToSelectTeam } from 'app/actions/navigation'; @@ -35,6 +36,7 @@ function mapDispatchToProps(dispatch) { actions: bindActionCreators({ closeDrawers, goBack, + goToAbout, goToAccountSettings, goToSelectTeam, clearErrors, diff --git a/app/scenes/settings/settings.js b/app/scenes/settings/settings.js index bcf8ffb21..198046915 100644 --- a/app/scenes/settings/settings.js +++ b/app/scenes/settings/settings.js @@ -21,6 +21,7 @@ export default class Settings extends PureComponent { actions: PropTypes.shape({ closeDrawers: PropTypes.func.isRequired, goBack: PropTypes.func.isRequired, + goToAbout: PropTypes.func.isRequired, goToAccountSettings: PropTypes.func.isRequired, goToSelectTeam: PropTypes.func.isRequired, clearErrors: PropTypes.func.isRequired, @@ -116,6 +117,15 @@ export default class Settings extends PureComponent { iconName='warning' iconType='material' onPress={this.openErrorEmail} + separator={true} + theme={theme} + /> + diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json index 07dfd1326..352d66633 100644 --- a/assets/base/i18n/en.json +++ b/assets/base/i18n/en.json @@ -16,6 +16,11 @@ "about.teamEditiont1": "Enterprise Edition", "about.title": "About Mattermost", "about.version": "Version:", + "mobile.about.appVersion": "App Version: {version} (Build {number})", + "mobile.about.serverVersion": "Server Version: {version} (Build {number})", + "mobile.about.serverVersionNoBuild": "Server Version: {version}", + "mobile.about.database": "Database: {type}", + "mobile.about.copyright": "Copyright 2015-{currentYear} Mattermost, Inc. All rights reserved", "access_history.title": "Access History", "activity_log.activeSessions": "Active Sessions", "activity_log.browser": "Browser: {browser}", @@ -1644,14 +1649,14 @@ "mobile.account_notifications.threads_start": "Threads that I start", "mobile.account_notifications.threads_start_participate": "Threads that I start or participate in", "mobile.channel_info.alertMessageDeleteChannel": "Are you sure you want to delete the {term} with {name}?", - "mobile.channel_info.alertMessageLeaveChannel": "Are you sure you want to leave the {term} with {name}?", + "mobile.channel_info.alertMessageLeaveChannel": "Are you sure you want to leave the {term} {name}?", "mobile.channel_info.alertNo": "No", "mobile.channel_info.alertTitleDeleteChannel": "Delete {term}", "mobile.channel_info.alertTitleLeaveChannel": "Leave {term}", "mobile.channel_info.alertYes": "Yes", "mobile.channel_info.privateChannel": "Private Channel", "mobile.channel_info.publicChannel": "Public Channel", - "mobile.channel_list.alertMessageLeaveChannel": "Are you sure you want to leave the {term} with {name}?", + "mobile.channel_list.alertMessageLeaveChannel": "Are you sure you want to leave the {term} {name}?", "mobile.channel_list.alertNo": "No", "mobile.channel_list.alertTitleLeaveChannel": "Leave {term}", "mobile.channel_list.alertYes": "Yes", diff --git a/fastlane/Matchfile b/fastlane/Matchfile new file mode 100644 index 000000000..4f3f56994 --- /dev/null +++ b/fastlane/Matchfile @@ -0,0 +1,9 @@ +git_url "git@github.com:mattermost/mattermost-mobile-private.git" + +type "development" # The default type, can be: appstore, adhoc, enterprise or development + +# app_identifier ["tools.fastlane.app", "tools.fastlane.app2"] +# username "user@fastlane.tools" # Your Apple Developer Portal username + +# For all available options run `fastlane match --help` +# Remove the # in the beginning of the line to enable the other options diff --git a/ios/Mattermost.xcodeproj/project.pbxproj b/ios/Mattermost.xcodeproj/project.pbxproj index 79bc9373f..735de6655 100644 --- a/ios/Mattermost.xcodeproj/project.pbxproj +++ b/ios/Mattermost.xcodeproj/project.pbxproj @@ -766,7 +766,7 @@ }; 13B07F861A680F5B00A75B9A = { DevelopmentTeam = UQ8HT4Q2XM; - ProvisioningStyle = Automatic; + ProvisioningStyle = Manual; SystemCapabilities = { com.apple.Push = { enabled = 1; @@ -1275,9 +1275,10 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Mattermost/Mattermost.entitlements; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CURRENT_PROJECT_VERSION = 19; DEAD_CODE_STRIPPING = NO; + DEVELOPMENT_TEAM = UQ8HT4Q2XM; HEADER_SEARCH_PATHS = ( "$(SRCROOT)/../node_modules/react-native/Libraries/PushNotificationIOS/**", "$(SRCROOT)/../node_modules/react-native-orientation/iOS/RCTOrientation/**", @@ -1291,8 +1292,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.mattermost.react.native; PRODUCT_NAME = Mattermost; - PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = ""; + PROVISIONING_PROFILE = "49d041fa-5540-475b-90c7-4cc99954c615"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc com.mattermost.react.native"; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -1302,9 +1303,10 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Mattermost/Mattermost.entitlements; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CURRENT_PROJECT_VERSION = 19; DEAD_CODE_STRIPPING = NO; + DEVELOPMENT_TEAM = UQ8HT4Q2XM; HEADER_SEARCH_PATHS = "$(SRCROOT)/../node_modules/react-native/Libraries/PushNotificationIOS/**"; INFOPLIST_FILE = Mattermost/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1315,8 +1317,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.mattermost.react.native; PRODUCT_NAME = Mattermost; - PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = ""; + PROVISIONING_PROFILE = "4d7f7521-3286-4c38-b9c0-e1055f5a0ff6"; + PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.mattermost.react.native"; VERSIONING_SYSTEM = "apple-generic"; }; name = Release;