diff --git a/app/components/post_textbox/post_textbox_base.js b/app/components/post_textbox/post_textbox_base.js index 6a9b9446c..4de59dcb3 100644 --- a/app/components/post_textbox/post_textbox_base.js +++ b/app/components/post_textbox/post_textbox_base.js @@ -409,8 +409,8 @@ export default class PostTextBoxBase extends PureComponent { } }; - handleUploadFiles = (images) => { - this.props.actions.initUploadFiles(images, this.props.rootId); + handleUploadFiles = (files) => { + this.props.actions.initUploadFiles(files, this.props.rootId); }; isFileLoading = () => { @@ -685,21 +685,21 @@ export default class PostTextBoxBase extends PureComponent { }); }; - showPasteImageErrorDialog = () => { + showPasteFilesErrorDialog = () => { const {formatMessage} = this.context.intl; Alert.alert( formatMessage({ - id: 'mobile.image_paste.error_title', - defaultMessage: 'Paste Image failed', + id: 'mobile.files_paste.error_title', + defaultMessage: 'Paste failed', }), formatMessage({ - id: 'mobile.image_paste.error_description', - defaultMessage: 'An error occurred while pasting the image. Please try again.', + id: 'mobile.files_paste.error_description', + defaultMessage: 'An error occurred while pasting the file(s). Please try again.', }), [ { text: formatMessage({ - id: 'mobile.image_paste.error_dismiss', + id: 'mobile.files_paste.error_dismiss', defaultMessage: 'Dismiss', }), }, @@ -707,27 +707,27 @@ export default class PostTextBoxBase extends PureComponent { ); }; - handlePasteImages = (error, images) => { + handlePasteFiles = (error, files) => { if (this.props.screenId === EphemeralStore.getNavigationTopComponentId()) { if (error) { - this.showPasteImageErrorDialog(); + this.showPasteFilesErrorDialog(); return; } - const {maxFileSize, files} = this.props; - const availableCount = MAX_FILE_COUNT - files.length; - if (images.length > availableCount) { + const {maxFileSize} = this.props; + const availableCount = MAX_FILE_COUNT - this.props.files.length; + if (files.length > availableCount) { this.onShowFileMaxWarning(); return; } - const largeImage = images.find((image) => image.fileSize > maxFileSize); - if (largeImage) { - this.onShowFileSizeWarning(largeImage.fileName); + const largeFile = files.find((image) => image.fileSize > maxFileSize); + if (largeFile) { + this.onShowFileSizeWarning(largeFile.fileName); return; } - this.handleUploadFiles(images); + this.handleUploadFiles(files); } }; @@ -780,7 +780,7 @@ export default class PostTextBoxBase extends PureComponent { onEndEditing={this.handleEndEditing} disableFullscreenUI={true} editable={!channelIsReadOnly} - onPaste={this.handlePasteImages} + onPaste={this.handlePasteFiles} keyboardAppearance={getKeyboardAppearanceFromTheme(theme)} /> diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json index 6e9b3de02..bf85fdfef 100644 --- a/assets/base/i18n/en.json +++ b/assets/base/i18n/en.json @@ -263,12 +263,12 @@ "mobile.file_upload.max_warning": "Uploads limited to 5 files maximum.", "mobile.file_upload.unsupportedMimeType": "Only files of the following MIME type can be uploaded:\n{mimeTypes}", "mobile.file_upload.video": "Video Library", + "mobile.files_paste.error_description": "An error occurred while pasting the file(s). Please try again.", + "mobile.files_paste.error_dismiss": "Dismiss", + "mobile.files_paste.error_title": "Paste failed", "mobile.flagged_posts.empty_description": "Flags are a way to mark messages for follow up. Your flags are personal, and cannot be seen by other users.", "mobile.flagged_posts.empty_title": "No Flagged Posts", "mobile.help.title": "Help", - "mobile.image_paste.error_description": "An error occurred while pasting the image. Please try again.", - "mobile.image_paste.error_dismiss": "Dismiss", - "mobile.image_paste.error_title": "Paste Image failed", "mobile.image_preview.save": "Save Image", "mobile.image_preview.save_video": "Save Video", "mobile.intro_messages.default_message": "This is the first channel teammates see when they sign up - use it for posting updates everyone needs to know.", diff --git a/ios/Mattermost.xcodeproj/project.pbxproj b/ios/Mattermost.xcodeproj/project.pbxproj index a33a2f7b8..b5bd7e490 100644 --- a/ios/Mattermost.xcodeproj/project.pbxproj +++ b/ios/Mattermost.xcodeproj/project.pbxproj @@ -43,12 +43,14 @@ 552835DCC0C24FC691EE6CAB /* Roboto-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8F0B22D2C9924FAFA7FB681C /* Roboto-LightItalic.ttf */; }; 55C6561DDBBA45929D88B6D1 /* OpenSans-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 32AC3D4EA79E44738A6E9766 /* OpenSans-BoldItalic.ttf */; }; 5A0920184BD344979BCFCD5C /* libRCTVideo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B89192186C764B9FA473403A /* libRCTVideo.a */; }; + 5A7A8D4251B9E3CD0CC672DC /* libPods-MattermostTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2774193E64D242854830A632 /* libPods-MattermostTests.a */; }; 5E1AF7B72B8D4A4E9E53FF9D /* FontAwesome.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 005346E5C0E542BFABAE1411 /* FontAwesome.ttf */; }; 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 62A8448264674B4D95A5A7C2 /* OpenSans-Semibold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C78A387124874496AD2C1466 /* OpenSans-Semibold.ttf */; }; 69AC753E496743BABB7A7124 /* OpenSans-SemiboldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0E617BF0F36D4E738F51D169 /* OpenSans-SemiboldItalic.ttf */; }; 71F30A436B5847DF9D319D15 /* Roboto-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F54ABFAE6CE4A6DB11D1ED7 /* Roboto-BlackItalic.ttf */; }; 72FB67307C2E4BA197BEC567 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = CF19152887874B7E996210B1 /* libz.tbd */; }; + 73278E8B36D98C81B6DDAA42 /* libPods-Mattermost.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A755BC875640C049D8D40CA /* libPods-Mattermost.a */; }; 74D116AD208A8D5600CF8A79 /* libRNKeychain.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 74D116AA208A8D3100CF8A79 /* libRNKeychain.a */; }; 7BD159C40A68467FB5A17141 /* FontAwesome5_Solid.ttf in Resources */ = {isa = PBXBuildFile; fileRef = DC1D660B55BE462A9C3B8028 /* FontAwesome5_Solid.ttf */; }; 7F151D3E221B062700FAD8F3 /* RuntimeUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F151D3D221B062700FAD8F3 /* RuntimeUtils.swift */; }; @@ -92,6 +94,8 @@ 7FABE00A2212650600D0F595 /* ChannelsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FABE0092212650600D0F595 /* ChannelsViewController.swift */; }; 7FABE04622137F5C00D0F595 /* libUploadAttachments.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FABE04522137F2A00D0F595 /* libUploadAttachments.a */; }; 7FABE0562213884700D0F595 /* libUploadAttachments.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FABE04522137F2A00D0F595 /* libUploadAttachments.a */; }; + 7FAE084E23562DE500762B6D /* UIImage+vImageScaling.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FAE084D23562DE500762B6D /* UIImage+vImageScaling.m */; }; + 7FAE089D23562E0E00762B6D /* SwimeProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FAE089C23562E0E00762B6D /* SwimeProxy.swift */; }; 7FBB5E9B1E1F5A4B000DE18A /* libRNVectorIcons.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FDF290C1E1F4B4E00DBBE56 /* libRNVectorIcons.a */; }; 7FD1DD0823273C6000E0D948 /* libRNCWebView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F26C1CB219C463300FEB42D /* libRNCWebView.a */; }; 7FDB92B11F706F58006CDFD1 /* libRNImagePicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FDB92A71F706F45006CDFD1 /* libRNImagePicker.a */; }; @@ -110,7 +114,6 @@ 92F9F0ED22F702E10035885A /* NSData+MimeType.m in Sources */ = {isa = PBXBuildFile; fileRef = 92F9F0EC22F702E10035885A /* NSData+MimeType.m */; }; 9358B95F95184EE0A4DCE629 /* OpenSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D4B1B363C2414DA19C1AC521 /* OpenSans-Bold.ttf */; }; A08D512E7ADC40CCAD055A9E /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = BC977883E2624E05975CA65B /* OpenSans-Regular.ttf */; }; - A9B746D2CFA9CEBFB8AE2B5B /* libPods-Mattermost.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 65FD5EA57EBAE06106094B2F /* libPods-Mattermost.a */; }; AA9605CFDA8E4E7CB8A041BF /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C5BD64DE829E455A997DCAD5 /* Roboto-Regular.ttf */; }; ABF5F93B1D0A47BAACEAC376 /* Roboto-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34B20A903038487E8D7DEA1E /* Roboto-Light.ttf */; }; C035DB50ED2045F09923FFAE /* MaterialCommunityIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 04AA5E8EF3B54735A11E3B95 /* MaterialCommunityIcons.ttf */; }; @@ -125,7 +128,6 @@ EC6AF34E03F647389D377064 /* Roboto-ThinItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 12D0B0E475FD46E29907305E /* Roboto-ThinItalic.ttf */; }; F006936FC2884C24A1321FC0 /* MaterialIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 356C9186FA374641A00EB2EA /* MaterialIcons.ttf */; }; F083DB472349411A8E6E7AAD /* OpenSans-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = BE17F630DB5D41FD93F32D22 /* OpenSans-LightItalic.ttf */; }; - F23C99AA5FA10E457A76803A /* libPods-MattermostTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4246DC09024BB33A3E491E25 /* libPods-MattermostTests.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -770,6 +772,7 @@ 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Mattermost/main.m; sourceTree = ""; }; 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; 17A75F5A3D0D4A4A995DCD76 /* libRNPasscodeStatus.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNPasscodeStatus.a; sourceTree = ""; }; + 2774193E64D242854830A632 /* libPods-MattermostTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MattermostTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 27A6EA89298440439DA9F98D /* JailMonkey.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = JailMonkey.xcodeproj; path = "../node_modules/jail-monkey/JailMonkey.xcodeproj"; sourceTree = ""; }; 2B25899FDAC149EB96ED3305 /* RNVectorIcons.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNVectorIcons.xcodeproj; path = "../node_modules/react-native-vector-icons/RNVectorIcons.xcodeproj"; sourceTree = ""; }; 2CBE9C0FB56E4FDA96C30792 /* RNSVG.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNSVG.xcodeproj; path = "../node_modules/react-native-svg/ios/RNSVG.xcodeproj"; sourceTree = ""; }; @@ -786,19 +789,18 @@ 41465DE822E9429EB8B90CB4 /* Pods-MattermostTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MattermostTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-MattermostTests/Pods-MattermostTests.release.xcconfig"; sourceTree = ""; }; 41898656FAE24E0BB390D0E4 /* RNReactNativeDocViewer.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNReactNativeDocViewer.xcodeproj; path = "../node_modules/react-native-doc-viewer/ios/RNReactNativeDocViewer.xcodeproj"; sourceTree = ""; }; 41F3AFE83AAF4B74878AB78A /* OpenSans-Italic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-Italic.ttf"; path = "../assets/fonts/OpenSans-Italic.ttf"; sourceTree = ""; }; - 4246DC09024BB33A3E491E25 /* libPods-MattermostTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MattermostTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 476BA76E31644398A6012911 /* libRNGestureHandler.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNGestureHandler.a; sourceTree = ""; }; 49DF9A2A231D0CB3008CC96D /* RNReactNativeHapticFeedback.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNReactNativeHapticFeedback.xcodeproj; path = "../node_modules/react-native-haptic-feedback/ios/RNReactNativeHapticFeedback.xcodeproj"; sourceTree = ""; }; 4A22BC320BA04E18A7F2A4E6 /* libReactNativeExceptionHandler.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libReactNativeExceptionHandler.a; sourceTree = ""; }; 4B19E38FBCB94C57BB03B8E6 /* libRNFetchBlob.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFetchBlob.a; sourceTree = ""; }; 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 = ""; }; 59A2AAD141C34AA7B4655F27 /* FontAwesome5_Regular.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Regular.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf"; sourceTree = ""; }; + 5A755BC875640C049D8D40CA /* libPods-Mattermost.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Mattermost.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 5C5FEE2D22F048709FB330F3 /* FontAwesome5_Brands.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Brands.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf"; sourceTree = ""; }; 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; 62A58E5E984E4CF1811620B8 /* RNCookieManagerIOS.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNCookieManagerIOS.xcodeproj; path = "../node_modules/react-native-cookies/ios/RNCookieManagerIOS.xcodeproj"; sourceTree = ""; }; 634A8F047C73D24A87850EC0 /* Pods-Mattermost.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mattermost.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Mattermost/Pods-Mattermost.debug.xcconfig"; sourceTree = ""; }; 6561AEAC21CC40B8A72ABB93 /* OpenSans-Light.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-Light.ttf"; path = "../assets/fonts/OpenSans-Light.ttf"; sourceTree = ""; }; - 65FD5EA57EBAE06106094B2F /* libPods-Mattermost.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Mattermost.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 6BAF8296411D4657B5A0E8F8 /* libRNReactNativeDocViewer.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNReactNativeDocViewer.a; sourceTree = ""; }; 6EFF13DD24CE4E26953E598A /* Roboto-Black.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Black.ttf"; path = "../assets/fonts/Roboto-Black.ttf"; sourceTree = ""; }; 71E626D4980A4560B26F0E1C /* Roboto-Bold.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Bold.ttf"; path = "../assets/fonts/Roboto-Bold.ttf"; sourceTree = ""; }; @@ -852,6 +854,9 @@ 7FABDFC12211A39000D0F595 /* Section.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Section.swift; sourceTree = ""; }; 7FABE0092212650600D0F595 /* ChannelsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelsViewController.swift; sourceTree = ""; }; 7FABE04022137F2900D0F595 /* UploadAttachments.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = UploadAttachments.xcodeproj; path = UploadAttachments/UploadAttachments.xcodeproj; sourceTree = ""; }; + 7FAE084C23562DE500762B6D /* UIImage+vImageScaling.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "UIImage+vImageScaling.h"; path = "Mattermost/UIImage+vImageScaling.h"; sourceTree = ""; }; + 7FAE084D23562DE500762B6D /* UIImage+vImageScaling.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "UIImage+vImageScaling.m"; path = "Mattermost/UIImage+vImageScaling.m"; sourceTree = ""; }; + 7FAE089C23562E0E00762B6D /* SwimeProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwimeProxy.swift; path = Mattermost/SwimeProxy.swift; sourceTree = ""; }; 7FDB92751F706F45006CDFD1 /* RNImagePicker.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNImagePicker.xcodeproj; path = "../node_modules/react-native-image-picker/ios/RNImagePicker.xcodeproj"; sourceTree = ""; }; 7FEB10961F6101710039A015 /* BlurAppScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlurAppScreen.h; path = Mattermost/BlurAppScreen.h; sourceTree = ""; }; 7FEB10971F6101710039A015 /* BlurAppScreen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BlurAppScreen.m; path = Mattermost/BlurAppScreen.m; sourceTree = ""; }; @@ -905,7 +910,7 @@ DC1D660B55BE462A9C3B8028 /* FontAwesome5_Solid.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Solid.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf"; sourceTree = ""; }; DE10E26B8E5644FB95A079FE /* AntDesign.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = AntDesign.ttf; path = "../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf"; sourceTree = ""; }; DF9DAAAA482343F3910A1A4C /* RCTVideo.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTVideo.xcodeproj; path = "../node_modules/react-native-video/ios/RCTVideo.xcodeproj"; sourceTree = ""; }; - E2D17ED040D0465DBF9112D3 /* Mattermost-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Mattermost-Regular.otf"; path = "../assets/fonts/Mattermost-Regular.otf"; sourceTree = ""; }; + E2D17ED040D0465DBF9112D3 /* Mattermost-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Mattermost-Regular.otf"; path = "../assets/fonts/Mattermost-Regular.otf"; sourceTree = ""; }; EBA6063A99C141098D40C67A /* RNPasscodeStatus.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNPasscodeStatus.xcodeproj; path = "../node_modules/react-native-passcode-status/ios/RNPasscodeStatus.xcodeproj"; sourceTree = ""; }; EDC04CBCF81642219D199CBB /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; sourceTree = ""; }; EE3EE4548D3F4A49B1274722 /* libRNLocalAuth.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNLocalAuth.a; sourceTree = ""; }; @@ -920,7 +925,7 @@ buildActionMask = 2147483647; files = ( 140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */, - F23C99AA5FA10E457A76803A /* libPods-MattermostTests.a in Frameworks */, + 5A7A8D4251B9E3CD0CC672DC /* libPods-MattermostTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -967,12 +972,12 @@ 7FD1DD0823273C6000E0D948 /* libRNCWebView.a in Frameworks */, 7F88A04422270FD400DC5DE2 /* libRNSentry.a in Frameworks */, 7F43D6061F6BF9EB001FC614 /* libPods-Mattermost.a in Frameworks */, - A9B746D2CFA9CEBFB8AE2B5B /* libPods-Mattermost.a in Frameworks */, 5A0920184BD344979BCFCD5C /* libRCTVideo.a in Frameworks */, 3F876A0DC6314E27B16C8A96 /* libRNReactNativeDocViewer.a in Frameworks */, 8D26455C994F46C39B1392F2 /* libRNSafeArea.a in Frameworks */, 3F55075810254369AB39F032 /* libRNGestureHandler.a in Frameworks */, 72FB67307C2E4BA197BEC567 /* libz.tbd in Frameworks */, + 73278E8B36D98C81B6DDAA42 /* libPods-Mattermost.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1150,6 +1155,9 @@ 9260D93222F83CA200F51A82 /* OnPasteEventManager.m */, 92F9F0EB22F702E10035885A /* NSData+MimeType.h */, 92F9F0EC22F702E10035885A /* NSData+MimeType.m */, + 7FAE089C23562E0E00762B6D /* SwimeProxy.swift */, + 7FAE084C23562DE500762B6D /* UIImage+vImageScaling.h */, + 7FAE084D23562DE500762B6D /* UIImage+vImageScaling.m */, ); name = Mattermost; sourceTree = ""; @@ -1255,10 +1263,10 @@ 7FFE32BF1FD9CCAA0038C7A0 /* Sentry.framework */, 7F43D6051F6BF9EB001FC614 /* libPods-Mattermost.a */, 7F43D5DF1F6BF994001FC614 /* libRNSVG.a */, - 65FD5EA57EBAE06106094B2F /* libPods-Mattermost.a */, - 4246DC09024BB33A3E491E25 /* libPods-MattermostTests.a */, CF19152887874B7E996210B1 /* libz.tbd */, 84596DD7229C853000981086 /* libReactNativeNavigation.a */, + 5A755BC875640C049D8D40CA /* libPods-Mattermost.a */, + 2774193E64D242854830A632 /* libPods-MattermostTests.a */, ); name = Frameworks; sourceTree = ""; @@ -1672,7 +1680,7 @@ 37DA4BA41E6F55AD002B058E /* Embed Frameworks */, AE4769B235D14E6C9C64EA78 /* Upload Debug Symbols to Sentry */, 7FFE32A91FD9CB650038C7A0 /* Embed App Extensions */, - 27FBE48ACE3E38C56E5D745C /* [CP] Copy Pods Resources */, + 5B498B6F4D17FD3BA2C4C0F4 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -2632,7 +2640,7 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 27FBE48ACE3E38C56E5D745C /* [CP] Copy Pods Resources */ = { + 5B498B6F4D17FD3BA2C4C0F4 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -2700,12 +2708,14 @@ 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, 7F151D3E221B062700FAD8F3 /* RuntimeUtils.swift in Sources */, 7FEB109E1F61019C0039A015 /* UIImage+ImageEffects.m in Sources */, + 7FAE089D23562E0E00762B6D /* SwimeProxy.swift in Sources */, 92F9F0ED22F702E10035885A /* NSData+MimeType.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, 7FEB10981F6101710039A015 /* BlurAppScreen.m in Sources */, 9260D98222F846D700F51A82 /* UIPasteboard+GetImageInfo.m in Sources */, 7FEB109D1F61019C0039A015 /* MattermostManaged.m in Sources */, 7F240ACD220D460300637665 /* MattermostBucketModule.m in Sources */, + 7FAE084E23562DE500762B6D /* UIImage+vImageScaling.m in Sources */, 7F5BA34722B99B7B005B05D3 /* Mattermost+RCTUITextView.m in Sources */, 9260D93322F83CA200F51A82 /* OnPasteEventManager.m in Sources */, ); diff --git a/ios/Mattermost/Mattermost+RCTUITextView.m b/ios/Mattermost/Mattermost+RCTUITextView.m index 05fdecddb..d89383a4a 100644 --- a/ios/Mattermost/Mattermost+RCTUITextView.m +++ b/ios/Mattermost/Mattermost+RCTUITextView.m @@ -32,10 +32,9 @@ return NO; } } - - // Allow copy and paste string and image - if (action == @selector(paste:)) { - return [UIPasteboard generalPasteboard].string != nil || [UIPasteboard generalPasteboard].image != nil; + + if (action == @selector(paste:) && [UIPasteboard generalPasteboard].numberOfItems > 0) { + return true; } return [super canPerformAction:action withSender:sender]; @@ -45,12 +44,14 @@ [super paste:sender]; UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; - if (!pasteboard.hasImages) { + if (pasteboard.hasURLs || pasteboard.hasStrings || pasteboard.hasColors) { return; } - NSArray *images = [pasteboard getCopiedImages]; - [OnPasteEventManager pasteImage:images]; + NSArray *files = [pasteboard getCopiedFiles]; + if (files != nil && files.count > 0) { + [OnPasteEventManager pasteFiles:files]; + } // Dismiss contextual menu [self resignFirstResponder]; diff --git a/ios/Mattermost/NSData+MimeType.m b/ios/Mattermost/NSData+MimeType.m index b8e31269e..c1e1867ca 100644 --- a/ios/Mattermost/NSData+MimeType.m +++ b/ios/Mattermost/NSData+MimeType.m @@ -39,17 +39,17 @@ switch (c) { case 0xFF: - return @".jpeg"; + return @"jpg"; break; case 0x89: - return @".png"; + return @"png"; break; case 0x47: - return @".gif"; + return @"gif"; break; case 0x49: case 0x4D: - return @".tiff"; + return @"tiff"; break; default: return @""; diff --git a/ios/Mattermost/OnPasteEventManager.h b/ios/Mattermost/OnPasteEventManager.h index 76deefe19..0733172a7 100644 --- a/ios/Mattermost/OnPasteEventManager.h +++ b/ios/Mattermost/OnPasteEventManager.h @@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN @interface OnPasteEventManager : RCTEventEmitter -+(void)pasteImage:(NSArray *)data; ++(void)pasteFiles:(NSArray *)data; @end diff --git a/ios/Mattermost/OnPasteEventManager.m b/ios/Mattermost/OnPasteEventManager.m index 0e359bf79..cd9236d05 100644 --- a/ios/Mattermost/OnPasteEventManager.m +++ b/ios/Mattermost/OnPasteEventManager.m @@ -38,7 +38,7 @@ RCT_EXPORT_MODULE(); [self sendEventWithName:@"onPaste" body:data.userInfo[@"data"]]; } -+(void)pasteImage:(NSArray *)data { ++(void)pasteFiles:(NSArray *)data { [[NSNotificationCenter defaultCenter] postNotificationName:@"onPaste" object:data userInfo:@{ @"data": data }]; diff --git a/ios/Mattermost/SwimeProxy.swift b/ios/Mattermost/SwimeProxy.swift new file mode 100644 index 000000000..8b3418467 --- /dev/null +++ b/ios/Mattermost/SwimeProxy.swift @@ -0,0 +1,61 @@ +// +// SwimeProxy.swift +// Mattermost +// +// Created by Elias Nahum on 15-10-19. +// Copyright © 2019 Facebook. All rights reserved. +// + +import Foundation +import Swime + +@objc @objcMembers public class MimeTypeProxy: NSObject { + public init(mime: String, ext: String) { + self.mime = mime + self.ext = ext + } + + /// Mime type string representation. For example "application/pdf" + public let mime: String + + /// Mime type extension. For example "pdf" + public let ext: String +} + +@objc @objcMembers public class SwimeProxy: NSObject { + public class var shared :SwimeProxy { + struct Singleton { + static let instance = SwimeProxy() + } + return Singleton.instance + } + + public func getMimeFromUti(uti: String) -> MimeTypeProxy? { + switch uti { + case "org.openxmlformats.openxml": + return MimeTypeProxy(mime: "application/xml", ext: ".xml") + case "org.openxmlformats.wordprocessingml.document": + return MimeTypeProxy(mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", ext: ".docx") + case "org.openxmlformats.spreadsheetml.sheet": + return MimeTypeProxy(mime: "pplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ext: ".xlsx") + case "org.openxmlformats.presentationml.presentation": + return MimeTypeProxy(mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation", ext: ".pptx") + default: + return nil + } + } + + @objc public func getMimeAndExtension(data: Data, uti: String) -> MimeTypeProxy? { + let mime = getMimeFromUti(uti: uti); + if (mime != nil) { + return mime + } + + let proxy = Swime.mimeType(data: data) + if (proxy != nil) { + return MimeTypeProxy(mime: proxy!.mime, ext: proxy!.ext) + } + + return nil + } +} diff --git a/ios/Mattermost/UIImage+vImageScaling.h b/ios/Mattermost/UIImage+vImageScaling.h new file mode 100644 index 000000000..3f81f51bb --- /dev/null +++ b/ios/Mattermost/UIImage+vImageScaling.h @@ -0,0 +1,16 @@ +// +// UIImage+vImageScaling.h +// UIImage+vImageScaling +// +// Created by Matt Donnelly on 03/07/2013. +// Copyright (c) 2013 Matt Donnelly. All rights reserved. +// taken from https://gist.github.com/mattdonnelly/5924492 + +#import + +@interface UIImage (vImageScaling) + +- (UIImage *)vImageScaledImageWithSize:(CGSize)destSize; +- (UIImage *)vImageScaledImageWithSize:(CGSize)destSize contentMode:(UIViewContentMode)contentMode; + +@end diff --git a/ios/Mattermost/UIImage+vImageScaling.m b/ios/Mattermost/UIImage+vImageScaling.m new file mode 100644 index 000000000..e452ef603 --- /dev/null +++ b/ios/Mattermost/UIImage+vImageScaling.m @@ -0,0 +1,48 @@ +// +// UIImage+vImageScaling.m +// UIImage+vImageScaling +// +// Created by Matt Donnelly on 03/07/2013. +// Copyright (c) 2013 Matt Donnelly. All rights reserved. +// originally taken from https://gist.github.com/mattdonnelly/5924492 + +#import +#import + +@implementation UIImage (vImageScaling) + +- (UIImage *)vImageScaledImageWithSize:(CGSize)destSize { + UIGraphicsBeginImageContext(CGSizeMake(destSize.width, destSize.height)); + [self drawInRect:CGRectMake(0, 0, destSize.width, destSize.height)]; + UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return newImage; +} + +- (UIImage *)vImageScaledImageWithSize:(CGSize)destSize contentMode:(UIViewContentMode)contentMode { + CGImageRef sourceRef = [self CGImage]; + NSUInteger sourceWidth = CGImageGetWidth(sourceRef); + NSUInteger sourceHeight = CGImageGetHeight(sourceRef); + CGFloat horizontalRatio = destSize.width / sourceWidth; + CGFloat verticalRatio = destSize.height / sourceHeight; + CGFloat ratio; + + switch (contentMode) { + case UIViewContentModeScaleAspectFill: + ratio = MAX(horizontalRatio, verticalRatio); + break; + + case UIViewContentModeScaleAspectFit: + ratio = MIN(horizontalRatio, verticalRatio); + break; + + default: + [NSException raise:NSInvalidArgumentException format:@"Unsupported content mode: %d", contentMode]; + } + + CGSize newSize = CGSizeMake(sourceWidth * ratio, sourceHeight * ratio); + + return [self vImageScaledImageWithSize:newSize]; +} + +@end diff --git a/ios/Mattermost/UIPasteboard+GetImageInfo.h b/ios/Mattermost/UIPasteboard+GetImageInfo.h index 74e3f79b9..a849aeb0d 100644 --- a/ios/Mattermost/UIPasteboard+GetImageInfo.h +++ b/ios/Mattermost/UIPasteboard+GetImageInfo.h @@ -12,7 +12,7 @@ NS_ASSUME_NONNULL_BEGIN @interface UIPasteboard (GetImageInfo) --(NSArray *)getCopiedImages; +-(NSArray *)getCopiedFiles; @end diff --git a/ios/Mattermost/UIPasteboard+GetImageInfo.m b/ios/Mattermost/UIPasteboard+GetImageInfo.m index b13816f53..7c84f1eef 100644 --- a/ios/Mattermost/UIPasteboard+GetImageInfo.m +++ b/ios/Mattermost/UIPasteboard+GetImageInfo.m @@ -8,45 +8,94 @@ #import "UIPasteboard+GetImageInfo.h" #import "NSData+MimeType.h" +#import "Mattermost-Swift.h" +#import "UIImage+vImageScaling.h" @implementation UIPasteboard (GetImageInfo) --(NSArray *)getCopiedImages { - NSArray *images = self.images; - NSMutableArray *imageInfos = [[NSMutableArray alloc] init]; - for (int i = 0; i < images.count; i++) { - UIImage *image = images[i]; - NSString *uri = self.string; - NSArray *types = self.pasteboardTypes; - - NSData *imageData; - if ([types[0] isEqual:@"public.jpeg"]) { - imageData = UIImageJPEGRepresentation(image, 1.0); - } else if ([types[0] isEqual:@"public.png"]) { - imageData = UIImagePNGRepresentation(image); - } else { - imageData = [self dataForPasteboardType:types[0]]; +-(NSArray *)getCopiedFiles { + NSMutableArray *fileInfos = [[NSMutableArray alloc] init]; + NSArray *> *items = self.items; + for (int i = 0; i < items.count; i++) { + NSDictionary *item = items[i]; + BOOL added = NO; + for (int j = 0; j < item.allKeys.count; j++) { + if (added) { + continue; + } + + NSString *type = item.allKeys[j]; + + @try { + NSString *uri = self.string; + NSData *fileData = item[type]; + + if ([type isEqual:@"public.jpeg"] || [type isEqual:@"public.heic"] || [type isEqual:@"public.png"]) { + fileData = [self getDataForImageItem:item[type] type:type]; + } + + SwimeProxy *swimeProxy = [SwimeProxy shared]; + MimeTypeProxy *mimeProxy = [swimeProxy getMimeAndExtensionWithData:fileData uti:type]; + NSString *extension; + NSString *mimeType; + if (mimeProxy != nil) { + extension = mimeProxy.ext; + mimeType = mimeProxy.mime; + } else { + extension = [fileData extension]; + mimeType = [fileData mimeType]; + } + + if ([extension length] == 0) { + continue; + } + + NSString *tempFilename = [NSString stringWithFormat:@"%@.%@", [[NSProcessInfo processInfo] globallyUniqueString], extension]; + NSURL *tempFileURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:tempFilename]]; + BOOL success = [fileData writeToURL:tempFileURL atomically:YES]; + if (success) { + added = YES; + uri = tempFileURL.absoluteString; + [fileInfos addObject:@{ + @"fileName": tempFilename, + @"fileSize": @([fileData length]), + @"type": mimeType, + @"uri": uri, + }]; + } + } @catch (NSException *exception) { + [fileInfos addObject:@{ + @"type": type, + @"error": exception.reason, + }]; + } } - NSString *extension = [imageData extension]; - NSString *mimeType = [imageData mimeType]; - - NSString *tempFilename = [NSString stringWithFormat:@"%@%@", [[NSProcessInfo processInfo] globallyUniqueString], extension]; - NSURL *tempFileURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:tempFilename]]; - BOOL success = [imageData writeToURL:tempFileURL atomically:YES]; - - if (success) { - uri = tempFileURL.absoluteString; - } - - [imageInfos addObject:@{ - @"fileName": tempFilename, - @"fileSize": @([imageData length]), - @"type": mimeType, - @"uri": uri, - }]; } - return imageInfos; + return fileInfos; +} + +-(NSData *) getDataForImageItem:(NSData *)imageData type:(NSString *)type { + UIImage *image; + if ([type isEqual:@"public.heic"]) { + CFDataRef cfdata = CFDataCreate(NULL, [imageData bytes], [imageData length]); + CGImageSourceRef source = CGImageSourceCreateWithData(cfdata, nil); + CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, 0, nil); + image = [[UIImage alloc] initWithCGImage:imageRef]; + } else { + image = (UIImage *)imageData; + } + size_t width = CGImageGetWidth(image.CGImage); + size_t height = CGImageGetHeight(image.CGImage); + if (width > 6048 || height > 4032) { + image = [image vImageScaledImageWithSize:CGSizeMake(2048, 2048) contentMode:UIViewContentModeScaleAspectFit]; + } + + if ([type isEqual:@"public.png"]) { + return UIImagePNGRepresentation(image); + } + + return UIImageJPEGRepresentation(image, 1.0); } @end diff --git a/ios/Podfile b/ios/Podfile index 3a701463e..425552f63 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -8,6 +8,7 @@ target 'Mattermost' do # Pods for Mattermost pod 'XCDYouTubeKit', '2.7.1' pod 'YoutubePlayer-in-WKWebView', '~> 0.3.1' + pod 'Swime', '3.0.6' target 'MattermostTests' do inherit! :search_paths diff --git a/ios/Podfile.lock b/ios/Podfile.lock index a59d3a50e..357fa8032 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,20 +1,24 @@ PODS: + - Swime (3.0.6) - XCDYouTubeKit (2.7.1) - YoutubePlayer-in-WKWebView (0.3.3) DEPENDENCIES: + - Swime (= 3.0.6) - XCDYouTubeKit (= 2.7.1) - YoutubePlayer-in-WKWebView (~> 0.3.1) SPEC REPOS: https://github.com/cocoapods/specs.git: + - Swime - XCDYouTubeKit - YoutubePlayer-in-WKWebView SPEC CHECKSUMS: + Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b XCDYouTubeKit: c8567fd5cb388a3099fa26eee4b30df2a467847d YoutubePlayer-in-WKWebView: 7694e858c5c3472ed067d6fe34eb9b944845e63c -PODFILE CHECKSUM: e565d3af8eabb0e489b73c79433e140e30f8fa9c +PODFILE CHECKSUM: 74e6d20d391445b945031efe1c5d16c093114192 COCOAPODS: 1.7.5 diff --git a/ios/SwimeProxy.swift b/ios/SwimeProxy.swift new file mode 100644 index 000000000..63f8c6821 --- /dev/null +++ b/ios/SwimeProxy.swift @@ -0,0 +1,9 @@ +// +// SwimeProxy.swift +// Mattermost +// +// Created by Elias Nahum on 15-10-19. +// Copyright © 2019 Facebook. All rights reserved. +// + +import Foundation diff --git a/package-lock.json b/package-lock.json index e1a56c472..687066ca5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8494,7 +8494,8 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "optional": true }, "aproba": { "version": "1.2.0", @@ -8515,12 +8516,14 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "optional": true }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -8535,17 +8538,20 @@ "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "optional": true }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "optional": true }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -8662,7 +8668,8 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "optional": true }, "ini": { "version": "1.3.5", @@ -8674,6 +8681,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -8688,6 +8696,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -8695,12 +8704,14 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "optional": true }, "minipass": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -8719,6 +8730,7 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "optional": true, "requires": { "minimist": "0.0.8" } @@ -8799,7 +8811,8 @@ "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "optional": true }, "object-assign": { "version": "4.1.1", @@ -8811,6 +8824,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "optional": true, "requires": { "wrappy": "1" } @@ -8896,7 +8910,8 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -8932,6 +8947,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -8951,6 +8967,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -8994,12 +9011,14 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "optional": true }, "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "optional": true } } }, @@ -17230,7 +17249,8 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "dev": true, + "optional": true }, "braces": { "version": "2.3.2", @@ -17493,7 +17513,8 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "dev": true, + "optional": true }, "micromatch": { "version": "3.1.10", @@ -17583,7 +17604,6 @@ "version": "github:mattermost/redux-offline#885024de96b6ec73650c340c8928066585c413df", "from": "github:mattermost/redux-offline#885024de96b6ec73650c340c8928066585c413df", "requires": { - "@react-native-community/netinfo": "^4.1.3", "redux-persist": "^4.5.0" }, "dependencies": {