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