diff --git a/android/app/build.gradle b/android/app/build.gradle index a49976081..f98de3ab3 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -144,6 +144,7 @@ android { } dependencies { + compile project(':react-native-orientation') compile project(':react-native-bottom-sheet') compile project(':react-native-push-notification') compile ('com.google.android.gms:play-services-gcm:9.4.0') { diff --git a/android/app/src/main/java/com/mattermost/MainActivity.java b/android/app/src/main/java/com/mattermost/MainActivity.java index ded879bcc..63fb8478f 100644 --- a/android/app/src/main/java/com/mattermost/MainActivity.java +++ b/android/app/src/main/java/com/mattermost/MainActivity.java @@ -1,9 +1,12 @@ package com.mattermost; import com.facebook.react.ReactActivity; +import com.github.yamill.orientation.OrientationPackage; import com.psykar.cookiemanager.CookieManagerPackage; import com.BV.LinearGradient.LinearGradientPackage; import com.reactnative.ivpusic.imagepicker.PickerPackage; +import android.content.Intent; +import android.content.res.Configuration; public class MainActivity extends ReactActivity { @@ -15,4 +18,12 @@ public class MainActivity extends ReactActivity { protected String getMainComponentName() { return "Mattermost"; } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + Intent intent = new Intent("onConfigurationChanged"); + intent.putExtra("newConfig", newConfig); + this.sendBroadcast(intent); + } } diff --git a/android/app/src/main/java/com/mattermost/MainApplication.java b/android/app/src/main/java/com/mattermost/MainApplication.java index 3dd054318..3b55bf2b1 100644 --- a/android/app/src/main/java/com/mattermost/MainApplication.java +++ b/android/app/src/main/java/com/mattermost/MainApplication.java @@ -17,6 +17,7 @@ import com.facebook.react.shell.MainReactPackage; import com.facebook.soloader.SoLoader; import com.BV.LinearGradient.LinearGradientPackage; import com.reactnative.ivpusic.imagepicker.PickerPackage; +import com.github.yamill.orientation.OrientationPackage; import java.util.Arrays; import java.util.List; @@ -40,7 +41,8 @@ public class MainApplication extends Application implements ReactApplication { new VectorIconsPackage(), new RNSvgPackage(), new LinearGradientPackage(), - new PickerPackage() + new PickerPackage(), + new OrientationPackage() ); } }; diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 14dccca6d..ca34c2ca4 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -1,4 +1,5 @@ + Mattermost diff --git a/android/settings.gradle b/android/settings.gradle index 4e3aeb7c7..62a6eb648 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -11,6 +11,8 @@ include ':react-native-vector-icons' project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android') include ':app' +include ':react-native-orientation' +project(':react-native-orientation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-orientation/android') include ':react-native-linear-gradient' project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android') include ':react-native-image-crop-picker' diff --git a/app/components/custom_list/index.js b/app/components/custom_list/index.js index 5d891d39b..7d2e1288a 100644 --- a/app/components/custom_list/index.js +++ b/app/components/custom_list/index.js @@ -102,8 +102,10 @@ export default class CustomList extends PureComponent { renderSectionHeader = (sectionData, sectionId) => { const style = getStyleFromTheme(this.props.theme); return ( - - {sectionId} + + + {sectionId} + ); }; @@ -205,13 +207,16 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => { color: changeOpacity(theme.centerChannelColor, 0.6) }, sectionContainer: { - backgroundColor: theme.sidebarHeaderBg, + backgroundColor: changeOpacity(theme.centerChannelColor, 0.07), paddingLeft: 10, paddingVertical: 2 }, + sectionWrapper: { + backgroundColor: theme.centerChannelBg + }, sectionText: { fontWeight: '600', - color: theme.sidebarHeaderTextColor + color: theme.centerChannelColor }, separator: { height: 1, diff --git a/app/components/file_upload_preview/file_upload_preview.js b/app/components/file_upload_preview/file_upload_preview.js index 74e6322c2..90a9c64e9 100644 --- a/app/components/file_upload_preview/file_upload_preview.js +++ b/app/components/file_upload_preview/file_upload_preview.js @@ -28,6 +28,7 @@ export default class FileUploadPreview extends PureComponent { createPostRequestStatus: PropTypes.string.isRequired, fetchCache: PropTypes.object.isRequired, files: PropTypes.array.isRequired, + inputHeight: PropTypes.number.isRequired, rootId: PropTypes.string, uploadFileRequestStatus: PropTypes.string.isRequired }; @@ -75,7 +76,7 @@ export default class FileUploadPreview extends PureComponent { {this.buildFilePreviews()} @@ -92,25 +93,12 @@ const style = StyleSheet.create({ }, container: { backgroundColor: 'rgba(0, 0, 0, 0.5)', - bottom: 40, height: deviceHeight, left: 0, + bottom: 0, position: 'absolute', width: '100%' }, - loader: { - backgroundColor: 'rgba(0, 0, 0, 0.7)', - height: 124, - width: '100%', - alignItems: 'center', - justifyContent: 'center', - bottom: 0, - position: 'absolute' - }, - loaderText: { - fontSize: 24, - color: '#fff' - }, preview: { alignItems: 'center', height: 115, diff --git a/app/components/post_textbox/post_textbox.js b/app/components/post_textbox/post_textbox.js index 2724aea02..15efe390f 100644 --- a/app/components/post_textbox/post_textbox.js +++ b/app/components/post_textbox/post_textbox.js @@ -229,6 +229,7 @@ export default class PostTextbox extends PureComponent { const {theme} = this.props; const style = getStyleSheet(theme); + const textInputHeight = Math.min(this.state.contentHeight, MAX_CONTENT_HEIGHT); let placeholder; if (this.props.rootId) { @@ -251,6 +252,7 @@ export default class PostTextbox extends PureComponent { { marginTop: 10, borderTopWidth: 1, borderBottomWidth: 1, - borderTopColor: changeOpacity(theme.newMessageSeparator, 0.5), - borderBottomColor: changeOpacity(theme.newMessageSeparator, 0.5), + borderTopColor: changeOpacity(theme.centerChannelColor, 0.1), + borderBottomColor: changeOpacity(theme.centerChannelColor, 0.1), backgroundColor: theme.centerChannelBg }, input: { diff --git a/app/scenes/image_preview/image_preview.js b/app/scenes/image_preview/image_preview.js index 32e5155a2..1f0b3a791 100644 --- a/app/scenes/image_preview/image_preview.js +++ b/app/scenes/image_preview/image_preview.js @@ -17,6 +17,7 @@ import { } from 'react-native'; import Icon from 'react-native-vector-icons/Ionicons'; import LinearGradient from 'react-native-linear-gradient'; +import Orientation from 'react-native-orientation'; import FileAttachmentIcon from 'app/components/file_attachment_list/file_attachment_icon'; import FileAttachmentPreview from 'app/components/file_attachment_list/file_attachment_preview'; @@ -76,6 +77,8 @@ export default class ImagePreview extends PureComponent { } componentDidMount() { + Orientation.unlockAllOrientations(); + // TODO: Use contentOffset on Android once PR is merged // This is a hack until this PR gets merged: https://github.com/facebook/react-native/pull/12502 // On Android there is a render animation for scrollViews. In order for scrollTo to work @@ -95,6 +98,10 @@ export default class ImagePreview extends PureComponent { } } + componentWillUnmount() { + Orientation.lockToPortrait(); + } + onMoveShouldSetPanResponderCapture = (evt, gestureState) => { const {dx, dy} = gestureState; return (Math.abs(dy) > DRAG_VERTICAL_THRESHOLD_START && dx < DRAG_HORIZONTAL_THRESHOLD); diff --git a/app/scenes/root/root.js b/app/scenes/root/root.js index 30504263e..2c1a4590a 100644 --- a/app/scenes/root/root.js +++ b/app/scenes/root/root.js @@ -3,6 +3,7 @@ import React, {PropTypes, PureComponent} from 'react'; import {AsyncStorage} from 'react-native'; +import Orientation from 'react-native-orientation'; import Loading from 'app/components/loading'; import {RequestStatus} from 'mattermost-redux/constants'; @@ -27,6 +28,8 @@ export default class Root extends PureComponent { }; componentDidMount() { + Orientation.lockToPortrait(); + // Any initialization logic for navigation, setting up the client, etc should go here this.init(); } diff --git a/ios/Mattermost.xcodeproj/project.pbxproj b/ios/Mattermost.xcodeproj/project.pbxproj index df3796cc3..79bc9373f 100644 --- a/ios/Mattermost.xcodeproj/project.pbxproj +++ b/ios/Mattermost.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; 1BCA51319AC6442991C6A208 /* Zocial.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0A091BF1A3D04650AD306A0D /* Zocial.ttf */; }; 2B4C9B708010475DA575B81D /* SimpleLineIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F1F071EE85494E269A50AE88 /* SimpleLineIcons.ttf */; }; + 374634801E8480C2005E1244 /* libRCTOrientation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 374634671E848085005E1244 /* libRCTOrientation.a */; }; 37DA4BA61E6F55D3002B058E /* RSKImageCropper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37DA4BA51E6F55D3002B058E /* RSKImageCropper.framework */; }; 37DA4BA71E6F55D3002B058E /* RSKImageCropper.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 37DA4BA51E6F55D3002B058E /* RSKImageCropper.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 37DA4BA91E6F55D3002B058E /* QBImagePicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37DA4BA81E6F55D3002B058E /* QBImagePicker.framework */; }; @@ -113,6 +114,13 @@ remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; remoteInfo = React; }; + 374634661E848085005E1244 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5C3B95629BA74FB3A8377CB7 /* RCTOrientation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTOrientation; + }; 37D8FEC11E80B5230091F3BD /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 7DCC3D826CE640AF8F491692 /* BVLinearGradient.xcodeproj */; @@ -359,6 +367,7 @@ 37DA4BA81E6F55D3002B058E /* QBImagePicker.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = QBImagePicker.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 51F5A483EA9F4A9A87ACFB59 /* Foundation.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Foundation.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Foundation.ttf"; sourceTree = ""; }; 59954D479A89488091EB588F /* RNSearchBar.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNSearchBar.xcodeproj; path = "../node_modules/react-native-search-bar/RNSearchBar.xcodeproj"; sourceTree = ""; }; + 5C3B95629BA74FB3A8377CB7 /* RCTOrientation.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTOrientation.xcodeproj; path = "../node_modules/react-native-orientation/iOS/RCTOrientation.xcodeproj"; sourceTree = ""; }; 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; 7DCC3D826CE640AF8F491692 /* BVLinearGradient.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = BVLinearGradient.xcodeproj; path = "../node_modules/react-native-linear-gradient/BVLinearGradient.xcodeproj"; sourceTree = ""; }; @@ -401,6 +410,7 @@ 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */, 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, + 374634801E8480C2005E1244 /* libRCTOrientation.a in Frameworks */, 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, 7F63D2841E6C9585001FAE12 /* libRCTPushNotification.a in Frameworks */, @@ -540,6 +550,14 @@ name = Products; sourceTree = ""; }; + 374634571E848085005E1244 /* Products */ = { + isa = PBXGroup; + children = ( + 374634671E848085005E1244 /* libRCTOrientation.a */, + ); + name = Products; + sourceTree = ""; + }; 37D8FEBE1E80B5230091F3BD /* Products */ = { isa = PBXGroup; children = ( @@ -655,6 +673,7 @@ B97AA6F961BB47D3A3297E8E /* RNDeviceInfo.xcodeproj */, 7DCC3D826CE640AF8F491692 /* BVLinearGradient.xcodeproj */, F9678BD770064C20ACFA154A /* imageCropPicker.xcodeproj */, + 5C3B95629BA74FB3A8377CB7 /* RCTOrientation.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -800,6 +819,10 @@ ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */; ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; }, + { + ProductGroup = 374634571E848085005E1244 /* Products */; + ProjectRef = 5C3B95629BA74FB3A8377CB7 /* RCTOrientation.xcodeproj */; + }, { ProductGroup = 7F63D27C1E6C957C001FAE12 /* Products */; ProjectRef = 7F63D27B1E6C957C001FAE12 /* RCTPushNotification.xcodeproj */; @@ -914,6 +937,13 @@ remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 374634671E848085005E1244 /* libRCTOrientation.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTOrientation.a; + remoteRef = 374634661E848085005E1244 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 37D8FEC21E80B5230091F3BD /* libBVLinearGradient.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1213,6 +1243,7 @@ LIBRARY_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1231,6 +1262,7 @@ LIBRARY_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1246,7 +1278,10 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 19; DEAD_CODE_STRIPPING = NO; - HEADER_SEARCH_PATHS = "$(SRCROOT)/../node_modules/react-native/Libraries/PushNotificationIOS/**"; + HEADER_SEARCH_PATHS = ( + "$(SRCROOT)/../node_modules/react-native/Libraries/PushNotificationIOS/**", + "$(SRCROOT)/../node_modules/react-native-orientation/iOS/RCTOrientation/**", + ); INFOPLIST_FILE = Mattermost/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( diff --git a/ios/Mattermost/AppDelegate.m b/ios/Mattermost/AppDelegate.m index a4e0cd2a9..4b109f197 100644 --- a/ios/Mattermost/AppDelegate.m +++ b/ios/Mattermost/AppDelegate.m @@ -11,6 +11,7 @@ #import "RCTPushNotificationManager.h" #import #import +#import "Orientation.h" @implementation AppDelegate @@ -61,4 +62,8 @@ fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler [RCTPushNotificationManager didReceiveLocalNotification:notification]; } +// Required for orientation +- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { + return [Orientation getOrientation]; +} @end diff --git a/ios/Mattermost/Info.plist b/ios/Mattermost/Info.plist index 07f1a570d..1530be964 100644 --- a/ios/Mattermost/Info.plist +++ b/ios/Mattermost/Info.plist @@ -2,10 +2,6 @@ - NSCameraUsageDescription - Take a Photo or Video and upload it to your mattermost instance - NSPhotoLibraryUsageDescription - Upload Photos and Videos to your Mattermost instance CFBundleDevelopmentRegion en CFBundleExecutable @@ -28,6 +24,8 @@ LSRequiresIPhoneOS + NSAllowsArbitraryLoads + NSAppTransportSecurity NSAllowsArbitraryLoads @@ -41,10 +39,12 @@ - NSAllowsArbitraryLoads - + NSCameraUsageDescription + Take a Photo or Video and upload it to your mattermost instance NSLocationWhenInUseUsageDescription + NSPhotoLibraryUsageDescription + Upload Photos and Videos to your Mattermost instance UIAppFonts Entypo.ttf diff --git a/package.json b/package.json index 8902d7763..5e1bcc001 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "react-native-keyboard-spacer": "0.3.1", "react-native-linear-gradient": "2.0.0", "react-native-message-bar": "1.6.0", + "react-native-orientation": "git+https://github.com/BonifyByForteil/react-native-orientation.git#newRN", "react-native-push-notification": "2.2.1", "react-native-search-bar": "enahum/react-native-search-bar.git", "react-native-svg": "4.5.0",