diff --git a/patches/react-native+0.63.4.patch b/patches/react-native+0.63.4.patch index 3aaa11b7f..ba1132911 100644 --- a/patches/react-native+0.63.4.patch +++ b/patches/react-native+0.63.4.patch @@ -1,156 +1,156 @@ diff --git a/node_modules/react-native/Libraries/Components/TextInput/TextInput.js b/node_modules/react-native/Libraries/Components/TextInput/TextInput.js index b124944..28535ed 100644 --- a/node_modules/react-native/Libraries/Components/TextInput/TextInput.js +++ b/node_modules/react-native/Libraries/Components/TextInput/TextInput.js @@ -207,6 +207,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, + /** * If `false`, disables spell-check style (i.e. red underlines). * The default value is inherited from `autoCorrect`. diff --git a/node_modules/react-native/Libraries/Components/Touchable/TouchableNativeFeedback.js b/node_modules/react-native/Libraries/Components/Touchable/TouchableNativeFeedback.js index 5dc03df..e526092 100644 --- a/node_modules/react-native/Libraries/Components/Touchable/TouchableNativeFeedback.js +++ b/node_modules/react-native/Libraries/Components/Touchable/TouchableNativeFeedback.js @@ -338,7 +338,7 @@ class TouchableNativeFeedback extends React.Component { } const getBackgroundProp = - Platform.OS === 'android' + Platform.OS === 'android' && Platform.Version >= 21 ? (background, useForeground) => useForeground && TouchableNativeFeedback.canUseNativeForeground() ? {nativeForegroundAndroid: background} 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 7e12add..6979293 100644 +index 7e12add..d21daf8 100644 --- a/node_modules/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h +++ b/node_modules/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h @@ -36,6 +36,7 @@ NS_ASSUME_NONNULL_BEGIN // The `caretHidden` property actually is not supported yet; // it's declared here only to conform to the interface. @property (nonatomic, assign) BOOL caretHidden; -+@property (nonatomic, assign) NSString *allowImagePasteForThreadID; ++@property (nonatomic, copy, nullable) NSString *allowImagePasteForThreadID; @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 88d3183..25d00e2 100644 --- a/node_modules/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m +++ b/node_modules/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m @@ -173,8 +173,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; + } } - (void)setContentOffset:(CGPoint)contentOffset animated:(__unused BOOL)animated @@ -261,6 +265,9 @@ - (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 3e1839b..8fe347e 100644 --- a/node_modules/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegate.h +++ b/node_modules/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegate.h @@ -32,6 +32,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)textInputDidChange; - (void)textInputDidChangeSelection; +- (void)textInputImagePasted:(NSString *)threadID; @optional diff --git a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m index aa69593..e98bfd6 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 RCTEventDispatcher *_eventDispatcher; @@ -479,6 +481,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 dca1437..cede0b4 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)