diff --git a/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h b/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h index 1215ff0843402f..205f9943262add 100644 --- a/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h +++ b/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h @@ -24,6 +24,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) BOOL contextMenuHidden; @property (nonatomic, assign, readonly) BOOL textWasPasted; +@property (nonatomic, assign, readonly) BOOL dictationRecognizing; @property (nonatomic, copy, nullable) NSString *placeholder; @property (nonatomic, strong, nullable) UIColor *placeholderColor; diff --git a/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m b/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m index 61b9dadc19bc4c..0befbaba4ed5b3 100644 --- a/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m +++ b/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m @@ -261,6 +261,17 @@ - (BOOL)canPerformAction:(SEL)action withSender:(id)sender return [super canPerformAction:action withSender:sender]; } +#pragma mark - Dictation + +- (void)dictationRecordingDidEnd { + _dictationRecognizing = YES; +} + +- (void)removeDictationResultPlaceholder:(id)placeholder willInsertResult:(BOOL)willInsertResult { + [super removeDictationResultPlaceholder:placeholder willInsertResult:willInsertResult]; + _dictationRecognizing = NO; +} + #pragma mark - Placeholder - (void)_invalidatePlaceholderVisibility diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h b/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h index 686af9e3a363e2..a8719ecd4d0165 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h +++ b/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h @@ -18,6 +18,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy, nullable) NSString *placeholder; @property (nonatomic, strong, nullable) UIColor *placeholderColor; @property (nonatomic, assign, readonly) BOOL textWasPasted; +@property (nonatomic, assign, readonly) BOOL dictationRecognizing; @property (nonatomic, assign) UIEdgeInsets textContainerInset; @property (nonatomic, strong, nullable) UIView *inputAccessoryView; @property (nonatomic, strong, nullable) UIView *inputView; diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m index cb496feb2791d1..b33ac10420ec3e 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -119,8 +119,13 @@ - (BOOL)textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldTex } }]; + BOOL shouldFallbackDictation = [self.backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"dictation"]; + if (@available(iOS 16.0, *)) { + shouldFallbackDictation = self.backedTextInputView.dictationRecognizing; + } + BOOL shouldFallbackToBareTextComparison = - [self.backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"dictation"] || + shouldFallbackDictation || [self.backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"ko-KR"] || self.backedTextInputView.markedTextRange || self.backedTextInputView.isSecureTextEntry || fontHasBeenUpdatedBySystem; diff --git a/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.h b/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.h index b26b41f8693d7b..91f8eb087acf87 100644 --- a/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.h +++ b/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.h @@ -24,6 +24,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) BOOL caretHidden; @property (nonatomic, assign) BOOL contextMenuHidden; @property (nonatomic, assign, readonly) BOOL textWasPasted; +@property (nonatomic, assign, readonly) BOOL dictationRecognizing; @property (nonatomic, strong, nullable) UIColor *placeholderColor; @property (nonatomic, assign) UIEdgeInsets textContainerInset; @property (nonatomic, assign, getter=isEditable) BOOL editable; diff --git a/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.m b/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.m index 3d116019b89cde..d6b613235f2b72 100644 --- a/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.m +++ b/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.m @@ -142,6 +142,17 @@ - (BOOL)canPerformAction:(SEL)action withSender:(id)sender return [super canPerformAction:action withSender:sender]; } +#pragma mark - Dictation + +- (void)dictationRecordingDidEnd { + _dictationRecognizing = YES; +} + +- (void)removeDictationResultPlaceholder:(id)placeholder willInsertResult:(BOOL)willInsertResult { + [super removeDictationResultPlaceholder:placeholder willInsertResult:willInsertResult]; + _dictationRecognizing = NO; +} + #pragma mark - Caret Manipulation - (CGRect)caretRectForPosition:(UITextPosition *)position