yeet
This commit is contained in:
128
node_modules/react-native/React/CoreModules/BUCK
generated
vendored
Normal file
128
node_modules/react-native/React/CoreModules/BUCK
generated
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "OBJC_ARC_PREPROCESSOR_FLAGS", "get_fbobjc_enable_exception_lang_compiler_flags_DEPRECATED", "get_preprocessor_flags_for_build_mode")
|
||||
load("@fbsource//tools/build_defs/oss:rn_defs.bzl", "rn_apple_library", "rn_extra_build_flags")
|
||||
load(
|
||||
"@fbsource//xplat/configurations/buck/apple/plugins/sad_xplat_hosted_configurations:react_module_registration.bzl",
|
||||
"react_module_plugin_providers",
|
||||
)
|
||||
|
||||
rn_apple_library(
|
||||
name = "CoreModulesApple",
|
||||
srcs = glob(
|
||||
[
|
||||
"**/*.m",
|
||||
"**/*.mm",
|
||||
],
|
||||
),
|
||||
exported_headers = glob(["**/*.h"]),
|
||||
compiler_flags = [
|
||||
"-Wno-error=unguarded-availability-new",
|
||||
"-Wno-unknown-warning-option",
|
||||
],
|
||||
contacts = ["oncall+react_native@xmail.facebook.com"],
|
||||
exported_linker_flags = [
|
||||
"-weak_framework",
|
||||
"UserNotifications",
|
||||
"-weak_framework",
|
||||
"WebKit",
|
||||
],
|
||||
exported_preprocessor_flags = rn_extra_build_flags(),
|
||||
extension_api_only = True,
|
||||
frameworks = [
|
||||
"Foundation",
|
||||
"UIKit",
|
||||
],
|
||||
header_path_prefix = "React",
|
||||
labels = ["supermodule:ios/default/public.react_native.infra"],
|
||||
lang_compiler_flags = get_fbobjc_enable_exception_lang_compiler_flags_DEPRECATED(),
|
||||
link_whole = True,
|
||||
platform_preprocessor_flags = [(
|
||||
"linux",
|
||||
["-D PIC_MODIFIER=@PLT"],
|
||||
)],
|
||||
plugins =
|
||||
react_module_plugin_providers(
|
||||
name = "AccessibilityManager",
|
||||
native_class_func = "RCTAccessibilityManagerCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "Appearance",
|
||||
native_class_func = "RCTAppearanceCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "DeviceInfo",
|
||||
native_class_func = "RCTDeviceInfoCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "ExceptionsManager",
|
||||
native_class_func = "RCTExceptionsManagerCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "PlatformConstants",
|
||||
native_class_func = "RCTPlatformCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "Clipboard",
|
||||
native_class_func = "RCTClipboardCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "I18nManager",
|
||||
native_class_func = "RCTI18nManagerCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "SourceCode",
|
||||
native_class_func = "RCTSourceCodeCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "ActionSheetManager",
|
||||
native_class_func = "RCTActionSheetManagerCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "AlertManager",
|
||||
native_class_func = "RCTAlertManagerCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "AsyncLocalStorage",
|
||||
native_class_func = "RCTAsyncLocalStorageCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "Timing",
|
||||
native_class_func = "RCTTimingCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "StatusBarManager",
|
||||
native_class_func = "RCTStatusBarManagerCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "KeyboardObserver",
|
||||
native_class_func = "RCTKeyboardObserverCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "AppState",
|
||||
native_class_func = "RCTAppStateCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "PerfMonitor",
|
||||
native_class_func = "RCTPerfMonitorCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "DevMenu",
|
||||
native_class_func = "RCTDevMenuCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "DevSettings",
|
||||
native_class_func = "RCTDevSettingsCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "RedBox",
|
||||
native_class_func = "RCTRedBoxCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "LogBox",
|
||||
native_class_func = "RCTLogBoxCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "TVNavigationEventEmitter",
|
||||
native_class_func = "RCTTVNavigationEventEmitterCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "WebSocketExecutor",
|
||||
native_class_func = "RCTWebSocketExecutorCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "WebSocketModule",
|
||||
native_class_func = "RCTWebSocketModuleCls",
|
||||
) + react_module_plugin_providers(
|
||||
name = "DevLoadingView",
|
||||
native_class_func = "RCTDevLoadingViewCls",
|
||||
),
|
||||
plugins_header = "FBCoreModulesPlugins.h",
|
||||
preprocessor_flags = OBJC_ARC_PREPROCESSOR_FLAGS + get_preprocessor_flags_for_build_mode() + rn_extra_build_flags() + [
|
||||
"-DRN_DISABLE_OSS_PLUGIN_HEADER",
|
||||
],
|
||||
reexport_all_header_dependencies = True,
|
||||
visibility = ["PUBLIC"],
|
||||
exported_deps = [
|
||||
"//xplat/js:RCTLinkingApple",
|
||||
"//xplat/js:RCTPushNotificationApple",
|
||||
"//xplat/js/react-native-github:ReactInternalApple",
|
||||
"//xplat/js/react-native-github/Libraries/FBReactNativeSpec:FBReactNativeSpecApple",
|
||||
],
|
||||
)
|
63
node_modules/react-native/React/CoreModules/CoreModulesPlugins.h
generated
vendored
Normal file
63
node_modules/react-native/React/CoreModules/CoreModulesPlugins.h
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated by an internal plugin build system
|
||||
*/
|
||||
|
||||
#ifdef RN_DISABLE_OSS_PLUGIN_HEADER
|
||||
|
||||
// FB Internal: FBCoreModulesPlugins.h is autogenerated by the build system.
|
||||
#import <React/FBCoreModulesPlugins.h>
|
||||
|
||||
#else
|
||||
|
||||
// OSS-compatibility layer
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wreturn-type-c-linkage"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// RCTTurboModuleManagerDelegate should call this to resolve module classes.
|
||||
Class RCTCoreModulesClassProvider(const char *name);
|
||||
|
||||
// Lookup functions
|
||||
Class RCTAccessibilityManagerCls(void) __attribute__((used));
|
||||
Class RCTAppearanceCls(void) __attribute__((used));
|
||||
Class RCTDeviceInfoCls(void) __attribute__((used));
|
||||
Class RCTExceptionsManagerCls(void) __attribute__((used));
|
||||
Class RCTPlatformCls(void) __attribute__((used));
|
||||
Class RCTClipboardCls(void) __attribute__((used));
|
||||
Class RCTI18nManagerCls(void) __attribute__((used));
|
||||
Class RCTSourceCodeCls(void) __attribute__((used));
|
||||
Class RCTActionSheetManagerCls(void) __attribute__((used));
|
||||
Class RCTAlertManagerCls(void) __attribute__((used));
|
||||
Class RCTAsyncLocalStorageCls(void) __attribute__((used));
|
||||
Class RCTTimingCls(void) __attribute__((used));
|
||||
Class RCTStatusBarManagerCls(void) __attribute__((used));
|
||||
Class RCTKeyboardObserverCls(void) __attribute__((used));
|
||||
Class RCTAppStateCls(void) __attribute__((used));
|
||||
Class RCTPerfMonitorCls(void) __attribute__((used));
|
||||
Class RCTDevMenuCls(void) __attribute__((used));
|
||||
Class RCTDevSettingsCls(void) __attribute__((used));
|
||||
Class RCTRedBoxCls(void) __attribute__((used));
|
||||
Class RCTLogBoxCls(void) __attribute__((used));
|
||||
Class RCTTVNavigationEventEmitterCls(void) __attribute__((used));
|
||||
Class RCTWebSocketExecutorCls(void) __attribute__((used));
|
||||
Class RCTWebSocketModuleCls(void) __attribute__((used));
|
||||
Class RCTDevLoadingViewCls(void) __attribute__((used));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#endif // RN_DISABLE_OSS_PLUGIN_HEADER
|
55
node_modules/react-native/React/CoreModules/CoreModulesPlugins.mm
generated
vendored
Normal file
55
node_modules/react-native/React/CoreModules/CoreModulesPlugins.mm
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated by an internal plugin build system
|
||||
*/
|
||||
|
||||
#ifndef RN_DISABLE_OSS_PLUGIN_HEADER
|
||||
|
||||
// OSS-compatibility layer
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
#import <string>
|
||||
#import <unordered_map>
|
||||
|
||||
Class RCTCoreModulesClassProvider(const char *name) {
|
||||
static std::unordered_map<std::string, Class (*)(void)> sCoreModuleClassMap = {
|
||||
{"AccessibilityManager", RCTAccessibilityManagerCls},
|
||||
{"Appearance", RCTAppearanceCls},
|
||||
{"DeviceInfo", RCTDeviceInfoCls},
|
||||
{"ExceptionsManager", RCTExceptionsManagerCls},
|
||||
{"PlatformConstants", RCTPlatformCls},
|
||||
{"Clipboard", RCTClipboardCls},
|
||||
{"I18nManager", RCTI18nManagerCls},
|
||||
{"SourceCode", RCTSourceCodeCls},
|
||||
{"ActionSheetManager", RCTActionSheetManagerCls},
|
||||
{"AlertManager", RCTAlertManagerCls},
|
||||
{"AsyncLocalStorage", RCTAsyncLocalStorageCls},
|
||||
{"Timing", RCTTimingCls},
|
||||
{"StatusBarManager", RCTStatusBarManagerCls},
|
||||
{"KeyboardObserver", RCTKeyboardObserverCls},
|
||||
{"AppState", RCTAppStateCls},
|
||||
{"PerfMonitor", RCTPerfMonitorCls},
|
||||
{"DevMenu", RCTDevMenuCls},
|
||||
{"DevSettings", RCTDevSettingsCls},
|
||||
{"RedBox", RCTRedBoxCls},
|
||||
{"LogBox", RCTLogBoxCls},
|
||||
{"TVNavigationEventEmitter", RCTTVNavigationEventEmitterCls},
|
||||
{"WebSocketExecutor", RCTWebSocketExecutorCls},
|
||||
{"WebSocketModule", RCTWebSocketModuleCls},
|
||||
{"DevLoadingView", RCTDevLoadingViewCls},
|
||||
};
|
||||
|
||||
auto p = sCoreModuleClassMap.find(name);
|
||||
if (p != sCoreModuleClassMap.end()) {
|
||||
auto classFunc = p->second;
|
||||
return classFunc();
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
#endif // RN_DISABLE_OSS_PLUGIN_HEADER
|
35
node_modules/react-native/React/CoreModules/RCTAccessibilityManager.h
generated
vendored
Normal file
35
node_modules/react-native/React/CoreModules/RCTAccessibilityManager.h
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
extern NSString *const RCTAccessibilityManagerDidUpdateMultiplierNotification; // posted when multiplier is changed
|
||||
|
||||
@interface RCTAccessibilityManager : NSObject <RCTBridgeModule>
|
||||
|
||||
@property (nonatomic, readonly) CGFloat multiplier;
|
||||
|
||||
/// map from UIKit categories to multipliers
|
||||
@property (nonatomic, copy) NSDictionary<NSString *, NSNumber *> *multipliers;
|
||||
|
||||
@property (nonatomic, assign) BOOL isBoldTextEnabled;
|
||||
@property (nonatomic, assign) BOOL isGrayscaleEnabled;
|
||||
@property (nonatomic, assign) BOOL isInvertColorsEnabled;
|
||||
@property (nonatomic, assign) BOOL isReduceMotionEnabled;
|
||||
@property (nonatomic, assign) BOOL isReduceTransparencyEnabled;
|
||||
@property (nonatomic, assign) BOOL isVoiceOverEnabled;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridge (RCTAccessibilityManager)
|
||||
|
||||
@property (nonatomic, readonly) RCTAccessibilityManager *accessibilityManager;
|
||||
|
||||
@end
|
363
node_modules/react-native/React/CoreModules/RCTAccessibilityManager.mm
generated
vendored
Normal file
363
node_modules/react-native/React/CoreModules/RCTAccessibilityManager.mm
generated
vendored
Normal file
@ -0,0 +1,363 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTAccessibilityManager.h"
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTEventDispatcher.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTUIManager.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
NSString *const RCTAccessibilityManagerDidUpdateMultiplierNotification =
|
||||
@"RCTAccessibilityManagerDidUpdateMultiplierNotification";
|
||||
|
||||
@interface RCTAccessibilityManager () <NativeAccessibilityManagerSpec>
|
||||
|
||||
@property (nonatomic, copy) NSString *contentSizeCategory;
|
||||
@property (nonatomic, assign) CGFloat multiplier;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTAccessibilityManager
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
@synthesize multipliers = _multipliers;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_multiplier = 1.0;
|
||||
|
||||
// TODO: can this be moved out of the startup path?
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(didReceiveNewContentSizeCategory:)
|
||||
name:UIContentSizeCategoryDidChangeNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(accessibilityAnnouncementDidFinish:)
|
||||
name:UIAccessibilityAnnouncementDidFinishNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(boldTextStatusDidChange:)
|
||||
name:UIAccessibilityBoldTextStatusDidChangeNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(grayscaleStatusDidChange:)
|
||||
name:UIAccessibilityGrayscaleStatusDidChangeNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(invertColorsStatusDidChange:)
|
||||
name:UIAccessibilityInvertColorsStatusDidChangeNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(reduceMotionStatusDidChange:)
|
||||
name:UIAccessibilityReduceMotionStatusDidChangeNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(reduceTransparencyStatusDidChange:)
|
||||
name:UIAccessibilityReduceTransparencyStatusDidChangeNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(voiceVoiceOverStatusDidChange:)
|
||||
name:UIAccessibilityVoiceOverStatusChanged
|
||||
object:nil];
|
||||
|
||||
self.contentSizeCategory = RCTSharedApplication().preferredContentSizeCategory;
|
||||
_isBoldTextEnabled = UIAccessibilityIsBoldTextEnabled();
|
||||
_isGrayscaleEnabled = UIAccessibilityIsGrayscaleEnabled();
|
||||
_isInvertColorsEnabled = UIAccessibilityIsInvertColorsEnabled();
|
||||
_isReduceMotionEnabled = UIAccessibilityIsReduceMotionEnabled();
|
||||
_isReduceTransparencyEnabled = UIAccessibilityIsReduceTransparencyEnabled();
|
||||
_isVoiceOverEnabled = UIAccessibilityIsVoiceOverRunning();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)didReceiveNewContentSizeCategory:(NSNotification *)note
|
||||
{
|
||||
self.contentSizeCategory = note.userInfo[UIContentSizeCategoryNewValueKey];
|
||||
}
|
||||
|
||||
- (void)accessibilityAnnouncementDidFinish:(__unused NSNotification *)notification
|
||||
{
|
||||
NSDictionary *userInfo = notification.userInfo;
|
||||
// Response dictionary to populate the event with.
|
||||
NSDictionary *response = @{
|
||||
@"announcement" : userInfo[UIAccessibilityAnnouncementKeyStringValue],
|
||||
@"success" : userInfo[UIAccessibilityAnnouncementKeyWasSuccessful]
|
||||
};
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"announcementFinished" body:response];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
- (void)boldTextStatusDidChange:(__unused NSNotification *)notification
|
||||
{
|
||||
BOOL newBoldTextEnabled = UIAccessibilityIsBoldTextEnabled();
|
||||
if (_isBoldTextEnabled != newBoldTextEnabled) {
|
||||
_isBoldTextEnabled = newBoldTextEnabled;
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"boldTextChanged" body:@(_isBoldTextEnabled)];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
|
||||
- (void)grayscaleStatusDidChange:(__unused NSNotification *)notification
|
||||
{
|
||||
BOOL newGrayscaleEnabled = UIAccessibilityIsGrayscaleEnabled();
|
||||
if (_isGrayscaleEnabled != newGrayscaleEnabled) {
|
||||
_isGrayscaleEnabled = newGrayscaleEnabled;
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"grayscaleChanged" body:@(_isGrayscaleEnabled)];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
|
||||
- (void)invertColorsStatusDidChange:(__unused NSNotification *)notification
|
||||
{
|
||||
BOOL newInvertColorsEnabled = UIAccessibilityIsInvertColorsEnabled();
|
||||
if (_isInvertColorsEnabled != newInvertColorsEnabled) {
|
||||
_isInvertColorsEnabled = newInvertColorsEnabled;
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"invertColorsChanged" body:@(_isInvertColorsEnabled)];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reduceMotionStatusDidChange:(__unused NSNotification *)notification
|
||||
{
|
||||
BOOL newReduceMotionEnabled = UIAccessibilityIsReduceMotionEnabled();
|
||||
if (_isReduceMotionEnabled != newReduceMotionEnabled) {
|
||||
_isReduceMotionEnabled = newReduceMotionEnabled;
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"reduceMotionChanged" body:@(_isReduceMotionEnabled)];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reduceTransparencyStatusDidChange:(__unused NSNotification *)notification
|
||||
{
|
||||
BOOL newReduceTransparencyEnabled = UIAccessibilityIsReduceTransparencyEnabled();
|
||||
if (_isReduceTransparencyEnabled != newReduceTransparencyEnabled) {
|
||||
_isReduceTransparencyEnabled = newReduceTransparencyEnabled;
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"reduceTransparencyChanged" body:@(_isReduceTransparencyEnabled)];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
|
||||
- (void)voiceVoiceOverStatusDidChange:(__unused NSNotification *)notification
|
||||
{
|
||||
BOOL newIsVoiceOverEnabled = UIAccessibilityIsVoiceOverRunning();
|
||||
if (_isVoiceOverEnabled != newIsVoiceOverEnabled) {
|
||||
_isVoiceOverEnabled = newIsVoiceOverEnabled;
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"screenReaderChanged" body:@(_isVoiceOverEnabled)];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setContentSizeCategory:(NSString *)contentSizeCategory
|
||||
{
|
||||
if (_contentSizeCategory != contentSizeCategory) {
|
||||
_contentSizeCategory = [contentSizeCategory copy];
|
||||
[self invalidateMultiplier];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)invalidateMultiplier
|
||||
{
|
||||
self.multiplier = [self multiplierForContentSizeCategory:_contentSizeCategory];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTAccessibilityManagerDidUpdateMultiplierNotification
|
||||
object:self];
|
||||
}
|
||||
|
||||
- (CGFloat)multiplierForContentSizeCategory:(NSString *)category
|
||||
{
|
||||
NSNumber *m = self.multipliers[category];
|
||||
if (m.doubleValue <= 0.0) {
|
||||
RCTLogError(@"Can't determine multiplier for category %@. Using 1.0.", category);
|
||||
m = @1.0;
|
||||
}
|
||||
return m.doubleValue;
|
||||
}
|
||||
|
||||
- (void)setMultipliers:(NSDictionary<NSString *, NSNumber *> *)multipliers
|
||||
{
|
||||
if (_multipliers != multipliers) {
|
||||
_multipliers = [multipliers copy];
|
||||
[self invalidateMultiplier];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *, NSNumber *> *)multipliers
|
||||
{
|
||||
if (_multipliers == nil) {
|
||||
_multipliers = @{
|
||||
UIContentSizeCategoryExtraSmall : @0.823,
|
||||
UIContentSizeCategorySmall : @0.882,
|
||||
UIContentSizeCategoryMedium : @0.941,
|
||||
UIContentSizeCategoryLarge : @1.0,
|
||||
UIContentSizeCategoryExtraLarge : @1.118,
|
||||
UIContentSizeCategoryExtraExtraLarge : @1.235,
|
||||
UIContentSizeCategoryExtraExtraExtraLarge : @1.353,
|
||||
UIContentSizeCategoryAccessibilityMedium : @1.786,
|
||||
UIContentSizeCategoryAccessibilityLarge : @2.143,
|
||||
UIContentSizeCategoryAccessibilityExtraLarge : @2.643,
|
||||
UIContentSizeCategoryAccessibilityExtraExtraLarge : @3.143,
|
||||
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge : @3.571
|
||||
};
|
||||
}
|
||||
return _multipliers;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setAccessibilityContentSizeMultipliers
|
||||
: (JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers &)
|
||||
JSMultipliers)
|
||||
{
|
||||
NSMutableDictionary<NSString *, NSNumber *> *multipliers = [NSMutableDictionary new];
|
||||
setMultipliers(multipliers, UIContentSizeCategoryExtraSmall, JSMultipliers.extraSmall());
|
||||
setMultipliers(multipliers, UIContentSizeCategorySmall, JSMultipliers.small());
|
||||
setMultipliers(multipliers, UIContentSizeCategoryMedium, JSMultipliers.medium());
|
||||
setMultipliers(multipliers, UIContentSizeCategoryLarge, JSMultipliers.large());
|
||||
setMultipliers(multipliers, UIContentSizeCategoryExtraLarge, JSMultipliers.extraLarge());
|
||||
setMultipliers(multipliers, UIContentSizeCategoryExtraExtraLarge, JSMultipliers.extraExtraLarge());
|
||||
setMultipliers(multipliers, UIContentSizeCategoryExtraExtraExtraLarge, JSMultipliers.extraExtraExtraLarge());
|
||||
setMultipliers(multipliers, UIContentSizeCategoryAccessibilityMedium, JSMultipliers.accessibilityMedium());
|
||||
setMultipliers(multipliers, UIContentSizeCategoryAccessibilityLarge, JSMultipliers.accessibilityLarge());
|
||||
setMultipliers(multipliers, UIContentSizeCategoryAccessibilityExtraLarge, JSMultipliers.accessibilityExtraLarge());
|
||||
setMultipliers(
|
||||
multipliers, UIContentSizeCategoryAccessibilityExtraExtraLarge, JSMultipliers.accessibilityExtraExtraLarge());
|
||||
setMultipliers(
|
||||
multipliers,
|
||||
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge,
|
||||
JSMultipliers.accessibilityExtraExtraExtraLarge());
|
||||
self.multipliers = multipliers;
|
||||
}
|
||||
|
||||
static void setMultipliers(
|
||||
NSMutableDictionary<NSString *, NSNumber *> *multipliers,
|
||||
NSString *key,
|
||||
folly::Optional<double> optionalDouble)
|
||||
{
|
||||
if (optionalDouble.hasValue()) {
|
||||
multipliers[key] = @(optionalDouble.value());
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setAccessibilityFocus : (double)reactTag)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIView *view = [self.bridge.uiManager viewForReactTag:@(reactTag)];
|
||||
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, view);
|
||||
});
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(announceForAccessibility : (NSString *)announcement)
|
||||
{
|
||||
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, announcement);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getMultiplier : (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
if (callback) {
|
||||
callback(@[ @(self.multiplier) ]);
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getCurrentBoldTextState
|
||||
: (RCTResponseSenderBlock)onSuccess onError
|
||||
: (__unused RCTResponseSenderBlock)onError)
|
||||
{
|
||||
onSuccess(@[ @(_isBoldTextEnabled) ]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getCurrentGrayscaleState
|
||||
: (RCTResponseSenderBlock)onSuccess onError
|
||||
: (__unused RCTResponseSenderBlock)onError)
|
||||
{
|
||||
onSuccess(@[ @(_isGrayscaleEnabled) ]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getCurrentInvertColorsState
|
||||
: (RCTResponseSenderBlock)onSuccess onError
|
||||
: (__unused RCTResponseSenderBlock)onError)
|
||||
{
|
||||
onSuccess(@[ @(_isInvertColorsEnabled) ]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getCurrentReduceMotionState
|
||||
: (RCTResponseSenderBlock)onSuccess onError
|
||||
: (__unused RCTResponseSenderBlock)onError)
|
||||
{
|
||||
onSuccess(@[ @(_isReduceMotionEnabled) ]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getCurrentReduceTransparencyState
|
||||
: (RCTResponseSenderBlock)onSuccess onError
|
||||
: (__unused RCTResponseSenderBlock)onError)
|
||||
{
|
||||
onSuccess(@[ @(_isReduceTransparencyEnabled) ]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getCurrentVoiceOverState
|
||||
: (RCTResponseSenderBlock)onSuccess onError
|
||||
: (__unused RCTResponseSenderBlock)onError)
|
||||
{
|
||||
onSuccess(@[ @(_isVoiceOverEnabled) ]);
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeAccessibilityManagerSpecJSI>(
|
||||
self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridge (RCTAccessibilityManager)
|
||||
|
||||
- (RCTAccessibilityManager *)accessibilityManager
|
||||
{
|
||||
return [self moduleForClass:[RCTAccessibilityManager class]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTAccessibilityManagerCls(void)
|
||||
{
|
||||
return RCTAccessibilityManager.class;
|
||||
}
|
14
node_modules/react-native/React/CoreModules/RCTActionSheetManager.h
generated
vendored
Normal file
14
node_modules/react-native/React/CoreModules/RCTActionSheetManager.h
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
|
||||
@interface RCTActionSheetManager : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
247
node_modules/react-native/React/CoreModules/RCTActionSheetManager.mm
generated
vendored
Normal file
247
node_modules/react-native/React/CoreModules/RCTActionSheetManager.mm
generated
vendored
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTActionSheetManager.h>
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTUIManager.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <RCTTypeSafety/RCTConvertHelpers.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@interface RCTActionSheetManager () <UIActionSheetDelegate, NativeActionSheetManagerSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTActionSheetManager {
|
||||
// Use NSMapTable, as UIAlertViews do not implement <NSCopying>
|
||||
// which is required for NSDictionary keys
|
||||
NSMapTable *_callbacks;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
- (void)presentViewController:(UIViewController *)alertController
|
||||
onParentViewController:(UIViewController *)parentViewController
|
||||
anchorViewTag:(NSNumber *)anchorViewTag
|
||||
{
|
||||
alertController.modalPresentationStyle = UIModalPresentationPopover;
|
||||
UIView *sourceView = parentViewController.view;
|
||||
|
||||
if (anchorViewTag) {
|
||||
sourceView = [self.bridge.uiManager viewForReactTag:anchorViewTag];
|
||||
} else {
|
||||
alertController.popoverPresentationController.permittedArrowDirections = 0;
|
||||
}
|
||||
alertController.popoverPresentationController.sourceView = sourceView;
|
||||
alertController.popoverPresentationController.sourceRect = sourceView.bounds;
|
||||
[parentViewController presentViewController:alertController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(showActionSheetWithOptions
|
||||
: (JS::NativeActionSheetManager::SpecShowActionSheetWithOptionsOptions &)options callback
|
||||
: (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
if (RCTRunningInAppExtension()) {
|
||||
RCTLogError(@"Unable to show action sheet from app extension");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_callbacks) {
|
||||
_callbacks = [NSMapTable strongToStrongObjectsMapTable];
|
||||
}
|
||||
|
||||
NSString *title = options.title();
|
||||
NSString *message = options.message();
|
||||
NSArray<NSString *> *buttons = RCTConvertOptionalVecToArray(options.options(), ^id(NSString *element) {
|
||||
return element;
|
||||
});
|
||||
NSInteger cancelButtonIndex =
|
||||
options.cancelButtonIndex() ? [RCTConvert NSInteger:@(*options.cancelButtonIndex())] : -1;
|
||||
NSArray<NSNumber *> *destructiveButtonIndices;
|
||||
if (options.destructiveButtonIndices()) {
|
||||
destructiveButtonIndices = RCTConvertVecToArray(*options.destructiveButtonIndices(), ^id(double element) {
|
||||
return @(element);
|
||||
});
|
||||
} else {
|
||||
NSNumber *destructiveButtonIndex = @-1;
|
||||
destructiveButtonIndices = @[ destructiveButtonIndex ];
|
||||
}
|
||||
|
||||
UIViewController *controller = RCTPresentedViewController();
|
||||
NSNumber *anchor = [RCTConvert NSNumber:options.anchor() ? @(*options.anchor()) : nil];
|
||||
UIColor *tintColor = [RCTConvert UIColor:options.tintColor() ? @(*options.tintColor()) : nil];
|
||||
|
||||
if (controller == nil) {
|
||||
RCTLogError(@"Tried to display action sheet but there is no application window. options: %@", @{
|
||||
@"title" : title,
|
||||
@"message" : message,
|
||||
@"options" : buttons,
|
||||
@"cancelButtonIndex" : @(cancelButtonIndex),
|
||||
@"destructiveButtonIndices" : destructiveButtonIndices,
|
||||
@"anchor" : anchor,
|
||||
@"tintColor" : tintColor,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The `anchor` option takes a view to set as the anchor for the share
|
||||
* popup to point to, on iPads running iOS 8. If it is not passed, it
|
||||
* defaults to centering the share popup on screen without any arrows.
|
||||
*/
|
||||
NSNumber *anchorViewTag = anchor;
|
||||
|
||||
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title
|
||||
message:message
|
||||
preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
|
||||
NSInteger index = 0;
|
||||
for (NSString *option in buttons) {
|
||||
UIAlertActionStyle style = UIAlertActionStyleDefault;
|
||||
if ([destructiveButtonIndices containsObject:@(index)]) {
|
||||
style = UIAlertActionStyleDestructive;
|
||||
} else if (index == cancelButtonIndex) {
|
||||
style = UIAlertActionStyleCancel;
|
||||
}
|
||||
|
||||
NSInteger localIndex = index;
|
||||
[alertController addAction:[UIAlertAction actionWithTitle:option
|
||||
style:style
|
||||
handler:^(__unused UIAlertAction *action) {
|
||||
callback(@[ @(localIndex) ]);
|
||||
}]];
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
alertController.view.tintColor = tintColor;
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
|
||||
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
|
||||
if (@available(iOS 13.0, *)) {
|
||||
NSString *userInterfaceStyle = [RCTConvert NSString:options.userInterfaceStyle()];
|
||||
|
||||
if (userInterfaceStyle == nil || [userInterfaceStyle isEqualToString:@""]) {
|
||||
alertController.overrideUserInterfaceStyle = UIUserInterfaceStyleUnspecified;
|
||||
} else if ([userInterfaceStyle isEqualToString:@"dark"]) {
|
||||
alertController.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
|
||||
} else if ([userInterfaceStyle isEqualToString:@"light"]) {
|
||||
alertController.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[self presentViewController:alertController onParentViewController:controller anchorViewTag:anchorViewTag];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(showShareActionSheetWithOptions
|
||||
: (JS::NativeActionSheetManager::SpecShowShareActionSheetWithOptionsOptions &)options failureCallback
|
||||
: (RCTResponseSenderBlock)failureCallback successCallback
|
||||
: (RCTResponseSenderBlock)successCallback)
|
||||
{
|
||||
if (RCTRunningInAppExtension()) {
|
||||
RCTLogError(@"Unable to show action sheet from app extension");
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableArray<id> *items = [NSMutableArray array];
|
||||
NSString *message = options.message();
|
||||
if (message) {
|
||||
[items addObject:message];
|
||||
}
|
||||
NSURL *URL = [RCTConvert NSURL:options.url()];
|
||||
if (URL) {
|
||||
if ([URL.scheme.lowercaseString isEqualToString:@"data"]) {
|
||||
NSError *error;
|
||||
NSData *data = [NSData dataWithContentsOfURL:URL options:(NSDataReadingOptions)0 error:&error];
|
||||
if (!data) {
|
||||
failureCallback(@[ RCTJSErrorFromNSError(error) ]);
|
||||
return;
|
||||
}
|
||||
[items addObject:data];
|
||||
} else {
|
||||
[items addObject:URL];
|
||||
}
|
||||
}
|
||||
if (items.count == 0) {
|
||||
RCTLogError(@"No `url` or `message` to share");
|
||||
return;
|
||||
}
|
||||
|
||||
UIActivityViewController *shareController = [[UIActivityViewController alloc] initWithActivityItems:items
|
||||
applicationActivities:nil];
|
||||
|
||||
NSString *subject = options.subject();
|
||||
if (subject) {
|
||||
[shareController setValue:subject forKey:@"subject"];
|
||||
}
|
||||
|
||||
NSArray *excludedActivityTypes =
|
||||
RCTConvertOptionalVecToArray(options.excludedActivityTypes(), ^id(NSString *element) {
|
||||
return element;
|
||||
});
|
||||
if (excludedActivityTypes) {
|
||||
shareController.excludedActivityTypes = excludedActivityTypes;
|
||||
}
|
||||
|
||||
UIViewController *controller = RCTPresentedViewController();
|
||||
shareController.completionWithItemsHandler =
|
||||
^(NSString *activityType, BOOL completed, __unused NSArray *returnedItems, NSError *activityError) {
|
||||
if (activityError) {
|
||||
failureCallback(@[ RCTJSErrorFromNSError(activityError) ]);
|
||||
} else if (completed || activityType == nil) {
|
||||
successCallback(@[ @(completed), RCTNullIfNil(activityType) ]);
|
||||
}
|
||||
};
|
||||
|
||||
NSNumber *anchorViewTag = [RCTConvert NSNumber:options.anchor() ? @(*options.anchor()) : nil];
|
||||
shareController.view.tintColor = [RCTConvert UIColor:options.tintColor() ? @(*options.tintColor()) : nil];
|
||||
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
|
||||
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
|
||||
if (@available(iOS 13.0, *)) {
|
||||
NSString *userInterfaceStyle = [RCTConvert NSString:options.userInterfaceStyle()];
|
||||
|
||||
if (userInterfaceStyle == nil || [userInterfaceStyle isEqualToString:@""]) {
|
||||
shareController.overrideUserInterfaceStyle = UIUserInterfaceStyleUnspecified;
|
||||
} else if ([userInterfaceStyle isEqualToString:@"dark"]) {
|
||||
shareController.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
|
||||
} else if ([userInterfaceStyle isEqualToString:@"light"]) {
|
||||
shareController.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[self presentViewController:shareController onParentViewController:controller anchorViewTag:anchorViewTag];
|
||||
}
|
||||
|
||||
- (std::shared_ptr<TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<NativeActionSheetManagerSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTActionSheetManagerCls(void)
|
||||
{
|
||||
return RCTActionSheetManager.class;
|
||||
}
|
14
node_modules/react-native/React/CoreModules/RCTAlertController.h
generated
vendored
Normal file
14
node_modules/react-native/React/CoreModules/RCTAlertController.h
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface RCTAlertController : UIAlertController
|
||||
|
||||
- (void)show:(BOOL)animated completion:(void (^)(void))completion;
|
||||
|
||||
@end
|
36
node_modules/react-native/React/CoreModules/RCTAlertController.m
generated
vendored
Normal file
36
node_modules/react-native/React/CoreModules/RCTAlertController.m
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import "RCTAlertController.h"
|
||||
|
||||
@interface RCTAlertController ()
|
||||
|
||||
@property (nonatomic, strong) UIWindow *alertWindow;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTAlertController
|
||||
|
||||
- (UIWindow *)alertWindow
|
||||
{
|
||||
if (_alertWindow == nil) {
|
||||
_alertWindow = [[UIWindow alloc] initWithFrame:RCTSharedApplication().keyWindow.bounds];
|
||||
_alertWindow.rootViewController = [UIViewController new];
|
||||
_alertWindow.windowLevel = UIWindowLevelAlert + 1;
|
||||
}
|
||||
return _alertWindow;
|
||||
}
|
||||
|
||||
- (void)show:(BOOL)animated completion:(void (^)(void))completion
|
||||
{
|
||||
[self.alertWindow makeKeyAndVisible];
|
||||
[self.alertWindow.rootViewController presentViewController:self animated:animated completion:completion];
|
||||
}
|
||||
|
||||
@end
|
22
node_modules/react-native/React/CoreModules/RCTAlertManager.h
generated
vendored
Normal file
22
node_modules/react-native/React/CoreModules/RCTAlertManager.h
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTInvalidating.h>
|
||||
|
||||
typedef NS_ENUM(NSInteger, RCTAlertViewStyle) {
|
||||
RCTAlertViewStyleDefault = 0,
|
||||
RCTAlertViewStyleSecureTextInput,
|
||||
RCTAlertViewStylePlainTextInput,
|
||||
RCTAlertViewStyleLoginAndPasswordInput
|
||||
};
|
||||
|
||||
@interface RCTAlertManager : NSObject <RCTBridgeModule, RCTInvalidating>
|
||||
|
||||
@end
|
203
node_modules/react-native/React/CoreModules/RCTAlertManager.mm
generated
vendored
Normal file
203
node_modules/react-native/React/CoreModules/RCTAlertManager.mm
generated
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTAlertManager.h"
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <RCTTypeSafety/RCTConvertHelpers.h>
|
||||
#import <React/RCTAssert.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
#import "RCTAlertController.h"
|
||||
|
||||
@implementation RCTConvert (UIAlertViewStyle)
|
||||
|
||||
RCT_ENUM_CONVERTER(
|
||||
RCTAlertViewStyle,
|
||||
(@{
|
||||
@"default" : @(RCTAlertViewStyleDefault),
|
||||
@"secure-text" : @(RCTAlertViewStyleSecureTextInput),
|
||||
@"plain-text" : @(RCTAlertViewStylePlainTextInput),
|
||||
@"login-password" : @(RCTAlertViewStyleLoginAndPasswordInput),
|
||||
}),
|
||||
RCTAlertViewStyleDefault,
|
||||
integerValue)
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTAlertManager () <NativeAlertManagerSpec>
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTAlertManager {
|
||||
NSHashTable *_alertControllers;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
for (UIAlertController *alertController in _alertControllers) {
|
||||
[alertController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NSDictionary} args Dictionary of the form
|
||||
*
|
||||
* @{
|
||||
* @"message": @"<Alert message>",
|
||||
* @"buttons": @[
|
||||
* @{@"<key1>": @"<title1>"},
|
||||
* @{@"<key2>": @"<title2>"},
|
||||
* ],
|
||||
* @"cancelButtonKey": @"<key2>",
|
||||
* }
|
||||
* The key from the `buttons` dictionary is passed back in the callback on click.
|
||||
* Buttons are displayed in the order they are specified.
|
||||
*/
|
||||
RCT_EXPORT_METHOD(alertWithArgs : (JS::NativeAlertManager::Args &)args callback : (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
NSString *title = [RCTConvert NSString:args.title()];
|
||||
NSString *message = [RCTConvert NSString:args.message()];
|
||||
RCTAlertViewStyle type = [RCTConvert RCTAlertViewStyle:args.type()];
|
||||
NSArray<NSDictionary *> *buttons =
|
||||
[RCTConvert NSDictionaryArray:RCTConvertOptionalVecToArray(args.buttons(), ^id(id<NSObject> element) {
|
||||
return element;
|
||||
})];
|
||||
NSString *defaultValue = [RCTConvert NSString:args.defaultValue()];
|
||||
NSString *cancelButtonKey = [RCTConvert NSString:args.cancelButtonKey()];
|
||||
NSString *destructiveButtonKey = [RCTConvert NSString:args.destructiveButtonKey()];
|
||||
UIKeyboardType keyboardType = [RCTConvert UIKeyboardType:args.keyboardType()];
|
||||
|
||||
if (!title && !message) {
|
||||
RCTLogError(@"Must specify either an alert title, or message, or both");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buttons.count == 0) {
|
||||
if (type == RCTAlertViewStyleDefault) {
|
||||
buttons = @[ @{@"0" : RCTUIKitLocalizedString(@"OK")} ];
|
||||
cancelButtonKey = @"0";
|
||||
} else {
|
||||
buttons = @[
|
||||
@{@"0" : RCTUIKitLocalizedString(@"OK")},
|
||||
@{@"1" : RCTUIKitLocalizedString(@"Cancel")},
|
||||
];
|
||||
cancelButtonKey = @"1";
|
||||
}
|
||||
}
|
||||
|
||||
RCTAlertController *alertController = [RCTAlertController alertControllerWithTitle:title
|
||||
message:nil
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
switch (type) {
|
||||
case RCTAlertViewStylePlainTextInput: {
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.secureTextEntry = NO;
|
||||
textField.text = defaultValue;
|
||||
textField.keyboardType = keyboardType;
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case RCTAlertViewStyleSecureTextInput: {
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.placeholder = RCTUIKitLocalizedString(@"Password");
|
||||
textField.secureTextEntry = YES;
|
||||
textField.text = defaultValue;
|
||||
textField.keyboardType = keyboardType;
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case RCTAlertViewStyleLoginAndPasswordInput: {
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.placeholder = RCTUIKitLocalizedString(@"Login");
|
||||
textField.text = defaultValue;
|
||||
textField.keyboardType = keyboardType;
|
||||
}];
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.placeholder = RCTUIKitLocalizedString(@"Password");
|
||||
textField.secureTextEntry = YES;
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case RCTAlertViewStyleDefault:
|
||||
break;
|
||||
}
|
||||
|
||||
alertController.message = message;
|
||||
|
||||
for (NSDictionary<NSString *, id> *button in buttons) {
|
||||
if (button.count != 1) {
|
||||
RCTLogError(@"Button definitions should have exactly one key.");
|
||||
}
|
||||
NSString *buttonKey = button.allKeys.firstObject;
|
||||
NSString *buttonTitle = [RCTConvert NSString:button[buttonKey]];
|
||||
UIAlertActionStyle buttonStyle = UIAlertActionStyleDefault;
|
||||
if ([buttonKey isEqualToString:cancelButtonKey]) {
|
||||
buttonStyle = UIAlertActionStyleCancel;
|
||||
} else if ([buttonKey isEqualToString:destructiveButtonKey]) {
|
||||
buttonStyle = UIAlertActionStyleDestructive;
|
||||
}
|
||||
__weak RCTAlertController *weakAlertController = alertController;
|
||||
[alertController
|
||||
addAction:[UIAlertAction
|
||||
actionWithTitle:buttonTitle
|
||||
style:buttonStyle
|
||||
handler:^(__unused UIAlertAction *action) {
|
||||
switch (type) {
|
||||
case RCTAlertViewStylePlainTextInput:
|
||||
case RCTAlertViewStyleSecureTextInput:
|
||||
callback(@[ buttonKey, [weakAlertController.textFields.firstObject text] ]);
|
||||
break;
|
||||
case RCTAlertViewStyleLoginAndPasswordInput: {
|
||||
NSDictionary<NSString *, NSString *> *loginCredentials = @{
|
||||
@"login" : [weakAlertController.textFields.firstObject text],
|
||||
@"password" : [weakAlertController.textFields.lastObject text]
|
||||
};
|
||||
callback(@[ buttonKey, loginCredentials ]);
|
||||
break;
|
||||
}
|
||||
case RCTAlertViewStyleDefault:
|
||||
callback(@[ buttonKey ]);
|
||||
break;
|
||||
}
|
||||
}]];
|
||||
}
|
||||
|
||||
if (!_alertControllers) {
|
||||
_alertControllers = [NSHashTable weakObjectsHashTable];
|
||||
}
|
||||
[_alertControllers addObject:alertController];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[alertController show:YES completion:nil];
|
||||
});
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeAlertManagerSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTAlertManagerCls(void)
|
||||
{
|
||||
return RCTAlertManager.class;
|
||||
}
|
12
node_modules/react-native/React/CoreModules/RCTAppState.h
generated
vendored
Normal file
12
node_modules/react-native/React/CoreModules/RCTAppState.h
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTEventEmitter.h>
|
||||
|
||||
@interface RCTAppState : RCTEventEmitter <RCTInvalidating>
|
||||
|
||||
@end
|
154
node_modules/react-native/React/CoreModules/RCTAppState.mm
generated
vendored
Normal file
154
node_modules/react-native/React/CoreModules/RCTAppState.mm
generated
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTAppState.h"
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTAssert.h>
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTEventDispatcher.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
static NSString *RCTCurrentAppState()
|
||||
{
|
||||
static NSDictionary *states;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
states = @{@(UIApplicationStateActive) : @"active", @(UIApplicationStateBackground) : @"background"};
|
||||
});
|
||||
|
||||
if (RCTRunningInAppExtension()) {
|
||||
return @"extension";
|
||||
}
|
||||
|
||||
return states[@(RCTSharedApplication().applicationState)] ?: @"unknown";
|
||||
}
|
||||
|
||||
@interface RCTAppState () <NativeAppStateSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTAppState {
|
||||
NSString *_lastKnownState;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
- (facebook::react::ModuleConstants<JS::NativeAppState::Constants>)constantsToExport
|
||||
{
|
||||
return (facebook::react::ModuleConstants<JS::NativeAppState::Constants>)[self getConstants];
|
||||
}
|
||||
|
||||
- (facebook::react::ModuleConstants<JS::NativeAppState::Constants>)getConstants
|
||||
{
|
||||
return facebook::react::typedConstants<JS::NativeAppState::Constants>({
|
||||
.initialAppState = RCTCurrentAppState(),
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (NSArray<NSString *> *)supportedEvents
|
||||
{
|
||||
return @[ @"appStateDidChange", @"memoryWarning" ];
|
||||
}
|
||||
|
||||
- (void)startObserving
|
||||
{
|
||||
for (NSString *name in @[
|
||||
UIApplicationDidBecomeActiveNotification,
|
||||
UIApplicationDidEnterBackgroundNotification,
|
||||
UIApplicationDidFinishLaunchingNotification,
|
||||
UIApplicationWillResignActiveNotification,
|
||||
UIApplicationWillEnterForegroundNotification
|
||||
]) {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleAppStateDidChange:)
|
||||
name:name
|
||||
object:nil];
|
||||
}
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleMemoryWarning)
|
||||
name:UIApplicationDidReceiveMemoryWarningNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)stopObserving
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
[self stopObserving];
|
||||
}
|
||||
|
||||
#pragma mark - App Notification Methods
|
||||
|
||||
- (void)handleMemoryWarning
|
||||
{
|
||||
if (self.bridge) {
|
||||
[self sendEventWithName:@"memoryWarning" body:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleAppStateDidChange:(NSNotification *)notification
|
||||
{
|
||||
NSString *newState;
|
||||
|
||||
if ([notification.name isEqualToString:UIApplicationWillResignActiveNotification]) {
|
||||
newState = @"inactive";
|
||||
} else if ([notification.name isEqualToString:UIApplicationWillEnterForegroundNotification]) {
|
||||
newState = @"background";
|
||||
} else {
|
||||
newState = RCTCurrentAppState();
|
||||
}
|
||||
|
||||
if (![newState isEqualToString:_lastKnownState]) {
|
||||
_lastKnownState = newState;
|
||||
if (self.bridge) {
|
||||
[self sendEventWithName:@"appStateDidChange" body:@{@"app_state" : _lastKnownState}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Public API
|
||||
|
||||
/**
|
||||
* Get the current background/foreground state of the app
|
||||
*/
|
||||
RCT_EXPORT_METHOD(getCurrentAppState : (RCTResponseSenderBlock)callback error : (__unused RCTResponseSenderBlock)error)
|
||||
{
|
||||
callback(@[ @{@"app_state" : RCTCurrentAppState()} ]);
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeAppStateSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTAppStateCls(void)
|
||||
{
|
||||
return RCTAppState.class;
|
||||
}
|
17
node_modules/react-native/React/CoreModules/RCTAppearance.h
generated
vendored
Normal file
17
node_modules/react-native/React/CoreModules/RCTAppearance.h
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTEventEmitter.h>
|
||||
|
||||
RCT_EXTERN void RCTEnableAppearancePreference(BOOL enabled);
|
||||
RCT_EXTERN void RCTOverrideAppearancePreference(NSString *const);
|
||||
|
||||
@interface RCTAppearance : RCTEventEmitter <RCTBridgeModule>
|
||||
@end
|
141
node_modules/react-native/React/CoreModules/RCTAppearance.mm
generated
vendored
Normal file
141
node_modules/react-native/React/CoreModules/RCTAppearance.mm
generated
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTAppearance.h"
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTConstants.h>
|
||||
#import <React/RCTEventEmitter.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
NSString *const RCTAppearanceColorSchemeLight = @"light";
|
||||
NSString *const RCTAppearanceColorSchemeDark = @"dark";
|
||||
|
||||
static BOOL sAppearancePreferenceEnabled = YES;
|
||||
void RCTEnableAppearancePreference(BOOL enabled)
|
||||
{
|
||||
sAppearancePreferenceEnabled = enabled;
|
||||
}
|
||||
|
||||
static NSString *sColorSchemeOverride = nil;
|
||||
void RCTOverrideAppearancePreference(NSString *const colorSchemeOverride)
|
||||
{
|
||||
sColorSchemeOverride = colorSchemeOverride;
|
||||
}
|
||||
|
||||
static NSString *RCTColorSchemePreference(UITraitCollection *traitCollection)
|
||||
{
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
|
||||
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
|
||||
if (@available(iOS 13.0, *)) {
|
||||
static NSDictionary *appearances;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
if (sColorSchemeOverride) {
|
||||
return sColorSchemeOverride;
|
||||
}
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
appearances = @{
|
||||
@(UIUserInterfaceStyleLight) : RCTAppearanceColorSchemeLight,
|
||||
@(UIUserInterfaceStyleDark) : RCTAppearanceColorSchemeDark
|
||||
};
|
||||
});
|
||||
|
||||
if (!sAppearancePreferenceEnabled) {
|
||||
// Return the default if the app doesn't allow different color schemes.
|
||||
return RCTAppearanceColorSchemeLight;
|
||||
}
|
||||
|
||||
traitCollection = traitCollection ?: [UITraitCollection currentTraitCollection];
|
||||
return appearances[@(traitCollection.userInterfaceStyle)] ?: RCTAppearanceColorSchemeLight;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Default to light on older OS version - same behavior as Android.
|
||||
return RCTAppearanceColorSchemeLight;
|
||||
}
|
||||
|
||||
@interface RCTAppearance () <NativeAppearanceSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTAppearance {
|
||||
NSString *_currentColorScheme;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE(Appearance)
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
- (std::shared_ptr<TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<NativeAppearanceSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSString *, getColorScheme)
|
||||
{
|
||||
_currentColorScheme = RCTColorSchemePreference(nil);
|
||||
return _currentColorScheme;
|
||||
}
|
||||
|
||||
- (void)appearanceChanged:(NSNotification *)notification
|
||||
{
|
||||
NSDictionary *userInfo = [notification userInfo];
|
||||
UITraitCollection *traitCollection = nil;
|
||||
if (userInfo) {
|
||||
traitCollection = userInfo[RCTUserInterfaceStyleDidChangeNotificationTraitCollectionKey];
|
||||
}
|
||||
NSString *newColorScheme = RCTColorSchemePreference(traitCollection);
|
||||
if (![_currentColorScheme isEqualToString:newColorScheme]) {
|
||||
_currentColorScheme = newColorScheme;
|
||||
[self sendEventWithName:@"appearanceChanged" body:@{@"colorScheme" : newColorScheme}];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - RCTEventEmitter
|
||||
|
||||
- (NSArray<NSString *> *)supportedEvents
|
||||
{
|
||||
return @[ @"appearanceChanged" ];
|
||||
}
|
||||
|
||||
- (void)startObserving
|
||||
{
|
||||
if (@available(iOS 13.0, *)) {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(appearanceChanged:)
|
||||
name:RCTUserInterfaceStyleDidChangeNotification
|
||||
object:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopObserving
|
||||
{
|
||||
if (@available(iOS 13.0, *)) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTAppearanceCls(void)
|
||||
{
|
||||
return RCTAppearance.class;
|
||||
}
|
41
node_modules/react-native/React/CoreModules/RCTAsyncLocalStorage.h
generated
vendored
Normal file
41
node_modules/react-native/React/CoreModules/RCTAsyncLocalStorage.h
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTInvalidating.h>
|
||||
|
||||
/**
|
||||
* A simple, asynchronous, persistent, key-value storage system designed as a
|
||||
* backend to the AsyncStorage JS module, which is modeled after LocalStorage.
|
||||
*
|
||||
* Current implementation stores small values in serialized dictionary and
|
||||
* larger values in separate files. Since we use a serial file queue
|
||||
* `RKFileQueue`, reading/writing from multiple threads should be perceived as
|
||||
* being atomic, unless someone bypasses the `RCTAsyncLocalStorage` API.
|
||||
*
|
||||
* Keys and values must always be strings or an error is returned.
|
||||
*/
|
||||
@interface RCTAsyncLocalStorage : NSObject <RCTBridgeModule, RCTInvalidating>
|
||||
|
||||
@property (nonatomic, assign) BOOL clearOnInvalidate;
|
||||
|
||||
@property (nonatomic, readonly, getter=isValid) BOOL valid;
|
||||
|
||||
// Clear the RCTAsyncLocalStorage data from native code
|
||||
- (void)clearAllData;
|
||||
|
||||
// For clearing data when the bridge may not exist, e.g. when logging out.
|
||||
+ (void)clearAllData;
|
||||
|
||||
// Grab data from the cache. ResponseBlock result array will have an error at position 0, and an array of arrays at
|
||||
// position 1.
|
||||
- (void)multiGet:(NSArray<NSString *> *)keys callback:(RCTResponseSenderBlock)callback;
|
||||
|
||||
// Add multiple key value pairs to the cache.
|
||||
- (void)multiSet:(NSArray<NSArray<NSString *> *> *)kvPairs callback:(RCTResponseSenderBlock)callback;
|
||||
|
||||
@end
|
476
node_modules/react-native/React/CoreModules/RCTAsyncLocalStorage.mm
generated
vendored
Normal file
476
node_modules/react-native/React/CoreModules/RCTAsyncLocalStorage.mm
generated
vendored
Normal file
@ -0,0 +1,476 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTAsyncLocalStorage.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <CommonCrypto/CommonCryptor.h>
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
static NSString *const RCTStorageDirectory = @"RCTAsyncLocalStorage_V1";
|
||||
static NSString *const RCTManifestFileName = @"manifest.json";
|
||||
static const NSUInteger RCTInlineValueThreshold = 1024;
|
||||
|
||||
#pragma mark - Static helper functions
|
||||
|
||||
static NSDictionary *RCTErrorForKey(NSString *key)
|
||||
{
|
||||
if (![key isKindOfClass:[NSString class]]) {
|
||||
return RCTMakeAndLogError(@"Invalid key - must be a string. Key: ", key, @{@"key" : key});
|
||||
} else if (key.length < 1) {
|
||||
return RCTMakeAndLogError(@"Invalid key - must be at least one character. Key: ", key, @{@"key" : key});
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
static void RCTAppendError(NSDictionary *error, NSMutableArray<NSDictionary *> **errors)
|
||||
{
|
||||
if (error && errors) {
|
||||
if (!*errors) {
|
||||
*errors = [NSMutableArray new];
|
||||
}
|
||||
[*errors addObject:error];
|
||||
}
|
||||
}
|
||||
|
||||
static NSString *RCTReadFile(NSString *filePath, NSString *key, NSDictionary **errorOut)
|
||||
{
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
|
||||
NSError *error;
|
||||
NSStringEncoding encoding;
|
||||
NSString *entryString = [NSString stringWithContentsOfFile:filePath usedEncoding:&encoding error:&error];
|
||||
NSDictionary *extraData = @{@"key" : RCTNullIfNil(key)};
|
||||
|
||||
if (error) {
|
||||
if (errorOut)
|
||||
*errorOut = RCTMakeError(@"Failed to read storage file.", error, extraData);
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (encoding != NSUTF8StringEncoding) {
|
||||
if (errorOut)
|
||||
*errorOut = RCTMakeError(@"Incorrect encoding of storage file: ", @(encoding), extraData);
|
||||
return nil;
|
||||
}
|
||||
return entryString;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
static NSString *RCTGetStorageDirectory()
|
||||
{
|
||||
static NSString *storageDirectory = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
#if TARGET_OS_TV
|
||||
storageDirectory = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
|
||||
#else
|
||||
storageDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
|
||||
#endif
|
||||
storageDirectory = [storageDirectory stringByAppendingPathComponent:RCTStorageDirectory];
|
||||
});
|
||||
return storageDirectory;
|
||||
}
|
||||
|
||||
static NSString *RCTGetManifestFilePath()
|
||||
{
|
||||
static NSString *manifestFilePath = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
manifestFilePath = [RCTGetStorageDirectory() stringByAppendingPathComponent:RCTManifestFileName];
|
||||
});
|
||||
return manifestFilePath;
|
||||
}
|
||||
|
||||
// Only merges objects - all other types are just clobbered (including arrays)
|
||||
static BOOL RCTMergeRecursive(NSMutableDictionary *destination, NSDictionary *source)
|
||||
{
|
||||
BOOL modified = NO;
|
||||
for (NSString *key in source) {
|
||||
id sourceValue = source[key];
|
||||
id destinationValue = destination[key];
|
||||
if ([sourceValue isKindOfClass:[NSDictionary class]]) {
|
||||
if ([destinationValue isKindOfClass:[NSDictionary class]]) {
|
||||
if ([destinationValue classForCoder] != [NSMutableDictionary class]) {
|
||||
destinationValue = [destinationValue mutableCopy];
|
||||
}
|
||||
if (RCTMergeRecursive(destinationValue, sourceValue)) {
|
||||
destination[key] = destinationValue;
|
||||
modified = YES;
|
||||
}
|
||||
} else {
|
||||
destination[key] = [sourceValue copy];
|
||||
modified = YES;
|
||||
}
|
||||
} else if (![source isEqual:destinationValue]) {
|
||||
destination[key] = [sourceValue copy];
|
||||
modified = YES;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
static dispatch_queue_t RCTGetMethodQueue()
|
||||
{
|
||||
// We want all instances to share the same queue since they will be reading/writing the same files.
|
||||
static dispatch_queue_t queue;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
queue = dispatch_queue_create("com.facebook.react.AsyncLocalStorageQueue", DISPATCH_QUEUE_SERIAL);
|
||||
});
|
||||
return queue;
|
||||
}
|
||||
|
||||
static NSCache *RCTGetCache()
|
||||
{
|
||||
// We want all instances to share the same cache since they will be reading/writing the same files.
|
||||
static NSCache *cache;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
cache = [NSCache new];
|
||||
cache.totalCostLimit = 2 * 1024 * 1024; // 2MB
|
||||
|
||||
// Clear cache in the event of a memory warning
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidReceiveMemoryWarningNotification
|
||||
object:nil
|
||||
queue:nil
|
||||
usingBlock:^(__unused NSNotification *note) {
|
||||
[cache removeAllObjects];
|
||||
}];
|
||||
});
|
||||
return cache;
|
||||
}
|
||||
|
||||
static BOOL RCTHasCreatedStorageDirectory = NO;
|
||||
static NSDictionary *RCTDeleteStorageDirectory()
|
||||
{
|
||||
NSError *error;
|
||||
[[NSFileManager defaultManager] removeItemAtPath:RCTGetStorageDirectory() error:&error];
|
||||
RCTHasCreatedStorageDirectory = NO;
|
||||
return error ? RCTMakeError(@"Failed to delete storage directory.", error, nil) : nil;
|
||||
}
|
||||
|
||||
#pragma mark - RCTAsyncLocalStorage
|
||||
|
||||
@interface RCTAsyncLocalStorage () <NativeAsyncStorageSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTAsyncLocalStorage {
|
||||
BOOL _haveSetup;
|
||||
// The manifest is a dictionary of all keys with small values inlined. Null values indicate values that are stored
|
||||
// in separate files (as opposed to nil values which don't exist). The manifest is read off disk at startup, and
|
||||
// written to disk after all mutations.
|
||||
NSMutableDictionary<NSString *, NSString *> *_manifest;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return RCTGetMethodQueue();
|
||||
}
|
||||
|
||||
- (void)clearAllData
|
||||
{
|
||||
dispatch_async(RCTGetMethodQueue(), ^{
|
||||
[self->_manifest removeAllObjects];
|
||||
[RCTGetCache() removeAllObjects];
|
||||
RCTDeleteStorageDirectory();
|
||||
});
|
||||
}
|
||||
|
||||
+ (void)clearAllData
|
||||
{
|
||||
dispatch_async(RCTGetMethodQueue(), ^{
|
||||
[RCTGetCache() removeAllObjects];
|
||||
RCTDeleteStorageDirectory();
|
||||
});
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
if (_clearOnInvalidate) {
|
||||
[RCTGetCache() removeAllObjects];
|
||||
RCTDeleteStorageDirectory();
|
||||
}
|
||||
_clearOnInvalidate = NO;
|
||||
[_manifest removeAllObjects];
|
||||
_haveSetup = NO;
|
||||
}
|
||||
|
||||
- (BOOL)isValid
|
||||
{
|
||||
return _haveSetup;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (NSString *)_filePathForKey:(NSString *)key
|
||||
{
|
||||
NSString *safeFileName = RCTMD5Hash(key);
|
||||
return [RCTGetStorageDirectory() stringByAppendingPathComponent:safeFileName];
|
||||
}
|
||||
|
||||
- (NSDictionary *)_ensureSetup
|
||||
{
|
||||
RCTAssertThread(RCTGetMethodQueue(), @"Must be executed on storage thread");
|
||||
|
||||
#if TARGET_OS_TV
|
||||
RCTLogWarn(@"Persistent storage is not supported on tvOS, your data may be removed at any point.");
|
||||
#endif
|
||||
|
||||
NSError *error = nil;
|
||||
if (!RCTHasCreatedStorageDirectory) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:RCTGetStorageDirectory()
|
||||
withIntermediateDirectories:YES
|
||||
attributes:nil
|
||||
error:&error];
|
||||
if (error) {
|
||||
return RCTMakeError(@"Failed to create storage directory.", error, nil);
|
||||
}
|
||||
RCTHasCreatedStorageDirectory = YES;
|
||||
}
|
||||
if (!_haveSetup) {
|
||||
NSDictionary *errorOut;
|
||||
NSString *serialized = RCTReadFile(RCTGetManifestFilePath(), RCTManifestFileName, &errorOut);
|
||||
_manifest = serialized ? RCTJSONParseMutable(serialized, &error) : [NSMutableDictionary new];
|
||||
if (error) {
|
||||
RCTLogWarn(@"Failed to parse manifest - creating new one.\n\n%@", error);
|
||||
_manifest = [NSMutableDictionary new];
|
||||
}
|
||||
_haveSetup = YES;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSDictionary *)_writeManifest:(NSMutableArray<NSDictionary *> **)errors
|
||||
{
|
||||
NSError *error;
|
||||
NSString *serialized = RCTJSONStringify(_manifest, &error);
|
||||
[serialized writeToFile:RCTGetManifestFilePath() atomically:YES encoding:NSUTF8StringEncoding error:&error];
|
||||
NSDictionary *errorOut;
|
||||
if (error) {
|
||||
errorOut = RCTMakeError(@"Failed to write manifest file.", error, nil);
|
||||
RCTAppendError(errorOut, errors);
|
||||
}
|
||||
return errorOut;
|
||||
}
|
||||
|
||||
- (NSDictionary *)_appendItemForKey:(NSString *)key toArray:(NSMutableArray<NSArray<NSString *> *> *)result
|
||||
{
|
||||
NSDictionary *errorOut = RCTErrorForKey(key);
|
||||
if (errorOut) {
|
||||
return errorOut;
|
||||
}
|
||||
NSString *value = [self _getValueForKey:key errorOut:&errorOut];
|
||||
[result addObject:@[ key, RCTNullIfNil(value) ]]; // Insert null if missing or failure.
|
||||
return errorOut;
|
||||
}
|
||||
|
||||
- (NSString *)_getValueForKey:(NSString *)key errorOut:(NSDictionary **)errorOut
|
||||
{
|
||||
NSString *value = _manifest[key]; // nil means missing, null means there may be a data file, else: NSString
|
||||
if (value == (id)kCFNull) {
|
||||
value = [RCTGetCache() objectForKey:key];
|
||||
if (!value) {
|
||||
NSString *filePath = [self _filePathForKey:key];
|
||||
value = RCTReadFile(filePath, key, errorOut);
|
||||
if (value) {
|
||||
[RCTGetCache() setObject:value forKey:key cost:value.length];
|
||||
} else {
|
||||
// file does not exist after all, so remove from manifest (no need to save
|
||||
// manifest immediately though, as cost of checking again next time is negligible)
|
||||
[_manifest removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
- (NSDictionary *)_writeEntry:(NSArray<NSString *> *)entry changedManifest:(BOOL *)changedManifest
|
||||
{
|
||||
if (entry.count != 2) {
|
||||
return RCTMakeAndLogError(@"Entries must be arrays of the form [key: string, value: string], got: ", entry, nil);
|
||||
}
|
||||
NSString *key = entry[0];
|
||||
NSDictionary *errorOut = RCTErrorForKey(key);
|
||||
if (errorOut) {
|
||||
return errorOut;
|
||||
}
|
||||
NSString *value = entry[1];
|
||||
NSString *filePath = [self _filePathForKey:key];
|
||||
NSError *error;
|
||||
if (value.length <= RCTInlineValueThreshold) {
|
||||
if (_manifest[key] == (id)kCFNull) {
|
||||
// If the value already existed but wasn't inlined, remove the old file.
|
||||
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
|
||||
[RCTGetCache() removeObjectForKey:key];
|
||||
}
|
||||
*changedManifest = YES;
|
||||
_manifest[key] = value;
|
||||
return nil;
|
||||
}
|
||||
[value writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
|
||||
[RCTGetCache() setObject:value forKey:key cost:value.length];
|
||||
if (error) {
|
||||
errorOut = RCTMakeError(@"Failed to write value.", error, @{@"key" : key});
|
||||
} else if (_manifest[key] != (id)kCFNull) {
|
||||
*changedManifest = YES;
|
||||
_manifest[key] = (id)kCFNull;
|
||||
}
|
||||
return errorOut;
|
||||
}
|
||||
|
||||
#pragma mark - Exported JS Functions
|
||||
|
||||
RCT_EXPORT_METHOD(multiGet : (NSArray<NSString *> *)keys callback : (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
NSDictionary *errorOut = [self _ensureSetup];
|
||||
if (errorOut) {
|
||||
callback(@[ @[ errorOut ], (id)kCFNull ]);
|
||||
return;
|
||||
}
|
||||
NSMutableArray<NSDictionary *> *errors;
|
||||
NSMutableArray<NSArray<NSString *> *> *result = [[NSMutableArray alloc] initWithCapacity:keys.count];
|
||||
for (NSString *key in keys) {
|
||||
id keyError;
|
||||
id value = [self _getValueForKey:key errorOut:&keyError];
|
||||
[result addObject:@[ key, RCTNullIfNil(value) ]];
|
||||
RCTAppendError(keyError, &errors);
|
||||
}
|
||||
callback(@[ RCTNullIfNil(errors), result ]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(multiSet : (NSArray<NSArray<NSString *> *> *)kvPairs callback : (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
NSDictionary *errorOut = [self _ensureSetup];
|
||||
if (errorOut) {
|
||||
callback(@[ @[ errorOut ] ]);
|
||||
return;
|
||||
}
|
||||
BOOL changedManifest = NO;
|
||||
NSMutableArray<NSDictionary *> *errors;
|
||||
for (NSArray<NSString *> *entry in kvPairs) {
|
||||
NSDictionary *keyError = [self _writeEntry:entry changedManifest:&changedManifest];
|
||||
RCTAppendError(keyError, &errors);
|
||||
}
|
||||
if (changedManifest) {
|
||||
[self _writeManifest:&errors];
|
||||
}
|
||||
callback(@[ RCTNullIfNil(errors) ]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(multiMerge : (NSArray<NSArray<NSString *> *> *)kvPairs callback : (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
NSDictionary *errorOut = [self _ensureSetup];
|
||||
if (errorOut) {
|
||||
callback(@[ @[ errorOut ] ]);
|
||||
return;
|
||||
}
|
||||
BOOL changedManifest = NO;
|
||||
NSMutableArray<NSDictionary *> *errors;
|
||||
for (__strong NSArray<NSString *> *entry in kvPairs) {
|
||||
NSDictionary *keyError;
|
||||
NSString *value = [self _getValueForKey:entry[0] errorOut:&keyError];
|
||||
if (!keyError) {
|
||||
if (value) {
|
||||
NSError *jsonError;
|
||||
NSMutableDictionary *mergedVal = RCTJSONParseMutable(value, &jsonError);
|
||||
if (RCTMergeRecursive(mergedVal, RCTJSONParse(entry[1], &jsonError))) {
|
||||
entry = @[ entry[0], RCTNullIfNil(RCTJSONStringify(mergedVal, NULL)) ];
|
||||
}
|
||||
if (jsonError) {
|
||||
keyError = RCTJSErrorFromNSError(jsonError);
|
||||
}
|
||||
}
|
||||
if (!keyError) {
|
||||
keyError = [self _writeEntry:entry changedManifest:&changedManifest];
|
||||
}
|
||||
}
|
||||
RCTAppendError(keyError, &errors);
|
||||
}
|
||||
if (changedManifest) {
|
||||
[self _writeManifest:&errors];
|
||||
}
|
||||
callback(@[ RCTNullIfNil(errors) ]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(multiRemove : (NSArray<NSString *> *)keys callback : (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
NSDictionary *errorOut = [self _ensureSetup];
|
||||
if (errorOut) {
|
||||
callback(@[ @[ errorOut ] ]);
|
||||
return;
|
||||
}
|
||||
NSMutableArray<NSDictionary *> *errors;
|
||||
BOOL changedManifest = NO;
|
||||
for (NSString *key in keys) {
|
||||
NSDictionary *keyError = RCTErrorForKey(key);
|
||||
if (!keyError) {
|
||||
if (_manifest[key] == (id)kCFNull) {
|
||||
NSString *filePath = [self _filePathForKey:key];
|
||||
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
|
||||
[RCTGetCache() removeObjectForKey:key];
|
||||
}
|
||||
if (_manifest[key]) {
|
||||
changedManifest = YES;
|
||||
[_manifest removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
RCTAppendError(keyError, &errors);
|
||||
}
|
||||
if (changedManifest) {
|
||||
[self _writeManifest:&errors];
|
||||
}
|
||||
callback(@[ RCTNullIfNil(errors) ]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(clear : (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
[_manifest removeAllObjects];
|
||||
[RCTGetCache() removeAllObjects];
|
||||
NSDictionary *error = RCTDeleteStorageDirectory();
|
||||
callback(@[ RCTNullIfNil(error) ]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getAllKeys : (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
NSDictionary *errorOut = [self _ensureSetup];
|
||||
if (errorOut) {
|
||||
callback(@[ errorOut, (id)kCFNull ]);
|
||||
} else {
|
||||
callback(@[ (id)kCFNull, _manifest.allKeys ]);
|
||||
}
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeAsyncStorageSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTAsyncLocalStorageCls(void)
|
||||
{
|
||||
return RCTAsyncLocalStorage.class;
|
||||
}
|
12
node_modules/react-native/React/CoreModules/RCTClipboard.h
generated
vendored
Normal file
12
node_modules/react-native/React/CoreModules/RCTClipboard.h
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
@interface RCTClipboard : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
53
node_modules/react-native/React/CoreModules/RCTClipboard.mm
generated
vendored
Normal file
53
node_modules/react-native/React/CoreModules/RCTClipboard.mm
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTClipboard.h"
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@interface RCTClipboard () <NativeClipboardSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTClipboard
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setString : (NSString *)content)
|
||||
{
|
||||
UIPasteboard *clipboard = [UIPasteboard generalPasteboard];
|
||||
clipboard.string = (content ?: @"");
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getString : (RCTPromiseResolveBlock)resolve reject : (__unused RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
UIPasteboard *clipboard = [UIPasteboard generalPasteboard];
|
||||
resolve((clipboard.string ?: @""));
|
||||
}
|
||||
|
||||
- (std::shared_ptr<TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<NativeClipboardSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTClipboardCls(void)
|
||||
{
|
||||
return RCTClipboard.class;
|
||||
}
|
13
node_modules/react-native/React/CoreModules/RCTDevLoadingView.h
generated
vendored
Normal file
13
node_modules/react-native/React/CoreModules/RCTDevLoadingView.h
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTDevLoadingViewProtocol.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface RCTDevLoadingView : NSObject <RCTDevLoadingViewProtocol, RCTBridgeModule>
|
||||
@end
|
229
node_modules/react-native/React/CoreModules/RCTDevLoadingView.mm
generated
vendored
Normal file
229
node_modules/react-native/React/CoreModules/RCTDevLoadingView.mm
generated
vendored
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTDevLoadingView.h>
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTDefines.h>
|
||||
#import <React/RCTDevLoadingViewSetEnabled.h>
|
||||
#import <React/RCTModalHostViewController.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@interface RCTDevLoadingView () <NativeDevLoadingViewSpec>
|
||||
@end
|
||||
|
||||
#if RCT_DEV | RCT_ENABLE_LOADING_VIEW
|
||||
|
||||
@implementation RCTDevLoadingView {
|
||||
UIWindow *_window;
|
||||
UILabel *_label;
|
||||
NSDate *_showDate;
|
||||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
+ (void)setEnabled:(BOOL)enabled
|
||||
{
|
||||
RCTDevLoadingViewSetEnabled(enabled);
|
||||
}
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)setBridge:(RCTBridge *)bridge
|
||||
{
|
||||
_bridge = bridge;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(hide)
|
||||
name:RCTJavaScriptDidLoadNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(hide)
|
||||
name:RCTJavaScriptDidFailToLoadNotification
|
||||
object:nil];
|
||||
|
||||
if (bridge.loading) {
|
||||
[self showWithURL:bridge.bundleURL];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showMessage:(NSString *)message color:(UIColor *)color backgroundColor:(UIColor *)backgroundColor
|
||||
{
|
||||
if (!RCTDevLoadingViewGetEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self->_showDate = [NSDate date];
|
||||
if (!self->_window && !RCTRunningInTestEnvironment()) {
|
||||
CGSize screenSize = [UIScreen mainScreen].bounds.size;
|
||||
|
||||
if (@available(iOS 11.0, *)) {
|
||||
UIWindow *window = RCTSharedApplication().keyWindow;
|
||||
self->_window =
|
||||
[[UIWindow alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, window.safeAreaInsets.top + 30)];
|
||||
self->_label = [[UILabel alloc] initWithFrame:CGRectMake(0, window.safeAreaInsets.top, screenSize.width, 30)];
|
||||
} else {
|
||||
self->_window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, 22)];
|
||||
self->_label = [[UILabel alloc] initWithFrame:self->_window.bounds];
|
||||
}
|
||||
[self->_window addSubview:self->_label];
|
||||
#if TARGET_OS_TV
|
||||
self->_window.windowLevel = UIWindowLevelNormal + 1;
|
||||
#else
|
||||
self->_window.windowLevel = UIWindowLevelStatusBar + 1;
|
||||
#endif
|
||||
// set a root VC so rotation is supported
|
||||
self->_window.rootViewController = [UIViewController new];
|
||||
|
||||
self->_label.font = [UIFont monospacedDigitSystemFontOfSize:12.0 weight:UIFontWeightRegular];
|
||||
self->_label.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
|
||||
self->_label.text = message;
|
||||
self->_label.textColor = color;
|
||||
self->_window.backgroundColor = backgroundColor;
|
||||
self->_window.hidden = NO;
|
||||
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
|
||||
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
|
||||
if (@available(iOS 13.0, *)) {
|
||||
UIWindowScene *scene = (UIWindowScene *)RCTSharedApplication().connectedScenes.anyObject;
|
||||
self->_window.windowScene = scene;
|
||||
}
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(showMessage
|
||||
: (NSString *)message withColor
|
||||
: (NSNumber *__nonnull)color withBackgroundColor
|
||||
: (NSNumber *__nonnull)backgroundColor)
|
||||
{
|
||||
[self showMessage:message color:[RCTConvert UIColor:color] backgroundColor:[RCTConvert UIColor:backgroundColor]];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(hide)
|
||||
{
|
||||
if (!RCTDevLoadingViewGetEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
const NSTimeInterval MIN_PRESENTED_TIME = 0.6;
|
||||
NSTimeInterval presentedTime = [[NSDate date] timeIntervalSinceDate:self->_showDate];
|
||||
NSTimeInterval delay = MAX(0, MIN_PRESENTED_TIME - presentedTime);
|
||||
CGRect windowFrame = self->_window.frame;
|
||||
[UIView animateWithDuration:0.25
|
||||
delay:delay
|
||||
options:0
|
||||
animations:^{
|
||||
self->_window.frame = CGRectOffset(windowFrame, 0, -windowFrame.size.height);
|
||||
}
|
||||
completion:^(__unused BOOL finished) {
|
||||
self->_window.frame = windowFrame;
|
||||
self->_window.hidden = YES;
|
||||
self->_window = nil;
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)showWithURL:(NSURL *)URL
|
||||
{
|
||||
UIColor *color;
|
||||
UIColor *backgroundColor;
|
||||
NSString *message;
|
||||
if (URL.fileURL) {
|
||||
// If dev mode is not enabled, we don't want to show this kind of notification
|
||||
#if !RCT_DEV
|
||||
return;
|
||||
#endif
|
||||
color = [UIColor whiteColor];
|
||||
backgroundColor = [UIColor blackColor];
|
||||
message = [NSString stringWithFormat:@"Connect to %@ to develop JavaScript.", RCT_PACKAGER_NAME];
|
||||
} else {
|
||||
color = [UIColor whiteColor];
|
||||
backgroundColor = [UIColor colorWithHue:1. / 3 saturation:1 brightness:.35 alpha:1];
|
||||
message = [NSString stringWithFormat:@"Loading from %@:%@...", URL.host, URL.port];
|
||||
}
|
||||
|
||||
[self showMessage:message color:color backgroundColor:backgroundColor];
|
||||
}
|
||||
|
||||
- (void)updateProgress:(RCTLoadingProgress *)progress
|
||||
{
|
||||
if (!progress) {
|
||||
return;
|
||||
}
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self->_label.text = [progress description];
|
||||
});
|
||||
}
|
||||
|
||||
- (std::shared_ptr<TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<NativeDevLoadingViewSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#else
|
||||
|
||||
@implementation RCTDevLoadingView
|
||||
|
||||
+ (NSString *)moduleName
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
+ (void)setEnabled:(BOOL)enabled
|
||||
{
|
||||
}
|
||||
- (void)showMessage:(NSString *)message color:(UIColor *)color backgroundColor:(UIColor *)backgroundColor
|
||||
{
|
||||
}
|
||||
- (void)showMessage:(NSString *)message withColor:(NSNumber *)color withBackgroundColor:(NSNumber *)backgroundColor
|
||||
{
|
||||
}
|
||||
- (void)showWithURL:(NSURL *)URL
|
||||
{
|
||||
}
|
||||
- (void)updateProgress:(RCTLoadingProgress *)progress
|
||||
{
|
||||
}
|
||||
- (void)hide
|
||||
{
|
||||
}
|
||||
- (std::shared_ptr<TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<NativeDevLoadingViewSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
Class RCTDevLoadingViewCls(void)
|
||||
{
|
||||
return RCTDevLoadingView.class;
|
||||
}
|
110
node_modules/react-native/React/CoreModules/RCTDevMenu.h
generated
vendored
Normal file
110
node_modules/react-native/React/CoreModules/RCTDevMenu.h
generated
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTDefines.h>
|
||||
|
||||
#if RCT_DEV_MENU
|
||||
|
||||
RCT_EXTERN NSString *const RCTShowDevMenuNotification;
|
||||
|
||||
#endif
|
||||
|
||||
@class RCTDevMenuItem;
|
||||
|
||||
/**
|
||||
* Developer menu, useful for exposing extra functionality when debugging.
|
||||
*/
|
||||
@interface RCTDevMenu : NSObject
|
||||
|
||||
/**
|
||||
* Deprecated, use RCTDevSettings instead.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL shakeToShow DEPRECATED_ATTRIBUTE;
|
||||
|
||||
/**
|
||||
* Deprecated, use RCTDevSettings instead.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL profilingEnabled DEPRECATED_ATTRIBUTE;
|
||||
|
||||
/**
|
||||
* Deprecated, use RCTDevSettings instead.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL liveReloadEnabled DEPRECATED_ATTRIBUTE;
|
||||
|
||||
/**
|
||||
* Deprecated, use RCTDevSettings instead.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL hotLoadingEnabled DEPRECATED_ATTRIBUTE;
|
||||
|
||||
/**
|
||||
* Presented items in development menu
|
||||
*/
|
||||
@property (nonatomic, copy, readonly) NSArray<RCTDevMenuItem *> *presentedItems;
|
||||
|
||||
/**
|
||||
* Detect if actions sheet (development menu) is shown
|
||||
*/
|
||||
- (BOOL)isActionSheetShown;
|
||||
|
||||
/**
|
||||
* Manually show the dev menu (can be called from JS).
|
||||
*/
|
||||
- (void)show;
|
||||
|
||||
/**
|
||||
* Deprecated, use `RCTReloadCommand` instead.
|
||||
*/
|
||||
- (void)reload DEPRECATED_ATTRIBUTE;
|
||||
|
||||
/**
|
||||
* Deprecated. Use the `-addItem:` method instead.
|
||||
*/
|
||||
- (void)addItem:(NSString *)title handler:(void (^)(void))handler DEPRECATED_ATTRIBUTE;
|
||||
|
||||
/**
|
||||
* Add custom item to the development menu. The handler will be called
|
||||
* when user selects the item.
|
||||
*/
|
||||
- (void)addItem:(RCTDevMenuItem *)item;
|
||||
|
||||
@end
|
||||
|
||||
typedef NSString * (^RCTDevMenuItemTitleBlock)(void);
|
||||
|
||||
/**
|
||||
* Developer menu item, used to expose additional functionality via the menu.
|
||||
*/
|
||||
@interface RCTDevMenuItem : NSObject
|
||||
|
||||
/**
|
||||
* This creates an item with a simple push-button interface, used to trigger an
|
||||
* action.
|
||||
*/
|
||||
+ (instancetype)buttonItemWithTitle:(NSString *)title handler:(dispatch_block_t)handler;
|
||||
|
||||
/**
|
||||
* This creates an item with a simple push-button interface, used to trigger an
|
||||
* action. getTitleForPresentation is called each time the item is about to be
|
||||
* presented, and should return the item's title.
|
||||
*/
|
||||
+ (instancetype)buttonItemWithTitleBlock:(RCTDevMenuItemTitleBlock)titleBlock handler:(dispatch_block_t)handler;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* This category makes the developer menu instance available via the
|
||||
* RCTBridge, which is useful for any class that needs to access the menu.
|
||||
*/
|
||||
@interface RCTBridge (RCTDevMenu)
|
||||
|
||||
@property (nonatomic, readonly) RCTDevMenu *devMenu;
|
||||
|
||||
@end
|
562
node_modules/react-native/React/CoreModules/RCTDevMenu.mm
generated
vendored
Normal file
562
node_modules/react-native/React/CoreModules/RCTDevMenu.mm
generated
vendored
Normal file
@ -0,0 +1,562 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTDevMenu.h>
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTBridge+Private.h>
|
||||
#import <React/RCTBundleURLProvider.h>
|
||||
#import <React/RCTDefines.h>
|
||||
#import <React/RCTDevSettings.h>
|
||||
#import <React/RCTKeyCommands.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTReloadCommand.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
#if RCT_DEV_MENU
|
||||
|
||||
#if RCT_ENABLE_INSPECTOR
|
||||
#import <React/RCTInspectorDevServerHelper.h>
|
||||
#endif
|
||||
|
||||
NSString *const RCTShowDevMenuNotification = @"RCTShowDevMenuNotification";
|
||||
|
||||
@implementation UIWindow (RCTDevMenu)
|
||||
|
||||
- (void)RCT_motionEnded:(__unused UIEventSubtype)motion withEvent:(UIEvent *)event
|
||||
{
|
||||
if (event.subtype == UIEventSubtypeMotionShake) {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTShowDevMenuNotification object:nil];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTDevMenuItem {
|
||||
RCTDevMenuItemTitleBlock _titleBlock;
|
||||
dispatch_block_t _handler;
|
||||
}
|
||||
|
||||
- (instancetype)initWithTitleBlock:(RCTDevMenuItemTitleBlock)titleBlock handler:(dispatch_block_t)handler
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_titleBlock = [titleBlock copy];
|
||||
_handler = [handler copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
RCT_NOT_IMPLEMENTED(-(instancetype)init)
|
||||
|
||||
+ (instancetype)buttonItemWithTitleBlock:(NSString * (^)(void))titleBlock handler:(dispatch_block_t)handler
|
||||
{
|
||||
return [[self alloc] initWithTitleBlock:titleBlock handler:handler];
|
||||
}
|
||||
|
||||
+ (instancetype)buttonItemWithTitle:(NSString *)title handler:(dispatch_block_t)handler
|
||||
{
|
||||
return [[self alloc]
|
||||
initWithTitleBlock:^NSString * {
|
||||
return title;
|
||||
}
|
||||
handler:handler];
|
||||
}
|
||||
|
||||
- (void)callHandler
|
||||
{
|
||||
if (_handler) {
|
||||
_handler();
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)title
|
||||
{
|
||||
if (_titleBlock) {
|
||||
return _titleBlock();
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
typedef void (^RCTDevMenuAlertActionHandler)(UIAlertAction *action);
|
||||
|
||||
@interface RCTDevMenu () <RCTBridgeModule, RCTInvalidating, NativeDevMenuSpec>
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTDevMenu {
|
||||
UIAlertController *_actionSheet;
|
||||
NSMutableArray<RCTDevMenuItem *> *_extraMenuItems;
|
||||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
// We're swizzling here because it's poor form to override methods in a category,
|
||||
// however UIWindow doesn't actually implement motionEnded:withEvent:, so there's
|
||||
// no need to call the original implementation.
|
||||
RCTSwapInstanceMethods([UIWindow class], @selector(motionEnded:withEvent:), @selector(RCT_motionEnded:withEvent:));
|
||||
}
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(showOnShake)
|
||||
name:RCTShowDevMenuNotification
|
||||
object:nil];
|
||||
_extraMenuItems = [NSMutableArray new];
|
||||
|
||||
#if TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST
|
||||
RCTKeyCommands *commands = [RCTKeyCommands sharedInstance];
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
|
||||
// Toggle debug menu
|
||||
[commands registerKeyCommandWithInput:@"d"
|
||||
modifierFlags:UIKeyModifierCommand
|
||||
action:^(__unused UIKeyCommand *command) {
|
||||
[weakSelf toggle];
|
||||
}];
|
||||
|
||||
// Toggle element inspector
|
||||
[commands registerKeyCommandWithInput:@"i"
|
||||
modifierFlags:UIKeyModifierCommand
|
||||
action:^(__unused UIKeyCommand *command) {
|
||||
[weakSelf.bridge.devSettings toggleElementInspector];
|
||||
}];
|
||||
|
||||
// Reload in normal mode
|
||||
[commands registerKeyCommandWithInput:@"n"
|
||||
modifierFlags:UIKeyModifierCommand
|
||||
action:^(__unused UIKeyCommand *command) {
|
||||
[weakSelf.bridge.devSettings setIsDebuggingRemotely:NO];
|
||||
}];
|
||||
#endif
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
_presentedItems = nil;
|
||||
[_actionSheet dismissViewControllerAnimated:YES
|
||||
completion:^(void){
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)showOnShake
|
||||
{
|
||||
if ([_bridge.devSettings isShakeToShowDevMenuEnabled]) {
|
||||
[self show];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)toggle
|
||||
{
|
||||
if (_actionSheet) {
|
||||
[_actionSheet dismissViewControllerAnimated:YES
|
||||
completion:^(void){
|
||||
}];
|
||||
_actionSheet = nil;
|
||||
} else {
|
||||
[self show];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isActionSheetShown
|
||||
{
|
||||
return _actionSheet != nil;
|
||||
}
|
||||
|
||||
- (void)addItem:(NSString *)title handler:(void (^)(void))handler
|
||||
{
|
||||
[self addItem:[RCTDevMenuItem buttonItemWithTitle:title handler:handler]];
|
||||
}
|
||||
|
||||
- (void)addItem:(RCTDevMenuItem *)item
|
||||
{
|
||||
[_extraMenuItems addObject:item];
|
||||
}
|
||||
|
||||
- (void)setDefaultJSBundle
|
||||
{
|
||||
[[RCTBundleURLProvider sharedSettings] resetToDefaults];
|
||||
self->_bridge.bundleURL = [[RCTBundleURLProvider sharedSettings] jsBundleURLForFallbackResource:nil
|
||||
fallbackExtension:nil];
|
||||
RCTTriggerReloadCommandListeners(@"Dev menu - reset to default");
|
||||
}
|
||||
|
||||
- (NSArray<RCTDevMenuItem *> *)_menuItemsToPresent
|
||||
{
|
||||
NSMutableArray<RCTDevMenuItem *> *items = [NSMutableArray new];
|
||||
|
||||
// Add built-in items
|
||||
__weak RCTBridge *bridge = _bridge;
|
||||
__weak RCTDevSettings *devSettings = _bridge.devSettings;
|
||||
__weak RCTDevMenu *weakSelf = self;
|
||||
|
||||
[items addObject:[RCTDevMenuItem buttonItemWithTitle:@"Reload"
|
||||
handler:^{
|
||||
RCTTriggerReloadCommandListeners(@"Dev menu - reload");
|
||||
}]];
|
||||
|
||||
if (!devSettings.isProfilingEnabled) {
|
||||
if (!devSettings.isRemoteDebuggingAvailable) {
|
||||
[items
|
||||
addObject:[RCTDevMenuItem
|
||||
buttonItemWithTitle:@"Debugger Unavailable"
|
||||
handler:^{
|
||||
NSString *message = RCTTurboModuleEnabled()
|
||||
? @"Debugging is not currently supported when TurboModule is enabled."
|
||||
: @"Include the RCTWebSocket library to enable JavaScript debugging.";
|
||||
UIAlertController *alertController =
|
||||
[UIAlertController alertControllerWithTitle:@"Debugger Unavailable"
|
||||
message:message
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
__weak __typeof__(alertController) weakAlertController = alertController;
|
||||
[alertController
|
||||
addAction:[UIAlertAction actionWithTitle:@"OK"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(__unused UIAlertAction *action) {
|
||||
[weakAlertController
|
||||
dismissViewControllerAnimated:YES
|
||||
completion:nil];
|
||||
}]];
|
||||
[RCTPresentedViewController() presentViewController:alertController
|
||||
animated:YES
|
||||
completion:NULL];
|
||||
}]];
|
||||
} else {
|
||||
[items addObject:[RCTDevMenuItem
|
||||
buttonItemWithTitleBlock:^NSString * {
|
||||
return devSettings.isDebuggingRemotely ? @"Stop Debugging" : @"Debug";
|
||||
}
|
||||
handler:^{
|
||||
devSettings.isDebuggingRemotely = !devSettings.isDebuggingRemotely;
|
||||
}]];
|
||||
}
|
||||
}
|
||||
|
||||
[items addObject:[RCTDevMenuItem
|
||||
buttonItemWithTitleBlock:^NSString * {
|
||||
return devSettings.isElementInspectorShown ? @"Hide Inspector" : @"Show Inspector";
|
||||
}
|
||||
handler:^{
|
||||
[devSettings toggleElementInspector];
|
||||
}]];
|
||||
|
||||
if (devSettings.isHotLoadingAvailable) {
|
||||
[items addObject:[RCTDevMenuItem
|
||||
buttonItemWithTitleBlock:^NSString * {
|
||||
// Previously known as "Hot Reloading". We won't use this term anymore.
|
||||
return devSettings.isHotLoadingEnabled ? @"Disable Fast Refresh" : @"Enable Fast Refresh";
|
||||
}
|
||||
handler:^{
|
||||
devSettings.isHotLoadingEnabled = !devSettings.isHotLoadingEnabled;
|
||||
}]];
|
||||
}
|
||||
|
||||
if (devSettings.isLiveReloadAvailable) {
|
||||
[items addObject:[RCTDevMenuItem
|
||||
buttonItemWithTitleBlock:^NSString * {
|
||||
return devSettings.isDebuggingRemotely
|
||||
? @"Systrace Unavailable"
|
||||
: devSettings.isProfilingEnabled ? @"Stop Systrace" : @"Start Systrace";
|
||||
}
|
||||
handler:^{
|
||||
if (devSettings.isDebuggingRemotely) {
|
||||
UIAlertController *alertController =
|
||||
[UIAlertController alertControllerWithTitle:@"Systrace Unavailable"
|
||||
message:@"Stop debugging to enable Systrace."
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
__weak __typeof__(alertController) weakAlertController = alertController;
|
||||
[alertController
|
||||
addAction:[UIAlertAction actionWithTitle:@"OK"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(__unused UIAlertAction *action) {
|
||||
[weakAlertController
|
||||
dismissViewControllerAnimated:YES
|
||||
completion:nil];
|
||||
}]];
|
||||
[RCTPresentedViewController() presentViewController:alertController
|
||||
animated:YES
|
||||
completion:NULL];
|
||||
} else {
|
||||
devSettings.isProfilingEnabled = !devSettings.isProfilingEnabled;
|
||||
}
|
||||
}]];
|
||||
// "Live reload" which refreshes on every edit was removed in favor of "Fast Refresh".
|
||||
// While native code for "Live reload" is still there, please don't add the option back.
|
||||
// See D15958697 for more context.
|
||||
}
|
||||
|
||||
[items
|
||||
addObject:[RCTDevMenuItem
|
||||
buttonItemWithTitleBlock:^NSString * {
|
||||
return @"Configure Bundler";
|
||||
}
|
||||
handler:^{
|
||||
UIAlertController *alertController = [UIAlertController
|
||||
alertControllerWithTitle:@"Configure Bundler"
|
||||
message:@"Provide a custom bundler address, port, and entrypoint."
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.placeholder = @"0.0.0.0";
|
||||
}];
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.placeholder = @"8081";
|
||||
}];
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.placeholder = @"index";
|
||||
}];
|
||||
[alertController
|
||||
addAction:[UIAlertAction
|
||||
actionWithTitle:@"Apply Changes"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(__unused UIAlertAction *action) {
|
||||
NSArray *textfields = alertController.textFields;
|
||||
UITextField *ipTextField = textfields[0];
|
||||
UITextField *portTextField = textfields[1];
|
||||
UITextField *bundleRootTextField = textfields[2];
|
||||
NSString *bundleRoot = bundleRootTextField.text;
|
||||
if (ipTextField.text.length == 0 && portTextField.text.length == 0) {
|
||||
[weakSelf setDefaultJSBundle];
|
||||
return;
|
||||
}
|
||||
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
|
||||
formatter.numberStyle = NSNumberFormatterDecimalStyle;
|
||||
NSNumber *portNumber =
|
||||
[formatter numberFromString:portTextField.text];
|
||||
if (portNumber == nil) {
|
||||
portNumber = [NSNumber numberWithInt:RCT_METRO_PORT];
|
||||
}
|
||||
[RCTBundleURLProvider sharedSettings].jsLocation = [NSString
|
||||
stringWithFormat:@"%@:%d", ipTextField.text, portNumber.intValue];
|
||||
__strong RCTBridge *strongBridge = bridge;
|
||||
if (strongBridge) {
|
||||
NSURL *bundleURL = bundleRoot.length
|
||||
? [[RCTBundleURLProvider sharedSettings]
|
||||
jsBundleURLForBundleRoot:bundleRoot
|
||||
fallbackResource:nil]
|
||||
: [strongBridge.delegate sourceURLForBridge:strongBridge];
|
||||
strongBridge.bundleURL = bundleURL;
|
||||
RCTTriggerReloadCommandListeners(@"Dev menu - apply changes");
|
||||
}
|
||||
}]];
|
||||
[alertController addAction:[UIAlertAction actionWithTitle:@"Reset to Default"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(__unused UIAlertAction *action) {
|
||||
[weakSelf setDefaultJSBundle];
|
||||
}]];
|
||||
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel"
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(__unused UIAlertAction *action) {
|
||||
return;
|
||||
}]];
|
||||
[RCTPresentedViewController() presentViewController:alertController animated:YES completion:NULL];
|
||||
}]];
|
||||
|
||||
[items addObjectsFromArray:_extraMenuItems];
|
||||
return items;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(show)
|
||||
{
|
||||
if (_actionSheet || !_bridge || RCTRunningInAppExtension()) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *bridgeDescription = _bridge.bridgeDescription;
|
||||
NSString *description =
|
||||
bridgeDescription.length > 0 ? [NSString stringWithFormat:@"Running %@", bridgeDescription] : nil;
|
||||
|
||||
// On larger devices we don't have an anchor point for the action sheet
|
||||
UIAlertControllerStyle style = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone
|
||||
? UIAlertControllerStyleActionSheet
|
||||
: UIAlertControllerStyleAlert;
|
||||
_actionSheet = [UIAlertController alertControllerWithTitle:@"React Native Debug Menu"
|
||||
message:description
|
||||
preferredStyle:style];
|
||||
|
||||
NSArray<RCTDevMenuItem *> *items = [self _menuItemsToPresent];
|
||||
for (RCTDevMenuItem *item in items) {
|
||||
[_actionSheet addAction:[UIAlertAction actionWithTitle:item.title
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:[self alertActionHandlerForDevItem:item]]];
|
||||
}
|
||||
|
||||
[_actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel"
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:[self alertActionHandlerForDevItem:nil]]];
|
||||
|
||||
_presentedItems = items;
|
||||
[RCTPresentedViewController() presentViewController:_actionSheet animated:YES completion:nil];
|
||||
|
||||
[_bridge enqueueJSCall:@"RCTNativeAppEventEmitter" method:@"emit" args:@[ @"RCTDevMenuShown" ] completion:NULL];
|
||||
}
|
||||
|
||||
- (RCTDevMenuAlertActionHandler)alertActionHandlerForDevItem:(RCTDevMenuItem *__nullable)item
|
||||
{
|
||||
return ^(__unused UIAlertAction *action) {
|
||||
if (item) {
|
||||
[item callHandler];
|
||||
}
|
||||
|
||||
self->_actionSheet = nil;
|
||||
};
|
||||
}
|
||||
|
||||
#pragma mark - deprecated methods and properties
|
||||
|
||||
#define WARN_DEPRECATED_DEV_MENU_EXPORT() \
|
||||
RCTLogWarn(@"Using deprecated method %s, use RCTDevSettings instead", __func__)
|
||||
|
||||
- (void)setShakeToShow:(BOOL)shakeToShow
|
||||
{
|
||||
_bridge.devSettings.isShakeToShowDevMenuEnabled = shakeToShow;
|
||||
}
|
||||
|
||||
- (BOOL)shakeToShow
|
||||
{
|
||||
return _bridge.devSettings.isShakeToShowDevMenuEnabled;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(reload)
|
||||
{
|
||||
WARN_DEPRECATED_DEV_MENU_EXPORT();
|
||||
RCTTriggerReloadCommandListeners(@"Unknown from JS");
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(debugRemotely : (BOOL)enableDebug)
|
||||
{
|
||||
WARN_DEPRECATED_DEV_MENU_EXPORT();
|
||||
_bridge.devSettings.isDebuggingRemotely = enableDebug;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setProfilingEnabled : (BOOL)enabled)
|
||||
{
|
||||
WARN_DEPRECATED_DEV_MENU_EXPORT();
|
||||
_bridge.devSettings.isProfilingEnabled = enabled;
|
||||
}
|
||||
|
||||
- (BOOL)profilingEnabled
|
||||
{
|
||||
return _bridge.devSettings.isProfilingEnabled;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setHotLoadingEnabled : (BOOL)enabled)
|
||||
{
|
||||
WARN_DEPRECATED_DEV_MENU_EXPORT();
|
||||
_bridge.devSettings.isHotLoadingEnabled = enabled;
|
||||
}
|
||||
|
||||
- (BOOL)hotLoadingEnabled
|
||||
{
|
||||
return _bridge.devSettings.isHotLoadingEnabled;
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeDevMenuSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#else // Unavailable when not in dev mode
|
||||
|
||||
@interface RCTDevMenu () <NativeDevMenuSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTDevMenu
|
||||
|
||||
- (void)show
|
||||
{
|
||||
}
|
||||
- (void)reload
|
||||
{
|
||||
}
|
||||
- (void)addItem:(NSString *)title handler:(dispatch_block_t)handler
|
||||
{
|
||||
}
|
||||
- (void)addItem:(RCTDevMenu *)item
|
||||
{
|
||||
}
|
||||
|
||||
- (void)debugRemotely:(BOOL)enableDebug
|
||||
{
|
||||
}
|
||||
|
||||
- (BOOL)isActionSheetShown
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
+ (NSString *)moduleName
|
||||
{
|
||||
return @"DevMenu";
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeDevMenuSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTDevMenuItem
|
||||
|
||||
+ (instancetype)buttonItemWithTitle:(NSString *)title handler:(void (^)(void))handler
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
+ (instancetype)buttonItemWithTitleBlock:(NSString * (^)(void))titleBlock handler:(void (^)(void))handler
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
@implementation RCTBridge (RCTDevMenu)
|
||||
|
||||
- (RCTDevMenu *)devMenu
|
||||
{
|
||||
#if RCT_DEV_MENU
|
||||
return [self moduleForClass:[RCTDevMenu class]];
|
||||
#else
|
||||
return nil;
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTDevMenuCls(void)
|
||||
{
|
||||
return RCTDevMenu.class;
|
||||
}
|
105
node_modules/react-native/React/CoreModules/RCTDevSettings.h
generated
vendored
Normal file
105
node_modules/react-native/React/CoreModules/RCTDevSettings.h
generated
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTDefines.h>
|
||||
#import <React/RCTEventEmitter.h>
|
||||
|
||||
@protocol RCTPackagerClientMethod;
|
||||
|
||||
/**
|
||||
* An abstraction for a key-value store to manage RCTDevSettings behavior.
|
||||
* The default implementation persists settings using NSUserDefaults.
|
||||
*/
|
||||
@protocol RCTDevSettingsDataSource <NSObject>
|
||||
|
||||
/**
|
||||
* Updates the setting with the given key to the given value.
|
||||
* How the data source's state changes depends on the implementation.
|
||||
*/
|
||||
- (void)updateSettingWithValue:(id)value forKey:(NSString *)key;
|
||||
|
||||
/**
|
||||
* Returns the value for the setting with the given key.
|
||||
*/
|
||||
- (id)settingForKey:(NSString *)key;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTDevSettings : RCTEventEmitter
|
||||
|
||||
- (instancetype)initWithDataSource:(id<RCTDevSettingsDataSource>)dataSource;
|
||||
|
||||
@property (nonatomic, readonly) BOOL isHotLoadingAvailable;
|
||||
@property (nonatomic, readonly) BOOL isLiveReloadAvailable;
|
||||
@property (nonatomic, readonly) BOOL isRemoteDebuggingAvailable;
|
||||
@property (nonatomic, readonly) BOOL isNuclideDebuggingAvailable;
|
||||
@property (nonatomic, readonly) BOOL isJSCSamplingProfilerAvailable;
|
||||
|
||||
/**
|
||||
* Whether the bridge is connected to a remote JS executor.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL isDebuggingRemotely;
|
||||
|
||||
/*
|
||||
* Whether shaking will show RCTDevMenu. The menu is enabled by default if RCT_DEV=1, but
|
||||
* you may wish to disable it so that you can provide your own shake handler.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL isShakeToShowDevMenuEnabled;
|
||||
|
||||
/**
|
||||
* Whether performance profiling is enabled.
|
||||
*/
|
||||
@property (nonatomic, assign, setter=setProfilingEnabled:) BOOL isProfilingEnabled;
|
||||
|
||||
/**
|
||||
* Whether hot loading is enabled.
|
||||
*/
|
||||
@property (nonatomic, assign, setter=setHotLoadingEnabled:) BOOL isHotLoadingEnabled;
|
||||
|
||||
/**
|
||||
* Enables starting of profiling sampler on launch
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL startSamplingProfilerOnLaunch;
|
||||
|
||||
/**
|
||||
* Whether the element inspector is visible.
|
||||
*/
|
||||
@property (nonatomic, readonly) BOOL isElementInspectorShown;
|
||||
|
||||
/**
|
||||
* Whether the performance monitor is visible.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL isPerfMonitorShown;
|
||||
|
||||
/**
|
||||
* Toggle the element inspector.
|
||||
*/
|
||||
- (void)toggleElementInspector;
|
||||
|
||||
/**
|
||||
* If loading bundle from metro, sets up HMRClient.
|
||||
*/
|
||||
- (void)setupHotModuleReloadClientIfApplicableForURL:(NSURL *)bundleURL;
|
||||
|
||||
#if RCT_DEV_MENU
|
||||
- (void)addHandler:(id<RCTPackagerClientMethod>)handler
|
||||
forPackagerMethod:(NSString *)name __deprecated_msg("Use RCTPackagerConnection directly instead");
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridge (RCTDevSettings)
|
||||
|
||||
@property (nonatomic, readonly) RCTDevSettings *devSettings;
|
||||
|
||||
@end
|
||||
|
||||
// In debug builds, the dev menu is enabled by default but it is further customizable using this method.
|
||||
// However, this method only has an effect in builds where the dev menu is actually compiled in.
|
||||
// (i.e. RCT_DEV or RCT_DEV_MENU is set)
|
||||
RCT_EXTERN void RCTDevSettingsSetEnabled(BOOL enabled);
|
552
node_modules/react-native/React/CoreModules/RCTDevSettings.mm
generated
vendored
Normal file
552
node_modules/react-native/React/CoreModules/RCTDevSettings.mm
generated
vendored
Normal file
@ -0,0 +1,552 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTDevSettings.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTBridge+Private.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTEventDispatcher.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTProfile.h>
|
||||
#import <React/RCTReloadCommand.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import <React/RCTDevMenu.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
static NSString *const kRCTDevSettingProfilingEnabled = @"profilingEnabled";
|
||||
static NSString *const kRCTDevSettingHotLoadingEnabled = @"hotLoadingEnabled";
|
||||
static NSString *const kRCTDevSettingIsInspectorShown = @"showInspector";
|
||||
static NSString *const kRCTDevSettingIsDebuggingRemotely = @"isDebuggingRemotely";
|
||||
static NSString *const kRCTDevSettingExecutorOverrideClass = @"executor-override";
|
||||
static NSString *const kRCTDevSettingShakeToShowDevMenu = @"shakeToShow";
|
||||
static NSString *const kRCTDevSettingIsPerfMonitorShown = @"RCTPerfMonitorKey";
|
||||
|
||||
static NSString *const kRCTDevSettingsUserDefaultsKey = @"RCTDevMenu";
|
||||
|
||||
#if ENABLE_PACKAGER_CONNECTION
|
||||
#import <React/RCTPackagerClient.h>
|
||||
#import <React/RCTPackagerConnection.h>
|
||||
#endif
|
||||
|
||||
#if RCT_ENABLE_INSPECTOR
|
||||
#import <React/RCTInspectorDevServerHelper.h>
|
||||
#endif
|
||||
|
||||
#if RCT_DEV
|
||||
static BOOL devSettingsMenuEnabled = YES;
|
||||
#else
|
||||
static BOOL devSettingsMenuEnabled = NO;
|
||||
#endif
|
||||
|
||||
void RCTDevSettingsSetEnabled(BOOL enabled)
|
||||
{
|
||||
devSettingsMenuEnabled = enabled;
|
||||
}
|
||||
|
||||
#if RCT_DEV_MENU
|
||||
|
||||
@interface RCTDevSettingsUserDefaultsDataSource : NSObject <RCTDevSettingsDataSource>
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTDevSettingsUserDefaultsDataSource {
|
||||
NSMutableDictionary *_settings;
|
||||
NSUserDefaults *_userDefaults;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [self initWithDefaultValues:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithDefaultValues:(NSDictionary *)defaultValues
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_userDefaults = [NSUserDefaults standardUserDefaults];
|
||||
if (defaultValues) {
|
||||
[self _reloadWithDefaults:defaultValues];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)updateSettingWithValue:(id)value forKey:(NSString *)key
|
||||
{
|
||||
RCTAssert((key != nil), @"%@", [NSString stringWithFormat:@"%@: Tried to update nil key", [self class]]);
|
||||
|
||||
id currentValue = [self settingForKey:key];
|
||||
if (currentValue == value || [currentValue isEqual:value]) {
|
||||
return;
|
||||
}
|
||||
if (value) {
|
||||
_settings[key] = value;
|
||||
} else {
|
||||
[_settings removeObjectForKey:key];
|
||||
}
|
||||
[_userDefaults setObject:_settings forKey:kRCTDevSettingsUserDefaultsKey];
|
||||
}
|
||||
|
||||
- (id)settingForKey:(NSString *)key
|
||||
{
|
||||
return _settings[key];
|
||||
}
|
||||
|
||||
- (void)_reloadWithDefaults:(NSDictionary *)defaultValues
|
||||
{
|
||||
NSDictionary *existingSettings = [_userDefaults objectForKey:kRCTDevSettingsUserDefaultsKey];
|
||||
_settings = existingSettings ? [existingSettings mutableCopy] : [NSMutableDictionary dictionary];
|
||||
for (NSString *key in [defaultValues keyEnumerator]) {
|
||||
if (!_settings[key]) {
|
||||
_settings[key] = defaultValues[key];
|
||||
}
|
||||
}
|
||||
[_userDefaults setObject:_settings forKey:kRCTDevSettingsUserDefaultsKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTDevSettings () <RCTBridgeModule, RCTInvalidating, NativeDevSettingsSpec> {
|
||||
BOOL _isJSLoaded;
|
||||
#if ENABLE_PACKAGER_CONNECTION
|
||||
RCTHandlerToken _reloadToken;
|
||||
#endif
|
||||
}
|
||||
|
||||
@property (nonatomic, strong) Class executorClass;
|
||||
@property (nonatomic, readwrite, strong) id<RCTDevSettingsDataSource> dataSource;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTDevSettings
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
// Default behavior is to use NSUserDefaults with shake and hot loading enabled.
|
||||
NSDictionary *defaultValues = @{
|
||||
kRCTDevSettingShakeToShowDevMenu : @YES,
|
||||
kRCTDevSettingHotLoadingEnabled : @YES,
|
||||
};
|
||||
RCTDevSettingsUserDefaultsDataSource *dataSource =
|
||||
[[RCTDevSettingsUserDefaultsDataSource alloc] initWithDefaultValues:defaultValues];
|
||||
return [self initWithDataSource:dataSource];
|
||||
}
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (instancetype)initWithDataSource:(id<RCTDevSettingsDataSource>)dataSource
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_dataSource = dataSource;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(jsLoaded:)
|
||||
name:RCTJavaScriptDidLoadNotification
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setBridge:(RCTBridge *)bridge
|
||||
{
|
||||
[super setBridge:bridge];
|
||||
|
||||
#if ENABLE_PACKAGER_CONNECTION
|
||||
RCTBridge *__weak weakBridge = bridge;
|
||||
_reloadToken = [[RCTPackagerConnection sharedPackagerConnection]
|
||||
addNotificationHandler:^(id params) {
|
||||
if (params != (id)kCFNull && [params[@"debug"] boolValue]) {
|
||||
weakBridge.executorClass = objc_lookUpClass("RCTWebSocketExecutor");
|
||||
}
|
||||
RCTTriggerReloadCommandListeners(@"Global hotkey");
|
||||
}
|
||||
queue:dispatch_get_main_queue()
|
||||
forMethod:@"reload"];
|
||||
#endif
|
||||
|
||||
#if RCT_ENABLE_INSPECTOR
|
||||
// We need this dispatch to the main thread because the bridge is not yet
|
||||
// finished with its initialisation. By the time it relinquishes control of
|
||||
// the main thread, this operation can be performed.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[bridge
|
||||
dispatchBlock:^{
|
||||
[RCTInspectorDevServerHelper connectWithBundleURL:bridge.bundleURL];
|
||||
}
|
||||
queue:RCTJSThread];
|
||||
});
|
||||
#endif
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self _synchronizeAllSettings];
|
||||
});
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
#if ENABLE_PACKAGER_CONNECTION
|
||||
[[RCTPackagerConnection sharedPackagerConnection] removeHandler:_reloadToken];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)supportedEvents
|
||||
{
|
||||
return @[ @"didPressMenuItem" ];
|
||||
}
|
||||
|
||||
- (void)_updateSettingWithValue:(id)value forKey:(NSString *)key
|
||||
{
|
||||
[_dataSource updateSettingWithValue:value forKey:key];
|
||||
}
|
||||
|
||||
- (id)settingForKey:(NSString *)key
|
||||
{
|
||||
return [_dataSource settingForKey:key];
|
||||
}
|
||||
|
||||
- (BOOL)isNuclideDebuggingAvailable
|
||||
{
|
||||
#if RCT_ENABLE_INSPECTOR
|
||||
return self.bridge.isInspectable;
|
||||
#else
|
||||
return false;
|
||||
#endif // RCT_ENABLE_INSPECTOR
|
||||
}
|
||||
|
||||
- (BOOL)isRemoteDebuggingAvailable
|
||||
{
|
||||
if (RCTTurboModuleEnabled()) {
|
||||
return NO;
|
||||
}
|
||||
Class jsDebuggingExecutorClass = objc_lookUpClass("RCTWebSocketExecutor");
|
||||
return (jsDebuggingExecutorClass != nil);
|
||||
}
|
||||
|
||||
- (BOOL)isHotLoadingAvailable
|
||||
{
|
||||
return self.bridge.bundleURL && !self.bridge.bundleURL.fileURL; // Only works when running from server
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(reload)
|
||||
{
|
||||
RCTTriggerReloadCommandListeners(@"Unknown From JS");
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(reloadWithReason : (NSString *)reason)
|
||||
{
|
||||
RCTTriggerReloadCommandListeners(reason);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(onFastRefresh)
|
||||
{
|
||||
[self.bridge onFastRefresh];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setIsShakeToShowDevMenuEnabled : (BOOL)enabled)
|
||||
{
|
||||
[self _updateSettingWithValue:@(enabled) forKey:kRCTDevSettingShakeToShowDevMenu];
|
||||
}
|
||||
|
||||
- (BOOL)isShakeToShowDevMenuEnabled
|
||||
{
|
||||
return [[self settingForKey:kRCTDevSettingShakeToShowDevMenu] boolValue];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setIsDebuggingRemotely : (BOOL)enabled)
|
||||
{
|
||||
[self _updateSettingWithValue:@(enabled) forKey:kRCTDevSettingIsDebuggingRemotely];
|
||||
[self _remoteDebugSettingDidChange];
|
||||
}
|
||||
|
||||
- (BOOL)isDebuggingRemotely
|
||||
{
|
||||
return [[self settingForKey:kRCTDevSettingIsDebuggingRemotely] boolValue];
|
||||
}
|
||||
|
||||
- (void)_remoteDebugSettingDidChange
|
||||
{
|
||||
// This value is passed as a command-line argument, so fall back to reading from NSUserDefaults directly
|
||||
NSString *executorOverride = [[NSUserDefaults standardUserDefaults] stringForKey:kRCTDevSettingExecutorOverrideClass];
|
||||
Class executorOverrideClass = executorOverride ? NSClassFromString(executorOverride) : nil;
|
||||
if (executorOverrideClass) {
|
||||
self.executorClass = executorOverrideClass;
|
||||
} else {
|
||||
BOOL enabled = self.isRemoteDebuggingAvailable && self.isDebuggingRemotely;
|
||||
self.executorClass = enabled ? objc_getClass("RCTWebSocketExecutor") : nil;
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setProfilingEnabled : (BOOL)enabled)
|
||||
{
|
||||
[self _updateSettingWithValue:@(enabled) forKey:kRCTDevSettingProfilingEnabled];
|
||||
[self _profilingSettingDidChange];
|
||||
}
|
||||
|
||||
- (BOOL)isProfilingEnabled
|
||||
{
|
||||
return [[self settingForKey:kRCTDevSettingProfilingEnabled] boolValue];
|
||||
}
|
||||
|
||||
- (void)_profilingSettingDidChange
|
||||
{
|
||||
BOOL enabled = self.isProfilingEnabled;
|
||||
if (self.isHotLoadingAvailable && enabled != RCTProfileIsProfiling()) {
|
||||
if (enabled) {
|
||||
[self.bridge startProfiling];
|
||||
} else {
|
||||
[self.bridge stopProfiling:^(NSData *logData) {
|
||||
RCTProfileSendResult(self.bridge, @"systrace", logData);
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setHotLoadingEnabled : (BOOL)enabled)
|
||||
{
|
||||
if (self.isHotLoadingEnabled != enabled) {
|
||||
[self _updateSettingWithValue:@(enabled) forKey:kRCTDevSettingHotLoadingEnabled];
|
||||
if (_isJSLoaded) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
if (enabled) {
|
||||
[self.bridge enqueueJSCall:@"HMRClient" method:@"enable" args:@[] completion:NULL];
|
||||
} else {
|
||||
[self.bridge enqueueJSCall:@"HMRClient" method:@"disable" args:@[] completion:NULL];
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isHotLoadingEnabled
|
||||
{
|
||||
return [[self settingForKey:kRCTDevSettingHotLoadingEnabled] boolValue];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(toggleElementInspector)
|
||||
{
|
||||
BOOL value = [[self settingForKey:kRCTDevSettingIsInspectorShown] boolValue];
|
||||
[self _updateSettingWithValue:@(!value) forKey:kRCTDevSettingIsInspectorShown];
|
||||
|
||||
if (_isJSLoaded) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[self.bridge.eventDispatcher sendDeviceEventWithName:@"toggleElementInspector" body:nil];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(addMenuItem : (NSString *)title)
|
||||
{
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
[self.bridge.devMenu addItem:[RCTDevMenuItem buttonItemWithTitle:title
|
||||
handler:^{
|
||||
[weakSelf sendEventWithName:@"didPressMenuItem"
|
||||
body:@{@"title" : title}];
|
||||
}]];
|
||||
}
|
||||
|
||||
- (BOOL)isElementInspectorShown
|
||||
{
|
||||
return [[self settingForKey:kRCTDevSettingIsInspectorShown] boolValue];
|
||||
}
|
||||
|
||||
- (void)setIsPerfMonitorShown:(BOOL)isPerfMonitorShown
|
||||
{
|
||||
[self _updateSettingWithValue:@(isPerfMonitorShown) forKey:kRCTDevSettingIsPerfMonitorShown];
|
||||
}
|
||||
|
||||
- (BOOL)isPerfMonitorShown
|
||||
{
|
||||
return [[self settingForKey:kRCTDevSettingIsPerfMonitorShown] boolValue];
|
||||
}
|
||||
|
||||
- (void)setExecutorClass:(Class)executorClass
|
||||
{
|
||||
_executorClass = executorClass;
|
||||
if (self.bridge.executorClass != executorClass) {
|
||||
// TODO (6929129): we can remove this special case test once we have better
|
||||
// support for custom executors in the dev menu. But right now this is
|
||||
// needed to prevent overriding a custom executor with the default if a
|
||||
// custom executor has been set directly on the bridge
|
||||
if (executorClass == Nil && self.bridge.executorClass != objc_lookUpClass("RCTWebSocketExecutor")) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.bridge.executorClass = executorClass;
|
||||
RCTTriggerReloadCommandListeners(@"Custom executor class reset");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addHandler:(id<RCTPackagerClientMethod>)handler forPackagerMethod:(NSString *)name
|
||||
{
|
||||
#if ENABLE_PACKAGER_CONNECTION
|
||||
[[RCTPackagerConnection sharedPackagerConnection] addHandler:handler forMethod:name];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)setupHotModuleReloadClientIfApplicableForURL:(NSURL *)bundleURL
|
||||
{
|
||||
if (bundleURL && !bundleURL.fileURL) { // isHotLoadingAvailable check
|
||||
NSString *const path = [bundleURL.path substringFromIndex:1]; // Strip initial slash.
|
||||
NSString *const host = bundleURL.host;
|
||||
NSNumber *const port = bundleURL.port;
|
||||
if (self.bridge) {
|
||||
[self.bridge enqueueJSCall:@"HMRClient"
|
||||
method:@"setup"
|
||||
args:@[ @"ios", path, host, RCTNullIfNil(port), @(YES) ]
|
||||
completion:NULL];
|
||||
} else {
|
||||
self.invokeJS(@"HMRClient", @"setup", @[ @"ios", path, host, RCTNullIfNil(port), @(YES) ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Internal
|
||||
|
||||
/**
|
||||
* Query the data source for all possible settings and make sure we're doing the right
|
||||
* thing for the state of each setting.
|
||||
*/
|
||||
- (void)_synchronizeAllSettings
|
||||
{
|
||||
[self _remoteDebugSettingDidChange];
|
||||
[self _profilingSettingDidChange];
|
||||
}
|
||||
|
||||
- (void)jsLoaded:(NSNotification *)notification
|
||||
{
|
||||
if (notification.userInfo[@"bridge"] != self.bridge) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isJSLoaded = YES;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// update state again after the bridge has finished loading
|
||||
[self _synchronizeAllSettings];
|
||||
|
||||
// Inspector can only be shown after JS has loaded
|
||||
if ([self isElementInspectorShown]) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[self.bridge.eventDispatcher sendDeviceEventWithName:@"toggleElementInspector" body:nil];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeDevSettingsSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#else // #if RCT_DEV_MENU
|
||||
|
||||
@interface RCTDevSettings () <NativeDevSettingsSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTDevSettings
|
||||
|
||||
- (instancetype)initWithDataSource:(id<RCTDevSettingsDataSource>)dataSource
|
||||
{
|
||||
return [super init];
|
||||
}
|
||||
- (BOOL)isHotLoadingAvailable
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
- (BOOL)isRemoteDebuggingAvailable
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
- (id)settingForKey:(NSString *)key
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
- (void)reload
|
||||
{
|
||||
}
|
||||
- (void)reloadWithReason:(NSString *)reason
|
||||
{
|
||||
}
|
||||
- (void)onFastRefresh
|
||||
{
|
||||
}
|
||||
- (void)setHotLoadingEnabled:(BOOL)isHotLoadingEnabled
|
||||
{
|
||||
}
|
||||
- (void)setIsDebuggingRemotely:(BOOL)isDebuggingRemotelyEnabled
|
||||
{
|
||||
}
|
||||
- (void)setProfilingEnabled:(BOOL)isProfilingEnabled
|
||||
{
|
||||
}
|
||||
- (void)toggleElementInspector
|
||||
{
|
||||
}
|
||||
- (void)setupHotModuleReloadClientIfApplicableForURL:(NSURL *)bundleURL
|
||||
{
|
||||
}
|
||||
- (void)addMenuItem:(NSString *)title
|
||||
{
|
||||
}
|
||||
- (void)setIsShakeToShowDevMenuEnabled:(BOOL)enabled
|
||||
{
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeDevSettingsSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif // #if RCT_DEV_MENU
|
||||
|
||||
@implementation RCTBridge (RCTDevSettings)
|
||||
|
||||
- (RCTDevSettings *)devSettings
|
||||
{
|
||||
#if RCT_DEV_MENU
|
||||
return devSettingsMenuEnabled ? [self moduleForClass:[RCTDevSettings class]] : nil;
|
||||
#else
|
||||
return nil;
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTDevSettingsCls(void)
|
||||
{
|
||||
return RCTDevSettings.class;
|
||||
}
|
14
node_modules/react-native/React/CoreModules/RCTDeviceInfo.h
generated
vendored
Normal file
14
node_modules/react-native/React/CoreModules/RCTDeviceInfo.h
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
|
||||
@interface RCTDeviceInfo : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
211
node_modules/react-native/React/CoreModules/RCTDeviceInfo.mm
generated
vendored
Normal file
211
node_modules/react-native/React/CoreModules/RCTDeviceInfo.mm
generated
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTDeviceInfo.h"
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTAccessibilityManager.h>
|
||||
#import <React/RCTAssert.h>
|
||||
#import <React/RCTConstants.h>
|
||||
#import <React/RCTEventDispatcher.h>
|
||||
#import <React/RCTUIUtils.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@interface RCTDeviceInfo () <NativeDeviceInfoSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTDeviceInfo {
|
||||
#if !TARGET_OS_TV
|
||||
UIInterfaceOrientation _currentInterfaceOrientation;
|
||||
NSDictionary *_currentInterfaceDimensions;
|
||||
#endif
|
||||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
- (void)setBridge:(RCTBridge *)bridge
|
||||
{
|
||||
_bridge = bridge;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(didReceiveNewContentSizeMultiplier)
|
||||
name:RCTAccessibilityManagerDidUpdateMultiplierNotification
|
||||
object:_bridge.accessibilityManager];
|
||||
#if !TARGET_OS_TV
|
||||
_currentInterfaceOrientation = [RCTSharedApplication() statusBarOrientation];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(interfaceOrientationDidChange)
|
||||
name:UIApplicationDidChangeStatusBarOrientationNotification
|
||||
object:nil];
|
||||
|
||||
_currentInterfaceDimensions = RCTExportedDimensions(_bridge);
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(interfaceFrameDidChange)
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(interfaceFrameDidChange)
|
||||
name:RCTUserInterfaceStyleDidChangeNotification
|
||||
object:nil];
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static BOOL RCTIsIPhoneX()
|
||||
{
|
||||
static BOOL isIPhoneX = NO;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
RCTAssertMainQueue();
|
||||
|
||||
CGSize screenSize = [UIScreen mainScreen].nativeBounds.size;
|
||||
CGSize iPhoneXScreenSize = CGSizeMake(1125, 2436);
|
||||
CGSize iPhoneXMaxScreenSize = CGSizeMake(1242, 2688);
|
||||
CGSize iPhoneXRScreenSize = CGSizeMake(828, 1792);
|
||||
|
||||
isIPhoneX = CGSizeEqualToSize(screenSize, iPhoneXScreenSize) ||
|
||||
CGSizeEqualToSize(screenSize, iPhoneXMaxScreenSize) || CGSizeEqualToSize(screenSize, iPhoneXRScreenSize);
|
||||
});
|
||||
|
||||
return isIPhoneX;
|
||||
}
|
||||
|
||||
static NSDictionary *RCTExportedDimensions(RCTBridge *bridge)
|
||||
{
|
||||
RCTAssertMainQueue();
|
||||
RCTDimensions dimensions = RCTGetDimensions(bridge.accessibilityManager.multiplier);
|
||||
__typeof(dimensions.window) window = dimensions.window;
|
||||
NSDictionary<NSString *, NSNumber *> *dimsWindow = @{
|
||||
@"width" : @(window.width),
|
||||
@"height" : @(window.height),
|
||||
@"scale" : @(window.scale),
|
||||
@"fontScale" : @(window.fontScale)
|
||||
};
|
||||
__typeof(dimensions.screen) screen = dimensions.screen;
|
||||
NSDictionary<NSString *, NSNumber *> *dimsScreen = @{
|
||||
@"width" : @(screen.width),
|
||||
@"height" : @(screen.height),
|
||||
@"scale" : @(screen.scale),
|
||||
@"fontScale" : @(screen.fontScale)
|
||||
};
|
||||
return @{@"window" : dimsWindow, @"screen" : dimsScreen};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *, id> *)constantsToExport
|
||||
{
|
||||
return [self getConstants];
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *, id> *)getConstants
|
||||
{
|
||||
return @{
|
||||
@"Dimensions" : RCTExportedDimensions(_bridge),
|
||||
// Note:
|
||||
// This prop is deprecated and will be removed in a future release.
|
||||
// Please use this only for a quick and temporary solution.
|
||||
// Use <SafeAreaView> instead.
|
||||
@"isIPhoneX_deprecated" : @(RCTIsIPhoneX()),
|
||||
};
|
||||
}
|
||||
|
||||
- (void)didReceiveNewContentSizeMultiplier
|
||||
{
|
||||
RCTBridge *bridge = _bridge;
|
||||
RCTExecuteOnMainQueue(^{
|
||||
// Report the event across the bridge.
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions" body:RCTExportedDimensions(bridge)];
|
||||
#pragma clang diagnostic pop
|
||||
});
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
- (void)interfaceOrientationDidChange
|
||||
{
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
RCTExecuteOnMainQueue(^{
|
||||
[weakSelf _interfaceOrientationDidChange];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)_interfaceOrientationDidChange
|
||||
{
|
||||
UIInterfaceOrientation nextOrientation = [RCTSharedApplication() statusBarOrientation];
|
||||
|
||||
// Update when we go from portrait to landscape, or landscape to portrait
|
||||
if ((UIInterfaceOrientationIsPortrait(_currentInterfaceOrientation) &&
|
||||
!UIInterfaceOrientationIsPortrait(nextOrientation)) ||
|
||||
(UIInterfaceOrientationIsLandscape(_currentInterfaceOrientation) &&
|
||||
!UIInterfaceOrientationIsLandscape(nextOrientation))) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions" body:RCTExportedDimensions(_bridge)];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
_currentInterfaceOrientation = nextOrientation;
|
||||
}
|
||||
|
||||
- (void)interfaceFrameDidChange
|
||||
{
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
RCTExecuteOnMainQueue(^{
|
||||
[weakSelf _interfaceFrameDidChange];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)_interfaceFrameDidChange
|
||||
{
|
||||
NSDictionary *nextInterfaceDimensions = RCTExportedDimensions(_bridge);
|
||||
|
||||
if (!([nextInterfaceDimensions isEqual:_currentInterfaceDimensions])) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions" body:nextInterfaceDimensions];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
_currentInterfaceDimensions = nextInterfaceDimensions;
|
||||
}
|
||||
|
||||
#endif // TARGET_OS_TV
|
||||
|
||||
- (std::shared_ptr<TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<NativeDeviceInfoSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTDeviceInfoCls(void)
|
||||
{
|
||||
return RCTDeviceInfo.class;
|
||||
}
|
47
node_modules/react-native/React/CoreModules/RCTExceptionsManager.h
generated
vendored
Normal file
47
node_modules/react-native/React/CoreModules/RCTExceptionsManager.h
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol RCTExceptionsManagerDelegate <NSObject>
|
||||
|
||||
- (void)handleSoftJSExceptionWithMessage:(nullable NSString *)message
|
||||
stack:(nullable NSArray *)stack
|
||||
exceptionId:(NSNumber *)exceptionId;
|
||||
- (void)handleFatalJSExceptionWithMessage:(nullable NSString *)message
|
||||
stack:(nullable NSArray *)stack
|
||||
exceptionId:(NSNumber *)exceptionId;
|
||||
|
||||
@optional
|
||||
- (void)updateJSExceptionWithMessage:(nullable NSString *)message
|
||||
stack:(nullable NSArray *)stack
|
||||
exceptionId:(NSNumber *)exceptionId;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTExceptionsManager : NSObject <RCTBridgeModule>
|
||||
|
||||
- (instancetype)initWithDelegate:(id<RCTExceptionsManagerDelegate>)delegate;
|
||||
|
||||
- (void)reportSoftException:(nullable NSString *)message
|
||||
stack:(nullable NSArray<NSDictionary *> *)stack
|
||||
exceptionId:(double)exceptionId;
|
||||
- (void)reportFatalException:(nullable NSString *)message
|
||||
stack:(nullable NSArray<NSDictionary *> *)stack
|
||||
exceptionId:(double)exceptionId;
|
||||
|
||||
@property (nonatomic, weak) id<RCTExceptionsManagerDelegate> delegate;
|
||||
|
||||
@property (nonatomic, assign) NSUInteger maxReloadAttempts;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
164
node_modules/react-native/React/CoreModules/RCTExceptionsManager.mm
generated
vendored
Normal file
164
node_modules/react-native/React/CoreModules/RCTExceptionsManager.mm
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTExceptionsManager.h"
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTDefines.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTRedBox.h>
|
||||
#import <React/RCTReloadCommand.h>
|
||||
#import <React/RCTRootView.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
@interface RCTExceptionsManager () <NativeExceptionsManagerSpec>
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTExceptionsManager
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (instancetype)initWithDelegate:(id<RCTExceptionsManagerDelegate>)delegate
|
||||
{
|
||||
if ((self = [self init])) {
|
||||
_delegate = delegate;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)reportSoft:(NSString *)message
|
||||
stack:(NSArray<NSDictionary *> *)stack
|
||||
exceptionId:(double)exceptionId
|
||||
suppressRedBox:(BOOL)suppressRedBox
|
||||
{
|
||||
if (!suppressRedBox) {
|
||||
[_bridge.redBox showErrorMessage:message withStack:stack errorCookie:((int)exceptionId)];
|
||||
}
|
||||
|
||||
if (_delegate) {
|
||||
[_delegate handleSoftJSExceptionWithMessage:message
|
||||
stack:stack
|
||||
exceptionId:[NSNumber numberWithDouble:exceptionId]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reportFatal:(NSString *)message
|
||||
stack:(NSArray<NSDictionary *> *)stack
|
||||
exceptionId:(double)exceptionId
|
||||
suppressRedBox:(BOOL)suppressRedBox
|
||||
{
|
||||
if (!suppressRedBox) {
|
||||
[_bridge.redBox showErrorMessage:message withStack:stack errorCookie:((int)exceptionId)];
|
||||
}
|
||||
|
||||
if (_delegate) {
|
||||
[_delegate handleFatalJSExceptionWithMessage:message
|
||||
stack:stack
|
||||
exceptionId:[NSNumber numberWithDouble:exceptionId]];
|
||||
}
|
||||
|
||||
static NSUInteger reloadRetries = 0;
|
||||
if (!RCT_DEBUG && reloadRetries < _maxReloadAttempts) {
|
||||
reloadRetries++;
|
||||
RCTTriggerReloadCommandListeners(@"JS Crash Reload");
|
||||
} else if (!RCT_DEV || !suppressRedBox) {
|
||||
NSString *description = [@"Unhandled JS Exception: " stringByAppendingString:message];
|
||||
NSDictionary *errorInfo = @{NSLocalizedDescriptionKey : description, RCTJSStackTraceKey : stack};
|
||||
RCTFatal([NSError errorWithDomain:RCTErrorDomain code:0 userInfo:errorInfo]);
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(reportSoftException
|
||||
: (NSString *)message stack
|
||||
: (NSArray<NSDictionary *> *)stack exceptionId
|
||||
: (double)exceptionId)
|
||||
{
|
||||
[self reportSoft:message stack:stack exceptionId:exceptionId suppressRedBox:NO];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(reportFatalException
|
||||
: (NSString *)message stack
|
||||
: (NSArray<NSDictionary *> *)stack exceptionId
|
||||
: (double)exceptionId)
|
||||
{
|
||||
[self reportFatal:message stack:stack exceptionId:exceptionId suppressRedBox:NO];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(updateExceptionMessage
|
||||
: (NSString *)message stack
|
||||
: (NSArray<NSDictionary *> *)stack exceptionId
|
||||
: (double)exceptionId)
|
||||
{
|
||||
[_bridge.redBox updateErrorMessage:message withStack:stack errorCookie:((int)exceptionId)];
|
||||
|
||||
if (_delegate && [_delegate respondsToSelector:@selector(updateJSExceptionWithMessage:stack:exceptionId:)]) {
|
||||
[_delegate updateJSExceptionWithMessage:message stack:stack exceptionId:[NSNumber numberWithDouble:exceptionId]];
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated. Use reportFatalException directly instead.
|
||||
RCT_EXPORT_METHOD(reportUnhandledException : (NSString *)message stack : (NSArray<NSDictionary *> *)stack)
|
||||
{
|
||||
[self reportFatalException:message stack:stack exceptionId:-1];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(dismissRedbox) {}
|
||||
|
||||
RCT_EXPORT_METHOD(reportException : (JS::NativeExceptionsManager::ExceptionData &)data)
|
||||
{
|
||||
NSString *message = data.message();
|
||||
double exceptionId = data.id_();
|
||||
id<NSObject> extraData = data.extraData();
|
||||
|
||||
// Reserialize data.stack() into an array of untyped dictionaries.
|
||||
// TODO: (moti) T53588496 Replace `(NSArray<NSDictionary *> *)stack` in
|
||||
// reportFatalException etc with a typed interface.
|
||||
NSMutableArray<NSDictionary *> *stackArray = [NSMutableArray<NSDictionary *> new];
|
||||
for (auto frame : data.stack()) {
|
||||
NSMutableDictionary *frameDict = [NSMutableDictionary new];
|
||||
if (frame.column().hasValue()) {
|
||||
frameDict[@"column"] = @(frame.column().value());
|
||||
}
|
||||
frameDict[@"file"] = frame.file();
|
||||
if (frame.lineNumber().hasValue()) {
|
||||
frameDict[@"lineNumber"] = @(frame.lineNumber().value());
|
||||
}
|
||||
frameDict[@"methodName"] = frame.methodName();
|
||||
if (frame.collapse().hasValue()) {
|
||||
frameDict[@"collapse"] = @(frame.collapse().value());
|
||||
}
|
||||
[stackArray addObject:frameDict];
|
||||
}
|
||||
NSDictionary *dict = (NSDictionary *)extraData;
|
||||
BOOL suppressRedBox = [[dict objectForKey:@"suppressRedBox"] boolValue];
|
||||
|
||||
if (data.isFatal()) {
|
||||
[self reportFatal:message stack:stackArray exceptionId:exceptionId suppressRedBox:suppressRedBox];
|
||||
} else {
|
||||
[self reportSoft:message stack:stackArray exceptionId:exceptionId suppressRedBox:suppressRedBox];
|
||||
}
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeExceptionsManagerSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTExceptionsManagerCls(void)
|
||||
{
|
||||
return RCTExceptionsManager.class;
|
||||
}
|
26
node_modules/react-native/React/CoreModules/RCTFPSGraph.h
generated
vendored
Normal file
26
node_modules/react-native/React/CoreModules/RCTFPSGraph.h
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTDefines.h>
|
||||
|
||||
#if RCT_DEV
|
||||
|
||||
@interface RCTFPSGraph : UIView
|
||||
|
||||
@property (nonatomic, assign, readonly) NSUInteger FPS;
|
||||
@property (nonatomic, assign, readonly) NSUInteger maxFPS;
|
||||
@property (nonatomic, assign, readonly) NSUInteger minFPS;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame color:(UIColor *)color NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (void)onTick:(NSTimeInterval)timestamp;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
123
node_modules/react-native/React/CoreModules/RCTFPSGraph.m
generated
vendored
Normal file
123
node_modules/react-native/React/CoreModules/RCTFPSGraph.m
generated
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTFPSGraph.h>
|
||||
|
||||
#import <React/RCTAssert.h>
|
||||
|
||||
#if RCT_DEV
|
||||
|
||||
@interface RCTFPSGraph ()
|
||||
|
||||
@property (nonatomic, strong, readonly) CAShapeLayer *graph;
|
||||
@property (nonatomic, strong, readonly) UILabel *label;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTFPSGraph {
|
||||
CAShapeLayer *_graph;
|
||||
UILabel *_label;
|
||||
|
||||
CGFloat *_frames;
|
||||
UIColor *_color;
|
||||
|
||||
NSTimeInterval _prevTime;
|
||||
NSUInteger _frameCount;
|
||||
NSUInteger _FPS;
|
||||
NSUInteger _maxFPS;
|
||||
NSUInteger _minFPS;
|
||||
NSUInteger _length;
|
||||
NSUInteger _height;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame color:(UIColor *)color
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
_frameCount = -1;
|
||||
_prevTime = -1;
|
||||
_maxFPS = 0;
|
||||
_minFPS = 60;
|
||||
_length = (NSUInteger)floor(frame.size.width);
|
||||
_height = (NSUInteger)floor(frame.size.height);
|
||||
_frames = calloc(sizeof(CGFloat), _length);
|
||||
_color = color;
|
||||
|
||||
[self.layer addSublayer:self.graph];
|
||||
[self addSubview:self.label];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
free(_frames);
|
||||
}
|
||||
|
||||
RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
|
||||
RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
|
||||
|
||||
- (CAShapeLayer *)graph
|
||||
{
|
||||
if (!_graph) {
|
||||
_graph = [CAShapeLayer new];
|
||||
_graph.frame = self.bounds;
|
||||
_graph.backgroundColor = [_color colorWithAlphaComponent:0.2].CGColor;
|
||||
_graph.fillColor = _color.CGColor;
|
||||
}
|
||||
|
||||
return _graph;
|
||||
}
|
||||
|
||||
- (UILabel *)label
|
||||
{
|
||||
if (!_label) {
|
||||
_label = [[UILabel alloc] initWithFrame:self.bounds];
|
||||
_label.font = [UIFont boldSystemFontOfSize:13];
|
||||
_label.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
|
||||
return _label;
|
||||
}
|
||||
|
||||
- (void)onTick:(NSTimeInterval)timestamp
|
||||
{
|
||||
_frameCount++;
|
||||
if (_prevTime == -1) {
|
||||
_prevTime = timestamp;
|
||||
} else if (timestamp - _prevTime >= 1) {
|
||||
_FPS = round(_frameCount / (timestamp - _prevTime));
|
||||
_minFPS = MIN(_minFPS, _FPS);
|
||||
_maxFPS = MAX(_maxFPS, _FPS);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self->_label.text = [NSString stringWithFormat:@"%lu", (unsigned long)self->_FPS];
|
||||
});
|
||||
|
||||
CGFloat scale = 60.0 / _height;
|
||||
for (NSUInteger i = 0; i < _length - 1; i++) {
|
||||
_frames[i] = _frames[i + 1];
|
||||
}
|
||||
_frames[_length - 1] = _FPS / scale;
|
||||
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
CGPathMoveToPoint(path, NULL, 0, _height);
|
||||
for (NSUInteger i = 0; i < _length; i++) {
|
||||
CGPathAddLineToPoint(path, NULL, i, _height - _frames[i]);
|
||||
}
|
||||
CGPathAddLineToPoint(path, NULL, _length - 1, _height);
|
||||
|
||||
_graph.path = path;
|
||||
CGPathRelease(path);
|
||||
|
||||
_prevTime = timestamp;
|
||||
_frameCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
17
node_modules/react-native/React/CoreModules/RCTI18nManager.h
generated
vendored
Normal file
17
node_modules/react-native/React/CoreModules/RCTI18nManager.h
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
* This is a experimental module for RTL support
|
||||
* This module bridges the i18n utility from RCTI18nUtil
|
||||
*/
|
||||
@interface RCTI18nManager : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
69
node_modules/react-native/React/CoreModules/RCTI18nManager.mm
generated
vendored
Normal file
69
node_modules/react-native/React/CoreModules/RCTI18nManager.mm
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
|
||||
#import <React/RCTI18nUtil.h>
|
||||
#import "RCTI18nManager.h"
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@interface RCTI18nManager () <NativeI18nManagerSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTI18nManager
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(allowRTL : (BOOL)value)
|
||||
{
|
||||
[[RCTI18nUtil sharedInstance] allowRTL:value];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(forceRTL : (BOOL)value)
|
||||
{
|
||||
[[RCTI18nUtil sharedInstance] forceRTL:value];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(swapLeftAndRightInRTL : (BOOL)value)
|
||||
{
|
||||
[[RCTI18nUtil sharedInstance] swapLeftAndRightInRTL:value];
|
||||
}
|
||||
|
||||
- (NSDictionary *)constantsToExport
|
||||
{
|
||||
return [self getConstants];
|
||||
}
|
||||
|
||||
- (NSDictionary *)getConstants
|
||||
{
|
||||
return @{
|
||||
@"isRTL" : @([[RCTI18nUtil sharedInstance] isRTL]),
|
||||
@"doLeftAndRightSwapInRTL" : @([[RCTI18nUtil sharedInstance] doLeftAndRightSwapInRTL])
|
||||
};
|
||||
}
|
||||
|
||||
- (std::shared_ptr<TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<NativeI18nManagerSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTI18nManagerCls(void)
|
||||
{
|
||||
return RCTI18nManager.class;
|
||||
}
|
12
node_modules/react-native/React/CoreModules/RCTKeyboardObserver.h
generated
vendored
Normal file
12
node_modules/react-native/React/CoreModules/RCTKeyboardObserver.h
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTEventEmitter.h>
|
||||
|
||||
@interface RCTKeyboardObserver : RCTEventEmitter
|
||||
|
||||
@end
|
142
node_modules/react-native/React/CoreModules/RCTKeyboardObserver.mm
generated
vendored
Normal file
142
node_modules/react-native/React/CoreModules/RCTKeyboardObserver.mm
generated
vendored
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTKeyboardObserver.h"
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTEventDispatcher.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
static NSDictionary *RCTParseKeyboardNotification(NSNotification *notification);
|
||||
|
||||
@interface RCTKeyboardObserver () <NativeKeyboardObserverSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTKeyboardObserver
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (void)startObserving
|
||||
{
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
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
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)supportedEvents
|
||||
{
|
||||
return @[
|
||||
@"keyboardWillShow",
|
||||
@"keyboardDidShow",
|
||||
@"keyboardWillHide",
|
||||
@"keyboardDidHide",
|
||||
@"keyboardWillChangeFrame",
|
||||
@"keyboardDidChangeFrame"
|
||||
];
|
||||
}
|
||||
|
||||
- (void)stopObserving
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
// Bridge might be already invalidated by the time the keyboard is about to be dismissed.
|
||||
// This might happen, for example, when reload from the packager is performed.
|
||||
// Thus we need to check against nil here.
|
||||
#define IMPLEMENT_KEYBOARD_HANDLER(EVENT) \
|
||||
-(void)EVENT : (NSNotification *)notification \
|
||||
{ \
|
||||
if (!self.bridge) { \
|
||||
return; \
|
||||
} \
|
||||
[self sendEventWithName:@ #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)
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeKeyboardObserverSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_INLINE NSDictionary *RCTRectDictionaryValue(CGRect rect)
|
||||
{
|
||||
return @{
|
||||
@"screenX" : @(rect.origin.x),
|
||||
@"screenY" : @(rect.origin.y),
|
||||
@"width" : @(rect.size.width),
|
||||
@"height" : @(rect.size.height),
|
||||
};
|
||||
}
|
||||
|
||||
static NSString *RCTAnimationNameForCurve(UIViewAnimationCurve curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case UIViewAnimationCurveEaseIn:
|
||||
return @"easeIn";
|
||||
case UIViewAnimationCurveEaseInOut:
|
||||
return @"easeInEaseOut";
|
||||
case UIViewAnimationCurveEaseOut:
|
||||
return @"easeOut";
|
||||
case UIViewAnimationCurveLinear:
|
||||
return @"linear";
|
||||
default:
|
||||
return @"keyboard";
|
||||
}
|
||||
}
|
||||
|
||||
static NSDictionary *RCTParseKeyboardNotification(NSNotification *notification)
|
||||
{
|
||||
#if TARGET_OS_TV
|
||||
return @{};
|
||||
#else
|
||||
NSDictionary *userInfo = notification.userInfo;
|
||||
CGRect beginFrame = [userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
|
||||
CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
|
||||
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
|
||||
UIViewAnimationCurve curve =
|
||||
static_cast<UIViewAnimationCurve>([userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]);
|
||||
NSInteger isLocalUserInfoKey = [userInfo[UIKeyboardIsLocalUserInfoKey] integerValue];
|
||||
|
||||
return @{
|
||||
@"startCoordinates" : RCTRectDictionaryValue(beginFrame),
|
||||
@"endCoordinates" : RCTRectDictionaryValue(endFrame),
|
||||
@"duration" : @(duration * 1000.0), // ms
|
||||
@"easing" : RCTAnimationNameForCurve(curve),
|
||||
@"isEventFromThisApp" : isLocalUserInfoKey == 1 ? @YES : @NO,
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
Class RCTKeyboardObserverCls(void)
|
||||
{
|
||||
return RCTKeyboardObserver.class;
|
||||
}
|
21
node_modules/react-native/React/CoreModules/RCTLogBox.h
generated
vendored
Normal file
21
node_modules/react-native/React/CoreModules/RCTLogBox.h
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTErrorCustomizer.h>
|
||||
|
||||
@class RCTJSStackFrame;
|
||||
|
||||
@interface RCTLogBox : NSObject <RCTBridgeModule>
|
||||
|
||||
- (void)show;
|
||||
- (void)hide;
|
||||
|
||||
@end
|
168
node_modules/react-native/React/CoreModules/RCTLogBox.mm
generated
vendored
Normal file
168
node_modules/react-native/React/CoreModules/RCTLogBox.mm
generated
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTLogBox.h"
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTDefines.h>
|
||||
#import <React/RCTErrorInfo.h>
|
||||
#import <React/RCTEventDispatcher.h>
|
||||
#import <React/RCTJSStackFrame.h>
|
||||
#import <React/RCTRedBoxSetEnabled.h>
|
||||
#import <React/RCTReloadCommand.h>
|
||||
#import <React/RCTRootView.h>
|
||||
#import <React/RCTSurface.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
#if RCT_DEV_MENU
|
||||
|
||||
@class RCTLogBoxView;
|
||||
|
||||
@interface RCTLogBoxView : UIWindow
|
||||
@end
|
||||
|
||||
@implementation RCTLogBoxView {
|
||||
RCTSurface *_surface;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame bridge:(RCTBridge *)bridge
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
self.windowLevel = UIWindowLevelStatusBar - 1;
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
|
||||
_surface = [[RCTSurface alloc] initWithBridge:bridge moduleName:@"LogBox" initialProperties:@{}];
|
||||
|
||||
[_surface start];
|
||||
[_surface setSize:frame.size];
|
||||
|
||||
if (![_surface synchronouslyWaitForStage:RCTSurfaceStageSurfaceDidInitialMounting timeout:1]) {
|
||||
RCTLogInfo(@"Failed to mount LogBox within 1s");
|
||||
}
|
||||
|
||||
UIViewController *_rootViewController = [UIViewController new];
|
||||
_rootViewController.view = (UIView *)_surface.view;
|
||||
_rootViewController.view.backgroundColor = [UIColor clearColor];
|
||||
_rootViewController.modalPresentationStyle = UIModalPresentationFullScreen;
|
||||
self.rootViewController = _rootViewController;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[RCTSharedApplication().delegate.window makeKeyWindow];
|
||||
}
|
||||
|
||||
- (void)show
|
||||
{
|
||||
[self becomeFirstResponder];
|
||||
[self makeKeyAndVisible];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTLogBox () <NativeLogBoxSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTLogBox {
|
||||
RCTLogBoxView *_view;
|
||||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(show)
|
||||
{
|
||||
if (RCTRedBoxGetEnabled()) {
|
||||
__weak RCTLogBox *weakSelf = self;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
__strong RCTLogBox *strongSelf = weakSelf;
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
if (!strongSelf->_view) {
|
||||
strongSelf->_view = [[RCTLogBoxView alloc] initWithFrame:[UIScreen mainScreen].bounds bridge:self->_bridge];
|
||||
}
|
||||
[strongSelf->_view show];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(hide)
|
||||
{
|
||||
if (RCTRedBoxGetEnabled()) {
|
||||
__weak RCTLogBox *weakSelf = self;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
__strong RCTLogBox *strongSelf = weakSelf;
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
strongSelf->_view = nil;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeLogBoxSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#else // Disabled
|
||||
|
||||
@interface RCTLogBox () <NativeLogBoxSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTLogBox
|
||||
|
||||
+ (NSString *)moduleName
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)show
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
- (void)hide
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeLogBoxSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
Class RCTLogBoxCls(void)
|
||||
{
|
||||
return RCTLogBox.class;
|
||||
}
|
573
node_modules/react-native/React/CoreModules/RCTPerfMonitor.mm
generated
vendored
Normal file
573
node_modules/react-native/React/CoreModules/RCTPerfMonitor.mm
generated
vendored
Normal file
@ -0,0 +1,573 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTDefines.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
#if RCT_DEV
|
||||
|
||||
#import <dlfcn.h>
|
||||
|
||||
#import <mach/mach.h>
|
||||
|
||||
#import <React/RCTDevSettings.h>
|
||||
|
||||
#import <React/RCTBridge+Private.h>
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTFPSGraph.h>
|
||||
#import <React/RCTInvalidating.h>
|
||||
#import <React/RCTJavaScriptExecutor.h>
|
||||
#import <React/RCTPerformanceLogger.h>
|
||||
#import <React/RCTRootView.h>
|
||||
#import <React/RCTUIManager.h>
|
||||
#import <React/RCTUtils.h>
|
||||
#import <ReactCommon/RCTTurboModule.h>
|
||||
|
||||
#if __has_include(<React/RCTDevMenu.h>)
|
||||
#import <React/RCTDevMenu.h>
|
||||
#endif
|
||||
|
||||
static NSString *const RCTPerfMonitorCellIdentifier = @"RCTPerfMonitorCellIdentifier";
|
||||
|
||||
static CGFloat const RCTPerfMonitorBarHeight = 50;
|
||||
static CGFloat const RCTPerfMonitorExpandHeight = 250;
|
||||
|
||||
typedef BOOL (*RCTJSCSetOptionType)(const char *);
|
||||
|
||||
static BOOL RCTJSCSetOption(const char *option)
|
||||
{
|
||||
static RCTJSCSetOptionType setOption;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
// As of iOS 13.4, it is no longer possible to change the JavaScriptCore
|
||||
// options at runtime. The options are protected and will cause an
|
||||
// exception when you try to change them after the VM has been initialized.
|
||||
// https://github.com/facebook/react-native/issues/28414
|
||||
if (@available(iOS 13.4, *)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
/**
|
||||
* JSC private C++ static method to toggle options at runtime
|
||||
*
|
||||
* JSC::Options::setOptions - JavaScriptCore/runtime/Options.h
|
||||
*/
|
||||
setOption = reinterpret_cast<RCTJSCSetOptionType>(dlsym(RTLD_DEFAULT, "_ZN3JSC7Options9setOptionEPKc"));
|
||||
|
||||
if (RCT_DEBUG && setOption == NULL) {
|
||||
RCTLogWarn(@"The symbol used to enable JSC runtime options is not available in this iOS version");
|
||||
}
|
||||
});
|
||||
|
||||
if (setOption) {
|
||||
return setOption(option);
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
static vm_size_t RCTGetResidentMemorySize(void)
|
||||
{
|
||||
vm_size_t memoryUsageInByte = 0;
|
||||
task_vm_info_data_t vmInfo;
|
||||
mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
|
||||
kern_return_t kernelReturn = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t)&vmInfo, &count);
|
||||
if (kernelReturn == KERN_SUCCESS) {
|
||||
memoryUsageInByte = (vm_size_t)vmInfo.phys_footprint;
|
||||
}
|
||||
return memoryUsageInByte;
|
||||
}
|
||||
|
||||
@interface RCTPerfMonitor
|
||||
: NSObject <RCTBridgeModule, RCTTurboModule, RCTInvalidating, UITableViewDataSource, UITableViewDelegate>
|
||||
|
||||
#if __has_include(<React/RCTDevMenu.h>)
|
||||
@property (nonatomic, strong, readonly) RCTDevMenuItem *devMenuItem;
|
||||
#endif
|
||||
@property (nonatomic, strong, readonly) UIPanGestureRecognizer *gestureRecognizer;
|
||||
@property (nonatomic, strong, readonly) UIView *container;
|
||||
@property (nonatomic, strong, readonly) UILabel *memory;
|
||||
@property (nonatomic, strong, readonly) UILabel *heap;
|
||||
@property (nonatomic, strong, readonly) UILabel *views;
|
||||
@property (nonatomic, strong, readonly) UITableView *metrics;
|
||||
@property (nonatomic, strong, readonly) RCTFPSGraph *jsGraph;
|
||||
@property (nonatomic, strong, readonly) RCTFPSGraph *uiGraph;
|
||||
@property (nonatomic, strong, readonly) UILabel *jsGraphLabel;
|
||||
@property (nonatomic, strong, readonly) UILabel *uiGraphLabel;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTPerfMonitor {
|
||||
#if __has_include(<React/RCTDevMenu.h>)
|
||||
RCTDevMenuItem *_devMenuItem;
|
||||
#endif
|
||||
UIPanGestureRecognizer *_gestureRecognizer;
|
||||
UIView *_container;
|
||||
UILabel *_memory;
|
||||
UILabel *_heap;
|
||||
UILabel *_views;
|
||||
UILabel *_uiGraphLabel;
|
||||
UILabel *_jsGraphLabel;
|
||||
UITableView *_metrics;
|
||||
|
||||
RCTFPSGraph *_uiGraph;
|
||||
RCTFPSGraph *_jsGraph;
|
||||
|
||||
CADisplayLink *_uiDisplayLink;
|
||||
CADisplayLink *_jsDisplayLink;
|
||||
|
||||
NSUInteger _heapSize;
|
||||
|
||||
dispatch_queue_t _queue;
|
||||
dispatch_io_t _io;
|
||||
int _stderr;
|
||||
int _pipe[2];
|
||||
NSString *_remaining;
|
||||
|
||||
CGRect _storedMonitorFrame;
|
||||
|
||||
NSArray *_perfLoggerMarks;
|
||||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
- (void)setBridge:(RCTBridge *)bridge
|
||||
{
|
||||
_bridge = bridge;
|
||||
|
||||
#if __has_include(<React/RCTDevMenu.h>)
|
||||
[_bridge.devMenu addItem:self.devMenuItem];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
[self hide];
|
||||
}
|
||||
|
||||
#if __has_include(<React/RCTDevMenu.h>)
|
||||
- (RCTDevMenuItem *)devMenuItem
|
||||
{
|
||||
if (!_devMenuItem) {
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
__weak RCTDevSettings *devSettings = self.bridge.devSettings;
|
||||
if (devSettings.isPerfMonitorShown) {
|
||||
[weakSelf show];
|
||||
}
|
||||
_devMenuItem = [RCTDevMenuItem
|
||||
buttonItemWithTitleBlock:^NSString * {
|
||||
return (devSettings.isPerfMonitorShown) ? @"Hide Perf Monitor" : @"Show Perf Monitor";
|
||||
}
|
||||
handler:^{
|
||||
if (devSettings.isPerfMonitorShown) {
|
||||
[weakSelf hide];
|
||||
devSettings.isPerfMonitorShown = NO;
|
||||
} else {
|
||||
[weakSelf show];
|
||||
devSettings.isPerfMonitorShown = YES;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
return _devMenuItem;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (UIPanGestureRecognizer *)gestureRecognizer
|
||||
{
|
||||
if (!_gestureRecognizer) {
|
||||
_gestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(gesture:)];
|
||||
}
|
||||
|
||||
return _gestureRecognizer;
|
||||
}
|
||||
|
||||
- (UIView *)container
|
||||
{
|
||||
if (!_container) {
|
||||
_container = [[UIView alloc] initWithFrame:CGRectMake(10, 25, 180, RCTPerfMonitorBarHeight)];
|
||||
_container.layer.borderWidth = 2;
|
||||
_container.layer.borderColor = [UIColor lightGrayColor].CGColor;
|
||||
[_container addGestureRecognizer:self.gestureRecognizer];
|
||||
[_container addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)]];
|
||||
|
||||
_container.backgroundColor = [UIColor whiteColor];
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
|
||||
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
|
||||
if (@available(iOS 13.0, *)) {
|
||||
_container.backgroundColor = [UIColor systemBackgroundColor];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return _container;
|
||||
}
|
||||
|
||||
- (UILabel *)memory
|
||||
{
|
||||
if (!_memory) {
|
||||
_memory = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 44, RCTPerfMonitorBarHeight)];
|
||||
_memory.font = [UIFont systemFontOfSize:12];
|
||||
_memory.numberOfLines = 3;
|
||||
_memory.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
|
||||
return _memory;
|
||||
}
|
||||
|
||||
- (UILabel *)heap
|
||||
{
|
||||
if (!_heap) {
|
||||
_heap = [[UILabel alloc] initWithFrame:CGRectMake(44, 0, 44, RCTPerfMonitorBarHeight)];
|
||||
_heap.font = [UIFont systemFontOfSize:12];
|
||||
_heap.numberOfLines = 3;
|
||||
_heap.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
|
||||
return _heap;
|
||||
}
|
||||
|
||||
- (UILabel *)views
|
||||
{
|
||||
if (!_views) {
|
||||
_views = [[UILabel alloc] initWithFrame:CGRectMake(88, 0, 44, RCTPerfMonitorBarHeight)];
|
||||
_views.font = [UIFont systemFontOfSize:12];
|
||||
_views.numberOfLines = 3;
|
||||
_views.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
|
||||
return _views;
|
||||
}
|
||||
|
||||
- (RCTFPSGraph *)uiGraph
|
||||
{
|
||||
if (!_uiGraph) {
|
||||
_uiGraph = [[RCTFPSGraph alloc] initWithFrame:CGRectMake(134, 14, 40, 30) color:[UIColor lightGrayColor]];
|
||||
}
|
||||
return _uiGraph;
|
||||
}
|
||||
|
||||
- (RCTFPSGraph *)jsGraph
|
||||
{
|
||||
if (!_jsGraph) {
|
||||
_jsGraph = [[RCTFPSGraph alloc] initWithFrame:CGRectMake(178, 14, 40, 30) color:[UIColor lightGrayColor]];
|
||||
}
|
||||
return _jsGraph;
|
||||
}
|
||||
|
||||
- (UILabel *)uiGraphLabel
|
||||
{
|
||||
if (!_uiGraphLabel) {
|
||||
_uiGraphLabel = [[UILabel alloc] initWithFrame:CGRectMake(134, 3, 40, 10)];
|
||||
_uiGraphLabel.font = [UIFont systemFontOfSize:11];
|
||||
_uiGraphLabel.textAlignment = NSTextAlignmentCenter;
|
||||
_uiGraphLabel.text = @"UI";
|
||||
}
|
||||
|
||||
return _uiGraphLabel;
|
||||
}
|
||||
|
||||
- (UILabel *)jsGraphLabel
|
||||
{
|
||||
if (!_jsGraphLabel) {
|
||||
_jsGraphLabel = [[UILabel alloc] initWithFrame:CGRectMake(178, 3, 38, 10)];
|
||||
_jsGraphLabel.font = [UIFont systemFontOfSize:11];
|
||||
_jsGraphLabel.textAlignment = NSTextAlignmentCenter;
|
||||
_jsGraphLabel.text = @"JS";
|
||||
}
|
||||
|
||||
return _jsGraphLabel;
|
||||
}
|
||||
|
||||
- (UITableView *)metrics
|
||||
{
|
||||
if (!_metrics) {
|
||||
_metrics = [[UITableView alloc] initWithFrame:CGRectMake(
|
||||
0,
|
||||
RCTPerfMonitorBarHeight,
|
||||
self.container.frame.size.width,
|
||||
self.container.frame.size.height - RCTPerfMonitorBarHeight)];
|
||||
_metrics.dataSource = self;
|
||||
_metrics.delegate = self;
|
||||
_metrics.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
|
||||
[_metrics registerClass:[UITableViewCell class] forCellReuseIdentifier:RCTPerfMonitorCellIdentifier];
|
||||
}
|
||||
|
||||
return _metrics;
|
||||
}
|
||||
|
||||
- (void)show
|
||||
{
|
||||
if (_container) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self.container addSubview:self.memory];
|
||||
[self.container addSubview:self.heap];
|
||||
[self.container addSubview:self.views];
|
||||
[self.container addSubview:self.uiGraph];
|
||||
[self.container addSubview:self.uiGraphLabel];
|
||||
|
||||
[self redirectLogs];
|
||||
|
||||
RCTJSCSetOption("logGC=1");
|
||||
|
||||
[self updateStats];
|
||||
|
||||
UIWindow *window = RCTSharedApplication().delegate.window;
|
||||
[window addSubview:self.container];
|
||||
|
||||
_uiDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(threadUpdate:)];
|
||||
[_uiDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
||||
|
||||
self.container.frame =
|
||||
(CGRect){self.container.frame.origin, {self.container.frame.size.width + 44, self.container.frame.size.height}};
|
||||
[self.container addSubview:self.jsGraph];
|
||||
[self.container addSubview:self.jsGraphLabel];
|
||||
|
||||
[_bridge
|
||||
dispatchBlock:^{
|
||||
self->_jsDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(threadUpdate:)];
|
||||
[self->_jsDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
|
||||
}
|
||||
queue:RCTJSThread];
|
||||
}
|
||||
|
||||
- (void)hide
|
||||
{
|
||||
if (!_container) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self.container removeFromSuperview];
|
||||
_container = nil;
|
||||
_jsGraph = nil;
|
||||
_uiGraph = nil;
|
||||
|
||||
RCTJSCSetOption("logGC=0");
|
||||
|
||||
[self stopLogs];
|
||||
|
||||
[_uiDisplayLink invalidate];
|
||||
[_jsDisplayLink invalidate];
|
||||
|
||||
_uiDisplayLink = nil;
|
||||
_jsDisplayLink = nil;
|
||||
}
|
||||
|
||||
- (void)redirectLogs
|
||||
{
|
||||
_stderr = dup(STDERR_FILENO);
|
||||
|
||||
if (pipe(_pipe) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
dup2(_pipe[1], STDERR_FILENO);
|
||||
close(_pipe[1]);
|
||||
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
_queue = dispatch_queue_create("com.facebook.react.RCTPerfMonitor", DISPATCH_QUEUE_SERIAL);
|
||||
_io = dispatch_io_create(
|
||||
DISPATCH_IO_STREAM,
|
||||
_pipe[0],
|
||||
_queue,
|
||||
^(__unused int error){
|
||||
});
|
||||
|
||||
dispatch_io_set_low_water(_io, 20);
|
||||
|
||||
dispatch_io_read(_io, 0, SIZE_MAX, _queue, ^(__unused bool done, dispatch_data_t data, __unused int error) {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_data_apply(
|
||||
data, ^bool(__unused dispatch_data_t region, __unused size_t offset, const void *buffer, size_t size) {
|
||||
write(self->_stderr, buffer, size);
|
||||
|
||||
NSString *log = [[NSString alloc] initWithBytes:buffer length:size encoding:NSUTF8StringEncoding];
|
||||
[weakSelf parse:log];
|
||||
return true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
- (void)stopLogs
|
||||
{
|
||||
dup2(_stderr, STDERR_FILENO);
|
||||
dispatch_io_close(_io, 0);
|
||||
}
|
||||
|
||||
- (void)parse:(NSString *)log
|
||||
{
|
||||
static NSRegularExpression *GCRegex;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSString *pattern =
|
||||
@"\\[GC: [\\d\\.]+ \\wb => (Eden|Full)Collection, (?:Skipped copying|Did copy), ([\\d\\.]+) \\wb, [\\d.]+ \\ws\\]";
|
||||
GCRegex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:nil];
|
||||
});
|
||||
|
||||
if (_remaining) {
|
||||
log = [_remaining stringByAppendingString:log];
|
||||
_remaining = nil;
|
||||
}
|
||||
|
||||
NSArray<NSString *> *lines = [log componentsSeparatedByString:@"\n"];
|
||||
if (lines.count == 1) { // no newlines
|
||||
_remaining = log;
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSString *line in lines) {
|
||||
NSTextCheckingResult *match = [GCRegex firstMatchInString:line options:0 range:NSMakeRange(0, line.length)];
|
||||
if (match) {
|
||||
NSString *heapSizeStr = [line substringWithRange:[match rangeAtIndex:2]];
|
||||
_heapSize = [heapSizeStr integerValue];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateStats
|
||||
{
|
||||
NSDictionary<NSNumber *, UIView *> *views = [_bridge.uiManager valueForKey:@"viewRegistry"];
|
||||
NSUInteger viewCount = views.count;
|
||||
NSUInteger visibleViewCount = 0;
|
||||
for (UIView *view in views.allValues) {
|
||||
if (view.window || view.superview.window) {
|
||||
visibleViewCount++;
|
||||
}
|
||||
}
|
||||
|
||||
double mem = (double)RCTGetResidentMemorySize() / 1024 / 1024;
|
||||
self.memory.text = [NSString stringWithFormat:@"RAM\n%.2lf\nMB", mem];
|
||||
self.heap.text = [NSString stringWithFormat:@"JSC\n%.2lf\nMB", (double)_heapSize / 1024];
|
||||
self.views.text =
|
||||
[NSString stringWithFormat:@"Views\n%lu\n%lu", (unsigned long)visibleViewCount, (unsigned long)viewCount];
|
||||
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
__strong __typeof__(weakSelf) strongSelf = weakSelf;
|
||||
if (strongSelf && strongSelf->_container.superview) {
|
||||
[strongSelf updateStats];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)gesture:(UIPanGestureRecognizer *)gestureRecognizer
|
||||
{
|
||||
CGPoint translation = [gestureRecognizer translationInView:self.container.superview];
|
||||
self.container.center = CGPointMake(self.container.center.x + translation.x, self.container.center.y + translation.y);
|
||||
[gestureRecognizer setTranslation:CGPointMake(0, 0) inView:self.container.superview];
|
||||
}
|
||||
|
||||
- (void)tap
|
||||
{
|
||||
[self loadPerformanceLoggerData];
|
||||
if (CGRectIsEmpty(_storedMonitorFrame)) {
|
||||
_storedMonitorFrame = CGRectMake(0, 20, self.container.window.frame.size.width, RCTPerfMonitorExpandHeight);
|
||||
[self.container addSubview:self.metrics];
|
||||
} else {
|
||||
[_metrics reloadData];
|
||||
}
|
||||
|
||||
[UIView animateWithDuration:.25
|
||||
animations:^{
|
||||
CGRect tmp = self.container.frame;
|
||||
self.container.frame = self->_storedMonitorFrame;
|
||||
self->_storedMonitorFrame = tmp;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)threadUpdate:(CADisplayLink *)displayLink
|
||||
{
|
||||
RCTFPSGraph *graph = displayLink == _jsDisplayLink ? _jsGraph : _uiGraph;
|
||||
[graph onTick:displayLink.timestamp];
|
||||
}
|
||||
|
||||
- (void)loadPerformanceLoggerData
|
||||
{
|
||||
NSUInteger i = 0;
|
||||
NSMutableArray<NSString *> *data = [NSMutableArray new];
|
||||
RCTPerformanceLogger *performanceLogger = [_bridge performanceLogger];
|
||||
NSArray<NSNumber *> *values = [performanceLogger valuesForTags];
|
||||
for (NSString *label in [performanceLogger labelsForTags]) {
|
||||
long long value = values[i + 1].longLongValue - values[i].longLongValue;
|
||||
NSString *unit = @"ms";
|
||||
if ([label hasSuffix:@"Size"]) {
|
||||
unit = @"b";
|
||||
} else if ([label hasSuffix:@"Count"]) {
|
||||
unit = @"";
|
||||
}
|
||||
[data addObject:[NSString stringWithFormat:@"%@: %lld%@", label, value, unit]];
|
||||
i += 2;
|
||||
}
|
||||
_perfLoggerMarks = [data copy];
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDataSource
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(__unused UITableView *)tableView
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(__unused UITableView *)tableView numberOfRowsInSection:(__unused NSInteger)section
|
||||
{
|
||||
return _perfLoggerMarks.count;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:RCTPerfMonitorCellIdentifier
|
||||
forIndexPath:indexPath];
|
||||
|
||||
if (!cell) {
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
|
||||
reuseIdentifier:RCTPerfMonitorCellIdentifier];
|
||||
}
|
||||
|
||||
cell.textLabel.text = _perfLoggerMarks[indexPath.row];
|
||||
cell.textLabel.font = [UIFont systemFontOfSize:12];
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate
|
||||
|
||||
- (CGFloat)tableView:(__unused UITableView *)tableView heightForRowAtIndexPath:(__unused NSIndexPath *)indexPath
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
Class RCTPerfMonitorCls(void)
|
||||
{
|
||||
#if RCT_DEV
|
||||
return RCTPerfMonitor.class;
|
||||
#else
|
||||
return nil;
|
||||
#endif
|
||||
}
|
14
node_modules/react-native/React/CoreModules/RCTPlatform.h
generated
vendored
Normal file
14
node_modules/react-native/React/CoreModules/RCTPlatform.h
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
@interface RCTPlatform : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
91
node_modules/react-native/React/CoreModules/RCTPlatform.mm
generated
vendored
Normal file
91
node_modules/react-native/React/CoreModules/RCTPlatform.mm
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTPlatform.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTUtils.h>
|
||||
#import <React/RCTVersion.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
static NSString *interfaceIdiom(UIUserInterfaceIdiom idiom)
|
||||
{
|
||||
switch (idiom) {
|
||||
case UIUserInterfaceIdiomPhone:
|
||||
return @"phone";
|
||||
case UIUserInterfaceIdiomPad:
|
||||
return @"pad";
|
||||
case UIUserInterfaceIdiomTV:
|
||||
return @"tv";
|
||||
case UIUserInterfaceIdiomCarPlay:
|
||||
return @"carplay";
|
||||
default:
|
||||
return @"unknown";
|
||||
}
|
||||
}
|
||||
|
||||
@interface RCTPlatform () <NativePlatformConstantsIOSSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTPlatform
|
||||
|
||||
RCT_EXPORT_MODULE(PlatformConstants)
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
// TODO: Use the generated struct return type.
|
||||
- (ModuleConstants<JS::NativePlatformConstantsIOS::Constants>)constantsToExport
|
||||
{
|
||||
return (ModuleConstants<JS::NativePlatformConstantsIOS::Constants>)[self getConstants];
|
||||
}
|
||||
|
||||
- (ModuleConstants<JS::NativePlatformConstantsIOS::Constants>)getConstants
|
||||
{
|
||||
UIDevice *device = [UIDevice currentDevice];
|
||||
auto versions = RCTGetReactNativeVersion();
|
||||
return typedConstants<JS::NativePlatformConstantsIOS::Constants>({
|
||||
.forceTouchAvailable = RCTForceTouchAvailable() ? true : false,
|
||||
.osVersion = [device systemVersion],
|
||||
.systemName = [device systemName],
|
||||
.interfaceIdiom = interfaceIdiom([device userInterfaceIdiom]),
|
||||
.isTesting = RCTRunningInTestEnvironment() ? true : false,
|
||||
.reactNativeVersion = JS::NativePlatformConstantsIOS::ConstantsReactNativeVersion::Builder(
|
||||
{.minor = [versions[@"minor"] doubleValue],
|
||||
.major = [versions[@"major"] doubleValue],
|
||||
.patch = [versions[@"patch"] doubleValue],
|
||||
.prerelease = [versions[@"prerelease"] isKindOfClass:[NSNull class]]
|
||||
? folly::Optional<double>{}
|
||||
: [versions[@"prerelease"] doubleValue]}),
|
||||
});
|
||||
}
|
||||
|
||||
- (std::shared_ptr<TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<NativePlatformConstantsIOSSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTPlatformCls(void)
|
||||
{
|
||||
return RCTPlatform.class;
|
||||
}
|
59
node_modules/react-native/React/CoreModules/RCTRedBox.h
generated
vendored
Normal file
59
node_modules/react-native/React/CoreModules/RCTRedBox.h
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTErrorCustomizer.h>
|
||||
|
||||
@class RCTJSStackFrame;
|
||||
|
||||
typedef void (^RCTRedBoxButtonPressHandler)(void);
|
||||
|
||||
@interface RCTRedBox : NSObject <RCTBridgeModule>
|
||||
|
||||
- (void)registerErrorCustomizer:(id<RCTErrorCustomizer>)errorCustomizer;
|
||||
- (void)showError:(NSError *)error;
|
||||
- (void)showErrorMessage:(NSString *)message;
|
||||
- (void)showErrorMessage:(NSString *)message withDetails:(NSString *)details;
|
||||
- (void)showErrorMessage:(NSString *)message withRawStack:(NSString *)rawStack;
|
||||
- (void)showErrorMessage:(NSString *)message withRawStack:(NSString *)rawStack errorCookie:(int)errorCookie;
|
||||
- (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack;
|
||||
- (void)updateErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack;
|
||||
- (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack errorCookie:(int)errorCookie;
|
||||
- (void)updateErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack errorCookie:(int)errorCookie;
|
||||
- (void)showErrorMessage:(NSString *)message withParsedStack:(NSArray<RCTJSStackFrame *> *)stack;
|
||||
- (void)updateErrorMessage:(NSString *)message withParsedStack:(NSArray<RCTJSStackFrame *> *)stack;
|
||||
- (void)showErrorMessage:(NSString *)message
|
||||
withParsedStack:(NSArray<RCTJSStackFrame *> *)stack
|
||||
errorCookie:(int)errorCookie;
|
||||
- (void)updateErrorMessage:(NSString *)message
|
||||
withParsedStack:(NSArray<RCTJSStackFrame *> *)stack
|
||||
errorCookie:(int)errorCookie;
|
||||
|
||||
- (void)dismiss;
|
||||
|
||||
- (void)addCustomButton:(NSString *)title onPressHandler:(RCTRedBoxButtonPressHandler)handler;
|
||||
|
||||
/** Overrides bridge.bundleURL. Modify on main thread only. You shouldn't need to use this. */
|
||||
@property (nonatomic, strong) NSURL *overrideBundleURL;
|
||||
|
||||
/** Overrides the default behavior of calling [bridge reload] on reload. You shouldn't need to use this. */
|
||||
@property (nonatomic, strong) dispatch_block_t overrideReloadAction;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* This category makes the red box instance available via the RCTBridge, which
|
||||
* is useful for any class that needs to access the red box or error log.
|
||||
*/
|
||||
@interface RCTBridge (RCTRedBox)
|
||||
|
||||
@property (nonatomic, readonly) RCTRedBox *redBox;
|
||||
|
||||
@end
|
802
node_modules/react-native/React/CoreModules/RCTRedBox.mm
generated
vendored
Normal file
802
node_modules/react-native/React/CoreModules/RCTRedBox.mm
generated
vendored
Normal file
@ -0,0 +1,802 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTRedBox.h"
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTDefines.h>
|
||||
#import <React/RCTErrorInfo.h>
|
||||
#import <React/RCTEventDispatcher.h>
|
||||
#import <React/RCTJSStackFrame.h>
|
||||
#import <React/RCTRedBoxExtraDataViewController.h>
|
||||
#import <React/RCTRedBoxSetEnabled.h>
|
||||
#import <React/RCTReloadCommand.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
#if RCT_DEV_MENU
|
||||
|
||||
@class RCTRedBoxWindow;
|
||||
|
||||
@interface UIButton (RCTRedBox)
|
||||
|
||||
@property (nonatomic) RCTRedBoxButtonPressHandler rct_handler;
|
||||
|
||||
- (void)rct_addBlock:(RCTRedBoxButtonPressHandler)handler forControlEvents:(UIControlEvents)controlEvents;
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIButton (RCTRedBox)
|
||||
|
||||
- (RCTRedBoxButtonPressHandler)rct_handler
|
||||
{
|
||||
return objc_getAssociatedObject(self, @selector(rct_handler));
|
||||
}
|
||||
|
||||
- (void)setRct_handler:(RCTRedBoxButtonPressHandler)rct_handler
|
||||
{
|
||||
objc_setAssociatedObject(self, @selector(rct_handler), rct_handler, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (void)rct_callBlock
|
||||
{
|
||||
if (self.rct_handler) {
|
||||
self.rct_handler();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)rct_addBlock:(RCTRedBoxButtonPressHandler)handler forControlEvents:(UIControlEvents)controlEvents
|
||||
{
|
||||
self.rct_handler = handler;
|
||||
[self addTarget:self action:@selector(rct_callBlock) forControlEvents:controlEvents];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@protocol RCTRedBoxWindowActionDelegate <NSObject>
|
||||
|
||||
- (void)redBoxWindow:(RCTRedBoxWindow *)redBoxWindow openStackFrameInEditor:(RCTJSStackFrame *)stackFrame;
|
||||
- (void)reloadFromRedBoxWindow:(RCTRedBoxWindow *)redBoxWindow;
|
||||
- (void)loadExtraDataViewController;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTRedBoxWindow : NSObject <UITableViewDelegate, UITableViewDataSource>
|
||||
@property (nonatomic, strong) UIViewController *rootViewController;
|
||||
@property (nonatomic, weak) id<RCTRedBoxWindowActionDelegate> actionDelegate;
|
||||
@end
|
||||
|
||||
@implementation RCTRedBoxWindow {
|
||||
UITableView *_stackTraceTableView;
|
||||
NSString *_lastErrorMessage;
|
||||
NSArray<RCTJSStackFrame *> *_lastStackTrace;
|
||||
int _lastErrorCookie;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
customButtonTitles:(NSArray<NSString *> *)customButtonTitles
|
||||
customButtonHandlers:(NSArray<RCTRedBoxButtonPressHandler> *)customButtonHandlers
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_lastErrorCookie = -1;
|
||||
|
||||
_rootViewController = [UIViewController new];
|
||||
UIView *rootView = _rootViewController.view;
|
||||
rootView.frame = frame;
|
||||
rootView.backgroundColor = [UIColor blackColor];
|
||||
|
||||
const CGFloat buttonHeight = 60;
|
||||
|
||||
CGRect detailsFrame = rootView.bounds;
|
||||
detailsFrame.size.height -= buttonHeight + [self bottomSafeViewHeight];
|
||||
|
||||
_stackTraceTableView = [[UITableView alloc] initWithFrame:detailsFrame style:UITableViewStylePlain];
|
||||
_stackTraceTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
_stackTraceTableView.delegate = self;
|
||||
_stackTraceTableView.dataSource = self;
|
||||
_stackTraceTableView.backgroundColor = [UIColor clearColor];
|
||||
#if !TARGET_OS_TV
|
||||
_stackTraceTableView.separatorColor = [UIColor colorWithWhite:1 alpha:0.3];
|
||||
_stackTraceTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
|
||||
#endif
|
||||
_stackTraceTableView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
|
||||
[rootView addSubview:_stackTraceTableView];
|
||||
|
||||
#if TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST
|
||||
NSString *reloadText = @"Reload\n(\u2318R)";
|
||||
NSString *dismissText = @"Dismiss\n(ESC)";
|
||||
NSString *copyText = @"Copy\n(\u2325\u2318C)";
|
||||
NSString *extraText = @"Extra Info\n(\u2318E)";
|
||||
#else
|
||||
NSString *reloadText = @"Reload JS";
|
||||
NSString *dismissText = @"Dismiss";
|
||||
NSString *copyText = @"Copy";
|
||||
NSString *extraText = @"Extra Info";
|
||||
#endif
|
||||
|
||||
UIButton *dismissButton = [self redBoxButton:dismissText
|
||||
accessibilityIdentifier:@"redbox-dismiss"
|
||||
selector:@selector(dismiss)
|
||||
block:nil];
|
||||
UIButton *reloadButton = [self redBoxButton:reloadText
|
||||
accessibilityIdentifier:@"redbox-reload"
|
||||
selector:@selector(reload)
|
||||
block:nil];
|
||||
UIButton *copyButton = [self redBoxButton:copyText
|
||||
accessibilityIdentifier:@"redbox-copy"
|
||||
selector:@selector(copyStack)
|
||||
block:nil];
|
||||
UIButton *extraButton = [self redBoxButton:extraText
|
||||
accessibilityIdentifier:@"redbox-extra"
|
||||
selector:@selector(showExtraDataViewController)
|
||||
block:nil];
|
||||
|
||||
CGFloat buttonWidth = frame.size.width / (4 + [customButtonTitles count]);
|
||||
CGFloat bottomButtonHeight = frame.size.height - buttonHeight - [self bottomSafeViewHeight];
|
||||
dismissButton.frame = CGRectMake(0, bottomButtonHeight, buttonWidth, buttonHeight);
|
||||
reloadButton.frame = CGRectMake(buttonWidth, bottomButtonHeight, buttonWidth, buttonHeight);
|
||||
copyButton.frame = CGRectMake(buttonWidth * 2, bottomButtonHeight, buttonWidth, buttonHeight);
|
||||
extraButton.frame = CGRectMake(buttonWidth * 3, bottomButtonHeight, buttonWidth, buttonHeight);
|
||||
|
||||
[rootView addSubview:dismissButton];
|
||||
[rootView addSubview:reloadButton];
|
||||
[rootView addSubview:copyButton];
|
||||
[rootView addSubview:extraButton];
|
||||
|
||||
for (NSUInteger i = 0; i < [customButtonTitles count]; i++) {
|
||||
UIButton *button = [self redBoxButton:customButtonTitles[i]
|
||||
accessibilityIdentifier:@""
|
||||
selector:nil
|
||||
block:customButtonHandlers[i]];
|
||||
button.frame = CGRectMake(buttonWidth * (4 + i), bottomButtonHeight, buttonWidth, buttonHeight);
|
||||
[rootView addSubview:button];
|
||||
}
|
||||
|
||||
UIView *topBorder =
|
||||
[[UIView alloc] initWithFrame:CGRectMake(0, bottomButtonHeight + 1, rootView.frame.size.width, 1)];
|
||||
topBorder.backgroundColor = [UIColor colorWithRed:0.70 green:0.70 blue:0.70 alpha:1.0];
|
||||
|
||||
[rootView addSubview:topBorder];
|
||||
|
||||
UIView *bottomSafeView = [UIView new];
|
||||
bottomSafeView.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];
|
||||
bottomSafeView.frame =
|
||||
CGRectMake(0, frame.size.height - [self bottomSafeViewHeight], frame.size.width, [self bottomSafeViewHeight]);
|
||||
|
||||
[rootView addSubview:bottomSafeView];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (UIButton *)redBoxButton:(NSString *)title
|
||||
accessibilityIdentifier:(NSString *)accessibilityIdentifier
|
||||
selector:(SEL)selector
|
||||
block:(RCTRedBoxButtonPressHandler)block
|
||||
{
|
||||
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
button.autoresizingMask =
|
||||
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin;
|
||||
button.accessibilityIdentifier = accessibilityIdentifier;
|
||||
button.titleLabel.font = [UIFont systemFontOfSize:13];
|
||||
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
||||
button.titleLabel.textAlignment = NSTextAlignmentCenter;
|
||||
button.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];
|
||||
[button setTitle:title forState:UIControlStateNormal];
|
||||
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
||||
[button setTitleColor:[UIColor colorWithWhite:1 alpha:0.5] forState:UIControlStateHighlighted];
|
||||
if (selector) {
|
||||
[button addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside];
|
||||
} else if (block) {
|
||||
[button rct_addBlock:block forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return button;
|
||||
}
|
||||
|
||||
- (NSInteger)bottomSafeViewHeight
|
||||
{
|
||||
if (@available(iOS 11.0, *)) {
|
||||
return RCTSharedApplication().delegate.window.safeAreaInsets.bottom;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
_stackTraceTableView.dataSource = nil;
|
||||
_stackTraceTableView.delegate = nil;
|
||||
}
|
||||
|
||||
- (NSString *)stripAnsi:(NSString *)text
|
||||
{
|
||||
NSError *error = nil;
|
||||
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\x1b\\[[0-9;]*m"
|
||||
options:NSRegularExpressionCaseInsensitive
|
||||
error:&error];
|
||||
return [regex stringByReplacingMatchesInString:text options:0 range:NSMakeRange(0, [text length]) withTemplate:@""];
|
||||
}
|
||||
|
||||
- (void)showErrorMessage:(NSString *)message
|
||||
withStack:(NSArray<RCTJSStackFrame *> *)stack
|
||||
isUpdate:(BOOL)isUpdate
|
||||
errorCookie:(int)errorCookie
|
||||
{
|
||||
// Remove ANSI color codes from the message
|
||||
NSString *messageWithoutAnsi = [self stripAnsi:message];
|
||||
|
||||
// Show if this is a new message, or if we're updating the previous message
|
||||
BOOL isNew = !self.rootViewController.isBeingPresented && !isUpdate;
|
||||
BOOL isUpdateForSameMessage = !isNew &&
|
||||
(self.rootViewController.isBeingPresented && isUpdate &&
|
||||
((errorCookie == -1 && [_lastErrorMessage isEqualToString:messageWithoutAnsi]) ||
|
||||
(errorCookie == _lastErrorCookie)));
|
||||
if (isNew || isUpdateForSameMessage) {
|
||||
_lastStackTrace = stack;
|
||||
// message is displayed using UILabel, which is unable to render text of
|
||||
// unlimited length, so we truncate it
|
||||
_lastErrorMessage = [messageWithoutAnsi substringToIndex:MIN((NSUInteger)10000, messageWithoutAnsi.length)];
|
||||
_lastErrorCookie = errorCookie;
|
||||
|
||||
[_stackTraceTableView reloadData];
|
||||
|
||||
if (!self.rootViewController.isBeingPresented) {
|
||||
[_stackTraceTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
|
||||
atScrollPosition:UITableViewScrollPositionTop
|
||||
animated:NO];
|
||||
[RCTKeyWindow().rootViewController presentViewController:self.rootViewController animated:YES completion:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dismiss
|
||||
{
|
||||
[self.rootViewController dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void)reload
|
||||
{
|
||||
[_actionDelegate reloadFromRedBoxWindow:self];
|
||||
}
|
||||
|
||||
- (void)showExtraDataViewController
|
||||
{
|
||||
[_actionDelegate loadExtraDataViewController];
|
||||
}
|
||||
|
||||
- (void)copyStack
|
||||
{
|
||||
NSMutableString *fullStackTrace;
|
||||
|
||||
if (_lastErrorMessage != nil) {
|
||||
fullStackTrace = [_lastErrorMessage mutableCopy];
|
||||
[fullStackTrace appendString:@"\n\n"];
|
||||
} else {
|
||||
fullStackTrace = [NSMutableString string];
|
||||
}
|
||||
|
||||
for (RCTJSStackFrame *stackFrame in _lastStackTrace) {
|
||||
[fullStackTrace appendString:[NSString stringWithFormat:@"%@\n", stackFrame.methodName]];
|
||||
if (stackFrame.file) {
|
||||
[fullStackTrace appendFormat:@" %@\n", [self formatFrameSource:stackFrame]];
|
||||
}
|
||||
}
|
||||
#if !TARGET_OS_TV
|
||||
UIPasteboard *pb = [UIPasteboard generalPasteboard];
|
||||
[pb setString:fullStackTrace];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (NSString *)formatFrameSource:(RCTJSStackFrame *)stackFrame
|
||||
{
|
||||
NSString *fileName = RCTNilIfNull(stackFrame.file) ? [stackFrame.file lastPathComponent] : @"<unknown file>";
|
||||
NSString *lineInfo = [NSString stringWithFormat:@"%@:%lld", fileName, (long long)stackFrame.lineNumber];
|
||||
|
||||
if (stackFrame.column != 0) {
|
||||
lineInfo = [lineInfo stringByAppendingFormat:@":%lld", (long long)stackFrame.column];
|
||||
}
|
||||
return lineInfo;
|
||||
}
|
||||
|
||||
#pragma mark - TableView
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(__unused UITableView *)tableView
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(__unused UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
return section == 0 ? 1 : _lastStackTrace.count;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (indexPath.section == 0) {
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"msg-cell"];
|
||||
return [self reuseCell:cell forErrorMessage:_lastErrorMessage];
|
||||
}
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
|
||||
NSUInteger index = indexPath.row;
|
||||
RCTJSStackFrame *stackFrame = _lastStackTrace[index];
|
||||
return [self reuseCell:cell forStackFrame:stackFrame];
|
||||
}
|
||||
|
||||
- (UITableViewCell *)reuseCell:(UITableViewCell *)cell forErrorMessage:(NSString *)message
|
||||
{
|
||||
if (!cell) {
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"msg-cell"];
|
||||
cell.textLabel.accessibilityIdentifier = @"redbox-error";
|
||||
cell.textLabel.textColor = [UIColor whiteColor];
|
||||
cell.textLabel.font = [UIFont boldSystemFontOfSize:16];
|
||||
cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
||||
cell.textLabel.numberOfLines = 0;
|
||||
cell.detailTextLabel.textColor = [UIColor whiteColor];
|
||||
cell.backgroundColor = [UIColor colorWithRed:0.82 green:0.10 blue:0.15 alpha:1.0];
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
}
|
||||
|
||||
cell.textLabel.text = message;
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)reuseCell:(UITableViewCell *)cell forStackFrame:(RCTJSStackFrame *)stackFrame
|
||||
{
|
||||
if (!cell) {
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"];
|
||||
cell.textLabel.font = [UIFont fontWithName:@"Menlo-Regular" size:14];
|
||||
cell.textLabel.lineBreakMode = NSLineBreakByCharWrapping;
|
||||
cell.textLabel.numberOfLines = 2;
|
||||
cell.detailTextLabel.textColor = [UIColor colorWithRed:0.70 green:0.70 blue:0.70 alpha:1.0];
|
||||
cell.detailTextLabel.font = [UIFont fontWithName:@"Menlo-Regular" size:11];
|
||||
cell.detailTextLabel.lineBreakMode = NSLineBreakByTruncatingMiddle;
|
||||
cell.backgroundColor = [UIColor clearColor];
|
||||
cell.selectedBackgroundView = [UIView new];
|
||||
cell.selectedBackgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.2];
|
||||
}
|
||||
|
||||
cell.textLabel.text = stackFrame.methodName ?: @"(unnamed method)";
|
||||
if (stackFrame.file) {
|
||||
cell.detailTextLabel.text = [self formatFrameSource:stackFrame];
|
||||
} else {
|
||||
cell.detailTextLabel.text = @"";
|
||||
}
|
||||
cell.textLabel.textColor = stackFrame.collapse ? [UIColor lightGrayColor] : [UIColor whiteColor];
|
||||
cell.detailTextLabel.textColor = stackFrame.collapse ? [UIColor colorWithRed:0.50 green:0.50 blue:0.50 alpha:1.0]
|
||||
: [UIColor colorWithRed:0.70 green:0.70 blue:0.70 alpha:1.0];
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (indexPath.section == 0) {
|
||||
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
|
||||
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
|
||||
|
||||
NSDictionary *attributes =
|
||||
@{NSFontAttributeName : [UIFont boldSystemFontOfSize:16], NSParagraphStyleAttributeName : paragraphStyle};
|
||||
CGRect boundingRect =
|
||||
[_lastErrorMessage boundingRectWithSize:CGSizeMake(tableView.frame.size.width - 30, CGFLOAT_MAX)
|
||||
options:NSStringDrawingUsesLineFragmentOrigin
|
||||
attributes:attributes
|
||||
context:nil];
|
||||
return ceil(boundingRect.size.height) + 40;
|
||||
} else {
|
||||
return 50;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (indexPath.section == 1) {
|
||||
NSUInteger row = indexPath.row;
|
||||
RCTJSStackFrame *stackFrame = _lastStackTrace[row];
|
||||
[_actionDelegate redBoxWindow:self openStackFrameInEditor:stackFrame];
|
||||
}
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
}
|
||||
|
||||
#pragma mark - Key commands
|
||||
|
||||
- (NSArray<UIKeyCommand *> *)keyCommands
|
||||
{
|
||||
// NOTE: We could use RCTKeyCommands for this, but since
|
||||
// we control this window, we can use the standard, non-hacky
|
||||
// mechanism instead
|
||||
|
||||
return @[
|
||||
// Dismiss red box
|
||||
[UIKeyCommand keyCommandWithInput:UIKeyInputEscape modifierFlags:0 action:@selector(dismiss)],
|
||||
|
||||
// Reload
|
||||
[UIKeyCommand keyCommandWithInput:@"r" modifierFlags:UIKeyModifierCommand action:@selector(reload)],
|
||||
|
||||
// Copy = Cmd-Option C since Cmd-C in the simulator copies the pasteboard from
|
||||
// the simulator to the desktop pasteboard.
|
||||
[UIKeyCommand keyCommandWithInput:@"c"
|
||||
modifierFlags:UIKeyModifierCommand | UIKeyModifierAlternate
|
||||
action:@selector(copyStack)],
|
||||
|
||||
// Extra data
|
||||
[UIKeyCommand keyCommandWithInput:@"e"
|
||||
modifierFlags:UIKeyModifierCommand
|
||||
action:@selector(showExtraDataViewController)]
|
||||
];
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeFirstResponder
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTRedBox () <
|
||||
RCTInvalidating,
|
||||
RCTRedBoxWindowActionDelegate,
|
||||
RCTRedBoxExtraDataActionDelegate,
|
||||
NativeRedBoxSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTRedBox {
|
||||
RCTRedBoxWindow *_window;
|
||||
NSMutableArray<id<RCTErrorCustomizer>> *_errorCustomizers;
|
||||
RCTRedBoxExtraDataViewController *_extraDataViewController;
|
||||
NSMutableArray<NSString *> *_customButtonTitles;
|
||||
NSMutableArray<RCTRedBoxButtonPressHandler> *_customButtonHandlers;
|
||||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (void)registerErrorCustomizer:(id<RCTErrorCustomizer>)errorCustomizer
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (!self->_errorCustomizers) {
|
||||
self->_errorCustomizers = [NSMutableArray array];
|
||||
}
|
||||
if (![self->_errorCustomizers containsObject:errorCustomizer]) {
|
||||
[self->_errorCustomizers addObject:errorCustomizer];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// WARNING: Should only be called from the main thread/dispatch queue.
|
||||
- (RCTErrorInfo *)_customizeError:(RCTErrorInfo *)error
|
||||
{
|
||||
RCTAssertMainQueue();
|
||||
if (!self->_errorCustomizers) {
|
||||
return error;
|
||||
}
|
||||
for (id<RCTErrorCustomizer> customizer in self->_errorCustomizers) {
|
||||
RCTErrorInfo *newInfo = [customizer customizeErrorInfo:error];
|
||||
if (newInfo) {
|
||||
error = newInfo;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
- (void)showError:(NSError *)error
|
||||
{
|
||||
[self showErrorMessage:error.localizedDescription
|
||||
withDetails:error.localizedFailureReason
|
||||
stack:error.userInfo[RCTJSStackTraceKey]
|
||||
errorCookie:-1];
|
||||
}
|
||||
|
||||
- (void)showErrorMessage:(NSString *)message
|
||||
{
|
||||
[self showErrorMessage:message withParsedStack:nil isUpdate:NO errorCookie:-1];
|
||||
}
|
||||
|
||||
- (void)showErrorMessage:(NSString *)message withDetails:(NSString *)details
|
||||
{
|
||||
[self showErrorMessage:message withDetails:details stack:nil errorCookie:-1];
|
||||
}
|
||||
|
||||
- (void)showErrorMessage:(NSString *)message
|
||||
withDetails:(NSString *)details
|
||||
stack:(NSArray<RCTJSStackFrame *> *)stack
|
||||
errorCookie:(int)errorCookie
|
||||
{
|
||||
NSString *combinedMessage = message;
|
||||
if (details) {
|
||||
combinedMessage = [NSString stringWithFormat:@"%@\n\n%@", message, details];
|
||||
}
|
||||
[self showErrorMessage:combinedMessage withParsedStack:stack isUpdate:NO errorCookie:errorCookie];
|
||||
}
|
||||
|
||||
- (void)showErrorMessage:(NSString *)message withRawStack:(NSString *)rawStack
|
||||
{
|
||||
[self showErrorMessage:message withRawStack:rawStack errorCookie:-1];
|
||||
}
|
||||
|
||||
- (void)showErrorMessage:(NSString *)message withRawStack:(NSString *)rawStack errorCookie:(int)errorCookie
|
||||
{
|
||||
NSArray<RCTJSStackFrame *> *stack = [RCTJSStackFrame stackFramesWithLines:rawStack];
|
||||
[self showErrorMessage:message withParsedStack:stack isUpdate:NO errorCookie:errorCookie];
|
||||
}
|
||||
|
||||
- (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack
|
||||
{
|
||||
[self showErrorMessage:message withStack:stack errorCookie:-1];
|
||||
}
|
||||
|
||||
- (void)updateErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack
|
||||
{
|
||||
[self updateErrorMessage:message withStack:stack errorCookie:-1];
|
||||
}
|
||||
|
||||
- (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack errorCookie:(int)errorCookie
|
||||
{
|
||||
[self showErrorMessage:message
|
||||
withParsedStack:[RCTJSStackFrame stackFramesWithDictionaries:stack]
|
||||
isUpdate:NO
|
||||
errorCookie:errorCookie];
|
||||
}
|
||||
|
||||
- (void)updateErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack errorCookie:(int)errorCookie
|
||||
{
|
||||
[self showErrorMessage:message
|
||||
withParsedStack:[RCTJSStackFrame stackFramesWithDictionaries:stack]
|
||||
isUpdate:YES
|
||||
errorCookie:errorCookie];
|
||||
}
|
||||
|
||||
- (void)showErrorMessage:(NSString *)message withParsedStack:(NSArray<RCTJSStackFrame *> *)stack
|
||||
{
|
||||
[self showErrorMessage:message withParsedStack:stack errorCookie:-1];
|
||||
}
|
||||
|
||||
- (void)updateErrorMessage:(NSString *)message withParsedStack:(NSArray<RCTJSStackFrame *> *)stack
|
||||
{
|
||||
[self updateErrorMessage:message withParsedStack:stack errorCookie:-1];
|
||||
}
|
||||
|
||||
- (void)showErrorMessage:(NSString *)message
|
||||
withParsedStack:(NSArray<RCTJSStackFrame *> *)stack
|
||||
errorCookie:(int)errorCookie
|
||||
{
|
||||
[self showErrorMessage:message withParsedStack:stack isUpdate:NO errorCookie:errorCookie];
|
||||
}
|
||||
|
||||
- (void)updateErrorMessage:(NSString *)message
|
||||
withParsedStack:(NSArray<RCTJSStackFrame *> *)stack
|
||||
errorCookie:(int)errorCookie
|
||||
{
|
||||
[self showErrorMessage:message withParsedStack:stack isUpdate:YES errorCookie:errorCookie];
|
||||
}
|
||||
|
||||
- (void)showErrorMessage:(NSString *)message
|
||||
withParsedStack:(NSArray<RCTJSStackFrame *> *)stack
|
||||
isUpdate:(BOOL)isUpdate
|
||||
errorCookie:(int)errorCookie
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self->_extraDataViewController == nil) {
|
||||
self->_extraDataViewController = [RCTRedBoxExtraDataViewController new];
|
||||
self->_extraDataViewController.actionDelegate = self;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[self->_bridge.eventDispatcher sendDeviceEventWithName:@"collectRedBoxExtraData" body:nil];
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
if (!self->_window) {
|
||||
self->_window = [[RCTRedBoxWindow alloc] initWithFrame:[UIScreen mainScreen].bounds
|
||||
customButtonTitles:self->_customButtonTitles
|
||||
customButtonHandlers:self->_customButtonHandlers];
|
||||
self->_window.actionDelegate = self;
|
||||
}
|
||||
|
||||
RCTErrorInfo *errorInfo = [[RCTErrorInfo alloc] initWithErrorMessage:message stack:stack];
|
||||
errorInfo = [self _customizeError:errorInfo];
|
||||
[self->_window showErrorMessage:errorInfo.errorMessage
|
||||
withStack:errorInfo.stack
|
||||
isUpdate:isUpdate
|
||||
errorCookie:errorCookie];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)loadExtraDataViewController
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// Make sure the CMD+E shortcut doesn't call this twice
|
||||
if (self->_extraDataViewController != nil && ![self->_window.rootViewController presentedViewController]) {
|
||||
[self->_window.rootViewController presentViewController:self->_extraDataViewController
|
||||
animated:YES
|
||||
completion:nil];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setExtraData : (NSDictionary *)extraData forIdentifier : (NSString *)identifier)
|
||||
{
|
||||
[_extraDataViewController addExtraData:extraData forIdentifier:identifier];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(dismiss)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self->_window dismiss];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
[self dismiss];
|
||||
}
|
||||
|
||||
- (void)redBoxWindow:(__unused RCTRedBoxWindow *)redBoxWindow openStackFrameInEditor:(RCTJSStackFrame *)stackFrame
|
||||
{
|
||||
NSURL *const bundleURL = _overrideBundleURL ?: _bridge.bundleURL;
|
||||
if (![bundleURL.scheme hasPrefix:@"http"]) {
|
||||
RCTLogWarn(@"Cannot open stack frame in editor because you're not connected to the packager.");
|
||||
return;
|
||||
}
|
||||
|
||||
NSData *stackFrameJSON = [RCTJSONStringify([stackFrame toDictionary], NULL) dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSString *postLength = [NSString stringWithFormat:@"%tu", stackFrameJSON.length];
|
||||
NSMutableURLRequest *request = [NSMutableURLRequest new];
|
||||
request.URL = [NSURL URLWithString:@"/open-stack-frame" relativeToURL:bundleURL];
|
||||
request.HTTPMethod = @"POST";
|
||||
request.HTTPBody = stackFrameJSON;
|
||||
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
|
||||
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
|
||||
|
||||
[[[NSURLSession sharedSession] dataTaskWithRequest:request] resume];
|
||||
}
|
||||
|
||||
- (void)reload
|
||||
{
|
||||
// Window is not used and can be nil
|
||||
[self reloadFromRedBoxWindow:nil];
|
||||
}
|
||||
|
||||
- (void)reloadFromRedBoxWindow:(__unused RCTRedBoxWindow *)redBoxWindow
|
||||
{
|
||||
if (_overrideReloadAction) {
|
||||
_overrideReloadAction();
|
||||
} else {
|
||||
RCTTriggerReloadCommandListeners(@"Redbox");
|
||||
}
|
||||
[self dismiss];
|
||||
}
|
||||
|
||||
- (void)addCustomButton:(NSString *)title onPressHandler:(RCTRedBoxButtonPressHandler)handler
|
||||
{
|
||||
if (!_customButtonTitles) {
|
||||
_customButtonTitles = [NSMutableArray new];
|
||||
_customButtonHandlers = [NSMutableArray new];
|
||||
}
|
||||
|
||||
[_customButtonTitles addObject:title];
|
||||
[_customButtonHandlers addObject:handler];
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeRedBoxSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridge (RCTRedBox)
|
||||
|
||||
- (RCTRedBox *)redBox
|
||||
{
|
||||
return RCTRedBoxGetEnabled() ? [self moduleForClass:[RCTRedBox class]] : nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#else // Disabled
|
||||
|
||||
@interface RCTRedBox () <NativeRedBoxSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTRedBox
|
||||
|
||||
+ (NSString *)moduleName
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
- (void)registerErrorCustomizer:(id<RCTErrorCustomizer>)errorCustomizer
|
||||
{
|
||||
}
|
||||
- (void)showError:(NSError *)error
|
||||
{
|
||||
}
|
||||
- (void)showErrorMessage:(NSString *)message
|
||||
{
|
||||
}
|
||||
- (void)showErrorMessage:(NSString *)message withDetails:(NSString *)details
|
||||
{
|
||||
}
|
||||
- (void)showErrorMessage:(NSString *)message withRawStack:(NSString *)rawStack
|
||||
{
|
||||
}
|
||||
- (void)showErrorMessage:(NSString *)message withRawStack:(NSString *)rawStack errorCookie:(int)errorCookie
|
||||
{
|
||||
}
|
||||
- (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack
|
||||
{
|
||||
}
|
||||
- (void)updateErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack
|
||||
{
|
||||
}
|
||||
- (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack errorCookie:(int)errorCookie
|
||||
{
|
||||
}
|
||||
- (void)updateErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack errorCookie:(int)errorCookie
|
||||
{
|
||||
}
|
||||
- (void)showErrorMessage:(NSString *)message withParsedStack:(NSArray<RCTJSStackFrame *> *)stack
|
||||
{
|
||||
}
|
||||
- (void)updateErrorMessage:(NSString *)message withParsedStack:(NSArray<RCTJSStackFrame *> *)stack
|
||||
{
|
||||
}
|
||||
- (void)showErrorMessage:(NSString *)message
|
||||
withParsedStack:(NSArray<RCTJSStackFrame *> *)stack
|
||||
errorCookie:(int)errorCookie
|
||||
{
|
||||
}
|
||||
- (void)updateErrorMessage:(NSString *)message
|
||||
withParsedStack:(NSArray<RCTJSStackFrame *> *)stack
|
||||
errorCookie:(int)errorCookie
|
||||
{
|
||||
}
|
||||
- (void)setExtraData:(NSDictionary *)extraData forIdentifier:(NSString *)identifier
|
||||
{
|
||||
}
|
||||
|
||||
- (void)dismiss
|
||||
{
|
||||
}
|
||||
|
||||
- (void)addCustomButton:(NSString *)title onPressHandler:(RCTRedBoxButtonPressHandler)handler
|
||||
{
|
||||
}
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeRedBoxSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridge (RCTRedBox)
|
||||
|
||||
- (RCTRedBox *)redBox
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
Class RCTRedBoxCls(void)
|
||||
{
|
||||
return RCTRedBox.class;
|
||||
}
|
14
node_modules/react-native/React/CoreModules/RCTSourceCode.h
generated
vendored
Normal file
14
node_modules/react-native/React/CoreModules/RCTSourceCode.h
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
@interface RCTSourceCode : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
56
node_modules/react-native/React/CoreModules/RCTSourceCode.mm
generated
vendored
Normal file
56
node_modules/react-native/React/CoreModules/RCTSourceCode.mm
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTSourceCode.h"
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@interface RCTSourceCode () <NativeSourceCodeSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTSourceCode
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *, id> *)constantsToExport
|
||||
{
|
||||
return [self getConstants];
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *, id> *)getConstants
|
||||
{
|
||||
return @{
|
||||
@"scriptURL" : self.bridge.bundleURL.absoluteString ?: @"",
|
||||
};
|
||||
}
|
||||
|
||||
- (std::shared_ptr<TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<NativeSourceCodeSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTSourceCodeCls(void)
|
||||
{
|
||||
return RCTSourceCode.class;
|
||||
}
|
24
node_modules/react-native/React/CoreModules/RCTStatusBarManager.h
generated
vendored
Normal file
24
node_modules/react-native/React/CoreModules/RCTStatusBarManager.h
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTEventEmitter.h>
|
||||
|
||||
@interface RCTConvert (UIStatusBar)
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
+ (UIStatusBarStyle)UIStatusBarStyle:(id)json;
|
||||
+ (UIStatusBarAnimation)UIStatusBarAnimation:(id)json;
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTStatusBarManager : RCTEventEmitter
|
||||
|
||||
@end
|
215
node_modules/react-native/React/CoreModules/RCTStatusBarManager.mm
generated
vendored
Normal file
215
node_modules/react-native/React/CoreModules/RCTStatusBarManager.mm
generated
vendored
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTStatusBarManager.h"
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
#import <React/RCTEventDispatcher.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
|
||||
@implementation RCTConvert (UIStatusBar)
|
||||
|
||||
+ (UIStatusBarStyle)UIStatusBarStyle:(id)json RCT_DYNAMIC
|
||||
{
|
||||
static NSDictionary *mapping;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
if (@available(iOS 13.0, *)) {
|
||||
mapping = @{
|
||||
@"default" : @(UIStatusBarStyleDefault),
|
||||
@"light-content" : @(UIStatusBarStyleLightContent),
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
|
||||
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
|
||||
@"dark-content" : @(UIStatusBarStyleDarkContent)
|
||||
#else
|
||||
@"dark-content": @(UIStatusBarStyleDefault)
|
||||
#endif
|
||||
};
|
||||
|
||||
} else {
|
||||
mapping = @{
|
||||
@"default" : @(UIStatusBarStyleDefault),
|
||||
@"light-content" : @(UIStatusBarStyleLightContent),
|
||||
@"dark-content" : @(UIStatusBarStyleDefault)
|
||||
};
|
||||
}
|
||||
});
|
||||
return _RCT_CAST(
|
||||
UIStatusBarStyle,
|
||||
[RCTConvertEnumValue("UIStatusBarStyle", mapping, @(UIStatusBarStyleDefault), json) integerValue]);
|
||||
}
|
||||
|
||||
RCT_ENUM_CONVERTER(
|
||||
UIStatusBarAnimation,
|
||||
(@{
|
||||
@"none" : @(UIStatusBarAnimationNone),
|
||||
@"fade" : @(UIStatusBarAnimationFade),
|
||||
@"slide" : @(UIStatusBarAnimationSlide),
|
||||
}),
|
||||
UIStatusBarAnimationNone,
|
||||
integerValue);
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
@interface RCTStatusBarManager () <NativeStatusBarManagerIOSSpec>
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
@implementation RCTStatusBarManager
|
||||
|
||||
static BOOL RCTViewControllerBasedStatusBarAppearance()
|
||||
{
|
||||
static BOOL value;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
value =
|
||||
[[[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"]
|
||||
?: @YES boolValue];
|
||||
});
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)supportedEvents
|
||||
{
|
||||
return @[ @"statusBarFrameDidChange", @"statusBarFrameWillChange" ];
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
- (void)startObserving
|
||||
{
|
||||
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
||||
[nc addObserver:self
|
||||
selector:@selector(applicationDidChangeStatusBarFrame:)
|
||||
name:UIApplicationDidChangeStatusBarFrameNotification
|
||||
object:nil];
|
||||
[nc addObserver:self
|
||||
selector:@selector(applicationWillChangeStatusBarFrame:)
|
||||
name:UIApplicationWillChangeStatusBarFrameNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)stopObserving
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
- (void)emitEvent:(NSString *)eventName forNotification:(NSNotification *)notification
|
||||
{
|
||||
CGRect frame = [notification.userInfo[UIApplicationStatusBarFrameUserInfoKey] CGRectValue];
|
||||
NSDictionary *event = @{
|
||||
@"frame" : @{
|
||||
@"x" : @(frame.origin.x),
|
||||
@"y" : @(frame.origin.y),
|
||||
@"width" : @(frame.size.width),
|
||||
@"height" : @(frame.size.height),
|
||||
},
|
||||
};
|
||||
[self sendEventWithName:eventName body:event];
|
||||
}
|
||||
|
||||
- (void)applicationDidChangeStatusBarFrame:(NSNotification *)notification
|
||||
{
|
||||
[self emitEvent:@"statusBarFrameDidChange" forNotification:notification];
|
||||
}
|
||||
|
||||
- (void)applicationWillChangeStatusBarFrame:(NSNotification *)notification
|
||||
{
|
||||
[self emitEvent:@"statusBarFrameWillChange" forNotification:notification];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getHeight : (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
callback(@[ @{
|
||||
@"height" : @(RCTSharedApplication().statusBarFrame.size.height),
|
||||
} ]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setStyle : (NSString *)style animated : (BOOL)animated)
|
||||
{
|
||||
UIStatusBarStyle statusBarStyle = [RCTConvert UIStatusBarStyle:style];
|
||||
if (RCTViewControllerBasedStatusBarAppearance()) {
|
||||
RCTLogError(@"RCTStatusBarManager module requires that the \
|
||||
UIViewControllerBasedStatusBarAppearance key in the Info.plist is set to NO");
|
||||
} else {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[RCTSharedApplication() setStatusBarStyle:statusBarStyle animated:animated];
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setHidden : (BOOL)hidden withAnimation : (NSString *)withAnimation)
|
||||
{
|
||||
UIStatusBarAnimation animation = [RCTConvert UIStatusBarAnimation:withAnimation];
|
||||
if (RCTViewControllerBasedStatusBarAppearance()) {
|
||||
RCTLogError(@"RCTStatusBarManager module requires that the \
|
||||
UIViewControllerBasedStatusBarAppearance key in the Info.plist is set to NO");
|
||||
} else {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[RCTSharedApplication() setStatusBarHidden:hidden withAnimation:animation];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setNetworkActivityIndicatorVisible : (BOOL)visible)
|
||||
{
|
||||
RCTSharedApplication().networkActivityIndicatorVisible = visible;
|
||||
}
|
||||
|
||||
- (facebook::react::ModuleConstants<JS::NativeStatusBarManagerIOS::Constants>)getConstants
|
||||
{
|
||||
return facebook::react::typedConstants<JS::NativeStatusBarManagerIOS::Constants>({
|
||||
.HEIGHT = RCTSharedApplication().statusBarFrame.size.height,
|
||||
.DEFAULT_BACKGROUND_COLOR = folly::none,
|
||||
});
|
||||
}
|
||||
|
||||
- (facebook::react::ModuleConstants<JS::NativeStatusBarManagerIOS::Constants>)constantsToExport
|
||||
{
|
||||
return (facebook::react::ModuleConstants<JS::NativeStatusBarManagerIOS::Constants>)[self getConstants];
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeStatusBarManagerIOSSpecJSI>(
|
||||
self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
#endif // TARGET_OS_TV
|
||||
|
||||
@end
|
||||
|
||||
Class RCTStatusBarManagerCls(void)
|
||||
{
|
||||
return RCTStatusBarManager.class;
|
||||
}
|
14
node_modules/react-native/React/CoreModules/RCTTVNavigationEventEmitter.h
generated
vendored
Normal file
14
node_modules/react-native/React/CoreModules/RCTTVNavigationEventEmitter.h
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTEventEmitter.h>
|
||||
|
||||
RCT_EXTERN NSString *const RCTTVNavigationEventNotification;
|
||||
|
||||
@interface RCTTVNavigationEventEmitter : RCTEventEmitter
|
||||
|
||||
@end
|
66
node_modules/react-native/React/CoreModules/RCTTVNavigationEventEmitter.mm
generated
vendored
Normal file
66
node_modules/react-native/React/CoreModules/RCTTVNavigationEventEmitter.mm
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTTVNavigationEventEmitter.h"
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
NSString *const RCTTVNavigationEventNotification = @"RCTTVNavigationEventNotification";
|
||||
|
||||
static NSString *const TVNavigationEventName = @"onHWKeyEvent";
|
||||
|
||||
@interface RCTTVNavigationEventEmitter () <NativeTVNavigationEventEmitterSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTTVNavigationEventEmitter
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (self = [super init]) {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleTVNavigationEventNotification:)
|
||||
name:RCTTVNavigationEventNotification
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)supportedEvents
|
||||
{
|
||||
return @[ TVNavigationEventName ];
|
||||
}
|
||||
|
||||
- (void)handleTVNavigationEventNotification:(NSNotification *)notif
|
||||
{
|
||||
if (self.bridge) {
|
||||
[self sendEventWithName:TVNavigationEventName body:notif.object];
|
||||
}
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeTVNavigationEventEmitterSpecJSI>(
|
||||
self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTTVNavigationEventEmitterCls(void)
|
||||
{
|
||||
return RCTTVNavigationEventEmitter.class;
|
||||
}
|
31
node_modules/react-native/React/CoreModules/RCTTiming.h
generated
vendored
Normal file
31
node_modules/react-native/React/CoreModules/RCTTiming.h
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTFrameUpdate.h>
|
||||
#import <React/RCTInvalidating.h>
|
||||
|
||||
@protocol RCTTimingDelegate
|
||||
|
||||
- (void)callTimers:(NSArray<NSNumber *> *)timers;
|
||||
- (void)immediatelyCallTimer:(nonnull NSNumber *)callbackID;
|
||||
- (void)callIdleCallbacks:(nonnull NSNumber *)absoluteFrameStartMS;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTTiming : NSObject <RCTBridgeModule, RCTInvalidating, RCTFrameUpdateObserver>
|
||||
|
||||
- (instancetype)initWithDelegate:(id<RCTTimingDelegate>)delegate;
|
||||
- (void)createTimerForNextFrame:(nonnull NSNumber *)callbackID
|
||||
duration:(NSTimeInterval)jsDuration
|
||||
jsSchedulingTime:(NSDate *)jsSchedulingTime
|
||||
repeats:(BOOL)repeats;
|
||||
- (void)deleteTimer:(double)timerID;
|
||||
|
||||
@end
|
417
node_modules/react-native/React/CoreModules/RCTTiming.mm
generated
vendored
Normal file
417
node_modules/react-native/React/CoreModules/RCTTiming.mm
generated
vendored
Normal file
@ -0,0 +1,417 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTTiming.h"
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
|
||||
#import <React/RCTAssert.h>
|
||||
#import <React/RCTBridge+Private.h>
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
static const NSTimeInterval kMinimumSleepInterval = 1;
|
||||
|
||||
// These timing contants should be kept in sync with the ones in `JSTimers.js`.
|
||||
// The duration of a frame. This assumes that we want to run at 60 fps.
|
||||
static const NSTimeInterval kFrameDuration = 1.0 / 60.0;
|
||||
// The minimum time left in a frame to trigger the idle callback.
|
||||
static const NSTimeInterval kIdleCallbackFrameDeadline = 0.001;
|
||||
|
||||
@interface _RCTTimer : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) NSDate *target;
|
||||
@property (nonatomic, assign, readonly) BOOL repeats;
|
||||
@property (nonatomic, copy, readonly) NSNumber *callbackID;
|
||||
@property (nonatomic, assign, readonly) NSTimeInterval interval;
|
||||
|
||||
@end
|
||||
|
||||
@implementation _RCTTimer
|
||||
|
||||
- (instancetype)initWithCallbackID:(NSNumber *)callbackID
|
||||
interval:(NSTimeInterval)interval
|
||||
targetTime:(NSTimeInterval)targetTime
|
||||
repeats:(BOOL)repeats
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_interval = interval;
|
||||
_repeats = repeats;
|
||||
_callbackID = callbackID;
|
||||
_target = [NSDate dateWithTimeIntervalSinceNow:targetTime];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `YES` if we should invoke the JS callback.
|
||||
*/
|
||||
- (BOOL)shouldFire:(NSDate *)now
|
||||
{
|
||||
if (_target && [_target timeIntervalSinceDate:now] <= 0) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)reschedule
|
||||
{
|
||||
// The JS Timers will do fine grained calculating of expired timeouts.
|
||||
_target = [NSDate dateWithTimeIntervalSinceNow:_interval];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface _RCTTimingProxy : NSObject
|
||||
|
||||
@end
|
||||
|
||||
// NSTimer retains its target, insert this class to break potential retain cycles
|
||||
@implementation _RCTTimingProxy {
|
||||
__weak id _target;
|
||||
}
|
||||
|
||||
+ (instancetype)proxyWithTarget:(id)target
|
||||
{
|
||||
_RCTTimingProxy *proxy = [self new];
|
||||
if (proxy) {
|
||||
proxy->_target = target;
|
||||
}
|
||||
return proxy;
|
||||
}
|
||||
|
||||
- (void)timerDidFire
|
||||
{
|
||||
[_target timerDidFire];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTTiming {
|
||||
NSMutableDictionary<NSNumber *, _RCTTimer *> *_timers;
|
||||
NSTimer *_sleepTimer;
|
||||
BOOL _sendIdleEvents;
|
||||
BOOL _inBackground;
|
||||
id<RCTTimingDelegate> _timingDelegate;
|
||||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
@synthesize paused = _paused;
|
||||
@synthesize pauseCallback = _pauseCallback;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (instancetype)initWithDelegate:(id<RCTTimingDelegate>)delegate
|
||||
{
|
||||
if (self = [super init]) {
|
||||
[self setup];
|
||||
_timingDelegate = delegate;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setBridge:(RCTBridge *)bridge
|
||||
{
|
||||
RCTAssert(!_bridge, @"Should never be initialized twice!");
|
||||
[self setup];
|
||||
_bridge = bridge;
|
||||
}
|
||||
|
||||
- (void)setup
|
||||
{
|
||||
_paused = YES;
|
||||
_timers = [NSMutableDictionary new];
|
||||
_inBackground = NO;
|
||||
|
||||
for (NSString *name in @[
|
||||
UIApplicationWillResignActiveNotification,
|
||||
UIApplicationDidEnterBackgroundNotification,
|
||||
UIApplicationWillTerminateNotification
|
||||
]) {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(appDidMoveToBackground)
|
||||
name:name
|
||||
object:nil];
|
||||
}
|
||||
|
||||
for (NSString *name in @[ UIApplicationDidBecomeActiveNotification, UIApplicationWillEnterForegroundNotification ]) {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(appDidMoveToForeground)
|
||||
name:name
|
||||
object:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_sleepTimer invalidate];
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return RCTJSThread;
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
[self stopTimers];
|
||||
_bridge = nil;
|
||||
_timingDelegate = nil;
|
||||
}
|
||||
|
||||
- (void)appDidMoveToBackground
|
||||
{
|
||||
// Deactivate the CADisplayLink while in the background.
|
||||
[self stopTimers];
|
||||
_inBackground = YES;
|
||||
|
||||
// Issue one final timer callback, which will schedule a
|
||||
// background NSTimer, if needed.
|
||||
[self didUpdateFrame:nil];
|
||||
}
|
||||
|
||||
- (void)appDidMoveToForeground
|
||||
{
|
||||
_inBackground = NO;
|
||||
[self startTimers];
|
||||
}
|
||||
|
||||
- (void)stopTimers
|
||||
{
|
||||
if (_inBackground) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_paused) {
|
||||
_paused = YES;
|
||||
if (_pauseCallback) {
|
||||
_pauseCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startTimers
|
||||
{
|
||||
if ((!_bridge && !_timingDelegate) || _inBackground || ![self hasPendingTimers]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_paused) {
|
||||
_paused = NO;
|
||||
if (_pauseCallback) {
|
||||
_pauseCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)hasPendingTimers
|
||||
{
|
||||
@synchronized(_timers) {
|
||||
return _sendIdleEvents || _timers.count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didUpdateFrame:(RCTFrameUpdate *)update
|
||||
{
|
||||
NSDate *nextScheduledTarget = [NSDate distantFuture];
|
||||
NSMutableArray<_RCTTimer *> *timersToCall = [NSMutableArray new];
|
||||
NSDate *now = [NSDate date]; // compare all the timers to the same base time
|
||||
@synchronized(_timers) {
|
||||
for (_RCTTimer *timer in _timers.allValues) {
|
||||
if ([timer shouldFire:now]) {
|
||||
[timersToCall addObject:timer];
|
||||
} else {
|
||||
nextScheduledTarget = [nextScheduledTarget earlierDate:timer.target];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call timers that need to be called
|
||||
if (timersToCall.count > 0) {
|
||||
NSArray<NSNumber *> *sortedTimers = [[timersToCall sortedArrayUsingComparator:^(_RCTTimer *a, _RCTTimer *b) {
|
||||
return [a.target compare:b.target];
|
||||
}] valueForKey:@"callbackID"];
|
||||
if (_bridge) {
|
||||
[_bridge enqueueJSCall:@"JSTimers" method:@"callTimers" args:@[ sortedTimers ] completion:NULL];
|
||||
} else {
|
||||
[_timingDelegate callTimers:sortedTimers];
|
||||
}
|
||||
}
|
||||
|
||||
for (_RCTTimer *timer in timersToCall) {
|
||||
if (timer.repeats) {
|
||||
[timer reschedule];
|
||||
nextScheduledTarget = [nextScheduledTarget earlierDate:timer.target];
|
||||
} else {
|
||||
@synchronized(_timers) {
|
||||
[_timers removeObjectForKey:timer.callbackID];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_sendIdleEvents) {
|
||||
NSTimeInterval currentTimestamp = [[NSDate date] timeIntervalSince1970];
|
||||
NSTimeInterval frameElapsed = currentTimestamp - update.timestamp;
|
||||
if (kFrameDuration - frameElapsed >= kIdleCallbackFrameDeadline) {
|
||||
NSNumber *absoluteFrameStartMS = @((currentTimestamp - frameElapsed) * 1000);
|
||||
if (_bridge) {
|
||||
[_bridge enqueueJSCall:@"JSTimers" method:@"callIdleCallbacks" args:@[ absoluteFrameStartMS ] completion:NULL];
|
||||
} else {
|
||||
[_timingDelegate callIdleCallbacks:absoluteFrameStartMS];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Switch to a paused state only if we didn't call any timer this frame, so if
|
||||
// in response to this timer another timer is scheduled, we don't pause and unpause
|
||||
// the displaylink frivolously.
|
||||
NSUInteger timerCount;
|
||||
@synchronized(_timers) {
|
||||
timerCount = _timers.count;
|
||||
}
|
||||
if (_inBackground) {
|
||||
if (timerCount) {
|
||||
[self scheduleSleepTimer:nextScheduledTarget];
|
||||
}
|
||||
} else if (!_sendIdleEvents && timersToCall.count == 0) {
|
||||
// No need to call the pauseCallback as RCTDisplayLink will ask us about our paused
|
||||
// status immediately after completing this call
|
||||
if (timerCount == 0) {
|
||||
_paused = YES;
|
||||
}
|
||||
// If the next timer is more than 1 second out, pause and schedule an NSTimer;
|
||||
else if ([nextScheduledTarget timeIntervalSinceNow] > kMinimumSleepInterval) {
|
||||
[self scheduleSleepTimer:nextScheduledTarget];
|
||||
_paused = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)scheduleSleepTimer:(NSDate *)sleepTarget
|
||||
{
|
||||
@synchronized(self) {
|
||||
if (!_sleepTimer || !_sleepTimer.valid) {
|
||||
_sleepTimer = [[NSTimer alloc] initWithFireDate:sleepTarget
|
||||
interval:0
|
||||
target:[_RCTTimingProxy proxyWithTarget:self]
|
||||
selector:@selector(timerDidFire)
|
||||
userInfo:nil
|
||||
repeats:NO];
|
||||
[[NSRunLoop currentRunLoop] addTimer:_sleepTimer forMode:NSDefaultRunLoopMode];
|
||||
} else {
|
||||
_sleepTimer.fireDate = [_sleepTimer.fireDate earlierDate:sleepTarget];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)timerDidFire
|
||||
{
|
||||
_sleepTimer = nil;
|
||||
if (_paused) {
|
||||
[self startTimers];
|
||||
|
||||
// Immediately dispatch frame, so we don't have to wait on the displaylink.
|
||||
[self didUpdateFrame:nil];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A method used for asynchronously creating a timer. If the timer has already expired,
|
||||
* (based on the provided jsSchedulingTime) then it will be immediately invoked.
|
||||
*
|
||||
* There's a small difference between the time when we call
|
||||
* setTimeout/setInterval/requestAnimation frame and the time it actually makes
|
||||
* it here. This is important and needs to be taken into account when
|
||||
* calculating the timer's target time. We calculate this by passing in
|
||||
* Date.now() from JS and then subtracting that from the current time here.
|
||||
*/
|
||||
RCT_EXPORT_METHOD(createTimer
|
||||
: (double)callbackID duration
|
||||
: (NSTimeInterval)jsDuration jsSchedulingTime
|
||||
: (double)jsSchedulingTime repeats
|
||||
: (BOOL)repeats)
|
||||
{
|
||||
NSNumber *callbackIdObjc = [NSNumber numberWithDouble:callbackID];
|
||||
NSDate *schedulingTime = [RCTConvert NSDate:[NSNumber numberWithDouble:jsSchedulingTime]];
|
||||
if (jsDuration == 0 && repeats == NO) {
|
||||
// For super fast, one-off timers, just enqueue them immediately rather than waiting a frame.
|
||||
if (_bridge) {
|
||||
[_bridge _immediatelyCallTimer:callbackIdObjc];
|
||||
} else {
|
||||
[_timingDelegate immediatelyCallTimer:callbackIdObjc];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
[self createTimerForNextFrame:callbackIdObjc duration:jsDuration jsSchedulingTime:schedulingTime repeats:repeats];
|
||||
}
|
||||
|
||||
/**
|
||||
* A method used for synchronously creating a timer. The timer will not be invoked until the
|
||||
* next frame, regardless of whether it has already expired (i.e. jsSchedulingTime is 0).
|
||||
*/
|
||||
- (void)createTimerForNextFrame:(nonnull NSNumber *)callbackID
|
||||
duration:(NSTimeInterval)jsDuration
|
||||
jsSchedulingTime:(NSDate *)jsSchedulingTime
|
||||
repeats:(BOOL)repeats
|
||||
{
|
||||
NSTimeInterval jsSchedulingOverhead = MAX(-jsSchedulingTime.timeIntervalSinceNow, 0);
|
||||
|
||||
NSTimeInterval targetTime = jsDuration - jsSchedulingOverhead;
|
||||
if (jsDuration < 0.018) { // Make sure short intervals run each frame
|
||||
jsDuration = 0;
|
||||
}
|
||||
|
||||
_RCTTimer *timer = [[_RCTTimer alloc] initWithCallbackID:callbackID
|
||||
interval:jsDuration
|
||||
targetTime:targetTime
|
||||
repeats:repeats];
|
||||
@synchronized(_timers) {
|
||||
_timers[callbackID] = timer;
|
||||
}
|
||||
|
||||
if (_inBackground) {
|
||||
[self scheduleSleepTimer:timer.target];
|
||||
} else if (_paused) {
|
||||
if ([timer.target timeIntervalSinceNow] > kMinimumSleepInterval) {
|
||||
[self scheduleSleepTimer:timer.target];
|
||||
} else {
|
||||
[self startTimers];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(deleteTimer : (double)timerID)
|
||||
{
|
||||
@synchronized(_timers) {
|
||||
[_timers removeObjectForKey:[NSNumber numberWithDouble:timerID]];
|
||||
}
|
||||
if (![self hasPendingTimers]) {
|
||||
[self stopTimers];
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setSendIdleEvents : (BOOL)sendIdleEvents)
|
||||
{
|
||||
_sendIdleEvents = sendIdleEvents;
|
||||
if (sendIdleEvents) {
|
||||
[self startTimers];
|
||||
} else if (![self hasPendingTimers]) {
|
||||
[self stopTimers];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTTimingCls(void)
|
||||
{
|
||||
return RCTTiming.class;
|
||||
}
|
19
node_modules/react-native/React/CoreModules/RCTWebSocketExecutor.h
generated
vendored
Normal file
19
node_modules/react-native/React/CoreModules/RCTWebSocketExecutor.h
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTDefines.h>
|
||||
#import <React/RCTJavaScriptExecutor.h>
|
||||
|
||||
#if RCT_DEV // Debug executors are only supported in dev mode
|
||||
|
||||
@interface RCTWebSocketExecutor : NSObject <RCTJavaScriptExecutor>
|
||||
|
||||
- (instancetype)initWithURL:(NSURL *)URL;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
292
node_modules/react-native/React/CoreModules/RCTWebSocketExecutor.mm
generated
vendored
Normal file
292
node_modules/react-native/React/CoreModules/RCTWebSocketExecutor.mm
generated
vendored
Normal file
@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTWebSocketExecutor.h>
|
||||
|
||||
#import <React/RCTAssert.h>
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTDefines.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTSRWebSocket.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import <ReactCommon/RCTTurboModule.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
#if RCT_DEV // Debug executors are only supported in dev mode
|
||||
|
||||
typedef void (^RCTWSMessageCallback)(NSError *error, NSDictionary<NSString *, id> *reply);
|
||||
|
||||
@interface RCTWebSocketExecutor () <RCTSRWebSocketDelegate, RCTTurboModule>
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTWebSocketExecutor {
|
||||
RCTSRWebSocket *_socket;
|
||||
dispatch_queue_t _jsQueue;
|
||||
NSMutableDictionary<NSNumber *, RCTWSMessageCallback> *_callbacks;
|
||||
dispatch_semaphore_t _socketOpenSemaphore;
|
||||
NSMutableDictionary<NSString *, NSString *> *_injectedObjects;
|
||||
NSURL *_url;
|
||||
NSError *_setupError;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
- (instancetype)initWithURL:(NSURL *)URL
|
||||
{
|
||||
RCTAssertParam(URL);
|
||||
|
||||
if ((self = [self init])) {
|
||||
_url = URL;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
if (!_url) {
|
||||
NSInteger port = [[[_bridge bundleURL] port] integerValue] ?: RCT_METRO_PORT;
|
||||
NSString *host = [[_bridge bundleURL] host] ?: @"localhost";
|
||||
NSString *URLString =
|
||||
[NSString stringWithFormat:@"http://%@:%lld/debugger-proxy?role=client", host, (long long)port];
|
||||
_url = [RCTConvert NSURL:URLString];
|
||||
}
|
||||
|
||||
_jsQueue = dispatch_queue_create("com.facebook.react.WebSocketExecutor", DISPATCH_QUEUE_SERIAL);
|
||||
_socket = [[RCTSRWebSocket alloc] initWithURL:_url];
|
||||
_socket.delegate = self;
|
||||
_callbacks = [NSMutableDictionary new];
|
||||
_injectedObjects = [NSMutableDictionary new];
|
||||
[_socket setDelegateDispatchQueue:_jsQueue];
|
||||
|
||||
NSURL *startDevToolsURL = [NSURL URLWithString:@"/launch-js-devtools" relativeToURL:_url];
|
||||
|
||||
NSURLSession *session = [NSURLSession sharedSession];
|
||||
NSURLSessionDataTask *dataTask =
|
||||
[session dataTaskWithRequest:[NSURLRequest requestWithURL:startDevToolsURL]
|
||||
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
|
||||
}];
|
||||
[dataTask resume];
|
||||
if (![self connectToProxy]) {
|
||||
[self invalidate];
|
||||
NSString *error = [NSString stringWithFormat:
|
||||
@"Connection to %@ timed out. Are you "
|
||||
"running node proxy? If you are running on the device, check if "
|
||||
"you have the right IP address in `RCTWebSocketExecutor.m`.",
|
||||
_url];
|
||||
_setupError = RCTErrorWithMessage(error);
|
||||
RCTFatal(_setupError);
|
||||
return;
|
||||
}
|
||||
|
||||
NSInteger retries = 3;
|
||||
BOOL runtimeIsReady = [self prepareJSRuntime];
|
||||
while (!runtimeIsReady && retries > 0) {
|
||||
runtimeIsReady = [self prepareJSRuntime];
|
||||
retries--;
|
||||
}
|
||||
if (!runtimeIsReady) {
|
||||
[self invalidate];
|
||||
NSString *error =
|
||||
@"Runtime is not ready for debugging.\n "
|
||||
"- Make sure Packager server is running.\n"
|
||||
"- Make sure the JavaScript Debugger is running and not paused on a "
|
||||
"breakpoint or exception and try reloading again.";
|
||||
_setupError = RCTErrorWithMessage(error);
|
||||
RCTFatal(_setupError);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)connectToProxy
|
||||
{
|
||||
_socketOpenSemaphore = dispatch_semaphore_create(0);
|
||||
[_socket open];
|
||||
long connected = dispatch_semaphore_wait(_socketOpenSemaphore, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 15));
|
||||
return connected == 0 && _socket.readyState == RCTSR_OPEN;
|
||||
}
|
||||
|
||||
- (BOOL)prepareJSRuntime
|
||||
{
|
||||
__block NSError *initError;
|
||||
dispatch_semaphore_t s = dispatch_semaphore_create(0);
|
||||
[self sendMessage:@{@"method" : @"prepareJSRuntime"}
|
||||
onReply:^(NSError *error, NSDictionary<NSString *, id> *reply) {
|
||||
initError = error;
|
||||
dispatch_semaphore_signal(s);
|
||||
}];
|
||||
long runtimeIsReady = dispatch_semaphore_wait(s, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 10));
|
||||
if (initError) {
|
||||
RCTLogInfo(@"Websocket runtime setup failed: %@", initError);
|
||||
}
|
||||
return runtimeIsReady == 0 && initError == nil;
|
||||
}
|
||||
|
||||
- (void)webSocket:(RCTSRWebSocket *)webSocket didReceiveMessage:(id)message
|
||||
{
|
||||
NSError *error = nil;
|
||||
NSDictionary<NSString *, id> *reply = RCTJSONParse(message, &error);
|
||||
NSNumber *messageID = reply[@"replyID"];
|
||||
RCTWSMessageCallback callback = _callbacks[messageID];
|
||||
if (callback) {
|
||||
callback(error, reply);
|
||||
[_callbacks removeObjectForKey:messageID];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webSocketDidOpen:(RCTSRWebSocket *)webSocket
|
||||
{
|
||||
dispatch_semaphore_signal(_socketOpenSemaphore);
|
||||
}
|
||||
|
||||
- (void)webSocket:(RCTSRWebSocket *)webSocket didFailWithError:(NSError *)error
|
||||
{
|
||||
dispatch_semaphore_signal(_socketOpenSemaphore);
|
||||
RCTLogInfo(@"WebSocket connection failed with error %@", error);
|
||||
}
|
||||
|
||||
- (void)sendMessage:(NSDictionary<NSString *, id> *)message onReply:(RCTWSMessageCallback)callback
|
||||
{
|
||||
static NSUInteger lastID = 10000;
|
||||
|
||||
if (_setupError) {
|
||||
callback(_setupError, nil);
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_async(_jsQueue, ^{
|
||||
if (!self.valid) {
|
||||
callback(RCTErrorWithMessage(@"Runtime is not ready for debugging. Make sure Packager server is running."), nil);
|
||||
return;
|
||||
}
|
||||
|
||||
NSNumber *expectedID = @(lastID++);
|
||||
self->_callbacks[expectedID] = [callback copy];
|
||||
NSMutableDictionary<NSString *, id> *messageWithID = [message mutableCopy];
|
||||
messageWithID[@"id"] = expectedID;
|
||||
[self->_socket send:RCTJSONStringify(messageWithID, NULL)];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)executeApplicationScript:(NSData *)script
|
||||
sourceURL:(NSURL *)URL
|
||||
onComplete:(RCTJavaScriptCompleteBlock)onComplete
|
||||
{
|
||||
// Hack: the bridge transitions out of loading state as soon as this method returns, which prevents us
|
||||
// from completely invalidating the bridge and preventing an endless barage of RCTLog.logIfNoNativeHook
|
||||
// calls if the JS execution environment is broken. We therefore block this thread until this message has returned.
|
||||
dispatch_semaphore_t scriptSem = dispatch_semaphore_create(0);
|
||||
|
||||
NSDictionary<NSString *, id> *message = @{
|
||||
@"method" : @"executeApplicationScript",
|
||||
@"url" : RCTNullIfNil(URL.absoluteString),
|
||||
@"inject" : _injectedObjects,
|
||||
};
|
||||
[self sendMessage:message
|
||||
onReply:^(NSError *socketError, NSDictionary<NSString *, id> *reply) {
|
||||
if (socketError) {
|
||||
onComplete(socketError);
|
||||
} else {
|
||||
NSString *error = reply[@"error"];
|
||||
onComplete(error ? RCTErrorWithMessage(error) : nil);
|
||||
}
|
||||
dispatch_semaphore_signal(scriptSem);
|
||||
}];
|
||||
|
||||
dispatch_semaphore_wait(scriptSem, DISPATCH_TIME_FOREVER);
|
||||
}
|
||||
|
||||
- (void)flushedQueue:(RCTJavaScriptCallback)onComplete
|
||||
{
|
||||
[self _executeJSCall:@"flushedQueue" arguments:@[] callback:onComplete];
|
||||
}
|
||||
|
||||
- (void)callFunctionOnModule:(NSString *)module
|
||||
method:(NSString *)method
|
||||
arguments:(NSArray *)args
|
||||
callback:(RCTJavaScriptCallback)onComplete
|
||||
{
|
||||
[self _executeJSCall:@"callFunctionReturnFlushedQueue" arguments:@[ module, method, args ] callback:onComplete];
|
||||
}
|
||||
|
||||
- (void)invokeCallbackID:(NSNumber *)cbID arguments:(NSArray *)args callback:(RCTJavaScriptCallback)onComplete
|
||||
{
|
||||
[self _executeJSCall:@"invokeCallbackAndReturnFlushedQueue" arguments:@[ cbID, args ] callback:onComplete];
|
||||
}
|
||||
|
||||
- (void)_executeJSCall:(NSString *)method arguments:(NSArray *)arguments callback:(RCTJavaScriptCallback)onComplete
|
||||
{
|
||||
RCTAssert(onComplete != nil, @"callback was missing for exec JS call");
|
||||
NSDictionary<NSString *, id> *message = @{@"method" : method, @"arguments" : arguments};
|
||||
[self sendMessage:message
|
||||
onReply:^(NSError *socketError, NSDictionary<NSString *, id> *reply) {
|
||||
if (socketError) {
|
||||
onComplete(nil, socketError);
|
||||
return;
|
||||
}
|
||||
|
||||
NSError *jsonError;
|
||||
id result = RCTJSONParse(reply[@"result"], &jsonError);
|
||||
NSString *error = reply[@"error"];
|
||||
onComplete(result, error ? RCTErrorWithMessage(error) : jsonError);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)injectJSONText:(NSString *)script
|
||||
asGlobalObjectNamed:(NSString *)objectName
|
||||
callback:(RCTJavaScriptCompleteBlock)onComplete
|
||||
{
|
||||
dispatch_async(_jsQueue, ^{
|
||||
self->_injectedObjects[objectName] = script;
|
||||
onComplete(nil);
|
||||
});
|
||||
}
|
||||
|
||||
- (void)executeBlockOnJavaScriptQueue:(dispatch_block_t)block
|
||||
{
|
||||
RCTExecuteOnMainQueue(block);
|
||||
}
|
||||
|
||||
- (void)executeAsyncBlockOnJavaScriptQueue:(dispatch_block_t)block
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), block);
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
_socket.delegate = nil;
|
||||
[_socket closeWithCode:1000 reason:@"Invalidated"];
|
||||
_socket = nil;
|
||||
}
|
||||
|
||||
- (BOOL)isValid
|
||||
{
|
||||
return _socket != nil && _socket.readyState == RCTSR_OPEN;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
RCTAssert(!self.valid, @"-invalidate must be called before -dealloc");
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
Class RCTWebSocketExecutorCls(void)
|
||||
{
|
||||
#if RCT_DEV
|
||||
return RCTWebSocketExecutor.class;
|
||||
#else
|
||||
return nil;
|
||||
#endif
|
||||
}
|
35
node_modules/react-native/React/CoreModules/RCTWebSocketModule.h
generated
vendored
Normal file
35
node_modules/react-native/React/CoreModules/RCTWebSocketModule.h
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTEventEmitter.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol RCTWebSocketContentHandler <NSObject>
|
||||
|
||||
- (id)processWebsocketMessage:(id __nullable)message
|
||||
forSocketID:(NSNumber *)socketID
|
||||
withType:(NSString *__nonnull __autoreleasing *__nonnull)type;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTWebSocketModule : RCTEventEmitter
|
||||
|
||||
// Register a custom handler for a specific websocket. The handler will be strongly held by the WebSocketModule.
|
||||
- (void)setContentHandler:(id<RCTWebSocketContentHandler> __nullable)handler forSocketID:(NSNumber *)socketID;
|
||||
|
||||
- (void)sendData:(NSData *)data forSocketID:(nonnull NSNumber *)socketID;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridge (RCTWebSocketModule)
|
||||
|
||||
- (RCTWebSocketModule *)webSocketModule;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
213
node_modules/react-native/React/CoreModules/RCTWebSocketModule.mm
generated
vendored
Normal file
213
node_modules/react-native/React/CoreModules/RCTWebSocketModule.mm
generated
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTWebSocketModule.h>
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTSRWebSocket.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import "CoreModulesPlugins.h"
|
||||
|
||||
@implementation RCTSRWebSocket (React)
|
||||
|
||||
- (NSNumber *)reactTag
|
||||
{
|
||||
return objc_getAssociatedObject(self, _cmd);
|
||||
}
|
||||
|
||||
- (void)setReactTag:(NSNumber *)reactTag
|
||||
{
|
||||
objc_setAssociatedObject(self, @selector(reactTag), reactTag, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTWebSocketModule () <RCTSRWebSocketDelegate, NativeWebSocketModuleSpec>
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTWebSocketModule {
|
||||
NSMutableDictionary<NSNumber *, RCTSRWebSocket *> *_sockets;
|
||||
NSMutableDictionary<NSNumber *, id<RCTWebSocketContentHandler>> *_contentHandlers;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
- (NSArray *)supportedEvents
|
||||
{
|
||||
return @[ @"websocketMessage", @"websocketOpen", @"websocketFailed", @"websocketClosed" ];
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
_contentHandlers = nil;
|
||||
for (RCTSRWebSocket *socket in _sockets.allValues) {
|
||||
socket.delegate = nil;
|
||||
[socket close];
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(connect
|
||||
: (NSURL *)URL protocols
|
||||
: (NSArray *)protocols options
|
||||
: (JS::NativeWebSocketModule::SpecConnectOptions &)options socketID
|
||||
: (double)socketID)
|
||||
{
|
||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
|
||||
|
||||
// We load cookies from sharedHTTPCookieStorage (shared with XHR and
|
||||
// fetch). To get secure cookies for wss URLs, replace wss with https
|
||||
// in the URL.
|
||||
NSURLComponents *components = [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:true];
|
||||
if ([components.scheme.lowercaseString isEqualToString:@"wss"]) {
|
||||
components.scheme = @"https";
|
||||
}
|
||||
|
||||
// Load and set the cookie header.
|
||||
NSArray<NSHTTPCookie *> *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:components.URL];
|
||||
request.allHTTPHeaderFields = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
|
||||
|
||||
// Load supplied headers
|
||||
if ([options.headers() isKindOfClass:NSDictionary.class]) {
|
||||
NSDictionary *headers = (NSDictionary *)options.headers();
|
||||
[headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
|
||||
[request addValue:[RCTConvert NSString:value] forHTTPHeaderField:key];
|
||||
}];
|
||||
}
|
||||
|
||||
RCTSRWebSocket *webSocket = [[RCTSRWebSocket alloc] initWithURLRequest:request protocols:protocols];
|
||||
[webSocket setDelegateDispatchQueue:[self methodQueue]];
|
||||
webSocket.delegate = self;
|
||||
webSocket.reactTag = @(socketID);
|
||||
if (!_sockets) {
|
||||
_sockets = [NSMutableDictionary new];
|
||||
}
|
||||
_sockets[@(socketID)] = webSocket;
|
||||
[webSocket open];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(send : (NSString *)message forSocketID : (double)socketID)
|
||||
{
|
||||
[_sockets[@(socketID)] send:message];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(sendBinary : (NSString *)base64String forSocketID : (double)socketID)
|
||||
{
|
||||
[self sendData:[[NSData alloc] initWithBase64EncodedString:base64String options:0] forSocketID:@(socketID)];
|
||||
}
|
||||
|
||||
- (void)sendData:(NSData *)data forSocketID:(NSNumber *__nonnull)socketID
|
||||
{
|
||||
[_sockets[socketID] send:data];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(ping : (double)socketID)
|
||||
{
|
||||
[_sockets[@(socketID)] sendPing:NULL];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(close : (double)code reason : (NSString *)reason socketID : (double)socketID)
|
||||
{
|
||||
[_sockets[@(socketID)] closeWithCode:code reason:reason];
|
||||
[_sockets removeObjectForKey:@(socketID)];
|
||||
}
|
||||
|
||||
- (void)setContentHandler:(id<RCTWebSocketContentHandler>)handler forSocketID:(NSString *)socketID
|
||||
{
|
||||
if (!_contentHandlers) {
|
||||
_contentHandlers = [NSMutableDictionary new];
|
||||
}
|
||||
_contentHandlers[socketID] = handler;
|
||||
}
|
||||
|
||||
#pragma mark - RCTSRWebSocketDelegate methods
|
||||
|
||||
- (void)webSocket:(RCTSRWebSocket *)webSocket didReceiveMessage:(id)message
|
||||
{
|
||||
NSString *type;
|
||||
|
||||
NSNumber *socketID = [webSocket reactTag];
|
||||
id contentHandler = _contentHandlers[socketID];
|
||||
if (contentHandler) {
|
||||
message = [contentHandler processWebsocketMessage:message forSocketID:socketID withType:&type];
|
||||
} else {
|
||||
if ([message isKindOfClass:[NSData class]]) {
|
||||
type = @"binary";
|
||||
message = [message base64EncodedStringWithOptions:0];
|
||||
} else {
|
||||
type = @"text";
|
||||
}
|
||||
}
|
||||
|
||||
[self sendEventWithName:@"websocketMessage" body:@{@"data" : message, @"type" : type, @"id" : webSocket.reactTag}];
|
||||
}
|
||||
|
||||
- (void)webSocketDidOpen:(RCTSRWebSocket *)webSocket
|
||||
{
|
||||
[self sendEventWithName:@"websocketOpen"
|
||||
body:@{@"id" : webSocket.reactTag, @"protocol" : webSocket.protocol ? webSocket.protocol : @""}];
|
||||
}
|
||||
|
||||
- (void)webSocket:(RCTSRWebSocket *)webSocket didFailWithError:(NSError *)error
|
||||
{
|
||||
NSNumber *socketID = [webSocket reactTag];
|
||||
_contentHandlers[socketID] = nil;
|
||||
_sockets[socketID] = nil;
|
||||
NSDictionary *body =
|
||||
@{@"message" : error.localizedDescription ?: @"Undefined, error is nil", @"id" : socketID ?: @(-1)};
|
||||
[self sendEventWithName:@"websocketFailed" body:body];
|
||||
}
|
||||
|
||||
- (void)webSocket:(RCTSRWebSocket *)webSocket
|
||||
didCloseWithCode:(NSInteger)code
|
||||
reason:(NSString *)reason
|
||||
wasClean:(BOOL)wasClean
|
||||
{
|
||||
NSNumber *socketID = [webSocket reactTag];
|
||||
_contentHandlers[socketID] = nil;
|
||||
_sockets[socketID] = nil;
|
||||
[self sendEventWithName:@"websocketClosed"
|
||||
body:@{
|
||||
@"code" : @(code),
|
||||
@"reason" : RCTNullIfNil(reason),
|
||||
@"clean" : @(wasClean),
|
||||
@"id" : socketID
|
||||
}];
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeWebSocketModuleSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridge (RCTWebSocketModule)
|
||||
|
||||
- (RCTWebSocketModule *)webSocketModule
|
||||
{
|
||||
return [self moduleForClass:[RCTWebSocketModule class]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTWebSocketModuleCls(void)
|
||||
{
|
||||
return RCTWebSocketModule.class;
|
||||
}
|
47
node_modules/react-native/React/CoreModules/React-CoreModules.podspec
generated
vendored
Normal file
47
node_modules/react-native/React/CoreModules/React-CoreModules.podspec
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||
#
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
|
||||
require "json"
|
||||
|
||||
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json")))
|
||||
version = package['version']
|
||||
|
||||
source = { :git => 'https://github.com/facebook/react-native.git' }
|
||||
if version == '1000.0.0'
|
||||
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
||||
source[:commit] = `git rev-parse HEAD`.strip
|
||||
else
|
||||
source[:tag] = "v#{version}"
|
||||
end
|
||||
|
||||
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
||||
folly_version = '2020.01.13.00'
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "React-CoreModules"
|
||||
s.version = version
|
||||
s.summary = "-" # TODO
|
||||
s.homepage = "https://reactnative.dev/"
|
||||
s.license = package["license"]
|
||||
s.author = "Facebook, Inc. and its affiliates"
|
||||
s.platforms = { :ios => "10.0", :tvos => "10.0" }
|
||||
s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness'
|
||||
s.source = source
|
||||
s.source_files = "**/*.{c,m,mm,cpp}"
|
||||
s.header_dir = "CoreModules"
|
||||
s.pod_target_xcconfig = {
|
||||
"USE_HEADERMAP" => "YES",
|
||||
"CLANG_CXX_LANGUAGE_STANDARD" => "c++14",
|
||||
"HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/React/CoreModules\" \"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
|
||||
s.dependency "FBReactNativeSpec", version
|
||||
s.dependency "Folly", folly_version
|
||||
s.dependency "RCTTypeSafety", version
|
||||
s.dependency "React-Core/CoreModulesHeaders", version
|
||||
s.dependency "React-RCTImage", version
|
||||
s.dependency "ReactCommon/turbomodule/core", version
|
||||
s.dependency "React-jsi", version
|
||||
end
|
Reference in New Issue
Block a user