mirror of
https://github.com/status-im/react-native.git
synced 2025-02-25 15:45:32 +00:00
Unfork UIManager
This commit is contained in:
parent
909e393f26
commit
94db4facf5
@ -7,6 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
13ACB6741AC2117000FF4204 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13ACB6711AC2113600FF4204 /* libRCTAnimation.a */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
@ -16,6 +17,13 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
13ACB6701AC2113600FF4204 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 13ACB66C1AC2113500FF4204 /* RCTAnimation.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RCTAnimation;
|
||||
};
|
||||
832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
|
||||
@ -33,6 +41,7 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
13ACB66C1AC2113500FF4204 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = ../../Libraries/Animation/RCTAnimation.xcodeproj; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* 2048.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = 2048.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = 2048/AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = 2048/AppDelegate.m; sourceTree = "<group>"; };
|
||||
@ -49,6 +58,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13ACB6741AC2117000FF4204 /* libRCTAnimation.a in Frameworks */,
|
||||
8323482C1A77B59500B55238 /* libReactKit.a in Frameworks */,
|
||||
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
|
||||
);
|
||||
@ -57,6 +67,14 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
13ACB66D1AC2113500FF4204 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13ACB6711AC2113600FF4204 /* libRCTAnimation.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13B07FAE1A68108700A75B9A /* 2048 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -75,6 +93,7 @@
|
||||
children = (
|
||||
834D32361A76971A00F38302 /* ReactKit.xcodeproj */,
|
||||
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
|
||||
13ACB66C1AC2113500FF4204 /* RCTAnimation.xcodeproj */,
|
||||
);
|
||||
name = Libraries;
|
||||
sourceTree = "<group>";
|
||||
@ -153,6 +172,10 @@
|
||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectReferences = (
|
||||
{
|
||||
ProductGroup = 13ACB66D1AC2113500FF4204 /* Products */;
|
||||
ProjectRef = 13ACB66C1AC2113500FF4204 /* RCTAnimation.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 832341B11AAA6A8300B99B32 /* Products */;
|
||||
ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
|
||||
@ -170,6 +193,13 @@
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
13ACB6711AC2113600FF4204 /* libRCTAnimation.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTAnimation.a;
|
||||
remoteRef = 13ACB6701AC2113600FF4204 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
832341B51AAA6A8300B99B32 /* libRCTText.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
|
256
Libraries/Animation/RCTAnimation.xcodeproj/project.pbxproj
Normal file
256
Libraries/Animation/RCTAnimation.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,256 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
13BE3DEE1AC21097009241FE /* RCTAnimationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* RCTAnimationManager.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
58B511D91A9E6C8500147676 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "include/$(PRODUCT_NAME)";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
134814201AA4EA6300B7C361 /* libRCTAnimation.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTAnimation.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13BE3DEC1AC21097009241FE /* RCTAnimationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAnimationManager.h; sourceTree = "<group>"; };
|
||||
13BE3DED1AC21097009241FE /* RCTAnimationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAnimationManager.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
58B511D81A9E6C8500147676 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
134814211AA4EA7D00B7C361 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
134814201AA4EA6300B7C361 /* libRCTAnimation.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
58B511D21A9E6C8500147676 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13BE3DEC1AC21097009241FE /* RCTAnimationManager.h */,
|
||||
13BE3DED1AC21097009241FE /* RCTAnimationManager.m */,
|
||||
134814211AA4EA7D00B7C361 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
58B511DA1A9E6C8500147676 /* RCTAnimation */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTAnimation" */;
|
||||
buildPhases = (
|
||||
58B511D71A9E6C8500147676 /* Sources */,
|
||||
58B511D81A9E6C8500147676 /* Frameworks */,
|
||||
58B511D91A9E6C8500147676 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = RCTAnimation;
|
||||
productName = RCTDataManager;
|
||||
productReference = 134814201AA4EA6300B7C361 /* libRCTAnimation.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
58B511D31A9E6C8500147676 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
TargetAttributes = {
|
||||
58B511DA1A9E6C8500147676 = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTAnimation" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 58B511D21A9E6C8500147676;
|
||||
productRefGroup = 58B511D21A9E6C8500147676;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
58B511DA1A9E6C8500147676 /* RCTAnimation */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
58B511D71A9E6C8500147676 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13BE3DEE1AC21097009241FE /* RCTAnimationManager.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
58B511ED1A9E6C8500147676 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
58B511EE1A9E6C8500147676 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
58B511F01A9E6C8500147676 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/ReactKit/build/Debug-iphoneos",
|
||||
);
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = RCTAnimation;
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
58B511F11A9E6C8500147676 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/ReactKit/build/Debug-iphoneos",
|
||||
);
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = RCTAnimation;
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTAnimation" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
58B511ED1A9E6C8500147676 /* Debug */,
|
||||
58B511EE1A9E6C8500147676 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTAnimation" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
58B511F01A9E6C8500147676 /* Debug */,
|
||||
58B511F11A9E6C8500147676 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 58B511D31A9E6C8500147676 /* Project object */;
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <Accelerate/Accelerate.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTBridgeModule.h"
|
@ -9,7 +9,6 @@
|
||||
|
||||
#import "RCTAnimationManager.h"
|
||||
|
||||
#import <Accelerate/Accelerate.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTSparseArray.h"
|
||||
@ -54,10 +53,10 @@
|
||||
|
||||
return ^(CGFloat t) {
|
||||
const CGFloat *delta = deltaData.bytes;
|
||||
const CGFloat *fromArray = fromData.bytes;
|
||||
const CGFloat *_fromArray = fromData.bytes;
|
||||
|
||||
CGFloat value[count];
|
||||
CG_APPEND(vDSP_vma,,D)(delta, 1, &t, 0, fromArray, 1, value, 1, count);
|
||||
CG_APPEND(vDSP_vma,,D)(delta, 1, &t, 0, _fromArray, 1, value, 1, count);
|
||||
return [NSValue valueWithBytes:value objCType:typeName];
|
||||
};
|
||||
}
|
||||
@ -84,10 +83,10 @@
|
||||
} else if ([obj respondsToSelector:@selector(count)]) {
|
||||
switch ([obj count]) {
|
||||
case 2:
|
||||
if ([obj respondsToSelector:@selector(objectForKey:)] && [obj objectForKey:@"w"]) {
|
||||
toValue = [NSValue valueWithCGSize:[RCTConvert CGSize:obj]];
|
||||
} else {
|
||||
if ([obj respondsToSelector:@selector(objectForKeyedSubscript:)] && obj[@"x"]) {
|
||||
toValue = [NSValue valueWithCGPoint:[RCTConvert CGPoint:obj]];
|
||||
} else {
|
||||
toValue = [NSValue valueWithCGSize:[RCTConvert CGSize:obj]];
|
||||
}
|
||||
break;
|
||||
case 4:
|
@ -50,9 +50,9 @@ NSString *const RCTOpenURLNotification = @"RCTOpenURLNotification";
|
||||
|
||||
+ (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
|
||||
{
|
||||
#ifdef __IPHONE_8_0
|
||||
[application registerForRemoteNotifications];
|
||||
#endif
|
||||
if ([application respondsToSelector:@selector(registerForRemoteNotifications)]) {
|
||||
[application registerForRemoteNotifications];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification
|
||||
@ -112,13 +112,22 @@ NSString *const RCTOpenURLNotification = @"RCTOpenURLNotification";
|
||||
{
|
||||
RCT_EXPORT();
|
||||
|
||||
#ifdef __IPHONE_8_0
|
||||
UIUserNotificationType types = UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert;
|
||||
UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
|
||||
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
|
||||
#else
|
||||
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
|
||||
|
||||
// if we are targeting iOS 7, *and* the new UIUserNotificationSettings
|
||||
// class is not available, then register using the old mechanism
|
||||
if (![UIUserNotificationSettings class]) {
|
||||
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
|
||||
UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert];
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
UIUserNotificationType types = UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert;
|
||||
UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
|
||||
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
|
||||
|
||||
}
|
||||
|
||||
+ (void)checkPermissions:(RCTResponseSenderBlock)callback
|
||||
@ -126,17 +135,11 @@ NSString *const RCTOpenURLNotification = @"RCTOpenURLNotification";
|
||||
RCT_EXPORT();
|
||||
|
||||
NSMutableDictionary *permissions = [[NSMutableDictionary alloc] init];
|
||||
#ifdef __IPHONE_8_0
|
||||
|
||||
UIUserNotificationType types = [[[UIApplication sharedApplication] currentUserNotificationSettings] types];
|
||||
permissions[@"alert"] = @((BOOL)(types & UIUserNotificationTypeAlert));
|
||||
permissions[@"badge"] = @((BOOL)(types & UIUserNotificationTypeBadge));
|
||||
permissions[@"sound"] = @((BOOL)(types & UIUserNotificationTypeSound));
|
||||
#else
|
||||
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
|
||||
permissions[@"alert"] = @((BOOL)(types & UIRemoteNotificationTypeAlert));
|
||||
permissions[@"badge"] = @((BOOL)(types & UIRemoteNotificationTypeBadge));
|
||||
permissions[@"sound"] = @((BOOL)(types & UIRemoteNotificationTypeSound));
|
||||
#endif
|
||||
|
||||
callback(@[permissions]);
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
#import "SRWebSocket.h"
|
||||
|
||||
#import <Availability.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#define HAS_ICU
|
||||
#endif
|
||||
@ -110,14 +112,19 @@ static NSString *newSHA1String(const char *bytes, size_t length) {
|
||||
assert(length >= 0);
|
||||
assert(length <= UINT32_MAX);
|
||||
CC_SHA1(bytes, (CC_LONG)length, md);
|
||||
|
||||
|
||||
NSData *data = [NSData dataWithBytes:md length:CC_SHA1_DIGEST_LENGTH];
|
||||
|
||||
if ([data respondsToSelector:@selector(base64EncodedStringWithOptions:)]) {
|
||||
return [data base64EncodedStringWithOptions:0];
|
||||
|
||||
#if (__IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0) \
|
||||
|| (__MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9)
|
||||
|
||||
if (![NSData instancesRespondToSelector:@selector(base64EncodedStringWithOptions:)]) {
|
||||
return [data base64Encoding];
|
||||
}
|
||||
|
||||
return [data base64Encoding];
|
||||
#endif
|
||||
|
||||
return [data base64EncodedStringWithOptions:0];
|
||||
}
|
||||
|
||||
@implementation NSData (SRWebSocket)
|
||||
@ -212,19 +219,19 @@ typedef void (^data_callback)(SRWebSocket *webSocket, NSData *data);
|
||||
|
||||
@implementation SRWebSocket {
|
||||
NSInteger _webSocketVersion;
|
||||
|
||||
|
||||
NSOperationQueue *_delegateOperationQueue;
|
||||
dispatch_queue_t _delegateDispatchQueue;
|
||||
|
||||
|
||||
dispatch_queue_t _workQueue;
|
||||
NSMutableArray *_consumers;
|
||||
|
||||
NSInputStream *_inputStream;
|
||||
NSOutputStream *_outputStream;
|
||||
|
||||
|
||||
NSMutableData *_readBuffer;
|
||||
NSUInteger _readBufferOffset;
|
||||
|
||||
|
||||
NSMutableData *_outputBuffer;
|
||||
NSUInteger _outputBufferOffset;
|
||||
|
||||
@ -233,18 +240,18 @@ typedef void (^data_callback)(SRWebSocket *webSocket, NSData *data);
|
||||
size_t _readOpCount;
|
||||
uint32_t _currentStringScanPosition;
|
||||
NSMutableData *_currentFrameData;
|
||||
|
||||
|
||||
NSString *_closeReason;
|
||||
|
||||
|
||||
NSString *_secKey;
|
||||
|
||||
|
||||
BOOL _pinnedCertFound;
|
||||
|
||||
|
||||
uint8_t _currentReadMaskKey[4];
|
||||
size_t _currentReadMaskOffset;
|
||||
|
||||
BOOL _consumerStopped;
|
||||
|
||||
|
||||
BOOL _closeWhenFinishedWriting;
|
||||
BOOL _failed;
|
||||
|
||||
@ -252,18 +259,18 @@ typedef void (^data_callback)(SRWebSocket *webSocket, NSData *data);
|
||||
NSURLRequest *_urlRequest;
|
||||
|
||||
CFHTTPMessageRef _receivedHTTPHeaders;
|
||||
|
||||
|
||||
BOOL _sentClose;
|
||||
BOOL _didFail;
|
||||
int _closeCode;
|
||||
|
||||
|
||||
BOOL _isPumping;
|
||||
|
||||
|
||||
NSMutableSet *_scheduledRunloops;
|
||||
|
||||
|
||||
// We use this to retain ourselves.
|
||||
__strong SRWebSocket *_selfRetain;
|
||||
|
||||
|
||||
NSArray *_requestedProtocols;
|
||||
SRIOConsumerPool *_consumerPool;
|
||||
}
|
||||
@ -287,12 +294,12 @@ static __strong NSData *CRLFCRLF;
|
||||
assert(request.URL);
|
||||
_url = request.URL;
|
||||
_urlRequest = request;
|
||||
|
||||
|
||||
_requestedProtocols = [protocols copy];
|
||||
|
||||
|
||||
[self _SR_commonInit];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -314,39 +321,38 @@ static __strong NSData *CRLFCRLF;
|
||||
|
||||
- (void)_SR_commonInit;
|
||||
{
|
||||
|
||||
NSString *scheme = _url.scheme.lowercaseString;
|
||||
assert([scheme isEqualToString:@"ws"] || [scheme isEqualToString:@"http"] || [scheme isEqualToString:@"wss"] || [scheme isEqualToString:@"https"]);
|
||||
|
||||
|
||||
if ([scheme isEqualToString:@"wss"] || [scheme isEqualToString:@"https"]) {
|
||||
_secure = YES;
|
||||
}
|
||||
|
||||
|
||||
_readyState = SR_CONNECTING;
|
||||
_consumerStopped = YES;
|
||||
_webSocketVersion = 13;
|
||||
|
||||
|
||||
_workQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
|
||||
|
||||
|
||||
// Going to set a specific on the queue so we can validate we're on the work queue
|
||||
dispatch_queue_set_specific(_workQueue, (__bridge void *)self, maybe_bridge(_workQueue), NULL);
|
||||
|
||||
|
||||
_delegateDispatchQueue = dispatch_get_main_queue();
|
||||
sr_dispatch_retain(_delegateDispatchQueue);
|
||||
|
||||
|
||||
_readBuffer = [[NSMutableData alloc] init];
|
||||
_outputBuffer = [[NSMutableData alloc] init];
|
||||
|
||||
|
||||
_currentFrameData = [[NSMutableData alloc] init];
|
||||
|
||||
_consumers = [[NSMutableArray alloc] init];
|
||||
|
||||
|
||||
_consumerPool = [[SRIOConsumerPool alloc] init];
|
||||
|
||||
|
||||
_scheduledRunloops = [[NSMutableSet alloc] init];
|
||||
|
||||
|
||||
[self _initializeStreams];
|
||||
|
||||
|
||||
// default handlers
|
||||
}
|
||||
|
||||
@ -362,15 +368,15 @@ static __strong NSData *CRLFCRLF;
|
||||
|
||||
[_inputStream close];
|
||||
[_outputStream close];
|
||||
|
||||
|
||||
sr_dispatch_release(_workQueue);
|
||||
_workQueue = NULL;
|
||||
|
||||
|
||||
if (_receivedHTTPHeaders) {
|
||||
CFRelease(_receivedHTTPHeaders);
|
||||
_receivedHTTPHeaders = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (_delegateDispatchQueue) {
|
||||
sr_dispatch_release(_delegateDispatchQueue);
|
||||
_delegateDispatchQueue = NULL;
|
||||
@ -499,17 +505,24 @@ static __strong NSData *CRLFCRLF;
|
||||
{
|
||||
SRFastLog(@"Connected");
|
||||
CFHTTPMessageRef request = CFHTTPMessageCreateRequest(NULL, CFSTR("GET"), (__bridge CFURLRef)_url, kCFHTTPVersion1_1);
|
||||
|
||||
|
||||
// Set host first so it defaults
|
||||
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Host"), (__bridge CFStringRef)(_url.port ? [NSString stringWithFormat:@"%@:%@", _url.host, _url.port] : _url.host));
|
||||
|
||||
|
||||
NSMutableData *keyBytes = [[NSMutableData alloc] initWithLength:16];
|
||||
SecRandomCopyBytes(kSecRandomDefault, keyBytes.length, keyBytes.mutableBytes);
|
||||
|
||||
if ([keyBytes respondsToSelector:@selector(base64EncodedStringWithOptions:)]) {
|
||||
_secKey = [keyBytes base64EncodedStringWithOptions:0];
|
||||
} else {
|
||||
#if (__IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0) \
|
||||
|| (__MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9)
|
||||
|
||||
if (![NSData instancesRespondToSelector:@selector(base64EncodedStringWithOptions:)]) {
|
||||
_secKey = [keyBytes base64Encoding];
|
||||
} else
|
||||
|
||||
#endif
|
||||
|
||||
{
|
||||
_secKey = [keyBytes base64EncodedStringWithOptions:0];
|
||||
}
|
||||
|
||||
assert([_secKey length] == 24);
|
||||
|
@ -15,6 +15,4 @@
|
||||
@property (nonatomic, assign) NSLineBreakMode lineBreakMode;
|
||||
@property (nonatomic, assign) NSUInteger numberOfLines;
|
||||
|
||||
- (NSNumber *)reactTagAtPoint:(CGPoint)point;
|
||||
|
||||
@end
|
||||
|
@ -26,6 +26,9 @@
|
||||
+ (float)float:(id)json;
|
||||
+ (int)int:(id)json;
|
||||
|
||||
+ (int64_t)int64_t:(id)json;
|
||||
+ (uint64_t)uint64_t:(id)json;
|
||||
|
||||
+ (NSInteger)NSInteger:(id)json;
|
||||
+ (NSUInteger)NSUInteger:(id)json;
|
||||
|
||||
@ -70,6 +73,7 @@
|
||||
+ (UIFont *)UIFont:(UIFont *)font withFamily:(id)json size:(id)json weight:(id)json;
|
||||
|
||||
+ (NSArray *)NSStringArray:(id)json;
|
||||
+ (NSArray *)NSURLArray:(id)json;
|
||||
+ (NSArray *)NSNumberArray:(id)json;
|
||||
+ (NSArray *)UIColorArray:(id)json;
|
||||
+ (NSArray *)CGColorArray:(id)json;
|
||||
@ -142,6 +146,14 @@ id RCTConvertValue(id target, NSString *keypath, id json);
|
||||
#define RCT_CONVERTER(type, name, getter) \
|
||||
RCT_CONVERTER_CUSTOM(type, name, [json getter])
|
||||
|
||||
/**
|
||||
* This macro is similar to RCT_CONVERTER, but specifically geared towards
|
||||
* numeric types. It will handle string input correctly, and provides more
|
||||
* detailed error reporting if a wrong value is passed in.
|
||||
*/
|
||||
#define RCT_NUMBER_CONVERTER(type, getter) \
|
||||
RCT_CONVERTER_CUSTOM(type, type, [[self NSNumber:json] getter])
|
||||
|
||||
/**
|
||||
* This macro is used for creating converters for enum types.
|
||||
*/
|
||||
@ -177,7 +189,7 @@ RCT_CONVERTER_CUSTOM(type, name, [json getter])
|
||||
* This macro is used for creating converter functions for structs that consist
|
||||
* of a number of CGFloat properties, such as CGPoint, CGRect, etc.
|
||||
*/
|
||||
#define RCT_CGSTRUCT_CONVERTER(type, values) \
|
||||
#define RCT_CGSTRUCT_CONVERTER(type, values, _aliases) \
|
||||
+ (type)type:(id)json \
|
||||
{ \
|
||||
@try { \
|
||||
@ -194,12 +206,23 @@ RCT_CONVERTER_CUSTOM(type, name, [json getter])
|
||||
RCTLogError(@"Expected array with count %zd, but count is %zd: %@", count, [json count], json); \
|
||||
} else { \
|
||||
for (NSUInteger i = 0; i < count; i++) { \
|
||||
((CGFloat *)&result)[i] = [json[i] doubleValue]; \
|
||||
((CGFloat *)&result)[i] = [self CGFloat:json[i]]; \
|
||||
} \
|
||||
} \
|
||||
} else if ([json isKindOfClass:[NSDictionary class]]) { \
|
||||
NSDictionary *aliases = _aliases; \
|
||||
if (aliases.count) { \
|
||||
json = [json mutableCopy]; \
|
||||
for (NSString *alias in aliases) { \
|
||||
NSString *key = aliases[alias]; \
|
||||
NSNumber *number = json[key]; \
|
||||
if (number) { \
|
||||
((NSMutableDictionary *)json)[key] = number; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
for (NSUInteger i = 0; i < count; i++) { \
|
||||
((CGFloat *)&result)[i] = [json[fields[i]] doubleValue]; \
|
||||
((CGFloat *)&result)[i] = [self CGFloat:json[fields[i]]]; \
|
||||
} \
|
||||
} else if (json && json != [NSNull null]) { \
|
||||
RCTLogError(@"Expected NSArray or NSDictionary for %s, received %@: %@", #type, [json class], json); \
|
||||
|
@ -13,25 +13,39 @@
|
||||
|
||||
#import "RCTLog.h"
|
||||
|
||||
CGFloat const RCTDefaultFontSize = 14;
|
||||
NSString *const RCTDefaultFontName = @"HelveticaNeue";
|
||||
NSString *const RCTDefaultFontWeight = @"normal";
|
||||
NSString *const RCTBoldFontWeight = @"bold";
|
||||
|
||||
@implementation RCTConvert
|
||||
|
||||
RCT_CONVERTER(BOOL, BOOL, boolValue)
|
||||
RCT_CONVERTER(double, double, doubleValue)
|
||||
RCT_CONVERTER(float, float, floatValue)
|
||||
RCT_CONVERTER(int, int, intValue)
|
||||
RCT_NUMBER_CONVERTER(double, doubleValue)
|
||||
RCT_NUMBER_CONVERTER(float, floatValue)
|
||||
RCT_NUMBER_CONVERTER(int, intValue)
|
||||
|
||||
RCT_CONVERTER(NSInteger, NSInteger, integerValue)
|
||||
RCT_CONVERTER_CUSTOM(NSUInteger, NSUInteger, [json unsignedIntegerValue])
|
||||
RCT_NUMBER_CONVERTER(int64_t, longLongValue);
|
||||
RCT_NUMBER_CONVERTER(uint64_t, unsignedLongLongValue);
|
||||
|
||||
RCT_NUMBER_CONVERTER(NSInteger, integerValue)
|
||||
RCT_NUMBER_CONVERTER(NSUInteger, unsignedIntegerValue)
|
||||
|
||||
RCT_CONVERTER_CUSTOM(NSArray *, NSArray, [NSArray arrayWithArray:json])
|
||||
RCT_CONVERTER_CUSTOM(NSDictionary *, NSDictionary, [NSDictionary dictionaryWithDictionary:json])
|
||||
RCT_CONVERTER(NSString *, NSString, description)
|
||||
RCT_CONVERTER_CUSTOM(NSNumber *, NSNumber, @([json doubleValue]))
|
||||
|
||||
+ (NSNumber *)NSNumber:(id)json
|
||||
{
|
||||
if ([json isKindOfClass:[NSNumber class]]) {
|
||||
return json;
|
||||
} else if ([json isKindOfClass:[NSString class]]) {
|
||||
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
|
||||
NSNumber *number = [formatter numberFromString:json];
|
||||
if (!number) {
|
||||
RCTLogError(@"JSON String '%@' could not be interpreted as a number", json);
|
||||
}
|
||||
return number;
|
||||
} else if (json && json != [NSNull null]) {
|
||||
RCTLogError(@"JSON value '%@' of class %@ could not be interpreted as a number", json, [json class]);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSURL *)NSURL:(id)json
|
||||
{
|
||||
@ -47,7 +61,12 @@ RCT_CONVERTER_CUSTOM(NSNumber *, NSNumber, @([json doubleValue]))
|
||||
}
|
||||
else if ([path length])
|
||||
{
|
||||
return [NSURL URLWithString:path relativeToURL:[[NSBundle mainBundle] resourceURL]];
|
||||
NSURL *URL = [NSURL URLWithString:path relativeToURL:[[NSBundle mainBundle] resourceURL]];
|
||||
if ([URL isFileURL] &&![[NSFileManager defaultManager] fileExistsAtPath:[URL absoluteString]]) {
|
||||
RCTLogWarn(@"The file '%@' does not exist", URL);
|
||||
return nil;
|
||||
}
|
||||
return URL;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
@ -58,11 +77,11 @@ RCT_CONVERTER_CUSTOM(NSNumber *, NSNumber, @([json doubleValue]))
|
||||
}
|
||||
|
||||
// JS Standard for time is milliseconds
|
||||
RCT_CONVERTER_CUSTOM(NSDate *, NSDate, [NSDate dateWithTimeIntervalSince1970:[json doubleValue] / 1000.0])
|
||||
RCT_CONVERTER_CUSTOM(NSTimeInterval, NSTimeInterval, [json doubleValue] / 1000.0)
|
||||
RCT_CONVERTER_CUSTOM(NSDate *, NSDate, [NSDate dateWithTimeIntervalSince1970:[self double:json] / 1000.0])
|
||||
RCT_CONVERTER_CUSTOM(NSTimeInterval, NSTimeInterval, [self double:json] / 1000.0)
|
||||
|
||||
// JS standard for time zones is minutes.
|
||||
RCT_CONVERTER_CUSTOM(NSTimeZone *, NSTimeZone, [NSTimeZone timeZoneForSecondsFromGMT:[json doubleValue] * 60.0])
|
||||
RCT_CONVERTER_CUSTOM(NSTimeZone *, NSTimeZone, [NSTimeZone timeZoneForSecondsFromGMT:[self double:json] * 60.0])
|
||||
|
||||
RCT_ENUM_CONVERTER(NSTextAlignment, (@{
|
||||
@"auto": @(NSTextAlignmentNatural),
|
||||
@ -90,11 +109,12 @@ RCT_ENUM_CONVERTER(UIKeyboardType, (@{
|
||||
@"default": @(UIKeyboardTypeDefault),
|
||||
}), UIKeyboardTypeDefault, integerValue)
|
||||
|
||||
RCT_CONVERTER(CGFloat, CGFloat, doubleValue)
|
||||
RCT_CGSTRUCT_CONVERTER(CGPoint, (@[@"x", @"y"]))
|
||||
RCT_CGSTRUCT_CONVERTER(CGSize, (@[@"w", @"h"]))
|
||||
RCT_CGSTRUCT_CONVERTER(CGRect, (@[@"x", @"y", @"w", @"h"]))
|
||||
RCT_CGSTRUCT_CONVERTER(UIEdgeInsets, (@[@"top", @"left", @"bottom", @"right"]))
|
||||
// TODO: normalise the use of w/width so we can do away with the alias values (#6566645)
|
||||
RCT_CONVERTER_CUSTOM(CGFloat, CGFloat, [self double:json])
|
||||
RCT_CGSTRUCT_CONVERTER(CGPoint, (@[@"x", @"y"]), nil)
|
||||
RCT_CGSTRUCT_CONVERTER(CGSize, (@[@"width", @"height"]), (@{@"w": @"width", @"h": @"height"}))
|
||||
RCT_CGSTRUCT_CONVERTER(CGRect, (@[@"x", @"y", @"width", @"height"]), (@{@"w": @"width", @"h": @"height"}))
|
||||
RCT_CGSTRUCT_CONVERTER(UIEdgeInsets, (@[@"top", @"left", @"bottom", @"right"]), nil)
|
||||
|
||||
RCT_ENUM_CONVERTER(CGLineJoin, (@{
|
||||
@"miter": @(kCGLineJoinMiter),
|
||||
@ -113,9 +133,9 @@ RCT_CGSTRUCT_CONVERTER(CATransform3D, (@[
|
||||
@"m21", @"m22", @"m23", @"m24",
|
||||
@"m31", @"m32", @"m33", @"m34",
|
||||
@"m41", @"m42", @"m43", @"m44"
|
||||
]))
|
||||
]), nil)
|
||||
|
||||
RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"]))
|
||||
RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"]), nil)
|
||||
|
||||
+ (UIColor *)UIColor:(id)json
|
||||
{
|
||||
@ -328,19 +348,19 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty
|
||||
} else {
|
||||
|
||||
// Color array
|
||||
color = [UIColor colorWithRed:[json[0] doubleValue]
|
||||
green:[json[1] doubleValue]
|
||||
blue:[json[2] doubleValue]
|
||||
alpha:[json count] > 3 ? [json[3] doubleValue] : 1];
|
||||
color = [UIColor colorWithRed:[self double:json[0]]
|
||||
green:[self double:json[1]]
|
||||
blue:[self double:json[2]]
|
||||
alpha:[json count] > 3 ? [self double:json[3]] : 1];
|
||||
}
|
||||
|
||||
} else if ([json isKindOfClass:[NSDictionary class]]) {
|
||||
|
||||
// Color dictionary
|
||||
color = [UIColor colorWithRed:[json[@"r"] doubleValue]
|
||||
green:[json[@"g"] doubleValue]
|
||||
blue:[json[@"b"] doubleValue]
|
||||
alpha:[json[@"a"] ?: @1 doubleValue]];
|
||||
color = [UIColor colorWithRed:[self double:json[@"r"]]
|
||||
green:[self double:json[@"g"]]
|
||||
blue:[self double:json[@"b"]]
|
||||
alpha:[self double:json[@"a"] ?: @1]];
|
||||
|
||||
} else if (json && ![json isKindOfClass:[NSNull class]]) {
|
||||
|
||||
@ -415,6 +435,11 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty
|
||||
|
||||
+ (UIFont *)UIFont:(UIFont *)font withFamily:(id)family size:(id)size weight:(id)weight
|
||||
{
|
||||
CGFloat const RCTDefaultFontSize = 14;
|
||||
NSString *const RCTDefaultFontName = @"HelveticaNeue";
|
||||
NSString *const RCTDefaultFontWeight = @"normal";
|
||||
NSString *const RCTBoldFontWeight = @"bold";
|
||||
|
||||
// Create descriptor
|
||||
UIFontDescriptor *fontDescriptor = font.fontDescriptor ?: [UIFontDescriptor fontDescriptorWithName:RCTDefaultFontName size:RCTDefaultFontSize];
|
||||
|
||||
@ -427,7 +452,7 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty
|
||||
// Get font family
|
||||
NSString *familyName = [self NSString:family];
|
||||
if (familyName) {
|
||||
if ([UIFont fontNamesForFamilyName:familyName].count == 0) {
|
||||
if ([UIFont fontNamesForFamilyName:familyName].count == 0) {
|
||||
font = [UIFont fontWithName:familyName size:fontDescriptor.pointSize];
|
||||
if (font) {
|
||||
// It's actually a font name, not a font family name,
|
||||
@ -437,11 +462,14 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty
|
||||
} else {
|
||||
// Not a valid font or family
|
||||
RCTLogError(@"Unrecognized font family '%@'", familyName);
|
||||
familyName = [UIFont fontWithDescriptor:fontDescriptor size:0].familyName;
|
||||
}
|
||||
} else {
|
||||
// Set font family
|
||||
fontDescriptor = [fontDescriptor fontDescriptorWithFamily:familyName];
|
||||
}
|
||||
} else {
|
||||
familyName = [UIFont fontWithDescriptor:fontDescriptor size:0].familyName;
|
||||
}
|
||||
|
||||
// Get font weight
|
||||
@ -451,29 +479,43 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty
|
||||
static NSSet *values;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
values = [NSSet setWithObjects:@"bold", @"normal", nil];
|
||||
values = [NSSet setWithObjects:RCTDefaultFontWeight, RCTBoldFontWeight, nil];
|
||||
});
|
||||
|
||||
if (fontWeight && ![values containsObject:fontWeight]) {
|
||||
RCTLogError(@"Unrecognized font weight '%@', must be one of %@", fontWeight, values);
|
||||
fontWeight = RCTDefaultFontWeight;
|
||||
}
|
||||
|
||||
UIFontDescriptorSymbolicTraits symbolicTraits = fontDescriptor.symbolicTraits;
|
||||
// this is hacky. we are appending the string -Medium because most fonts we currently use
|
||||
// just need to have -Medium appended to get the bold we want. we're going to revamp this
|
||||
// to make it easier to know which options are available in JS. t4996115
|
||||
if ([fontWeight isEqualToString:RCTBoldFontWeight]) {
|
||||
symbolicTraits |= UIFontDescriptorTraitBold;
|
||||
} else {
|
||||
symbolicTraits &= ~UIFontDescriptorTraitBold;
|
||||
font = nil;
|
||||
for (NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) {
|
||||
if ([fontName hasSuffix:@"-Medium"]) {
|
||||
font = [UIFont fontWithName:fontName size:fontDescriptor.pointSize];
|
||||
break;
|
||||
}
|
||||
if ([fontName hasSuffix:@"-Bold"]) {
|
||||
font = [UIFont fontWithName:fontName size:fontDescriptor.pointSize];
|
||||
// But keep searching in case there's a medium option
|
||||
}
|
||||
}
|
||||
if (font) {
|
||||
fontDescriptor = font.fontDescriptor;
|
||||
}
|
||||
}
|
||||
fontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits:symbolicTraits];
|
||||
}
|
||||
|
||||
// TODO: font style
|
||||
|
||||
// Create font
|
||||
return [UIFont fontWithDescriptor:fontDescriptor size:fontDescriptor.pointSize];
|
||||
return [UIFont fontWithDescriptor:fontDescriptor size:0];
|
||||
}
|
||||
|
||||
RCT_ARRAY_CONVERTER(NSString)
|
||||
RCT_ARRAY_CONVERTER(NSURL)
|
||||
RCT_ARRAY_CONVERTER(NSNumber)
|
||||
RCT_ARRAY_CONVERTER(UIColor)
|
||||
|
||||
@ -729,6 +771,9 @@ static id RCTConvertValueWithExplicitEncoding(id target, NSString *key, id json,
|
||||
@"extAlignment": ^(id val) {
|
||||
return [RCTConvert NSTextAlignment:val];
|
||||
},
|
||||
@"ritingDirection": ^(id val) {
|
||||
return [RCTConvert NSWritingDirection:val];
|
||||
},
|
||||
@"Cap": ^(id val) {
|
||||
return [RCTConvert CGLineCap:val];
|
||||
},
|
||||
|
@ -29,6 +29,7 @@ NSString *const RCTReloadNotification = @"RCTReloadNotification";
|
||||
RCTBridge *_bridge;
|
||||
RCTTouchHandler *_touchHandler;
|
||||
id<RCTJavaScriptExecutor> _executor;
|
||||
BOOL _registered;
|
||||
}
|
||||
|
||||
static Class _globalExecutorClass;
|
||||
@ -36,7 +37,7 @@ static Class _globalExecutorClass;
|
||||
+ (void)initialize
|
||||
{
|
||||
|
||||
#if DEBUG
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
|
||||
// Register Cmd-R as a global refresh key
|
||||
[[RCTKeyCommands sharedInstance] registerKeyCommandWithInput:@"r"
|
||||
@ -144,6 +145,7 @@ static Class _globalExecutorClass;
|
||||
} else {
|
||||
|
||||
[_bridge.uiManager registerRootView:self];
|
||||
_registered = YES;
|
||||
|
||||
NSString *moduleName = _moduleName ?: @"";
|
||||
NSDictionary *appParameters = @{
|
||||
@ -163,6 +165,14 @@ static Class _globalExecutorClass;
|
||||
return;
|
||||
}
|
||||
|
||||
// Clean up
|
||||
[self removeGestureRecognizer:_touchHandler];
|
||||
[_touchHandler invalidate];
|
||||
[_executor invalidate];
|
||||
[_bridge invalidate];
|
||||
|
||||
_registered = NO;
|
||||
|
||||
// Choose local executor if specified, followed by global, followed by default
|
||||
_executor = [[_executorClass ?: _globalExecutorClass ?: [RCTContextExecutor class] alloc] init];
|
||||
_bridge = [[RCTBridge alloc] initWithExecutor:_executor moduleProvider:_moduleProvider];
|
||||
@ -231,10 +241,10 @@ static Class _globalExecutorClass;
|
||||
sourceCodeModule.scriptURL = _scriptURL;
|
||||
sourceCodeModule.scriptText = rawText;
|
||||
|
||||
[_bridge enqueueApplicationScript:rawText url:_scriptURL onComplete:^(NSError *error) {
|
||||
[_bridge enqueueApplicationScript:rawText url:_scriptURL onComplete:^(NSError *_error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (_bridge.isValid) {
|
||||
[self bundleFinishedLoading:error];
|
||||
[self bundleFinishedLoading:_error];
|
||||
}
|
||||
});
|
||||
}];
|
||||
@ -254,9 +264,12 @@ static Class _globalExecutorClass;
|
||||
[self loadBundle];
|
||||
}
|
||||
|
||||
- (BOOL)isReactRootView
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
return YES;
|
||||
[super layoutSubviews];
|
||||
if (_registered) {
|
||||
[_bridge.uiManager setFrame:self.frame forRootView:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reload
|
||||
|
@ -129,13 +129,15 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) {
|
||||
// Find closest React-managed touchable view
|
||||
UIView *targetView = touch.view;
|
||||
while (targetView) {
|
||||
if (targetView.reactTag && targetView.userInteractionEnabled) { // TODO: implement respondsToTouch: mechanism
|
||||
if (targetView.reactTag && targetView.userInteractionEnabled &&
|
||||
[targetView reactRespondsToTouch:touch]) {
|
||||
break;
|
||||
}
|
||||
targetView = targetView.superview;
|
||||
}
|
||||
|
||||
if (!targetView.reactTag || !targetView.userInteractionEnabled) {
|
||||
NSNumber *reactTag = [targetView reactTagAtPoint:[touch locationInView:targetView]];
|
||||
if (!reactTag || !targetView.userInteractionEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -155,7 +157,7 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) {
|
||||
|
||||
// Create touch
|
||||
NSMutableDictionary *reactTouch = [[NSMutableDictionary alloc] initWithCapacity:9];
|
||||
reactTouch[@"target"] = [targetView reactTagAtPoint:[touch locationInView:targetView]];
|
||||
reactTouch[@"target"] = reactTag;
|
||||
reactTouch[@"identifier"] = @(touchID);
|
||||
reactTouch[@"touches"] = [NSNull null]; // We hijack this touchObj to serve both as an event
|
||||
reactTouch[@"changedTouches"] = [NSNull null]; // and as a Touch object, so making this JIT friendly.
|
||||
@ -248,15 +250,15 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) {
|
||||
|
||||
if (_recordingInteractionTiming) {
|
||||
[_bridgeInteractionTiming addObject:@{
|
||||
@"timeSeconds": @(touch.originatingTime),
|
||||
@"operation": @"taskOriginated",
|
||||
@"taskID": @(touch.id),
|
||||
}];
|
||||
@"timeSeconds": @(touch.originatingTime),
|
||||
@"operation": @"taskOriginated",
|
||||
@"taskID": @(touch.id),
|
||||
}];
|
||||
[_bridgeInteractionTiming addObject:@{
|
||||
@"timeSeconds": @(enqueueTime),
|
||||
@"operation": @"taskEnqueuedPending",
|
||||
@"taskID": @(touch.id),
|
||||
}];
|
||||
@"timeSeconds": @(enqueueTime),
|
||||
@"operation": @"taskEnqueuedPending",
|
||||
@"taskID": @(touch.id),
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,18 +275,18 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) {
|
||||
if (_recordingInteractionTiming) {
|
||||
for (RCTTouchEvent *touch in _pendingTouches) {
|
||||
[_bridgeInteractionTiming addObject:@{
|
||||
@"timeSeconds": @(sender.timestamp),
|
||||
@"operation": @"frameAlignedDispatch",
|
||||
@"taskID": @(touch.id),
|
||||
}];
|
||||
@"timeSeconds": @(sender.timestamp),
|
||||
@"operation": @"frameAlignedDispatch",
|
||||
@"taskID": @(touch.id),
|
||||
}];
|
||||
}
|
||||
|
||||
if (pendingCount > 0 || sender.timestamp - _mostRecentEnqueueJS < 0.1) {
|
||||
[_bridgeInteractionTiming addObject:@{
|
||||
@"timeSeconds": @(sender.timestamp),
|
||||
@"operation": @"mainThreadDisplayLink",
|
||||
@"taskID": @([RCTTouchEvent newID]),
|
||||
}];
|
||||
@"timeSeconds": @(sender.timestamp),
|
||||
@"operation": @"mainThreadDisplayLink",
|
||||
@"taskID": @([RCTTouchEvent newID]),
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,8 @@ static NSError *RCTNSErrorFromJSError(JSContextRef context, JSValueRef jsError)
|
||||
return [self initWithJavaScriptThread:javaScriptThread globalContextRef:NULL];
|
||||
}
|
||||
|
||||
- (instancetype)initWithJavaScriptThread:(NSThread *)javaScriptThread globalContextRef:(JSGlobalContextRef)context
|
||||
- (instancetype)initWithJavaScriptThread:(NSThread *)javaScriptThread
|
||||
globalContextRef:(JSGlobalContextRef)context
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_javaScriptThread = javaScriptThread;
|
||||
|
@ -184,7 +184,8 @@ static void RCTReportError(RCTJavaScriptCallback callback, NSString *fmt, ...)
|
||||
asGlobalObjectNamed:(NSString *)objectName
|
||||
callback:(RCTJavaScriptCompleteBlock)onComplete
|
||||
{
|
||||
RCTAssert(!_objectsToInject[objectName], @"already injected object named %@", _objectsToInject[objectName]);
|
||||
RCTAssert(!_objectsToInject[objectName],
|
||||
@"already injected object named %@", _objectsToInject[objectName]);
|
||||
_objectsToInject[objectName] = script;
|
||||
onComplete(nil);
|
||||
}
|
||||
|
@ -14,8 +14,6 @@
|
||||
#import "RCTInvalidating.h"
|
||||
#import "RCTViewManager.h"
|
||||
|
||||
@class RCTRootView;
|
||||
|
||||
@protocol RCTScrollableProtocol;
|
||||
|
||||
/**
|
||||
@ -33,10 +31,15 @@
|
||||
|
||||
/**
|
||||
* Register a root view with the RCTUIManager. Theoretically, a single manager
|
||||
* can support multiple root views, however this feature is not currently exposed
|
||||
* and may eventually be removed.
|
||||
* can support multiple root views, however this feature is not currently exposed.
|
||||
*/
|
||||
- (void)registerRootView:(RCTRootView *)rootView;
|
||||
- (void)registerRootView:(UIView *)rootView;
|
||||
|
||||
/**
|
||||
* Update the frame of a root view. This might be in response to a screen rotation
|
||||
* or some other layout event outsde of the React-managed view hierarchy.
|
||||
*/
|
||||
- (void)setFrame:(CGRect)frame forRootView:(UIView *)rootView;
|
||||
|
||||
/**
|
||||
* Schedule a block to be executed on the UI thread. Useful if you need to execute
|
||||
|
@ -19,7 +19,6 @@
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTNavigator.h"
|
||||
#import "RCTRootView.h"
|
||||
#import "RCTScrollableProtocol.h"
|
||||
#import "RCTShadowView.h"
|
||||
@ -55,7 +54,7 @@ static void RCTTraverseViewNodes(id<RCTViewNodeProtocol> view, react_view_node_b
|
||||
|
||||
@implementation RCTAnimation
|
||||
|
||||
UIViewAnimationCurve UIViewAnimationCurveFromRCTAnimationType(RCTAnimationType type)
|
||||
static UIViewAnimationCurve UIViewAnimationCurveFromRCTAnimationType(RCTAnimationType type)
|
||||
{
|
||||
switch (type) {
|
||||
case RCTAnimationTypeLinear:
|
||||
@ -67,7 +66,7 @@ UIViewAnimationCurve UIViewAnimationCurveFromRCTAnimationType(RCTAnimationType t
|
||||
case RCTAnimationTypeEaseInEaseOut:
|
||||
return UIViewAnimationCurveEaseInOut;
|
||||
default:
|
||||
RCTCAssert(NO, @"Unsupported animation type %zd", type);
|
||||
RCTLogError(@"Unsupported animation type %zd", type);
|
||||
return UIViewAnimationCurveEaseInOut;
|
||||
}
|
||||
}
|
||||
@ -157,6 +156,15 @@ UIViewAnimationCurve UIViewAnimationCurveFromRCTAnimationType(RCTAnimationType t
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTUIManager ()
|
||||
|
||||
// NOTE: these are properties so that they can be accessed by unit tests
|
||||
@property (nonatomic, strong) RCTSparseArray *viewManagerRegistry; // RCT thread only
|
||||
@property (nonatomic, strong) RCTSparseArray *shadowViewRegistry; // RCT thread only
|
||||
@property (nonatomic, strong) RCTSparseArray *viewRegistry; // Main thread only
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTUIManager
|
||||
{
|
||||
dispatch_queue_t _shadowQueue;
|
||||
@ -174,11 +182,6 @@ UIViewAnimationCurve UIViewAnimationCurveFromRCTAnimationType(RCTAnimationType t
|
||||
NSMutableDictionary *_defaultShadowViews; // RCT thread only
|
||||
NSMutableDictionary *_defaultViews; // Main thread only
|
||||
NSDictionary *_viewManagers;
|
||||
|
||||
// Keyed by React tag
|
||||
RCTSparseArray *_viewManagerRegistry; // RCT thread only
|
||||
RCTSparseArray *_shadowViewRegistry; // RCT thread only
|
||||
RCTSparseArray *_viewRegistry; // Main thread only
|
||||
}
|
||||
|
||||
@synthesize bridge =_bridge;
|
||||
@ -277,11 +280,14 @@ static NSString *RCTViewNameForModuleName(NSString *moduleName)
|
||||
[_pendingUIBlocksLock unlock];
|
||||
}
|
||||
|
||||
- (void)registerRootView:(RCTRootView *)rootView;
|
||||
- (void)registerRootView:(UIView *)rootView;
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
|
||||
NSNumber *reactTag = rootView.reactTag;
|
||||
RCTAssert(RCTIsReactRootView(reactTag),
|
||||
@"View %@ with tag #%@ is not a root view", rootView, reactTag);
|
||||
|
||||
UIView *existingView = _viewRegistry[reactTag];
|
||||
RCTCAssert(existingView == nil || existingView == rootView,
|
||||
@"Expect all root views to have unique tag. Added %@ twice", reactTag);
|
||||
@ -291,7 +297,7 @@ static NSString *RCTViewNameForModuleName(NSString *moduleName)
|
||||
CGRect frame = rootView.frame;
|
||||
|
||||
// Register manager (TODO: should we do this, or leave it nil?)
|
||||
_viewManagerRegistry[reactTag] = _viewManagers[@"View"];
|
||||
_viewManagerRegistry[reactTag] = _viewManagers[@"RCTView"];
|
||||
|
||||
// Register shadow view
|
||||
dispatch_async(_shadowQueue, ^{
|
||||
@ -300,13 +306,31 @@ static NSString *RCTViewNameForModuleName(NSString *moduleName)
|
||||
shadowView.reactTag = reactTag;
|
||||
shadowView.frame = frame;
|
||||
shadowView.backgroundColor = [UIColor whiteColor];
|
||||
shadowView.reactRootView = YES; // can this just be inferred from the fact that it has no superview?
|
||||
_shadowViewRegistry[shadowView.reactTag] = shadowView;
|
||||
|
||||
[_rootViewTags addObject:reactTag];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)setFrame:(CGRect)frame forRootView:(UIView *)rootView
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
|
||||
NSNumber *reactTag = rootView.reactTag;
|
||||
RCTAssert(RCTIsReactRootView(reactTag), @"Specified view %@ is not a root view", reactTag);
|
||||
|
||||
dispatch_async(_bridge.shadowQueue, ^{
|
||||
RCTShadowView *rootShadowView = _shadowViewRegistry[reactTag];
|
||||
RCTAssert(rootShadowView != nil, @"Could not locate root view with tag %@", reactTag);
|
||||
rootShadowView.frame = frame;
|
||||
[rootShadowView updateLayout];
|
||||
|
||||
RCTViewManagerUIBlock uiBlock = [self uiBlockWithLayoutUpdateForRootView:rootShadowView];
|
||||
[self addUIBlock:uiBlock];
|
||||
[self flushUIBlocks];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters views from registries
|
||||
*/
|
||||
@ -389,21 +413,6 @@ static NSString *RCTViewNameForModuleName(NSString *moduleName)
|
||||
UIView *view = viewRegistry[reactTag];
|
||||
CGRect frame = [frames[ii] CGRectValue];
|
||||
|
||||
// These frames are in terms of anchorPoint = topLeft, but internally the
|
||||
// views are anchorPoint = center for easier scale and rotation animations.
|
||||
// Convert the frame so it works with anchorPoint = center.
|
||||
CGPoint position = {CGRectGetMidX(frame), CGRectGetMidY(frame)};
|
||||
CGRect bounds = {0, 0, frame.size};
|
||||
|
||||
// Avoid crashes due to nan coords
|
||||
if (isnan(position.x) || isnan(position.y) ||
|
||||
isnan(bounds.origin.x) || isnan(bounds.origin.y) ||
|
||||
isnan(bounds.size.width) || isnan(bounds.size.height)) {
|
||||
RCTLogError(@"Invalid layout for (%@)%@. position: %@. bounds: %@",
|
||||
[view reactTag], self, NSStringFromCGPoint(position), NSStringFromCGRect(bounds));
|
||||
continue;
|
||||
}
|
||||
|
||||
void (^completion)(BOOL finished) = ^(BOOL finished) {
|
||||
if (self->_layoutAnimation.callback) {
|
||||
self->_layoutAnimation.callback(@[@(finished)]);
|
||||
@ -415,21 +424,22 @@ static NSString *RCTViewNameForModuleName(NSString *moduleName)
|
||||
RCTAnimation *updateAnimation = isNew ? nil: _layoutAnimation.updateAnimation;
|
||||
if (updateAnimation) {
|
||||
[updateAnimation performAnimations:^{
|
||||
view.layer.position = position;
|
||||
view.layer.bounds = bounds;
|
||||
[view reactSetFrame:frame];
|
||||
for (RCTViewManagerUIBlock block in updateBlocks) {
|
||||
block(self, _viewRegistry);
|
||||
}
|
||||
} withCompletionBlock:completion];
|
||||
} else {
|
||||
view.layer.position = position;
|
||||
view.layer.bounds = bounds;
|
||||
[view reactSetFrame:frame];
|
||||
for (RCTViewManagerUIBlock block in updateBlocks) {
|
||||
block(self, _viewRegistry);
|
||||
}
|
||||
completion(YES);
|
||||
}
|
||||
|
||||
// TODO: deprecate this
|
||||
[view reactSetBorders];
|
||||
|
||||
// Animate view creation
|
||||
BOOL shouldAnimateCreation = isNew && ![parentsAreNew[ii] boolValue];
|
||||
RCTAnimation *createAnimation = _layoutAnimation.createAnimation;
|
||||
@ -461,7 +471,7 @@ static NSString *RCTViewNameForModuleName(NSString *moduleName)
|
||||
* TODO: this is quite inefficient. If this was handled via the
|
||||
* ViewManager instead, it could be done more efficiently.
|
||||
*/
|
||||
RCTRootView *rootView = _viewRegistry[rootViewTag];
|
||||
UIView *rootView = _viewRegistry[rootViewTag];
|
||||
RCTTraverseViewNodes(rootView, ^(id<RCTViewNodeProtocol> view) {
|
||||
if ([view respondsToSelector:@selector(reactBridgeDidFinishTransaction)]) {
|
||||
[view reactBridgeDidFinishTransaction];
|
||||
@ -549,13 +559,15 @@ static NSString *RCTViewNameForModuleName(NSString *moduleName)
|
||||
|
||||
RCTShadowView *rootShadowView = _shadowViewRegistry[rootReactTag];
|
||||
RCTAssert(rootShadowView.superview == nil, @"root view cannot have superview (ID %@)", rootReactTag);
|
||||
[self _purgeChildren:@[rootShadowView] fromRegistry:_shadowViewRegistry];
|
||||
[self _purgeChildren:rootShadowView.reactSubviews fromRegistry:_shadowViewRegistry];
|
||||
_shadowViewRegistry[rootReactTag] = nil;
|
||||
[_rootViewTags removeObject:rootReactTag];
|
||||
|
||||
[self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){
|
||||
RCTCAssertMainThread();
|
||||
UIView *rootView = viewRegistry[rootReactTag];
|
||||
[uiManager _purgeChildren:@[rootView] fromRegistry:viewRegistry];
|
||||
[uiManager _purgeChildren:rootView.reactSubviews fromRegistry:viewRegistry];
|
||||
viewRegistry[rootReactTag] = nil;
|
||||
}];
|
||||
}
|
||||
|
||||
@ -701,7 +713,7 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
}];
|
||||
|
||||
// Update layout
|
||||
[shadowView updateShadowViewLayout];
|
||||
[shadowView updateLayout];
|
||||
}
|
||||
|
||||
- (void)createAndRegisterViewWithReactTag:(NSNumber *)reactTag
|
||||
@ -781,7 +793,9 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
if (!reactTag) return;
|
||||
[self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
UIView *newResponder = viewRegistry[reactTag];
|
||||
[newResponder reactWillMakeFirstResponder];
|
||||
[newResponder becomeFirstResponder];
|
||||
[newResponder reactDidMakeFirstResponder];
|
||||
}];
|
||||
}
|
||||
|
||||
@ -830,6 +844,13 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
_nextLayoutAnimation = nil;
|
||||
}
|
||||
|
||||
[self flushUIBlocks];
|
||||
}
|
||||
|
||||
- (void)flushUIBlocks
|
||||
{
|
||||
RCTAssert(![NSThread isMainThread], @"Should be called on shadow thread");
|
||||
|
||||
// First copy the previous blocks into a temporary variable, then reset the
|
||||
// pending blocks to a new array. This guards against mutation while
|
||||
// processing the pending blocks in another thread.
|
||||
@ -858,7 +879,7 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
[self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
UIView *view = viewRegistry[reactTag];
|
||||
if (!view) {
|
||||
RCTLogError(@"measure cannot find view with tag %zd", reactTag);
|
||||
RCTLogError(@"measure cannot find view with tag %@", reactTag);
|
||||
return;
|
||||
}
|
||||
CGRect frame = view.frame;
|
||||
@ -868,7 +889,8 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
rootView = rootView.superview;
|
||||
}
|
||||
|
||||
RCTCAssert([rootView isReactRootView], @"React view not inside RCTRootView");
|
||||
// TODO: this doesn't work because sometimes view is inside a modal window
|
||||
// RCTCAssert([rootView isReactRootView], @"React view is not inside a react root view");
|
||||
|
||||
// By convention, all coordinates, whether they be touch coordinates, or
|
||||
// measurement coordinates are with respect to the root view.
|
||||
@ -885,16 +907,9 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: This could be modified to accept any `RCTViewNodeProtocol`, if
|
||||
* appropriate changes were made to that protocol to support `superview`
|
||||
* traversal - which is possibly more difficult than it sounds since a
|
||||
* `superview` is not a "react superview".
|
||||
*/
|
||||
+ (void)measureLayoutOnNodes:(RCTShadowView *)view
|
||||
ancestor:(RCTShadowView *)ancestor
|
||||
errorCallback:(RCTResponseSenderBlock)errorCallback
|
||||
callback:(__unused RCTResponseSenderBlock)callback
|
||||
static void RCTMeasureLayout(RCTShadowView *view,
|
||||
RCTShadowView *ancestor,
|
||||
RCTResponseSenderBlock callback)
|
||||
{
|
||||
if (!view) {
|
||||
RCTLogError(@"Attempting to measure view that does not exist");
|
||||
@ -904,7 +919,7 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
RCTLogError(@"Attempting to measure relative to ancestor that does not exist");
|
||||
return;
|
||||
}
|
||||
CGRect result = [RCTShadowView measureLayout:view relativeTo:ancestor];
|
||||
CGRect result = [view measureLayoutRelativeToAncestor:ancestor];
|
||||
if (CGRectIsNull(result)) {
|
||||
RCTLogError(@"view %@ (tag #%@) is not a decendant of %@ (tag #%@)",
|
||||
view, view.reactTag, ancestor, ancestor.reactTag);
|
||||
@ -918,7 +933,7 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
RCTLogError(@"Attempted to measure layout but offset or dimensions were NaN");
|
||||
return;
|
||||
}
|
||||
callback(@[@(topOffset), @(leftOffset), @(width), @(height)]);
|
||||
callback(@[@(leftOffset), @(topOffset), @(width), @(height)]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -937,7 +952,7 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
|
||||
RCTShadowView *shadowView = _shadowViewRegistry[reactTag];
|
||||
RCTShadowView *ancestorShadowView = _shadowViewRegistry[ancestorReactTag];
|
||||
[RCTUIManager measureLayoutOnNodes:shadowView ancestor:ancestorShadowView errorCallback:errorCallback callback:callback];
|
||||
RCTMeasureLayout(shadowView, ancestorShadowView, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -954,7 +969,7 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
RCT_EXPORT();
|
||||
|
||||
RCTShadowView *shadowView = _shadowViewRegistry[reactTag];
|
||||
[RCTUIManager measureLayoutOnNodes:shadowView ancestor:[shadowView superview] errorCallback:errorCallback callback:callback];
|
||||
RCTMeasureLayout(shadowView, shadowView.reactSuperview, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -981,7 +996,7 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
CGRect layoutRect = [RCTConvert CGRect:rect];
|
||||
|
||||
[childShadowViews enumerateObjectsUsingBlock:^(RCTShadowView *childShadowView, NSUInteger idx, BOOL *stop) {
|
||||
CGRect childLayout = [RCTShadowView measureLayout:childShadowView relativeTo:shadowView];
|
||||
CGRect childLayout = [childShadowView measureLayoutRelativeToAncestor:shadowView];
|
||||
if (CGRectIsNull(childLayout)) {
|
||||
RCTLogError(@"View %@ (tag #%@) is not a decendant of %@ (tag #%@)",
|
||||
childShadowView, childShadowView.reactTag, shadowView, shadowView.reactTag);
|
||||
@ -1183,9 +1198,9 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
},
|
||||
} mutableCopy];
|
||||
|
||||
[_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, Class cls, BOOL *stop) {
|
||||
if (RCTClassOverridesClassMethod(cls, @selector(customBubblingEventTypes))) {
|
||||
NSDictionary *eventTypes = [cls customBubblingEventTypes];
|
||||
[_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, RCTViewManager *manager, BOOL *stop) {
|
||||
if (RCTClassOverridesInstanceMethod([manager class], @selector(customBubblingEventTypes))) {
|
||||
NSDictionary *eventTypes = [manager customBubblingEventTypes];
|
||||
for (NSString *eventName in eventTypes) {
|
||||
RCTCAssert(!customBubblingEventTypesConfigs[eventName],
|
||||
@"Event '%@' registered multiple times.", eventName);
|
||||
@ -1235,9 +1250,9 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
},
|
||||
} mutableCopy];
|
||||
|
||||
[_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, Class cls, BOOL *stop) {
|
||||
if (RCTClassOverridesClassMethod(cls, @selector(customDirectEventTypes))) {
|
||||
NSDictionary *eventTypes = [cls customDirectEventTypes];
|
||||
[_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, RCTViewManager *manager, BOOL *stop) {
|
||||
if (RCTClassOverridesInstanceMethod([manager class], @selector(customDirectEventTypes))) {
|
||||
NSDictionary *eventTypes = [manager customDirectEventTypes];
|
||||
for (NSString *eventName in eventTypes) {
|
||||
RCTCAssert(!customDirectEventTypes[eventName], @"Event '%@' registered multiple times.", eventName);
|
||||
}
|
||||
@ -1266,7 +1281,7 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
},
|
||||
@"modalFullscreenView": @{
|
||||
@"width": @(RCTScreenSize().width),
|
||||
@"height": @(RCTScreenSize().width),
|
||||
@"height": @(RCTScreenSize().height),
|
||||
},
|
||||
},
|
||||
@"StyleConstants": @{
|
||||
@ -1312,10 +1327,10 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
},
|
||||
} mutableCopy];
|
||||
|
||||
[_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, Class cls, BOOL *stop) {
|
||||
[_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, RCTViewManager *manager, BOOL *stop) {
|
||||
// TODO: should these be inherited?
|
||||
NSDictionary *constants = RCTClassOverridesClassMethod(cls, @selector(constantsToExport)) ? [cls constantsToExport] : nil;
|
||||
if ([constants count]) {
|
||||
NSDictionary *constants = RCTClassOverridesInstanceMethod([manager class], @selector(constantsToExport)) ? [manager constantsToExport] : nil;
|
||||
if (constants.count) {
|
||||
NSMutableDictionary *constantsNamespace = [NSMutableDictionary dictionaryWithDictionary:allJSConstants[name]];
|
||||
RCTAssert(constantsNamespace[@"Constants"] == nil , @"Cannot redefine Constants in namespace: %@", name);
|
||||
// add an additional 'Constants' namespace for each class
|
||||
@ -1350,12 +1365,18 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
NSSet *rootViewTags = [_rootViewTags copy];
|
||||
[self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
for (NSNumber *reactTag in rootViewTags) {
|
||||
RCTRootView *rootView = viewRegistry[reactTag];
|
||||
[rootView startOrResetInteractionTiming];
|
||||
id rootView = viewRegistry[reactTag];
|
||||
if ([rootView respondsToSelector:@selector(startOrResetInteractionTiming)]) {
|
||||
[rootView startOrResetInteractionTiming];
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
// TODO: remove horrible hack - this is only here so that
|
||||
// [rootView endAndResetInteractionTiming] below doesn't raise warnings
|
||||
- (NSDictionary *)endAndResetInteractionTiming { return nil; }
|
||||
|
||||
- (void)endAndResetInteractionTiming:(RCTResponseSenderBlock)onSuccess
|
||||
onError:(RCTResponseSenderBlock)onError
|
||||
{
|
||||
@ -1365,8 +1386,8 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
||||
[self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
NSMutableDictionary *timingData = [[NSMutableDictionary alloc] init];
|
||||
for (NSNumber *reactTag in rootViewTags) {
|
||||
RCTRootView *rootView = viewRegistry[reactTag];
|
||||
if (rootView) {
|
||||
id rootView = viewRegistry[reactTag];
|
||||
if ([rootView respondsToSelector:@selector(endAndResetInteractionTiming)]) {
|
||||
timingData[reactTag.stringValue] = [rootView endAndResetInteractionTiming];
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,6 @@
|
||||
830A229E1A66C68A008503DA /* RCTRootView.m in Sources */ = {isa = PBXBuildFile; fileRef = 830A229D1A66C68A008503DA /* RCTRootView.m */; };
|
||||
830BA4551A8E3BDA00D53203 /* RCTCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 830BA4541A8E3BDA00D53203 /* RCTCache.m */; };
|
||||
832348161A77A5AA00B55238 /* Layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FC71A68125100A75B9A /* Layout.c */; };
|
||||
83C911101AAE6521001323A3 /* RCTAnimationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 83C9110F1AAE6521001323A3 /* RCTAnimationManager.m */; };
|
||||
83CBBA511A601E3B00E9B192 /* RCTAssert.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA4B1A601E3B00E9B192 /* RCTAssert.m */; };
|
||||
83CBBA521A601E3B00E9B192 /* RCTLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA4E1A601E3B00E9B192 /* RCTLog.m */; };
|
||||
83CBBA531A601E3B00E9B192 /* RCTUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA501A601E3B00E9B192 /* RCTUtils.m */; };
|
||||
@ -169,8 +168,6 @@
|
||||
830BA4541A8E3BDA00D53203 /* RCTCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTCache.m; sourceTree = "<group>"; };
|
||||
83BEE46C1A6D19BC00B5863B /* RCTSparseArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSparseArray.h; sourceTree = "<group>"; };
|
||||
83BEE46D1A6D19BC00B5863B /* RCTSparseArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSparseArray.m; sourceTree = "<group>"; };
|
||||
83C9110E1AAE6521001323A3 /* RCTAnimationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAnimationManager.h; sourceTree = "<group>"; };
|
||||
83C9110F1AAE6521001323A3 /* RCTAnimationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAnimationManager.m; sourceTree = "<group>"; };
|
||||
83CBBA2E1A601D0E00E9B192 /* libReactKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReactKit.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
83CBBA4A1A601E3B00E9B192 /* RCTAssert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAssert.h; sourceTree = "<group>"; };
|
||||
83CBBA4B1A601E3B00E9B192 /* RCTAssert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAssert.m; sourceTree = "<group>"; };
|
||||
@ -230,8 +227,6 @@
|
||||
1372B7091AB030C200659ED6 /* RCTAppState.m */,
|
||||
13B07FE71A69327A00A75B9A /* RCTAlertManager.h */,
|
||||
13B07FE81A69327A00A75B9A /* RCTAlertManager.m */,
|
||||
83C9110E1AAE6521001323A3 /* RCTAnimationManager.h */,
|
||||
83C9110F1AAE6521001323A3 /* RCTAnimationManager.m */,
|
||||
58114A4F1AAE93D500E7D092 /* RCTAsyncLocalStorage.h */,
|
||||
58114A4E1AAE93D500E7D092 /* RCTAsyncLocalStorage.m */,
|
||||
13B07FE91A69327A00A75B9A /* RCTExceptionsManager.h */,
|
||||
@ -489,7 +484,6 @@
|
||||
13A1F71E1A75392D00D3D453 /* RCTKeyCommands.m in Sources */,
|
||||
83CBBA531A601E3B00E9B192 /* RCTUtils.m in Sources */,
|
||||
14435CE61AAC4AE100FC20F4 /* RCTMapManager.m in Sources */,
|
||||
83C911101AAE6521001323A3 /* RCTAnimationManager.m in Sources */,
|
||||
13C156051AB1A2840079392D /* RCTWebView.m in Sources */,
|
||||
83CBBA601A601EAA00E9B192 /* RCTBridge.m in Sources */,
|
||||
13C156061AB1A2840079392D /* RCTWebViewManager.m in Sources */,
|
||||
|
@ -44,6 +44,8 @@ RCT_REMAP_VIEW_PROPERTY(timeZoneOffsetInMinutes, timeZone)
|
||||
- (NSDictionary *)constantsToExport
|
||||
{
|
||||
UIDatePicker *dp = [[UIDatePicker alloc] init];
|
||||
[dp layoutIfNeeded];
|
||||
|
||||
return @{
|
||||
@"ComponentHeight": @(CGRectGetHeight(dp.frame)),
|
||||
@"ComponentWidth": @(CGRectGetWidth(dp.frame)),
|
||||
|
@ -487,16 +487,14 @@ NSInteger kNeverProgressed = -10000;
|
||||
// We can actually recover from this situation, but it would be nice to know
|
||||
// when this error happens. This simply means that JS hasn't caught up to a
|
||||
// back navigation before progressing. It's likely a bug in the JS code that
|
||||
// catches up/schedules navigations. Eventually, let's recover from this
|
||||
// error state, but in the mean time, let's get notified about any JS bugs.
|
||||
// catches up/schedules navigations.
|
||||
if (!(jsGettingAhead ||
|
||||
jsCatchingUp ||
|
||||
jsMakingNoProgressButNeedsToCatchUp ||
|
||||
jsMakingNoProgressAndDoesntNeedTo)) {
|
||||
RCTLogError(@"JS has only made partial progress to catch up to UIKit");
|
||||
}
|
||||
RCTAssert(
|
||||
jsGettingAhead ||
|
||||
jsCatchingUp ||
|
||||
jsMakingNoProgressButNeedsToCatchUp ||
|
||||
jsMakingNoProgressAndDoesntNeedTo,
|
||||
@"JS has only made partial progress to catch up to UIKit"
|
||||
);
|
||||
NSAssert(
|
||||
currentReactCount <= _currentViews.count,
|
||||
@"Cannot adjust current top of stack beyond available views"
|
||||
);
|
||||
@ -504,7 +502,7 @@ NSInteger kNeverProgressed = -10000;
|
||||
// Views before the previous react count must not have changed. Views greater than previousReactCount
|
||||
// up to currentReactCount may have changed.
|
||||
for (NSInteger i = 0; i < MIN(_currentViews.count, MIN(_previousViews.count, previousReactCount)); i++) {
|
||||
NSAssert(_currentViews[i] == _previousViews[i], @"current view should equal previous view");
|
||||
RCTAssert(_currentViews[i] == _previousViews[i], @"current view should equal previous view");
|
||||
}
|
||||
RCTAssert(currentReactCount >= 1, @"should be at least one current view");
|
||||
if (jsGettingAhead) {
|
||||
@ -545,7 +543,7 @@ didMoveToNavigationController:(UINavigationController *)navigationController
|
||||
|
||||
RCTAssert(
|
||||
(navigationController == nil || [_navigationController.viewControllers containsObject:wrapperViewController]),
|
||||
@"if navigation controller is not nil, it should container the wrapper view controller"
|
||||
@"if navigation controller is not nil, it should contain the wrapper view controller"
|
||||
);
|
||||
RCTAssert(_navigationController.navigationLock == RCTNavigationLockJavaScript ||
|
||||
_numberOfViewControllerMovesToIgnore == 0,
|
||||
|
@ -49,11 +49,6 @@ typedef void (^RCTApplierBlock)(RCTSparseArray *);
|
||||
*/
|
||||
@property (nonatomic, assign, getter=isNewView) BOOL newView;
|
||||
|
||||
/**
|
||||
* Is this the shadowView for an RCTRootView
|
||||
*/
|
||||
@property (nonatomic, assign, getter=isReactRootView) BOOL reactRootView;
|
||||
|
||||
/**
|
||||
* Position and dimensions.
|
||||
* Defaults to { 0, 0, NAN, NAN }.
|
||||
@ -149,7 +144,7 @@ typedef void (^RCTApplierBlock)(RCTSparseArray *);
|
||||
/**
|
||||
* Triggers a recalculation of the shadow view's layout.
|
||||
*/
|
||||
- (void)updateShadowViewLayout;
|
||||
- (void)updateLayout;
|
||||
|
||||
/**
|
||||
* Computes the recursive offset, meaning the sum of all descendant offsets -
|
||||
@ -157,10 +152,8 @@ typedef void (^RCTApplierBlock)(RCTSparseArray *);
|
||||
* sum of `top`/`left`s, as this function uses the *actual* positions of
|
||||
* children, not the style specified positions - it computes this based on the
|
||||
* resulting layout. It does not yet compensate for native scroll view insets or
|
||||
* transforms or anchor points. Returns an array containing the `x, y, width,
|
||||
* height` of the shadow view relative to the ancestor, or `nil` if the `view`
|
||||
* is not a descendent of `ancestor`.
|
||||
* transforms or anchor points.
|
||||
*/
|
||||
+ (CGRect)measureLayout:(RCTShadowView *)view relativeTo:(RCTShadowView *)ancestor;
|
||||
- (CGRect)measureLayoutRelativeToAncestor:(RCTShadowView *)ancestor;
|
||||
|
||||
@end
|
||||
|
@ -17,8 +17,6 @@
|
||||
typedef void (^RCTActionBlock)(RCTShadowView *shadowViewSelf, id value);
|
||||
typedef void (^RCTResetActionBlock)(RCTShadowView *shadowViewSelf);
|
||||
|
||||
#define MAX_TREE_DEPTH 30
|
||||
|
||||
const NSString *const RCTBackgroundColorProp = @"backgroundColor";
|
||||
|
||||
typedef enum {
|
||||
@ -213,17 +211,18 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st
|
||||
[self applyLayoutNode:_cssNode viewsWithNewFrame:viewsWithNewFrame absolutePosition:CGPointZero];
|
||||
}
|
||||
|
||||
+ (CGRect)measureLayout:(RCTShadowView *)shadowView relativeTo:(RCTShadowView *)ancestor
|
||||
- (CGRect)measureLayoutRelativeToAncestor:(RCTShadowView *)ancestor
|
||||
{
|
||||
CGFloat totalOffsetTop = 0.0;
|
||||
CGFloat totalOffsetLeft = 0.0;
|
||||
CGSize size = shadowView.frame.size;
|
||||
NSInteger depth = 0;
|
||||
while (depth < MAX_TREE_DEPTH && shadowView && shadowView != ancestor) {
|
||||
CGSize size = self.frame.size;
|
||||
NSInteger depth = 30; // max depth to search
|
||||
RCTShadowView *shadowView = self;
|
||||
while (depth && shadowView && shadowView != ancestor) {
|
||||
totalOffsetTop += shadowView.frame.origin.y;
|
||||
totalOffsetLeft += shadowView.frame.origin.x;
|
||||
shadowView = shadowView->_superview;
|
||||
depth++;
|
||||
depth--;
|
||||
}
|
||||
if (ancestor != shadowView) {
|
||||
return CGRectNull;
|
||||
@ -259,6 +258,11 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isReactRootView
|
||||
{
|
||||
return RCTIsReactRootView(self.reactTag);
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
free_css_node(_cssNode);
|
||||
@ -514,7 +518,7 @@ RCT_STYLE_PROPERTY(FlexWrap, flexWrap, flex_wrap, css_wrap_type_t)
|
||||
[self dirtyPropagation];
|
||||
}
|
||||
|
||||
- (void)updateShadowViewLayout
|
||||
- (void)updateLayout
|
||||
{
|
||||
if (_recomputePadding) {
|
||||
RCTProcessMetaProps(_paddingMetaProps, _cssNode->style.padding);
|
||||
|
@ -73,7 +73,7 @@ typedef void (^RCTViewManagerUIBlock)(RCTUIManager *uiManager, RCTSparseArray *v
|
||||
* Note that this method is not inherited when you subclass a view module, and
|
||||
* you should not call [super customBubblingEventTypes] when overriding it.
|
||||
*/
|
||||
+ (NSDictionary *)customBubblingEventTypes;
|
||||
- (NSDictionary *)customBubblingEventTypes;
|
||||
|
||||
/**
|
||||
* Returns a dictionary of config data passed to JS that defines eligible events
|
||||
@ -89,7 +89,7 @@ typedef void (^RCTViewManagerUIBlock)(RCTUIManager *uiManager, RCTSparseArray *v
|
||||
* Note that this method is not inherited when you subclass a view module, and
|
||||
* you should not call [super customDirectEventTypes] when overriding it.
|
||||
*/
|
||||
+ (NSDictionary *)customDirectEventTypes;
|
||||
- (NSDictionary *)customDirectEventTypes;
|
||||
|
||||
/**
|
||||
* Called to notify manager that layout has finished, in case any calculated
|
||||
|
@ -44,12 +44,12 @@
|
||||
return [[RCTShadowView alloc] init];
|
||||
}
|
||||
|
||||
+ (NSDictionary *)customBubblingEventTypes
|
||||
- (NSDictionary *)customBubblingEventTypes
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSDictionary *)customDirectEventTypes
|
||||
- (NSDictionary *)customDirectEventTypes
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
@ -101,7 +101,7 @@ RCT_CUSTOM_VIEW_PROPERTY(pointerEvents, RCTView)
|
||||
return;
|
||||
}
|
||||
|
||||
switch ([RCTConvert NSInteger:json]) {
|
||||
switch ([RCTConvert RCTPointerEvents:json]) {
|
||||
case RCTPointerEventsUnspecified:
|
||||
// Pointer events "unspecified" acts as if a stylesheet had not specified,
|
||||
// which is different than "auto" in CSS (which cannot and will not be
|
||||
@ -116,6 +116,12 @@ RCT_CUSTOM_VIEW_PROPERTY(pointerEvents, RCTView)
|
||||
RCTLogError(@"UIView base class does not support pointerEvent value: %@", json);
|
||||
}
|
||||
}
|
||||
RCT_CUSTOM_VIEW_PROPERTY(removeClippedSubviews, RCTView)
|
||||
{
|
||||
if ([view respondsToSelector:@selector(setRemoveClippedSubviews:)]) {
|
||||
view.removeClippedSubviews = json ? [RCTConvert BOOL:json] : defaultView.removeClippedSubviews;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - ShadowView properties
|
||||
|
||||
@ -149,4 +155,15 @@ RCT_CUSTOM_SHADOW_PROPERTY(position, RCTShadowView)
|
||||
view.positionType = json ? [RCTConvert css_position_type_t:json] : defaultView.positionType;
|
||||
}
|
||||
|
||||
// Border properties - to be deprecated
|
||||
|
||||
RCT_REMAP_VIEW_PROPERTY(borderTopWidth, reactBorderTop.width);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderRightWidth, reactBorderRight.width);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderBottomWidth, reactBorderBottom.width);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderLeftWidth, reactBorderLeft.width);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderTopColor, reactBorderTop.color);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderRightColor, reactBorderRight.color);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderBottomColor, reactBorderBottom.color);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderLeftColor, reactBorderLeft.color);
|
||||
|
||||
@end
|
||||
|
@ -22,7 +22,7 @@
|
||||
- (id<RCTViewNodeProtocol>)reactSuperview;
|
||||
- (NSNumber *)reactTagAtPoint:(CGPoint)point;
|
||||
|
||||
// View is an RCTRootView
|
||||
// View/ShadowView is a root view
|
||||
- (BOOL)isReactRootView;
|
||||
|
||||
@optional
|
||||
|
@ -15,6 +15,12 @@
|
||||
|
||||
@interface UIView (ReactKit) <RCTViewNodeProtocol>
|
||||
|
||||
/**
|
||||
* Used by the UIIManager to set the view frame.
|
||||
* May be overriden to disable animation, etc.
|
||||
*/
|
||||
- (void)reactSetFrame:(CGRect)frame;
|
||||
|
||||
/**
|
||||
* This method finds and returns the containing view controller for the view.
|
||||
*/
|
||||
@ -28,4 +34,20 @@
|
||||
*/
|
||||
- (void)addControllerToClosestParent:(UIViewController *)controller;
|
||||
|
||||
/**
|
||||
* Responder overrides - to be deprecated.
|
||||
*/
|
||||
- (void)reactWillMakeFirstResponder;
|
||||
- (void)reactDidMakeFirstResponder;
|
||||
- (BOOL)reactRespondsToTouch:(UITouch *)touch;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIView (ReactKitBorders)
|
||||
|
||||
/**
|
||||
* Borders stuff - pay no attention to this, it's going away (#6548297)
|
||||
*/
|
||||
- (void)reactSetBorders;
|
||||
|
||||
@end
|
||||
|
@ -12,6 +12,7 @@
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import "RCTAssert.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTWrapperViewController.h"
|
||||
|
||||
@implementation UIView (ReactKit)
|
||||
@ -61,6 +62,27 @@
|
||||
return self.superview;
|
||||
}
|
||||
|
||||
- (void)reactSetFrame:(CGRect)frame
|
||||
{
|
||||
// These frames are in terms of anchorPoint = topLeft, but internally the
|
||||
// views are anchorPoint = center for easier scale and rotation animations.
|
||||
// Convert the frame so it works with anchorPoint = center.
|
||||
CGPoint position = {CGRectGetMidX(frame), CGRectGetMidY(frame)};
|
||||
CGRect bounds = {CGPointZero, frame.size};
|
||||
|
||||
// Avoid crashes due to nan coords
|
||||
if (isnan(position.x) || isnan(position.y) ||
|
||||
isnan(bounds.origin.x) || isnan(bounds.origin.y) ||
|
||||
isnan(bounds.size.width) || isnan(bounds.size.height)) {
|
||||
RCTLogError(@"Invalid layout for (%@)%@. position: %@. bounds: %@",
|
||||
self.reactTag, self, NSStringFromCGPoint(position), NSStringFromCGRect(bounds));
|
||||
return;
|
||||
}
|
||||
|
||||
self.layer.position = position;
|
||||
self.layer.bounds = bounds;
|
||||
}
|
||||
|
||||
- (UIViewController *)backingViewController
|
||||
{
|
||||
id responder = [self nextResponder];
|
||||
@ -86,4 +108,167 @@
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Responder overrides - to be deprecated.
|
||||
*/
|
||||
- (void)reactWillMakeFirstResponder {};
|
||||
- (void)reactDidMakeFirstResponder {};
|
||||
- (BOOL)reactRespondsToTouch:(UITouch *)touch
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Borders
|
||||
|
||||
// Note: the value of this enum determines their relative zPosition
|
||||
typedef NS_ENUM(NSUInteger, RCTBorderSide) {
|
||||
RCTBorderSideTop = 0,
|
||||
RCTBorderSideRight = 1,
|
||||
RCTBorderSideBottom = 2,
|
||||
RCTBorderSideLeft = 3
|
||||
};
|
||||
|
||||
@interface RCTSingleSidedBorder : NSObject
|
||||
|
||||
@property (nonatomic, readwrite, assign) CGFloat width;
|
||||
@property (nonatomic, readwrite, strong) UIColor *color;
|
||||
@property (nonatomic, readonly, assign) RCTBorderSide side;
|
||||
|
||||
- (instancetype)initWithSide:(RCTBorderSide)side superlayer:(CALayer *)superlayer;
|
||||
|
||||
- (void)superLayerBoundsDidChange;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTSingleSidedBorder
|
||||
{
|
||||
CALayer *_borderLayer;
|
||||
}
|
||||
|
||||
- (instancetype)initWithSide:(RCTBorderSide)side superlayer:(CALayer *)superlayer
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_side = side;
|
||||
|
||||
_borderLayer = [CALayer layer];
|
||||
_borderLayer.delegate = self;
|
||||
_borderLayer.zPosition = INT_MAX - _side;
|
||||
|
||||
[superlayer insertSublayer:_borderLayer atIndex:0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
_borderLayer.delegate = nil;
|
||||
}
|
||||
|
||||
- (void)setWidth:(CGFloat)width
|
||||
{
|
||||
_width = width;
|
||||
[_borderLayer setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)setColor:(UIColor *)color
|
||||
{
|
||||
_color = color;
|
||||
_borderLayer.backgroundColor = _color.CGColor;
|
||||
[_borderLayer setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)superLayerBoundsDidChange
|
||||
{
|
||||
[_borderLayer setNeedsLayout];
|
||||
}
|
||||
|
||||
#pragma mark - CALayerDelegate
|
||||
|
||||
- (void)layoutSublayersOfLayer:(CALayer *)layer
|
||||
{
|
||||
CGSize superlayerSize = layer.superlayer.frame.size;
|
||||
|
||||
CGFloat xPosition = 0.0f;
|
||||
CGFloat yPosition = 0.0f;
|
||||
|
||||
// Note: we ensure side layers are below top & bottom for snapshot test consistency
|
||||
|
||||
switch (self.side) {
|
||||
case RCTBorderSideTop:
|
||||
layer.frame = CGRectMake(xPosition, yPosition, superlayerSize.width, self.width);
|
||||
break;
|
||||
case RCTBorderSideRight:
|
||||
xPosition = superlayerSize.width - self.width;
|
||||
layer.frame = CGRectMake(xPosition, yPosition, self.width, superlayerSize.height);
|
||||
[layer.superlayer insertSublayer:layer atIndex:0];
|
||||
break;
|
||||
case RCTBorderSideBottom:
|
||||
yPosition = superlayerSize.height - self.width;
|
||||
layer.frame = CGRectMake(xPosition, yPosition, superlayerSize.width, self.width);
|
||||
break;
|
||||
case RCTBorderSideLeft:
|
||||
layer.frame = CGRectMake(xPosition, yPosition, self.width, superlayerSize.height);
|
||||
[layer.superlayer insertSublayer:layer atIndex:0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Disable animations for layer
|
||||
- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
|
||||
{
|
||||
return (id)[NSNull null];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIView (ReactKitBorders)
|
||||
|
||||
- (void)reactSetBorders
|
||||
{
|
||||
NSMutableDictionary *borders = objc_getAssociatedObject(self, @selector(_createOrGetBorderWithSide:));
|
||||
if (borders) {
|
||||
for (RCTSingleSidedBorder *border in [borders allValues]) {
|
||||
[border superLayerBoundsDidChange];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (RCTSingleSidedBorder *)reactBorderTop
|
||||
{
|
||||
return [self _createOrGetBorderWithSide:RCTBorderSideTop];
|
||||
}
|
||||
|
||||
- (RCTSingleSidedBorder *)reactBorderRight
|
||||
{
|
||||
return [self _createOrGetBorderWithSide:RCTBorderSideRight];
|
||||
}
|
||||
|
||||
- (RCTSingleSidedBorder *)reactBorderBottom
|
||||
{
|
||||
return [self _createOrGetBorderWithSide:RCTBorderSideBottom];
|
||||
}
|
||||
|
||||
- (RCTSingleSidedBorder *)reactBorderLeft
|
||||
{
|
||||
return [self _createOrGetBorderWithSide:RCTBorderSideLeft];
|
||||
}
|
||||
|
||||
- (RCTSingleSidedBorder *)_createOrGetBorderWithSide:(RCTBorderSide)side
|
||||
{
|
||||
NSMutableDictionary *borders = objc_getAssociatedObject(self, _cmd);
|
||||
if (!borders) {
|
||||
borders = [[NSMutableDictionary alloc] init];
|
||||
objc_setAssociatedObject(self, _cmd, borders, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
RCTSingleSidedBorder *border = [borders objectForKey:@(side)];
|
||||
if (!border) {
|
||||
border = [[RCTSingleSidedBorder alloc] initWithSide:side superlayer:self.layer];
|
||||
[borders setObject:border forKey:@(side)];
|
||||
}
|
||||
return border;
|
||||
}
|
||||
|
||||
@end
|
||||
|
Loading…
x
Reference in New Issue
Block a user