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 "ABI47_0_0RCTKeyboardObserver.h" 9 10#import <ABI47_0_0FBReactNativeSpec/ABI47_0_0FBReactNativeSpec.h> 11#import <ABI47_0_0React/ABI47_0_0RCTEventDispatcherProtocol.h> 12 13#import "ABI47_0_0CoreModulesPlugins.h" 14 15static NSDictionary *ABI47_0_0RCTParseKeyboardNotification(NSNotification *notification); 16 17@interface ABI47_0_0RCTKeyboardObserver () <ABI47_0_0NativeKeyboardObserverSpec> 18@end 19 20@implementation ABI47_0_0RCTKeyboardObserver 21 22ABI47_0_0RCT_EXPORT_MODULE() 23 24- (void)startObserving 25{ 26 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 27 28#define ADD_KEYBOARD_HANDLER(NAME, SELECTOR) [nc addObserver:self selector:@selector(SELECTOR:) name:NAME object:nil] 29 30 ADD_KEYBOARD_HANDLER(UIKeyboardWillShowNotification, keyboardWillShow); 31 ADD_KEYBOARD_HANDLER(UIKeyboardDidShowNotification, keyboardDidShow); 32 ADD_KEYBOARD_HANDLER(UIKeyboardWillHideNotification, keyboardWillHide); 33 ADD_KEYBOARD_HANDLER(UIKeyboardDidHideNotification, keyboardDidHide); 34 ADD_KEYBOARD_HANDLER(UIKeyboardWillChangeFrameNotification, keyboardWillChangeFrame); 35 ADD_KEYBOARD_HANDLER(UIKeyboardDidChangeFrameNotification, keyboardDidChangeFrame); 36 37#undef ADD_KEYBOARD_HANDLER 38} 39 40- (NSArray<NSString *> *)supportedEvents 41{ 42 return @[ 43 @"keyboardWillShow", 44 @"keyboardDidShow", 45 @"keyboardWillHide", 46 @"keyboardDidHide", 47 @"keyboardWillChangeFrame", 48 @"keyboardDidChangeFrame" 49 ]; 50} 51 52- (void)stopObserving 53{ 54 [[NSNotificationCenter defaultCenter] removeObserver:self]; 55} 56 57// Bridge might be already invalidated by the time the keyboard is about to be dismissed. 58// This might happen, for example, when reload from the packager is performed. 59// Thus we need to check against nil here. 60#define IMPLEMENT_KEYBOARD_HANDLER(EVENT) \ 61 -(void)EVENT : (NSNotification *)notification \ 62 { \ 63 if (!self.callableJSModules) { \ 64 return; \ 65 } \ 66 [self sendEventWithName:@ #EVENT body:ABI47_0_0RCTParseKeyboardNotification(notification)]; \ 67 } 68 69IMPLEMENT_KEYBOARD_HANDLER(keyboardWillShow) 70IMPLEMENT_KEYBOARD_HANDLER(keyboardDidShow) 71IMPLEMENT_KEYBOARD_HANDLER(keyboardWillHide) 72IMPLEMENT_KEYBOARD_HANDLER(keyboardDidHide) 73IMPLEMENT_KEYBOARD_HANDLER(keyboardWillChangeFrame) 74IMPLEMENT_KEYBOARD_HANDLER(keyboardDidChangeFrame) 75 76- (std::shared_ptr<ABI47_0_0facebook::ABI47_0_0React::TurboModule>)getTurboModule: 77 (const ABI47_0_0facebook::ABI47_0_0React::ObjCTurboModule::InitParams &)params 78{ 79 return std::make_shared<ABI47_0_0facebook::ABI47_0_0React::NativeKeyboardObserverSpecJSI>(params); 80} 81 82@end 83 84NS_INLINE NSDictionary *ABI47_0_0RCTRectDictionaryValue(CGRect rect) 85{ 86 return @{ 87 @"screenX" : @(rect.origin.x), 88 @"screenY" : @(rect.origin.y), 89 @"width" : @(rect.size.width), 90 @"height" : @(rect.size.height), 91 }; 92} 93 94static NSString *ABI47_0_0RCTAnimationNameForCurve(UIViewAnimationCurve curve) 95{ 96 switch (curve) { 97 case UIViewAnimationCurveEaseIn: 98 return @"easeIn"; 99 case UIViewAnimationCurveEaseInOut: 100 return @"easeInEaseOut"; 101 case UIViewAnimationCurveEaseOut: 102 return @"easeOut"; 103 case UIViewAnimationCurveLinear: 104 return @"linear"; 105 default: 106 return @"keyboard"; 107 } 108} 109 110static NSDictionary *ABI47_0_0RCTParseKeyboardNotification(NSNotification *notification) 111{ 112 NSDictionary *userInfo = notification.userInfo; 113 CGRect beginFrame = [userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue]; 114 CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; 115 NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 116 UIViewAnimationCurve curve = 117 static_cast<UIViewAnimationCurve>([userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]); 118 NSInteger isLocalUserInfoKey = [userInfo[UIKeyboardIsLocalUserInfoKey] integerValue]; 119 120 return @{ 121 @"startCoordinates" : ABI47_0_0RCTRectDictionaryValue(beginFrame), 122 @"endCoordinates" : ABI47_0_0RCTRectDictionaryValue(endFrame), 123 @"duration" : @(duration * 1000.0), // ms 124 @"easing" : ABI47_0_0RCTAnimationNameForCurve(curve), 125 @"isEventFromThisApp" : isLocalUserInfoKey == 1 ? @YES : @NO, 126 }; 127} 128 129Class ABI47_0_0RCTKeyboardObserverCls(void) 130{ 131 return ABI47_0_0RCTKeyboardObserver.class; 132} 133