1/* 2 * Copyright (c) Meta Platforms, Inc. and affiliates. 3 * 4 * This source code is licensed under the MIT license found in the 5 * LICENSE file in the root directory of this source tree. 6 */ 7 8#import <ABI48_0_0React/ABI48_0_0RCTBaseTextInputViewManager.h> 9 10#import <ABI48_0_0React/ABI48_0_0RCTBridge.h> 11#import <ABI48_0_0React/ABI48_0_0RCTConvert.h> 12#import <ABI48_0_0React/ABI48_0_0RCTFont.h> 13#import <ABI48_0_0React/ABI48_0_0RCTShadowView+Layout.h> 14#import <ABI48_0_0React/ABI48_0_0RCTShadowView.h> 15#import <ABI48_0_0React/ABI48_0_0RCTUIManager.h> 16#import <ABI48_0_0React/ABI48_0_0RCTUIManagerObserverCoordinator.h> 17#import <ABI48_0_0React/ABI48_0_0RCTUIManagerUtils.h> 18 19#import <ABI48_0_0React/ABI48_0_0RCTBaseTextInputShadowView.h> 20#import <ABI48_0_0React/ABI48_0_0RCTBaseTextInputView.h> 21#import <ABI48_0_0React/ABI48_0_0RCTConvert+Text.h> 22 23@interface ABI48_0_0RCTBaseTextInputViewManager () <ABI48_0_0RCTUIManagerObserver> 24 25@end 26 27@implementation ABI48_0_0RCTBaseTextInputViewManager { 28 NSHashTable<ABI48_0_0RCTBaseTextInputShadowView *> *_shadowViews; 29} 30 31ABI48_0_0RCT_EXPORT_MODULE() 32 33#pragma mark - Unified <TextInput> properties 34 35ABI48_0_0RCT_REMAP_VIEW_PROPERTY(autoCapitalize, backedTextInputView.autocapitalizationType, UITextAutocapitalizationType) 36ABI48_0_0RCT_REMAP_VIEW_PROPERTY(autoCorrect, backedTextInputView.autocorrectionType, UITextAutocorrectionType) 37ABI48_0_0RCT_REMAP_VIEW_PROPERTY(contextMenuHidden, backedTextInputView.contextMenuHidden, BOOL) 38ABI48_0_0RCT_REMAP_VIEW_PROPERTY(editable, backedTextInputView.editable, BOOL) 39ABI48_0_0RCT_REMAP_VIEW_PROPERTY(enablesReturnKeyAutomatically, backedTextInputView.enablesReturnKeyAutomatically, BOOL) 40ABI48_0_0RCT_REMAP_VIEW_PROPERTY(keyboardAppearance, backedTextInputView.keyboardAppearance, UIKeyboardAppearance) 41ABI48_0_0RCT_REMAP_VIEW_PROPERTY(placeholder, backedTextInputView.placeholder, NSString) 42ABI48_0_0RCT_REMAP_VIEW_PROPERTY(placeholderTextColor, backedTextInputView.placeholderColor, UIColor) 43ABI48_0_0RCT_REMAP_VIEW_PROPERTY(returnKeyType, backedTextInputView.returnKeyType, UIReturnKeyType) 44ABI48_0_0RCT_REMAP_VIEW_PROPERTY(selectionColor, backedTextInputView.tintColor, UIColor) 45ABI48_0_0RCT_REMAP_VIEW_PROPERTY(spellCheck, backedTextInputView.spellCheckingType, UITextSpellCheckingType) 46ABI48_0_0RCT_REMAP_VIEW_PROPERTY(caretHidden, backedTextInputView.caretHidden, BOOL) 47ABI48_0_0RCT_REMAP_VIEW_PROPERTY(clearButtonMode, backedTextInputView.clearButtonMode, UITextFieldViewMode) 48ABI48_0_0RCT_REMAP_VIEW_PROPERTY(scrollEnabled, backedTextInputView.scrollEnabled, BOOL) 49ABI48_0_0RCT_REMAP_VIEW_PROPERTY(secureTextEntry, backedTextInputView.secureTextEntry, BOOL) 50ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(autoFocus, BOOL) 51ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(submitBehavior, NSString) 52ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(clearTextOnFocus, BOOL) 53ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(keyboardType, UIKeyboardType) 54ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(showSoftInputOnFocus, BOOL) 55ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(maxLength, NSNumber) 56ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(selectTextOnFocus, BOOL) 57ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(selection, ABI48_0_0RCTTextSelection) 58ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(inputAccessoryViewID, NSString) 59ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(textContentType, NSString) 60ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(passwordRules, NSString) 61 62ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(onChange, ABI48_0_0RCTBubblingEventBlock) 63ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(onKeyPressSync, ABI48_0_0RCTDirectEventBlock) 64ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(onChangeSync, ABI48_0_0RCTDirectEventBlock) 65ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(onSelectionChange, ABI48_0_0RCTDirectEventBlock) 66ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(onTextInput, ABI48_0_0RCTDirectEventBlock) 67ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(onScroll, ABI48_0_0RCTDirectEventBlock) 68 69ABI48_0_0RCT_EXPORT_VIEW_PROPERTY(mostRecentEventCount, NSInteger) 70 71ABI48_0_0RCT_EXPORT_SHADOW_PROPERTY(text, NSString) 72ABI48_0_0RCT_EXPORT_SHADOW_PROPERTY(placeholder, NSString) 73ABI48_0_0RCT_EXPORT_SHADOW_PROPERTY(onContentSizeChange, ABI48_0_0RCTBubblingEventBlock) 74 75ABI48_0_0RCT_CUSTOM_VIEW_PROPERTY(multiline, BOOL, UIView) 76{ 77 // No op. 78 // This View Manager doesn't use this prop but it must be exposed here via ViewConfig to enable Fabric component use 79 // it. 80} 81 82- (ABI48_0_0RCTShadowView *)shadowView 83{ 84 ABI48_0_0RCTBaseTextInputShadowView *shadowView = [[ABI48_0_0RCTBaseTextInputShadowView alloc] initWithBridge:self.bridge]; 85 shadowView.textAttributes.fontSizeMultiplier = 86 [[[self.bridge moduleForName:@"AccessibilityManager" 87 lazilyLoadIfNecessary:YES] valueForKey:@"multiplier"] floatValue]; 88 [_shadowViews addObject:shadowView]; 89 return shadowView; 90} 91 92- (void)setBridge:(ABI48_0_0RCTBridge *)bridge 93{ 94 [super setBridge:bridge]; 95 96 _shadowViews = [NSHashTable weakObjectsHashTable]; 97 98 [bridge.uiManager.observerCoordinator addObserver:self]; 99 100 [[NSNotificationCenter defaultCenter] addObserver:self 101 selector:@selector(handleDidUpdateMultiplierNotification) 102 name:@"ABI48_0_0RCTAccessibilityManagerDidUpdateMultiplierNotification" 103 object:[bridge moduleForName:@"AccessibilityManager" 104 lazilyLoadIfNecessary:YES]]; 105} 106 107ABI48_0_0RCT_EXPORT_METHOD(focus : (nonnull NSNumber *)viewTag) 108{ 109 [self.bridge.uiManager addUIBlock:^(ABI48_0_0RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) { 110 UIView *view = viewRegistry[viewTag]; 111 [view ABI48_0_0ReactFocus]; 112 }]; 113} 114 115ABI48_0_0RCT_EXPORT_METHOD(blur : (nonnull NSNumber *)viewTag) 116{ 117 [self.bridge.uiManager addUIBlock:^(ABI48_0_0RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) { 118 UIView *view = viewRegistry[viewTag]; 119 [view ABI48_0_0ReactBlur]; 120 }]; 121} 122 123ABI48_0_0RCT_EXPORT_METHOD(setTextAndSelection 124 : (nonnull NSNumber *)viewTag mostRecentEventCount 125 : (NSInteger)mostRecentEventCount value 126 : (NSString *)value start 127 : (NSInteger)start end 128 : (NSInteger)end) 129{ 130 [self.bridge.uiManager addUIBlock:^(ABI48_0_0RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) { 131 ABI48_0_0RCTBaseTextInputView *view = (ABI48_0_0RCTBaseTextInputView *)viewRegistry[viewTag]; 132 NSInteger eventLag = view.nativeEventCount - mostRecentEventCount; 133 if (eventLag != 0) { 134 return; 135 } 136 ABI48_0_0RCTExecuteOnUIManagerQueue(^{ 137 ABI48_0_0RCTBaseTextInputShadowView *shadowView = 138 (ABI48_0_0RCTBaseTextInputShadowView *)[self.bridge.uiManager shadowViewForABI48_0_0ReactTag:viewTag]; 139 if (value) { 140 [shadowView setText:value]; 141 } 142 [self.bridge.uiManager setNeedsLayout]; 143 ABI48_0_0RCTExecuteOnMainQueue(^{ 144 [view setSelectionStart:start selectionEnd:end]; 145 }); 146 }); 147 }]; 148} 149 150#pragma mark - ABI48_0_0RCTUIManagerObserver 151 152- (void)uiManagerWillPerformMounting:(__unused ABI48_0_0RCTUIManager *)uiManager 153{ 154 for (ABI48_0_0RCTBaseTextInputShadowView *shadowView in _shadowViews) { 155 [shadowView uiManagerWillPerformMounting]; 156 } 157} 158 159#pragma mark - Font Size Multiplier 160 161- (void)handleDidUpdateMultiplierNotification 162{ 163 CGFloat fontSizeMultiplier = 164 [[[self.bridge moduleForName:@"AccessibilityManager"] valueForKey:@"multiplier"] floatValue]; 165 166 NSHashTable<ABI48_0_0RCTBaseTextInputShadowView *> *shadowViews = _shadowViews; 167 ABI48_0_0RCTExecuteOnUIManagerQueue(^{ 168 for (ABI48_0_0RCTBaseTextInputShadowView *shadowView in shadowViews) { 169 shadowView.textAttributes.fontSizeMultiplier = fontSizeMultiplier; 170 [shadowView dirtyLayout]; 171 } 172 173 [self.bridge.uiManager setNeedsLayout]; 174 }); 175} 176 177@end 178