diff --git a/React/Base/RCTKeyboardObserver.h b/React/Base/RCTKeyboardObserver.h new file mode 100644 index 000000000..8fad021f3 --- /dev/null +++ b/React/Base/RCTKeyboardObserver.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import "RCTBridgeModule.h" + +@interface RCTKeyboardObserver : NSObject + +@end diff --git a/React/Base/RCTKeyboardObserver.m b/React/Base/RCTKeyboardObserver.m new file mode 100644 index 000000000..5b0174cdf --- /dev/null +++ b/React/Base/RCTKeyboardObserver.m @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "RCTKeyboardObserver.h" + +#import "RCTEventDispatcher.h" + +static NSDictionary *RCTParseKeyboardNotification(NSNotification *notification); + +@implementation RCTKeyboardObserver + +@synthesize bridge = _bridge; + +RCT_EXPORT_MODULE() + +- (instancetype)init +{ + if ((self = [super init])) { + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + +#define ADD_KEYBOARD_HANDLER(NAME, SELECTOR) \ + [nc addObserver:self selector:@selector(SELECTOR:) name:NAME object:nil] + + ADD_KEYBOARD_HANDLER(UIKeyboardWillShowNotification, keyboardWillShow); + ADD_KEYBOARD_HANDLER(UIKeyboardDidShowNotification, keyboardDidShow); + ADD_KEYBOARD_HANDLER(UIKeyboardWillHideNotification, keyboardWillHide); + ADD_KEYBOARD_HANDLER(UIKeyboardDidHideNotification, keyboardDidHide); + ADD_KEYBOARD_HANDLER(UIKeyboardWillChangeFrameNotification, keyboardWillChangeFrame); + ADD_KEYBOARD_HANDLER(UIKeyboardDidChangeFrameNotification, keyboardDidChangeFrame); + +#undef ADD_KEYBOARD_HANDLER + } + + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +#define IMPLEMENT_KEYBOARD_HANDLER(EVENT) \ +- (void)EVENT:(NSNotification *)notification \ +{ \ + [_bridge.eventDispatcher \ + sendDeviceEventWithName:@#EVENT \ + body:RCTParseKeyboardNotification(notification)]; \ +} + +IMPLEMENT_KEYBOARD_HANDLER(keyboardWillShow) +IMPLEMENT_KEYBOARD_HANDLER(keyboardDidShow) +IMPLEMENT_KEYBOARD_HANDLER(keyboardWillHide) +IMPLEMENT_KEYBOARD_HANDLER(keyboardDidHide) +IMPLEMENT_KEYBOARD_HANDLER(keyboardWillChangeFrame) +IMPLEMENT_KEYBOARD_HANDLER(keyboardDidChangeFrame) + +@end + +static NSDictionary *RCTRectDictionaryValue(CGRect rect) +{ + return @{ + @"screenX": @(rect.origin.x), + @"screenY": @(rect.origin.y), + @"width": @(rect.size.width), + @"height": @(rect.size.height), + }; +} + +static NSDictionary *RCTParseKeyboardNotification(NSNotification *notification) +{ + NSDictionary *userInfo = notification.userInfo; + CGRect beginFrame = [userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue]; + CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; + NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + + return @{ + @"startCoordinates": RCTRectDictionaryValue(beginFrame), + @"endCoordinates": RCTRectDictionaryValue(endFrame), + @"duration": @(duration * 1000.0), // ms + }; +} diff --git a/React/React.xcodeproj/project.pbxproj b/React/React.xcodeproj/project.pbxproj index a13b6f357..97a278353 100644 --- a/React/React.xcodeproj/project.pbxproj +++ b/React/React.xcodeproj/project.pbxproj @@ -71,6 +71,7 @@ 830A229E1A66C68A008503DA /* RCTRootView.m in Sources */ = {isa = PBXBuildFile; fileRef = 830A229D1A66C68A008503DA /* RCTRootView.m */; }; 832348161A77A5AA00B55238 /* Layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FC71A68125100A75B9A /* Layout.c */; }; 83392EB31B6634E10013B15F /* RCTModalHostViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83392EB21B6634E10013B15F /* RCTModalHostViewController.m */; }; + 8385CF351B8B77CD00C6273E /* RCTKeyboardObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 8385CF341B8B77CD00C6273E /* RCTKeyboardObserver.m */; }; 83A1FE8C1B62640A00BE0E65 /* RCTModalHostView.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A1FE8B1B62640A00BE0E65 /* RCTModalHostView.m */; }; 83A1FE8F1B62643A00BE0E65 /* RCTModalHostViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A1FE8E1B62643A00BE0E65 /* RCTModalHostViewManager.m */; }; 83CBBA511A601E3B00E9B192 /* RCTAssert.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA4B1A601E3B00E9B192 /* RCTAssert.m */; }; @@ -233,6 +234,8 @@ 830A229D1A66C68A008503DA /* RCTRootView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRootView.m; sourceTree = ""; }; 83392EB11B6634E10013B15F /* RCTModalHostViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTModalHostViewController.h; sourceTree = ""; }; 83392EB21B6634E10013B15F /* RCTModalHostViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTModalHostViewController.m; sourceTree = ""; }; + 8385CF331B8B77CD00C6273E /* RCTKeyboardObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTKeyboardObserver.h; sourceTree = ""; }; + 8385CF341B8B77CD00C6273E /* RCTKeyboardObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTKeyboardObserver.m; sourceTree = ""; }; 83A1FE8A1B62640A00BE0E65 /* RCTModalHostView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTModalHostView.h; sourceTree = ""; }; 83A1FE8B1B62640A00BE0E65 /* RCTModalHostView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTModalHostView.m; sourceTree = ""; }; 83A1FE8D1B62643A00BE0E65 /* RCTModalHostViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTModalHostViewManager.h; sourceTree = ""; }; @@ -448,14 +451,15 @@ 83CBBA491A601E3B00E9B192 /* Base */ = { isa = PBXGroup; children = ( - 138D6A121B53CD290074A87E /* RCTCache.h */, - 138D6A131B53CD290074A87E /* RCTCache.m */, 83CBBA4A1A601E3B00E9B192 /* RCTAssert.h */, 83CBBA4B1A601E3B00E9B192 /* RCTAssert.m */, 14C2CA771B3ACB0400E6CBB2 /* RCTBatchedBridge.m */, 83CBBA5E1A601EAA00E9B192 /* RCTBridge.h */, 83CBBA5F1A601EAA00E9B192 /* RCTBridge.m */, + 1482F9E61B55B927000ADFF3 /* RCTBridgeDelegate.h */, 830213F31A654E0800B993E6 /* RCTBridgeModule.h */, + 138D6A121B53CD290074A87E /* RCTCache.h */, + 138D6A131B53CD290074A87E /* RCTCache.m */, 83CBBACA1A6023D300E9B192 /* RCTConvert.h */, 83CBBACB1A6023D300E9B192 /* RCTConvert.m */, 13AF1F851AE6E777005F5298 /* RCTDefines.h */, @@ -469,6 +473,8 @@ 83CBBA631A601ECA00E9B192 /* RCTJavaScriptExecutor.h */, 14200DA81AC179B3008EE6BA /* RCTJavaScriptLoader.h */, 14200DA91AC179B3008EE6BA /* RCTJavaScriptLoader.m */, + 8385CF331B8B77CD00C6273E /* RCTKeyboardObserver.h */, + 8385CF341B8B77CD00C6273E /* RCTKeyboardObserver.m */, 13A1F71C1A75392D00D3D453 /* RCTKeyCommands.h */, 13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */, 83CBBA4D1A601E3B00E9B192 /* RCTLog.h */, @@ -495,7 +501,6 @@ 1345A83B1B265A0E00583190 /* RCTURLRequestHandler.h */, 83CBBA4F1A601E3B00E9B192 /* RCTUtils.h */, 83CBBA501A601E3B00E9B192 /* RCTUtils.m */, - 1482F9E61B55B927000ADFF3 /* RCTBridgeDelegate.h */, ); path = Base; sourceTree = ""; @@ -603,6 +608,7 @@ 13CC8A821B17642100940AE7 /* RCTBorderDrawing.m in Sources */, 83CBBA511A601E3B00E9B192 /* RCTAssert.m in Sources */, 13AF20451AE707F9005F5298 /* RCTSlider.m in Sources */, + 8385CF351B8B77CD00C6273E /* RCTKeyboardObserver.m in Sources */, 58114A501AAE93D500E7D092 /* RCTAsyncLocalStorage.m in Sources */, 832348161A77A5AA00B55238 /* Layout.c in Sources */, 14F4D38B1AE1B7E40049C042 /* RCTProfile.m in Sources */,