From 2ae45ec3ce50cb9d95782173f6dfca74e8110848 Mon Sep 17 00:00:00 2001 From: VidocqH Date: Tue, 28 Jan 2025 05:07:26 -0800 Subject: [PATCH] fix TextInput `dataDetectorTypes` (#48952) Summary: Setting `dataDetectorTypes` has no effect. As I am new to the react native codebase, it seems like `dataDetectorTypes` has not implemented on new arch yet. issue: https://github.com/facebook/react-native/issues/48951 ## Changelog: [IOS] [FIXED] - implement `dataDetectorTypes` in the same way as the old architecture Pull Request resolved: https://github.com/facebook/react-native/pull/48952 Test Plan: image Reviewed By: javache Differential Revision: D68715166 Pulled By: cipolleschi fbshipit-source-id: 612119e7453da012e6f75e1fc3a22ddedcb569a4 --- .../RCTBackedTextInputViewProtocol.h | 1 + .../TextInput/Singleline/RCTUITextField.mm | 4 +++ .../TextInput/RCTTextInputComponentView.mm | 6 ++++ .../TextInput/RCTTextInputUtils.h | 2 ++ .../TextInput/RCTTextInputUtils.mm | 28 +++++++++++++++++++ .../components/iostextinput/primitives.h | 7 +++++ .../iostextinput/propsConversions.h | 7 +++++ .../TextInput/TextInputExample.ios.js | 8 ++++++ 8 files changed, 63 insertions(+) diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h b/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h index 1f1af7ee7f0..d2cec7f1bfb 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h +++ b/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h @@ -30,6 +30,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) BOOL caretHidden; @property (nonatomic, assign) BOOL enablesReturnKeyAutomatically; @property (nonatomic, assign) UITextFieldViewMode clearButtonMode; +@property (nonatomic, assign) UIDataDetectorTypes dataDetectorTypes; @property (nonatomic, getter=isScrollEnabled) BOOL scrollEnabled; @property (nonatomic, strong, nullable) NSString *inputAccessoryViewID; @property (nonatomic, strong, nullable) NSString *inputAccessoryViewButtonLabel; diff --git a/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.mm b/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.mm index 338a1f4fa99..d1bcd88a988 100644 --- a/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.mm +++ b/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.mm @@ -19,6 +19,10 @@ NSArray *_initialValueTrailingBarButtonGroups; } +// This should not be needed but internal build were failing without it. +// This variable is unused. +@synthesize dataDetectorTypes; + - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index faa494a615d..940c4bd608e 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -194,6 +194,12 @@ static NSSet *returnKeyTypesSet; _backedTextInputView.editable = newTextInputProps.traits.editable; } + if (newTextInputProps.multiline && + newTextInputProps.traits.dataDetectorTypes != oldTextInputProps.traits.dataDetectorTypes) { + _backedTextInputView.dataDetectorTypes = + RCTUITextViewDataDetectorTypesFromStringVector(newTextInputProps.traits.dataDetectorTypes); + } + if (newTextInputProps.traits.enablesReturnKeyAutomatically != oldTextInputProps.traits.enablesReturnKeyAutomatically) { _backedTextInputView.enablesReturnKeyAutomatically = newTextInputProps.traits.enablesReturnKeyAutomatically; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.h b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.h index 02a1570df34..5f20d8762f4 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.h +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.h @@ -41,4 +41,6 @@ UITextInputPasswordRules *RCTUITextInputPasswordRulesFromString(const std::strin UITextSmartInsertDeleteType RCTUITextSmartInsertDeleteTypeFromOptionalBool(std::optional smartInsertDelete); +UIDataDetectorTypes RCTUITextViewDataDetectorTypesFromStringVector(const std::vector &dataDetectorTypes); + NS_ASSUME_NONNULL_END diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm index 6e562ada332..fb7d5ca1c17 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm @@ -269,3 +269,31 @@ UITextSmartInsertDeleteType RCTUITextSmartInsertDeleteTypeFromOptionalBool(std:: ? (*smartInsertDelete ? UITextSmartInsertDeleteTypeYes : UITextSmartInsertDeleteTypeNo) : UITextSmartInsertDeleteTypeDefault; } + +UIDataDetectorTypes RCTUITextViewDataDetectorTypesFromStringVector(const std::vector &dataDetectorTypes) +{ + static dispatch_once_t onceToken; + static NSDictionary *dataDetectorTypesMap = nil; + + dispatch_once(&onceToken, ^{ + dataDetectorTypesMap = @{ + @"link" : @(UIDataDetectorTypeLink), + @"phoneNumber" : @(UIDataDetectorTypePhoneNumber), + @"address" : @(UIDataDetectorTypeAddress), + @"calendarEvent" : @(UIDataDetectorTypeCalendarEvent), + @"trackingNumber" : @(UIDataDetectorTypeShipmentTrackingNumber), + @"flightNumber" : @(UIDataDetectorTypeFlightNumber), + @"lookupSuggestion" : @(UIDataDetectorTypeLookupSuggestion), + @"all" : @(UIDataDetectorTypeAll) + }; + }); + + UIDataDetectorTypes ret = UIDataDetectorTypeNone; + for (const auto &dataType : dataDetectorTypes) { + NSNumber *val = dataDetectorTypesMap[RCTNSStringFromString(dataType)]; + if (val) { + ret |= (UIDataDetectorTypes)val.unsignedIntValue; + } + } + return ret; +} diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/primitives.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/primitives.h index a6e6dfd2a49..a5ace05d642 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/primitives.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/primitives.h @@ -10,6 +10,7 @@ #include #include #include +#include namespace facebook::react { @@ -192,6 +193,12 @@ class TextInputTraits final { */ bool selectTextOnFocus{false}; + /* + * iOS-only + * Default value: `empty` (`null`). + */ + std::vector dataDetectorTypes{}; + /* * iOS-only (inherently iOS-specific) * Default value: `` (default content type). diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/propsConversions.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/propsConversions.h index ccbbe207736..8039fbf56b1 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/propsConversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/propsConversions.h @@ -136,6 +136,13 @@ static TextInputTraits convertRawProp( sourceTraits.smartInsertDelete, defaultTraits.smartInsertDelete); + traits.dataDetectorTypes = convertRawProp( + context, + rawProps, + "dataDetectorTypes", + sourceTraits.dataDetectorTypes, + defaultTraits.dataDetectorTypes); + return traits; } diff --git a/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js b/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js index d94a57d4b1b..fcec23ea083 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js @@ -633,6 +633,14 @@ const textInputExamples: Array = [ style={styles.multiline} dataDetectorTypes="phoneNumber" /> + ); },