diff --git a/patches/react-native+0.70.9.patch b/patches/react-native+0.70.9.patch index 1a15cf602..2093276e4 100644 --- a/patches/react-native+0.70.9.patch +++ b/patches/react-native+0.70.9.patch @@ -1,198 +1,210 @@ diff --git a/node_modules/react-native/Libraries/Components/TextInput/TextInput.js b/node_modules/react-native/Libraries/Components/TextInput/TextInput.js index 8fa1171..316b482 100644 --- a/node_modules/react-native/Libraries/Components/TextInput/TextInput.js +++ b/node_modules/react-native/Libraries/Components/TextInput/TextInput.js @@ -208,6 +208,13 @@ export type TextContentType = type PasswordRules = string; type IOSProps = $ReadOnly<{| + /** + * If set, allows pasting of images for given threadID. + * The default value is NULL. + * @platform ios + */ + allowImagePasteForThreadID?: ?string, + /** * When the clear button should appear on the right side of the text view. * This property is supported only for single-line TextInput component. +diff --git a/node_modules/react-native/Libraries/Lists/FlatList.js b/node_modules/react-native/Libraries/Lists/FlatList.js +index a569626..1ea1c03 100644 +--- a/node_modules/react-native/Libraries/Lists/FlatList.js ++++ b/node_modules/react-native/Libraries/Lists/FlatList.js +@@ -295,7 +295,6 @@ export type Props = { + * Also inherits [ScrollView Props](docs/scrollview.html#props), unless it is nested in another FlatList of same orientation. + */ + class FlatList extends React.PureComponent, void> { +- props: Props; + /** + * Scrolls to the end of the content. May be janky without `getItemLayout` prop. + */ diff --git a/node_modules/react-native/Libraries/Lists/VirtualizedList.js b/node_modules/react-native/Libraries/Lists/VirtualizedList.js index 69e6309..5343e6a 100644 --- a/node_modules/react-native/Libraries/Lists/VirtualizedList.js +++ b/node_modules/react-native/Libraries/Lists/VirtualizedList.js @@ -34,6 +34,7 @@ const RefreshControl = require('../Components/RefreshControl/RefreshControl'); const ScrollView = require('../Components/ScrollView/ScrollView'); const View = require('../Components/View/View'); const Batchinator = require('../Interaction/Batchinator'); +const Platform = require('../Utilities/Platform'); const ReactNative = require('../Renderer/shims/ReactNative'); const flattenStyle = require('../StyleSheet/flattenStyle'); const StyleSheet = require('../StyleSheet/StyleSheet'); @@ -2170,9 +2171,10 @@ function describeNestedLists(childList: { } const styles = StyleSheet.create({ - verticallyInverted: { - transform: [{scaleY: -1}], - }, + verticallyInverted: + Platform.OS === 'android' + ? { scaleY: -1 } + : { transform: [{scaleY: -1}] }, horizontallyInverted: { transform: [{scaleX: -1}], }, diff --git a/node_modules/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h b/node_modules/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h index 5ccb6b6..1f326d4 100644 --- a/node_modules/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h +++ b/node_modules/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h @@ -35,6 +35,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) BOOL caretHidden; +@property (nonatomic, copy, nullable) NSString *allowImagePasteForThreadID; + @property (nonatomic, strong, nullable) NSString *inputAccessoryViewID; @end diff --git a/node_modules/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m b/node_modules/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m index 92371bc..e991835 100644 --- a/node_modules/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m +++ b/node_modules/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m @@ -164,8 +164,12 @@ - (void)setSelectedTextRange:(UITextRange *)selectedTextRange notifyDelegate:(BO - (void)paste:(id)sender { - [super paste:sender]; - _textWasPasted = YES; + if ([UIPasteboard generalPasteboard].hasImages && _allowImagePasteForThreadID) { + [_textInputDelegate textInputImagePasted:_allowImagePasteForThreadID]; + } else { + [super paste:sender]; + _textWasPasted = YES; + } } // Turn off scroll animation to fix flaky scrolling. @@ -254,6 +258,10 @@ - (BOOL)canPerformAction:(SEL)action withSender:(id)sender return NO; } + if (action == @selector(paste:) && [UIPasteboard generalPasteboard].hasImages) { + return (_allowImagePasteForThreadID != NULL); + } + return [super canPerformAction:action withSender:sender]; } diff --git a/node_modules/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegate.h b/node_modules/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegate.h index c2a4362..90f8583 100644 --- a/node_modules/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegate.h +++ b/node_modules/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegate.h @@ -33,6 +33,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)textInputDidChangeSelection; +- (void)textInputImagePasted:(NSString *)threadID; + @optional - (void)scrollViewDidScroll:(UIScrollView *)scrollView; diff --git a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m index a492492..e3b38cb 100644 --- a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -19,6 +19,8 @@ #import #import +#import + @implementation RCTBaseTextInputView { __weak RCTBridge *_bridge; __weak id _eventDispatcher; @@ -491,6 +493,46 @@ - (void)textInputDidChangeSelection }); } +- (void)textInputImagePasted:(NSString *)threadID +{ + NSFileManager *fileManager = [NSFileManager defaultManager]; + UIPasteboard *clipboard = [UIPasteboard generalPasteboard]; + NSData *imageData = [clipboard dataForPasteboardType:(NSString*)kUTTypeImage]; + + UIImage *uiImage = [UIImage imageWithData:imageData]; + + if (!imageData) { + RCTLog(@"Failed to get image from UIPasteboard."); + return; + } + + NSString *fileName = [@([imageData hash]) stringValue]; + NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES]; + + // We add the PNG file extension because EXImageLoader fails without it. + // Our code ignores file extensions and looks at magic numbers directly. + NSURL *fileURL = [[tmpDirURL URLByAppendingPathComponent:fileName] URLByAppendingPathExtension:@"png"]; + NSString *fileDest = [fileURL path]; + + if (![fileManager fileExistsAtPath:fileDest]) { + BOOL fileWritten = [imageData writeToFile:fileDest atomically:true]; + if (!fileWritten) { + RCTLog(@"Failed to save image to temporary directory."); + return; + } + } + + NSDictionary *eventBody = @{ + @"fileName": fileName, + @"filePath": fileDest, + @"height": @(uiImage.size.height), + @"width": @(uiImage.size.width), + @"threadID": threadID, + }; + + [_eventDispatcher sendAppEventWithName:@"imagePasted" body:eventBody]; +} + - (void)updateLocalData { [self enforceTextAttributesIfNeeded]; diff --git a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m index b1ecf85..3462f98 100644 --- a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m +++ b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m @@ -33,6 +33,7 @@ @implementation RCTBaseTextInputViewManager #pragma mark - Unified properties +RCT_REMAP_VIEW_PROPERTY(allowImagePasteForThreadID, backedTextInputView.allowImagePasteForThreadID, NSString) RCT_REMAP_VIEW_PROPERTY(autoCapitalize, backedTextInputView.autocapitalizationType, UITextAutocapitalizationType) RCT_REMAP_VIEW_PROPERTY(autoCorrect, backedTextInputView.autocorrectionType, UITextAutocorrectionType) RCT_REMAP_VIEW_PROPERTY(contextMenuHidden, backedTextInputView.contextMenuHidden, BOOL) diff --git a/node_modules/react-native/ReactAndroid/build.gradle b/node_modules/react-native/ReactAndroid/build.gradle index 3be8b26..3f7bba8 100644 --- a/node_modules/react-native/ReactAndroid/build.gradle +++ b/node_modules/react-native/ReactAndroid/build.gradle @@ -61,7 +61,7 @@ task createNativeDepsDirectories { } task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) { - src("https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION.replace("_", ".")}/source/boost_${BOOST_VERSION}.tar.gz") + src("https://archives.boost.io/release/${BOOST_VERSION.replace("_", ".")}/source/boost_${BOOST_VERSION}.tar.gz") onlyIfNewer(true) overwrite(false) dest(new File(downloadsDir, "boost_${BOOST_VERSION}.tar.gz")) diff --git a/node_modules/react-native/third-party-podspecs/boost.podspec b/node_modules/react-native/third-party-podspecs/boost.podspec index 2f1fcc4..fa82134 100644 --- a/node_modules/react-native/third-party-podspecs/boost.podspec +++ b/node_modules/react-native/third-party-podspecs/boost.podspec @@ -10,7 +10,7 @@ Pod::Spec.new do |spec| spec.homepage = 'http://www.boost.org' spec.summary = 'Boost provides free peer-reviewed portable C++ source libraries.' spec.authors = 'Rene Rivera' - spec.source = { :http => 'https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.bz2', + spec.source = { :http => 'https://archives.boost.io/release/1.76.0/source/boost_1_76_0.tar.bz2', :sha256 => 'f0397ba6e982c4450f27bf32a2a83292aba035b827a5623a14636ea583318c41' } # Pinning to the same version as React.podspec.