yeet
This commit is contained in:
14
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceShadowNode.cpp
generated
vendored
Normal file
14
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceShadowNode.cpp
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.
|
||||
*/
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
extern const char RCTARTSurfaceViewComponentName[] = "ARTSurfaceView";
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
27
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceShadowNode.h
generated
vendored
Normal file
27
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceShadowNode.h
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/components/view/ConcreteViewShadowNode.h>
|
||||
#include "RCTARTSurfaceViewProps.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
extern const char RCTARTSurfaceViewComponentName[];
|
||||
|
||||
/*
|
||||
* `ShadowNode` for <ARTSurfaceView> component.
|
||||
*/
|
||||
using RCTARTSurfaceShadowNode = ConcreteViewShadowNode<
|
||||
RCTARTSurfaceViewComponentName,
|
||||
RCTARTSurfaceViewProps,
|
||||
ViewEventEmitter>;
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
20
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentDescriptor.h
generated
vendored
Normal file
20
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentDescriptor.h
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/core/ConcreteComponentDescriptor.h>
|
||||
#include "RCTARTSurfaceShadowNode.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
using RCTARTSurfaceComponentDescriptor =
|
||||
ConcreteComponentDescriptor<RCTARTSurfaceShadowNode>;
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
15
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentView.h
generated
vendored
Normal file
15
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentView.h
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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/RCTViewComponentView.h>
|
||||
|
||||
/**
|
||||
* UIView class for root <ARTSurfaceView> component.
|
||||
*/
|
||||
@interface RCTARTSurfaceViewComponentView : RCTViewComponentView
|
||||
|
||||
@end
|
41
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentView.mm
generated
vendored
Normal file
41
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentView.mm
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 "RCTARTSurfaceViewComponentView.h"
|
||||
#import <react/uimanager/ComponentDescriptorProvider.h>
|
||||
#import "RCTARTSurfaceViewComponentDescriptor.h"
|
||||
|
||||
#import "FBRCTFabricComponentsPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@implementation RCTARTSurfaceViewComponentView {
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static const auto defaultProps = std::make_shared<const RCTARTSurfaceViewProps>();
|
||||
_props = defaultProps;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<RCTARTSurfaceComponentDescriptor>();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTARTSurfaceViewCls(void)
|
||||
{
|
||||
return RCTARTSurfaceViewComponentView.class;
|
||||
}
|
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewProps.cpp
generated
vendored
Normal file
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewProps.cpp
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.
|
||||
*/
|
||||
|
||||
#include "RCTARTSurfaceViewProps.h"
|
||||
|
||||
#include <react/core/propsConversions.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
RCTARTSurfaceViewProps::RCTARTSurfaceViewProps(
|
||||
const RCTARTSurfaceViewProps &sourceProps,
|
||||
const RawProps &rawProps)
|
||||
: ViewProps(sourceProps, rawProps) {}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
26
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewProps.h
generated
vendored
Normal file
26
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewProps.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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/components/view/ViewProps.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class RCTARTSurfaceViewProps final : public ViewProps {
|
||||
public:
|
||||
RCTARTSurfaceViewProps() = default;
|
||||
RCTARTSurfaceViewProps(
|
||||
const RCTARTSurfaceViewProps &sourceProps,
|
||||
const RawProps &rawProps);
|
||||
|
||||
#pragma mark - Props
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.h
generated
vendored
Normal file
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.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/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* UIView class for root <ActivityIndicator> component.
|
||||
*/
|
||||
@interface RCTActivityIndicatorViewComponentView : RCTViewComponentView
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
97
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm
generated
vendored
Normal file
97
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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 "RCTActivityIndicatorViewComponentView.h"
|
||||
|
||||
#import <react/components/rncore/ComponentDescriptors.h>
|
||||
#import <react/components/rncore/EventEmitters.h>
|
||||
#import <react/components/rncore/Props.h>
|
||||
|
||||
#import "FBRCTFabricComponentsPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
static UIActivityIndicatorViewStyle convertActivityIndicatorViewStyle(const ActivityIndicatorViewSize &size)
|
||||
{
|
||||
switch (size) {
|
||||
case ActivityIndicatorViewSize::Small:
|
||||
return UIActivityIndicatorViewStyleWhite;
|
||||
case ActivityIndicatorViewSize::Large:
|
||||
return UIActivityIndicatorViewStyleWhiteLarge;
|
||||
}
|
||||
}
|
||||
|
||||
@implementation RCTActivityIndicatorViewComponentView {
|
||||
UIActivityIndicatorView *_activityIndicatorView;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<ActivityIndicatorViewComponentDescriptor>();
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static const auto defaultProps = std::make_shared<const ActivityIndicatorViewProps>();
|
||||
_props = defaultProps;
|
||||
|
||||
_activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:self.bounds];
|
||||
_activityIndicatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
|
||||
if (defaultProps->animating) {
|
||||
[_activityIndicatorView startAnimating];
|
||||
} else {
|
||||
[_activityIndicatorView stopAnimating];
|
||||
}
|
||||
_activityIndicatorView.color = [UIColor colorWithCGColor:defaultProps->color.get()];
|
||||
_activityIndicatorView.hidesWhenStopped = defaultProps->hidesWhenStopped;
|
||||
_activityIndicatorView.activityIndicatorViewStyle = convertActivityIndicatorViewStyle(defaultProps->size);
|
||||
|
||||
[self addSubview:_activityIndicatorView];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
const auto &oldViewProps = *std::static_pointer_cast<const ActivityIndicatorViewProps>(_props);
|
||||
const auto &newViewProps = *std::static_pointer_cast<const ActivityIndicatorViewProps>(props);
|
||||
|
||||
if (oldViewProps.animating != newViewProps.animating) {
|
||||
if (newViewProps.animating) {
|
||||
[_activityIndicatorView startAnimating];
|
||||
} else {
|
||||
[_activityIndicatorView stopAnimating];
|
||||
}
|
||||
}
|
||||
|
||||
if (oldViewProps.color.get() != newViewProps.color.get()) {
|
||||
_activityIndicatorView.color = [UIColor colorWithCGColor:newViewProps.color.get()];
|
||||
}
|
||||
|
||||
// TODO: This prop should be deprecated.
|
||||
if (oldViewProps.hidesWhenStopped != newViewProps.hidesWhenStopped) {
|
||||
_activityIndicatorView.hidesWhenStopped = newViewProps.hidesWhenStopped;
|
||||
}
|
||||
|
||||
if (oldViewProps.size != newViewProps.size) {
|
||||
_activityIndicatorView.activityIndicatorViewStyle = convertActivityIndicatorViewStyle(newViewProps.size);
|
||||
}
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTActivityIndicatorViewCls(void)
|
||||
{
|
||||
return RCTActivityIndicatorViewComponentView.class;
|
||||
}
|
19
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.h
generated
vendored
Normal file
19
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.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/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* UIView class for root <Image> component.
|
||||
*/
|
||||
@interface RCTImageComponentView : RCTViewComponentView
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
204
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm
generated
vendored
Normal file
204
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* 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 "RCTImageComponentView.h"
|
||||
|
||||
#import <React/RCTImageResponseDelegate.h>
|
||||
#import <React/RCTImageResponseObserverProxy.h>
|
||||
#import <react/components/image/ImageComponentDescriptor.h>
|
||||
#import <react/components/image/ImageEventEmitter.h>
|
||||
#import <react/components/image/ImageProps.h>
|
||||
#import <react/imagemanager/ImageInstrumentation.h>
|
||||
#import <react/imagemanager/ImageRequest.h>
|
||||
#import <react/imagemanager/RCTImageInstrumentationProxy.h>
|
||||
#import <react/imagemanager/RCTImagePrimitivesConversions.h>
|
||||
|
||||
#import "RCTConversions.h"
|
||||
#import "RCTFabricComponentsPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@interface RCTImageComponentView () <RCTImageResponseDelegate>
|
||||
@end
|
||||
|
||||
@implementation RCTImageComponentView {
|
||||
UIImageView *_imageView;
|
||||
ImageShadowNode::ConcreteState::Shared _state;
|
||||
ImageResponseObserverCoordinator const *_coordinator;
|
||||
RCTImageResponseObserverProxy _imageResponseObserverProxy;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static auto const defaultProps = std::make_shared<ImageProps const>();
|
||||
_props = defaultProps;
|
||||
|
||||
_imageView = [[UIImageView alloc] initWithFrame:self.bounds];
|
||||
_imageView.clipsToBounds = YES;
|
||||
_imageView.contentMode = (UIViewContentMode)RCTResizeModeFromImageResizeMode(defaultProps->resizeMode);
|
||||
|
||||
_imageResponseObserverProxy = RCTImageResponseObserverProxy(self);
|
||||
|
||||
self.contentView = _imageView;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<ImageComponentDescriptor>();
|
||||
}
|
||||
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
auto const &oldImageProps = *std::static_pointer_cast<ImageProps const>(_props);
|
||||
auto const &newImageProps = *std::static_pointer_cast<ImageProps const>(props);
|
||||
|
||||
// `resizeMode`
|
||||
if (oldImageProps.resizeMode != newImageProps.resizeMode) {
|
||||
if (newImageProps.resizeMode == ImageResizeMode::Repeat) {
|
||||
// Repeat resize mode is handled by the UIImage. Use scale to fill
|
||||
// so the repeated image fills the UIImageView.
|
||||
_imageView.contentMode = UIViewContentModeScaleToFill;
|
||||
} else {
|
||||
_imageView.contentMode = (UIViewContentMode)RCTResizeModeFromImageResizeMode(newImageProps.resizeMode);
|
||||
}
|
||||
}
|
||||
|
||||
// `tintColor`
|
||||
if (oldImageProps.tintColor != newImageProps.tintColor) {
|
||||
_imageView.tintColor = [UIColor colorWithCGColor:newImageProps.tintColor.get()];
|
||||
}
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
}
|
||||
|
||||
- (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState
|
||||
{
|
||||
_state = std::static_pointer_cast<ImageShadowNode::ConcreteState const>(state);
|
||||
auto _oldState = std::static_pointer_cast<ImageShadowNode::ConcreteState const>(oldState);
|
||||
auto data = _state->getData();
|
||||
|
||||
// This call (setting `coordinator`) must be unconditional (at the same block as setting `State`)
|
||||
// because the setter stores a raw pointer to object that `State` owns.
|
||||
self.coordinator = &data.getImageRequest().getObserverCoordinator();
|
||||
|
||||
bool havePreviousData = _oldState && _oldState->getData().getImageSource() != ImageSource{};
|
||||
|
||||
if (!havePreviousData || data.getImageSource() != _oldState->getData().getImageSource()) {
|
||||
// Loading actually starts a little before this, but this is the first time we know
|
||||
// the image is loading and can fire an event from this component
|
||||
std::static_pointer_cast<ImageEventEmitter const>(_eventEmitter)->onLoadStart();
|
||||
|
||||
// TODO (T58941612): Tracking for visibility should be done directly on this class.
|
||||
// For now, we consolidate instrumentation logic in the image loader, so that pre-Fabric gets the same treatment.
|
||||
auto instrumentation = std::static_pointer_cast<RCTImageInstrumentationProxy const>(
|
||||
data.getImageRequest().getSharedImageInstrumentation());
|
||||
if (instrumentation) {
|
||||
instrumentation->trackNativeImageView(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setCoordinator:(ImageResponseObserverCoordinator const *)coordinator
|
||||
{
|
||||
if (_coordinator) {
|
||||
_coordinator->removeObserver(_imageResponseObserverProxy);
|
||||
}
|
||||
_coordinator = coordinator;
|
||||
if (_coordinator != nullptr) {
|
||||
_coordinator->addObserver(_imageResponseObserverProxy);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
[super prepareForRecycle];
|
||||
self.coordinator = nullptr;
|
||||
_imageView.image = nil;
|
||||
_state.reset();
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
self.coordinator = nullptr;
|
||||
}
|
||||
|
||||
#pragma mark - RCTImageResponseDelegate
|
||||
|
||||
- (void)didReceiveImage:(UIImage *)image fromObserver:(void const *)observer
|
||||
{
|
||||
if (!_eventEmitter || !_state) {
|
||||
// Notifications are delivered asynchronously and might arrive after the view is already recycled.
|
||||
// In the future, we should incorporate an `EventEmitter` into a separate object owned by `ImageRequest` or `State`.
|
||||
// See for more info: T46311063.
|
||||
return;
|
||||
}
|
||||
|
||||
std::static_pointer_cast<ImageEventEmitter const>(_eventEmitter)->onLoad();
|
||||
std::static_pointer_cast<ImageEventEmitter const>(_eventEmitter)->onLoadEnd();
|
||||
|
||||
const auto &imageProps = *std::static_pointer_cast<ImageProps const>(_props);
|
||||
|
||||
if (imageProps.tintColor) {
|
||||
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
||||
}
|
||||
|
||||
if (imageProps.resizeMode == ImageResizeMode::Repeat) {
|
||||
image = [image resizableImageWithCapInsets:RCTUIEdgeInsetsFromEdgeInsets(imageProps.capInsets)
|
||||
resizingMode:UIImageResizingModeTile];
|
||||
} else if (imageProps.capInsets != EdgeInsets()) {
|
||||
// Applying capInsets of 0 will switch the "resizingMode" of the image to "tile" which is undesired.
|
||||
image = [image resizableImageWithCapInsets:RCTUIEdgeInsetsFromEdgeInsets(imageProps.capInsets)
|
||||
resizingMode:UIImageResizingModeStretch];
|
||||
}
|
||||
|
||||
self->_imageView.image = image;
|
||||
|
||||
// Apply trilinear filtering to smooth out mis-sized images.
|
||||
self->_imageView.layer.minificationFilter = kCAFilterTrilinear;
|
||||
self->_imageView.layer.magnificationFilter = kCAFilterTrilinear;
|
||||
|
||||
auto data = _state->getData();
|
||||
auto instrumentation = std::static_pointer_cast<RCTImageInstrumentationProxy const>(
|
||||
data.getImageRequest().getSharedImageInstrumentation());
|
||||
if (instrumentation) {
|
||||
instrumentation->didSetImage();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didReceiveProgress:(float)progress fromObserver:(void const *)observer
|
||||
{
|
||||
if (!_eventEmitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::static_pointer_cast<ImageEventEmitter const>(_eventEmitter)->onProgress(progress);
|
||||
}
|
||||
|
||||
- (void)didReceiveFailureFromObserver:(void const *)observer
|
||||
{
|
||||
_imageView.image = nil;
|
||||
|
||||
if (!_eventEmitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::static_pointer_cast<ImageEventEmitter const>(_eventEmitter)->onError();
|
||||
std::static_pointer_cast<ImageEventEmitter const>(_eventEmitter)->onLoadEnd();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTImageCls(void)
|
||||
{
|
||||
return RCTImageComponentView.class;
|
||||
}
|
25
node_modules/react-native/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.h
generated
vendored
Normal file
25
node_modules/react-native/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.h
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RCTLegacyViewManagerInteropComponentView : RCTViewComponentView
|
||||
|
||||
/**
|
||||
Returns true for components that are supported by LegacyViewManagerInterop layer, false otherwise.
|
||||
*/
|
||||
+ (BOOL)isSupported:(NSString *)componentName;
|
||||
|
||||
+ (void)supportLegacyViewManagerWithName:(NSString *)componentName;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
148
node_modules/react-native/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm
generated
vendored
Normal file
148
node_modules/react-native/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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 "RCTLegacyViewManagerInteropComponentView.h"
|
||||
|
||||
#import <React/UIView+React.h>
|
||||
#import <react/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.h>
|
||||
#import <react/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.h>
|
||||
#import <react/utils/ManagedObjectWrapper.h>
|
||||
#import "RCTLegacyViewManagerInteropCoordinatorAdapter.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@implementation RCTLegacyViewManagerInteropComponentView {
|
||||
NSMutableDictionary<NSNumber *, UIView *> *_viewsToBeMounted;
|
||||
NSMutableArray<UIView *> *_viewsToBeUnmounted;
|
||||
RCTLegacyViewManagerInteropCoordinatorAdapter *_adapter;
|
||||
LegacyViewManagerInteropShadowNode::ConcreteState::Shared _state;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static const auto defaultProps = std::make_shared<const LegacyViewManagerInteropViewProps>();
|
||||
_props = defaultProps;
|
||||
_viewsToBeMounted = [NSMutableDictionary new];
|
||||
_viewsToBeUnmounted = [NSMutableArray new];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (NSMutableSet<NSString *> *)supportedViewManagers
|
||||
{
|
||||
static NSMutableSet<NSString *> *supported =
|
||||
[NSMutableSet setWithObjects:@"Picker", @"DatePicker", @"ProgressView", @"SegmentedControl", @"MaskedView", nil];
|
||||
return supported;
|
||||
}
|
||||
|
||||
+ (BOOL)isSupported:(NSString *)componentName
|
||||
{
|
||||
return [[RCTLegacyViewManagerInteropComponentView supportedViewManagers] containsObject:componentName];
|
||||
}
|
||||
|
||||
+ (void)supportLegacyViewManagerWithName:(NSString *)componentName
|
||||
{
|
||||
[[RCTLegacyViewManagerInteropComponentView supportedViewManagers] addObject:componentName];
|
||||
}
|
||||
|
||||
- (RCTLegacyViewManagerInteropCoordinator *)coordinator
|
||||
{
|
||||
if (_state != nullptr) {
|
||||
const auto &state = _state->getData();
|
||||
return unwrapManagedObject(state.coordinator);
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)componentViewName_DO_NOT_USE_THIS_IS_BROKEN
|
||||
{
|
||||
const auto &state = _state->getData();
|
||||
RCTLegacyViewManagerInteropCoordinator *coordinator = unwrapManagedObject(state.coordinator);
|
||||
return coordinator.componentViewName;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
_adapter = nil;
|
||||
[_viewsToBeMounted removeAllObjects];
|
||||
[_viewsToBeUnmounted removeAllObjects];
|
||||
_state.reset();
|
||||
[super prepareForRecycle];
|
||||
}
|
||||
|
||||
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
||||
{
|
||||
[_viewsToBeMounted setObject:childComponentView forKey:[NSNumber numberWithInteger:index]];
|
||||
}
|
||||
|
||||
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
||||
{
|
||||
[_viewsToBeUnmounted addObject:childComponentView];
|
||||
}
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<LegacyViewManagerInteropComponentDescriptor>();
|
||||
}
|
||||
|
||||
- (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState
|
||||
{
|
||||
_state = std::static_pointer_cast<LegacyViewManagerInteropShadowNode::ConcreteState const>(state);
|
||||
}
|
||||
|
||||
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask
|
||||
{
|
||||
[super finalizeUpdates:updateMask];
|
||||
|
||||
if (!_adapter) {
|
||||
_adapter = [[RCTLegacyViewManagerInteropCoordinatorAdapter alloc] initWithCoordinator:self.coordinator
|
||||
reactTag:self.tag];
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
_adapter.eventInterceptor = ^(std::string eventName, folly::dynamic event) {
|
||||
if (weakSelf) {
|
||||
__typeof(self) strongSelf = weakSelf;
|
||||
auto eventEmitter =
|
||||
std::static_pointer_cast<LegacyViewManagerInteropViewEventEmitter const>(strongSelf->_eventEmitter);
|
||||
eventEmitter->dispatchEvent(eventName, event);
|
||||
}
|
||||
};
|
||||
self.contentView = _adapter.paperView;
|
||||
}
|
||||
|
||||
for (NSNumber *key in _viewsToBeMounted) {
|
||||
[_adapter.paperView insertReactSubview:_viewsToBeMounted[key] atIndex:key.integerValue];
|
||||
}
|
||||
|
||||
[_viewsToBeMounted removeAllObjects];
|
||||
|
||||
for (UIView *view in _viewsToBeUnmounted) {
|
||||
[_adapter.paperView removeReactSubview:view];
|
||||
}
|
||||
|
||||
[_viewsToBeUnmounted removeAllObjects];
|
||||
|
||||
[_adapter.paperView didUpdateReactSubviews];
|
||||
|
||||
if (updateMask & RNComponentViewUpdateMaskProps) {
|
||||
const auto &newProps = *std::static_pointer_cast<const LegacyViewManagerInteropViewProps>(_props);
|
||||
[_adapter setProps:newProps.otherProps];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Native Commands
|
||||
|
||||
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
|
||||
{
|
||||
[_adapter handleCommand:(NSString *)commandName args:(NSArray *)args];
|
||||
}
|
||||
|
||||
@end
|
27
node_modules/react-native/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropCoordinatorAdapter.h
generated
vendored
Normal file
27
node_modules/react-native/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropCoordinatorAdapter.h
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RCTLegacyViewManagerInteropCoordinatorAdapter : NSObject
|
||||
|
||||
- (instancetype)initWithCoordinator:(RCTLegacyViewManagerInteropCoordinator *)coordinator reactTag:(NSInteger)tag;
|
||||
|
||||
@property (strong, nonatomic) UIView *paperView;
|
||||
|
||||
@property (nonatomic, copy, nullable) void (^eventInterceptor)(std::string eventName, folly::dynamic event);
|
||||
|
||||
- (void)setProps:(folly::dynamic const &)props;
|
||||
|
||||
- (void)handleCommand:(NSString *)commandName args:(NSArray *)args;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
58
node_modules/react-native/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropCoordinatorAdapter.mm
generated
vendored
Normal file
58
node_modules/react-native/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropCoordinatorAdapter.mm
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 "RCTLegacyViewManagerInteropCoordinatorAdapter.h"
|
||||
#import <React/UIView+React.h>
|
||||
|
||||
@implementation RCTLegacyViewManagerInteropCoordinatorAdapter {
|
||||
RCTLegacyViewManagerInteropCoordinator *_coordinator;
|
||||
NSInteger _tag;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoordinator:(RCTLegacyViewManagerInteropCoordinator *)coordinator reactTag:(NSInteger)tag
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_coordinator = coordinator;
|
||||
_tag = tag;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_paperView removeFromSuperview];
|
||||
[_coordinator removeObserveForTag:_tag];
|
||||
}
|
||||
|
||||
- (UIView *)paperView
|
||||
{
|
||||
if (!_paperView) {
|
||||
_paperView = _coordinator.paperView;
|
||||
_paperView.reactTag = [NSNumber numberWithInteger:_tag];
|
||||
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
[_coordinator addObserveForTag:_tag
|
||||
usingBlock:^(std::string eventName, folly::dynamic event) {
|
||||
if (weakSelf.eventInterceptor) {
|
||||
weakSelf.eventInterceptor(eventName, event);
|
||||
}
|
||||
}];
|
||||
}
|
||||
return _paperView;
|
||||
}
|
||||
|
||||
- (void)setProps:(const folly::dynamic &)props
|
||||
{
|
||||
[_coordinator setProps:props forView:self.paperView];
|
||||
}
|
||||
|
||||
- (void)handleCommand:(NSString *)commandName args:(NSArray *)args
|
||||
{
|
||||
[_coordinator handleCommand:commandName args:args reactTag:_tag];
|
||||
}
|
||||
|
||||
@end
|
22
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.h
generated
vendored
Normal file
22
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.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>
|
||||
|
||||
@protocol RCTFabricModalHostViewControllerDelegate <NSObject>
|
||||
- (void)boundsDidChange:(CGRect)newBounds;
|
||||
@end
|
||||
|
||||
@interface RCTFabricModalHostViewController : UIViewController
|
||||
|
||||
@property (nonatomic, weak) id<RCTFabricModalHostViewControllerDelegate> delegate;
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
@property (nonatomic, assign) UIInterfaceOrientationMask supportedInterfaceOrientations;
|
||||
#endif
|
||||
|
||||
@end
|
94
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm
generated
vendored
Normal file
94
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm
generated
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 "RCTFabricModalHostViewController.h"
|
||||
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTSurfaceTouchHandler.h>
|
||||
|
||||
@implementation RCTFabricModalHostViewController {
|
||||
CGRect _lastViewBounds;
|
||||
RCTSurfaceTouchHandler *_touchHandler;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (!(self = [super init])) {
|
||||
return nil;
|
||||
}
|
||||
_touchHandler = [RCTSurfaceTouchHandler new];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLayoutSubviews
|
||||
{
|
||||
[super viewDidLayoutSubviews];
|
||||
if (!CGRectEqualToRect(_lastViewBounds, self.view.bounds)) {
|
||||
[_delegate boundsDidChange:self.view.bounds];
|
||||
_lastViewBounds = self.view.bounds;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)loadView
|
||||
{
|
||||
[super loadView];
|
||||
[_touchHandler attachToView:self.view];
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle
|
||||
{
|
||||
return [RCTSharedApplication() statusBarStyle];
|
||||
}
|
||||
|
||||
- (void)viewDidDisappear:(BOOL)animated
|
||||
{
|
||||
[super viewDidDisappear:animated];
|
||||
_lastViewBounds = CGRectZero;
|
||||
}
|
||||
|
||||
- (BOOL)prefersStatusBarHidden
|
||||
{
|
||||
return [RCTSharedApplication() isStatusBarHidden];
|
||||
}
|
||||
|
||||
- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)())completion
|
||||
{
|
||||
UIView *snapshot = [self.view snapshotViewAfterScreenUpdates:NO];
|
||||
[self.view addSubview:snapshot];
|
||||
|
||||
[super dismissViewControllerAnimated:flag
|
||||
completion:^{
|
||||
[snapshot removeFromSuperview];
|
||||
if (completion) {
|
||||
completion();
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
#if RCT_DEV
|
||||
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
|
||||
{
|
||||
UIInterfaceOrientationMask appSupportedOrientationsMask =
|
||||
[RCTSharedApplication() supportedInterfaceOrientationsForWindow:[RCTSharedApplication() keyWindow]];
|
||||
if (!(_supportedInterfaceOrientations & appSupportedOrientationsMask)) {
|
||||
RCTLogError(
|
||||
@"Modal was presented with 0x%x orientations mask but the application only supports 0x%x."
|
||||
@"Add more interface orientations to your app's Info.plist to fix this."
|
||||
@"NOTE: This will crash in non-dev mode.",
|
||||
(unsigned)_supportedInterfaceOrientations,
|
||||
(unsigned)appSupportedOrientationsMask);
|
||||
return UIInterfaceOrientationMaskAll;
|
||||
}
|
||||
|
||||
return _supportedInterfaceOrientations;
|
||||
}
|
||||
#endif // RCT_DEV
|
||||
#endif // !TARGET_OS_TV
|
||||
|
||||
@end
|
15
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.h
generated
vendored
Normal file
15
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.h
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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/RCTViewComponentView.h>
|
||||
|
||||
/**
|
||||
* UIView class for root <ModalHostView> component.
|
||||
*/
|
||||
@interface RCTModalHostViewComponentView : RCTViewComponentView
|
||||
|
||||
@end
|
231
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm
generated
vendored
Normal file
231
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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 "RCTModalHostViewComponentView.h"
|
||||
|
||||
#import <React/UIView+React.h>
|
||||
#import <react/components/modal/ModalHostViewComponentDescriptor.h>
|
||||
#import <react/components/modal/ModalHostViewState.h>
|
||||
#import <react/components/rncore/EventEmitters.h>
|
||||
#import <react/components/rncore/Props.h>
|
||||
|
||||
#import "FBRCTFabricComponentsPlugins.h"
|
||||
#import "RCTConversions.h"
|
||||
#import "RCTFabricModalHostViewController.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
static UIInterfaceOrientationMask supportedOrientationsMask(ModalHostViewSupportedOrientationsMask mask)
|
||||
{
|
||||
UIInterfaceOrientationMask supportedOrientations = 0;
|
||||
|
||||
if (mask & ModalHostViewSupportedOrientations::Portrait) {
|
||||
supportedOrientations |= UIInterfaceOrientationMaskPortrait;
|
||||
}
|
||||
|
||||
if (mask & ModalHostViewSupportedOrientations::PortraitUpsideDown) {
|
||||
supportedOrientations |= UIInterfaceOrientationMaskPortraitUpsideDown;
|
||||
}
|
||||
|
||||
if (mask & ModalHostViewSupportedOrientations::Landscape) {
|
||||
supportedOrientations |= UIInterfaceOrientationMaskLandscape;
|
||||
}
|
||||
|
||||
if (mask & ModalHostViewSupportedOrientations::LandscapeLeft) {
|
||||
supportedOrientations |= UIInterfaceOrientationMaskLandscapeLeft;
|
||||
}
|
||||
|
||||
if (mask & ModalHostViewSupportedOrientations::LandscapeRight) {
|
||||
supportedOrientations |= UIInterfaceOrientationMaskLandscapeRight;
|
||||
}
|
||||
|
||||
if (supportedOrientations == 0) {
|
||||
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
|
||||
return UIInterfaceOrientationMaskAll;
|
||||
} else {
|
||||
return UIInterfaceOrientationMaskPortrait;
|
||||
}
|
||||
}
|
||||
|
||||
return supportedOrientations;
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::tuple<BOOL, UIModalTransitionStyle> animationConfiguration(ModalHostViewAnimationType const animation)
|
||||
{
|
||||
switch (animation) {
|
||||
case ModalHostViewAnimationType::None:
|
||||
return std::make_tuple(NO, UIModalTransitionStyleCoverVertical);
|
||||
case ModalHostViewAnimationType::Slide:
|
||||
return std::make_tuple(YES, UIModalTransitionStyleCoverVertical);
|
||||
case ModalHostViewAnimationType::Fade:
|
||||
return std::make_tuple(YES, UIModalTransitionStyleCrossDissolve);
|
||||
}
|
||||
}
|
||||
|
||||
static UIModalPresentationStyle presentationConfiguration(ModalHostViewProps const &props)
|
||||
{
|
||||
if (props.transparent) {
|
||||
return UIModalPresentationOverFullScreen;
|
||||
}
|
||||
switch (props.presentationStyle) {
|
||||
case ModalHostViewPresentationStyle::FullScreen:
|
||||
return UIModalPresentationFullScreen;
|
||||
case ModalHostViewPresentationStyle::PageSheet:
|
||||
return UIModalPresentationPageSheet;
|
||||
case ModalHostViewPresentationStyle::FormSheet:
|
||||
return UIModalPresentationFormSheet;
|
||||
case ModalHostViewPresentationStyle::OverFullScreen:
|
||||
return UIModalPresentationOverFullScreen;
|
||||
}
|
||||
}
|
||||
|
||||
static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(CGRect rect)
|
||||
{
|
||||
;
|
||||
auto orientation = rect.size.width < rect.size.height
|
||||
? ModalHostViewEventEmitter::OnOrientationChangeOrientation::Portrait
|
||||
: ModalHostViewEventEmitter::OnOrientationChangeOrientation::Landscape;
|
||||
return {orientation};
|
||||
}
|
||||
|
||||
@interface RCTModalHostViewComponentView () <RCTFabricModalHostViewControllerDelegate>
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTModalHostViewComponentView {
|
||||
RCTFabricModalHostViewController *_viewController;
|
||||
ModalHostViewShadowNode::ConcreteState::Shared _state;
|
||||
BOOL _shouldAnimatePresentation;
|
||||
BOOL _isPresented;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static const auto defaultProps = std::make_shared<const ModalHostViewProps>();
|
||||
_props = defaultProps;
|
||||
_shouldAnimatePresentation = YES;
|
||||
_viewController = [RCTFabricModalHostViewController new];
|
||||
_viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
|
||||
_viewController.delegate = self;
|
||||
_isPresented = NO;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)ensurePresentedOnlyIfNeeded
|
||||
{
|
||||
BOOL shouldBePresented = !_isPresented && self.window;
|
||||
if (shouldBePresented) {
|
||||
UIViewController *controller = [self reactViewController];
|
||||
_isPresented = YES;
|
||||
return [controller
|
||||
presentViewController:_viewController
|
||||
animated:_shouldAnimatePresentation
|
||||
completion:^{
|
||||
if (!self->_eventEmitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(std::dynamic_pointer_cast<ModalHostViewEventEmitter const>(self->_eventEmitter));
|
||||
auto eventEmitter = std::static_pointer_cast<ModalHostViewEventEmitter const>(self->_eventEmitter);
|
||||
eventEmitter->onShow(ModalHostViewEventEmitter::OnShow{});
|
||||
}];
|
||||
}
|
||||
|
||||
BOOL shouldBeHidden = _isPresented && !self.superview;
|
||||
if (shouldBeHidden) {
|
||||
_isPresented = NO;
|
||||
[_viewController dismissViewControllerAnimated:_shouldAnimatePresentation completion:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didMoveToWindow
|
||||
{
|
||||
[super didMoveToWindow];
|
||||
[self ensurePresentedOnlyIfNeeded];
|
||||
}
|
||||
|
||||
- (void)didMoveToSuperview
|
||||
{
|
||||
[super didMoveToSuperview];
|
||||
[self ensurePresentedOnlyIfNeeded];
|
||||
}
|
||||
|
||||
#pragma mark - RCTFabricModalHostViewControllerDelegate
|
||||
|
||||
- (void)boundsDidChange:(CGRect)newBounds
|
||||
{
|
||||
if (_eventEmitter) {
|
||||
assert(std::dynamic_pointer_cast<ModalHostViewEventEmitter const>(_eventEmitter));
|
||||
|
||||
auto eventEmitter = std::static_pointer_cast<ModalHostViewEventEmitter const>(_eventEmitter);
|
||||
eventEmitter->onOrientationChange(onOrientationChangeStruct(newBounds));
|
||||
}
|
||||
|
||||
if (_state != nullptr) {
|
||||
auto newState = ModalHostViewState{RCTSizeFromCGSize(newBounds.size)};
|
||||
_state->updateState(std::move(newState));
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<ModalHostViewComponentDescriptor>();
|
||||
}
|
||||
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
[super prepareForRecycle];
|
||||
_state.reset();
|
||||
_isPresented = NO;
|
||||
}
|
||||
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
const auto &newProps = *std::static_pointer_cast<const ModalHostViewProps>(props);
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
_viewController.supportedInterfaceOrientations = supportedOrientationsMask(newProps.supportedOrientations);
|
||||
#endif
|
||||
|
||||
std::tuple<BOOL, UIModalTransitionStyle> result = animationConfiguration(newProps.animationType);
|
||||
_shouldAnimatePresentation = std::get<0>(result);
|
||||
_viewController.modalTransitionStyle = std::get<1>(result);
|
||||
|
||||
_viewController.modalPresentationStyle = presentationConfiguration(newProps);
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
}
|
||||
|
||||
- (void)updateState:(facebook::react::State::Shared const &)state
|
||||
oldState:(facebook::react::State::Shared const &)oldState
|
||||
{
|
||||
_state = std::static_pointer_cast<const ModalHostViewShadowNode::ConcreteState>(state);
|
||||
}
|
||||
|
||||
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
||||
{
|
||||
[_viewController.view insertSubview:childComponentView atIndex:index];
|
||||
}
|
||||
|
||||
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
||||
{
|
||||
[childComponentView removeFromSuperview];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTModalHostViewCls(void)
|
||||
{
|
||||
return RCTModalHostViewComponentView.class;
|
||||
}
|
49
node_modules/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h
generated
vendored
Normal file
49
node_modules/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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: FBRCTFabricComponentsPlugins.h is autogenerated by the build system.
|
||||
#import <React/FBRCTFabricComponentsPlugins.h>
|
||||
|
||||
#else
|
||||
|
||||
// OSS-compatibility layer
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <React/RCTComponentViewProtocol.h>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wreturn-type-c-linkage"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTFabricComponentsProvider(const char *name);
|
||||
|
||||
// Lookup functions
|
||||
Class<RCTComponentViewProtocol> RCTSafeAreaViewCls(void) __attribute__((used));
|
||||
Class<RCTComponentViewProtocol> RCTScrollViewCls(void) __attribute__((used));
|
||||
Class<RCTComponentViewProtocol> RCTPullToRefreshViewCls(void) __attribute__((used));
|
||||
Class<RCTComponentViewProtocol> RCTActivityIndicatorViewCls(void) __attribute__((used));
|
||||
Class<RCTComponentViewProtocol> RCTSliderCls(void) __attribute__((used));
|
||||
Class<RCTComponentViewProtocol> RCTSwitchCls(void) __attribute__((used));
|
||||
Class<RCTComponentViewProtocol> RCTUnimplementedNativeViewCls(void) __attribute__((used));
|
||||
Class<RCTComponentViewProtocol> RCTModalHostViewCls(void) __attribute__((used));
|
||||
Class<RCTComponentViewProtocol> RCTARTSurfaceViewCls(void) __attribute__((used));
|
||||
Class<RCTComponentViewProtocol> RCTImageCls(void) __attribute__((used));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#endif // RN_DISABLE_OSS_PLUGIN_HEADER
|
41
node_modules/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm
generated
vendored
Normal file
41
node_modules/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm
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.
|
||||
*
|
||||
* @generated by an internal plugin build system
|
||||
*/
|
||||
|
||||
#ifndef RN_DISABLE_OSS_PLUGIN_HEADER
|
||||
|
||||
// OSS-compatibility layer
|
||||
|
||||
#import "RCTFabricComponentsPlugins.h"
|
||||
|
||||
#import <string>
|
||||
#import <unordered_map>
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTFabricComponentsProvider(const char *name) {
|
||||
static std::unordered_map<std::string, Class (*)(void)> sFabricComponentsClassMap = {
|
||||
{"SafeAreaView", RCTSafeAreaViewCls},
|
||||
{"ScrollView", RCTScrollViewCls},
|
||||
{"PullToRefreshView", RCTPullToRefreshViewCls},
|
||||
{"ActivityIndicatorView", RCTActivityIndicatorViewCls},
|
||||
{"Slider", RCTSliderCls},
|
||||
{"Switch", RCTSwitchCls},
|
||||
{"UnimplementedNativeView", RCTUnimplementedNativeViewCls},
|
||||
{"ModalHostView", RCTModalHostViewCls},
|
||||
{"ARTSurfaceView", RCTARTSurfaceViewCls},
|
||||
{"Image", RCTImageCls},
|
||||
};
|
||||
|
||||
auto p = sFabricComponentsClassMap.find(name);
|
||||
if (p != sFabricComponentsClassMap.end()) {
|
||||
auto classFunc = p->second;
|
||||
return classFunc();
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
#endif // RN_DISABLE_OSS_PLUGIN_HEADER
|
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.h
generated
vendored
Normal file
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.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/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* UIView class for root <View> component.
|
||||
*/
|
||||
@interface RCTRootComponentView : RCTViewComponentView
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
34
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm
generated
vendored
Normal file
34
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 "RCTRootComponentView.h"
|
||||
|
||||
#import <react/components/root/RootComponentDescriptor.h>
|
||||
#import <react/components/root/RootProps.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@implementation RCTRootComponentView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static const auto defaultProps = std::make_shared<const RootProps>();
|
||||
_props = defaultProps;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<RootComponentDescriptor>();
|
||||
}
|
||||
|
||||
@end
|
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.h
generated
vendored
Normal file
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.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/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* UIView class for root <SafeAreaView> component.
|
||||
*/
|
||||
@interface RCTSafeAreaViewComponentView : RCTViewComponentView
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
99
node_modules/react-native/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm
generated
vendored
Normal file
99
node_modules/react-native/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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 "RCTSafeAreaViewComponentView.h"
|
||||
|
||||
#import <React/RCTUtils.h>
|
||||
#import <react/components/safeareaview/SafeAreaViewComponentDescriptor.h>
|
||||
#import <react/components/safeareaview/SafeAreaViewState.h>
|
||||
#import "FBRCTFabricComponentsPlugins.h"
|
||||
#import "RCTConversions.h"
|
||||
#import "RCTFabricComponentsPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@implementation RCTSafeAreaViewComponentView {
|
||||
SafeAreaViewShadowNode::ConcreteState::Shared _state;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static auto const defaultProps = std::make_shared<SafeAreaViewProps const>();
|
||||
_props = defaultProps;
|
||||
self.clipsToBounds = YES;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (UIEdgeInsets)_safeAreaInsets
|
||||
{
|
||||
if (@available(iOS 11.0, tvOS 11.0, *)) {
|
||||
return self.safeAreaInsets;
|
||||
}
|
||||
|
||||
return UIEdgeInsetsZero;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
}
|
||||
|
||||
- (void)safeAreaInsetsDidChange
|
||||
{
|
||||
[super safeAreaInsetsDidChange];
|
||||
|
||||
[self _updateStateIfNecessary];
|
||||
}
|
||||
|
||||
- (void)_updateStateIfNecessary
|
||||
{
|
||||
if (!_state) {
|
||||
return;
|
||||
}
|
||||
|
||||
UIEdgeInsets insets = [self _safeAreaInsets];
|
||||
insets.left = RCTRoundPixelValue(insets.left);
|
||||
insets.top = RCTRoundPixelValue(insets.top);
|
||||
insets.right = RCTRoundPixelValue(insets.right);
|
||||
insets.bottom = RCTRoundPixelValue(insets.bottom);
|
||||
|
||||
auto oldPadding = _state->getData().padding;
|
||||
auto newPadding = RCTEdgeInsetsFromUIEdgeInsets(insets);
|
||||
auto threshold = 1.0 / RCTScreenScale() + 0.01; // Size of a pixel plus some small threshold.
|
||||
auto deltaPadding = newPadding - oldPadding;
|
||||
|
||||
if (std::abs(deltaPadding.left) < threshold && std::abs(deltaPadding.top) < threshold &&
|
||||
std::abs(deltaPadding.right) < threshold && std::abs(deltaPadding.bottom) < threshold) {
|
||||
return;
|
||||
}
|
||||
|
||||
_state->updateState(SafeAreaViewState{newPadding});
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
- (void)updateState:(facebook::react::State::Shared const &)state
|
||||
oldState:(facebook::react::State::Shared const &)oldState
|
||||
{
|
||||
_state = std::static_pointer_cast<SafeAreaViewShadowNode::ConcreteState const>(state);
|
||||
[self _updateStateIfNecessary];
|
||||
}
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<SafeAreaViewComponentDescriptor>();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTSafeAreaViewCls(void)
|
||||
{
|
||||
return RCTSafeAreaViewComponentView.class;
|
||||
}
|
39
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.h
generated
vendored
Normal file
39
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.h
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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/RCTGenericDelegateSplitter.h>
|
||||
#import <React/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/*
|
||||
* `UIScrollView` subclass which has some improvements and tweaks
|
||||
* which are not directly related to React Native.
|
||||
*/
|
||||
@interface RCTEnhancedScrollView : UIScrollView
|
||||
|
||||
/*
|
||||
* Returns a delegate splitter that can be used to create as many `UIScrollView` delegates as needed.
|
||||
* Use that instead of accessing `delegate` property directly.
|
||||
*
|
||||
* This class overrides the `delegate` property and wires that to the delegate splitter.
|
||||
*
|
||||
* We never know which another part of the app might introspect the view hierarchy and mess with `UIScrollView`'s
|
||||
* delegate, so we expose a fake delegate connected to the original one via the splitter to make the component as
|
||||
* resilient to other code as possible: even if something else nil the delegate, other delegates that were subscribed
|
||||
* via the splitter will continue working.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) RCTGenericDelegateSplitter<id<UIScrollViewDelegate>> *delegateSplitter;
|
||||
|
||||
@property (nonatomic, assign) BOOL pinchGestureEnabled;
|
||||
@property (nonatomic, assign) BOOL centerContent;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
73
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.mm
generated
vendored
Normal file
73
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.mm
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 "RCTEnhancedScrollView.h"
|
||||
|
||||
@implementation RCTEnhancedScrollView {
|
||||
__weak id<UIScrollViewDelegate> _publicDelegate;
|
||||
}
|
||||
|
||||
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
|
||||
{
|
||||
if ([key isEqualToString:@"delegate"]) {
|
||||
// For `delegate` property, we issue KVO notifications manually.
|
||||
// We need that to block notifications caused by setting the original `UIScrollView`s property.
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [super automaticallyNotifiesObserversForKey:key];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
// We set the default behavior to "never" so that iOS
|
||||
// doesn't do weird things to UIScrollView insets automatically
|
||||
// and keeps it as an opt-in behavior.
|
||||
self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
||||
}
|
||||
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
_delegateSplitter = [[RCTGenericDelegateSplitter alloc] initWithDelegateUpdateBlock:^(id delegate) {
|
||||
[weakSelf setPrivateDelegate:delegate];
|
||||
}];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setPrivateDelegate:(id<UIScrollViewDelegate>)delegate
|
||||
{
|
||||
[super setDelegate:delegate];
|
||||
}
|
||||
|
||||
- (id<UIScrollViewDelegate>)delegate
|
||||
{
|
||||
return _publicDelegate;
|
||||
}
|
||||
|
||||
- (void)setDelegate:(id<UIScrollViewDelegate>)delegate
|
||||
{
|
||||
if (_publicDelegate == delegate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_publicDelegate) {
|
||||
[_delegateSplitter removeDelegate:_publicDelegate];
|
||||
}
|
||||
|
||||
[self willChangeValueForKey:@"delegate"];
|
||||
_publicDelegate = delegate;
|
||||
[self didChangeValueForKey:@"delegate"];
|
||||
|
||||
if (_publicDelegate) {
|
||||
[_delegateSplitter addDelegate:_publicDelegate];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
23
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h
generated
vendored
Normal file
23
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/*
|
||||
* UIView class for root <PullToRefreshView> component.
|
||||
* This view is designed to only serve ViewController-like purpose for the actual `UIRefreshControl` view which is being
|
||||
* attached to some `UIScrollView` (not to this view).
|
||||
*/
|
||||
@interface RCTPullToRefreshViewComponentView : RCTViewComponentView
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
190
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm
generated
vendored
Normal file
190
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* 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 "RCTPullToRefreshViewComponentView.h"
|
||||
|
||||
#import <react/components/rncore/ComponentDescriptors.h>
|
||||
#import <react/components/rncore/EventEmitters.h>
|
||||
#import <react/components/rncore/Props.h>
|
||||
#import <react/components/rncore/RCTComponentViewHelpers.h>
|
||||
|
||||
#import <React/RCTConversions.h>
|
||||
#import <React/RCTRefreshableProtocol.h>
|
||||
#import <React/RCTScrollViewComponentView.h>
|
||||
|
||||
#import "FBRCTFabricComponentsPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@interface RCTPullToRefreshViewComponentView () <RCTPullToRefreshViewViewProtocol, RCTRefreshableProtocol>
|
||||
@end
|
||||
|
||||
@implementation RCTPullToRefreshViewComponentView {
|
||||
UIRefreshControl *_refreshControl;
|
||||
RCTScrollViewComponentView *_scrollViewComponentView;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
// This view is not designed to be visible, it only serves UIViewController-like purpose managing
|
||||
// attaching and detaching of a pull-to-refresh view to a scroll view.
|
||||
// The pull-to-refresh view is not a subview of this view.
|
||||
self.hidden = YES;
|
||||
|
||||
static auto const defaultProps = std::make_shared<PullToRefreshViewProps const>();
|
||||
_props = defaultProps;
|
||||
|
||||
_refreshControl = [[UIRefreshControl alloc] init];
|
||||
[_refreshControl addTarget:self
|
||||
action:@selector(handleUIControlEventValueChanged)
|
||||
forControlEvents:UIControlEventValueChanged];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<PullToRefreshViewComponentDescriptor>();
|
||||
}
|
||||
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
auto const &oldConcreteProps = *std::static_pointer_cast<PullToRefreshViewProps const>(_props);
|
||||
auto const &newConcreteProps = *std::static_pointer_cast<PullToRefreshViewProps const>(props);
|
||||
|
||||
if (newConcreteProps.refreshing != oldConcreteProps.refreshing) {
|
||||
if (newConcreteProps.refreshing) {
|
||||
[_refreshControl beginRefreshing];
|
||||
} else {
|
||||
[_refreshControl endRefreshing];
|
||||
}
|
||||
}
|
||||
|
||||
BOOL needsUpdateTitle = NO;
|
||||
|
||||
if (newConcreteProps.title != oldConcreteProps.title) {
|
||||
needsUpdateTitle = YES;
|
||||
}
|
||||
|
||||
if (newConcreteProps.titleColor != oldConcreteProps.titleColor) {
|
||||
needsUpdateTitle = YES;
|
||||
}
|
||||
|
||||
if (needsUpdateTitle) {
|
||||
[self _updateTitle];
|
||||
}
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)handleUIControlEventValueChanged
|
||||
{
|
||||
std::static_pointer_cast<PullToRefreshViewEventEmitter const>(_eventEmitter)->onRefresh({});
|
||||
}
|
||||
|
||||
- (void)_updateTitle
|
||||
{
|
||||
auto const &concreteProps = *std::static_pointer_cast<PullToRefreshViewProps const>(_props);
|
||||
|
||||
if (concreteProps.title.empty()) {
|
||||
_refreshControl.attributedTitle = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
|
||||
if (concreteProps.titleColor) {
|
||||
attributes[NSForegroundColorAttributeName] = RCTUIColorFromSharedColor(concreteProps.titleColor);
|
||||
}
|
||||
|
||||
_refreshControl.attributedTitle =
|
||||
[[NSAttributedString alloc] initWithString:RCTNSStringFromString(concreteProps.title) attributes:attributes];
|
||||
}
|
||||
|
||||
#pragma mark - Attaching & Detaching
|
||||
|
||||
- (void)didMoveToWindow
|
||||
{
|
||||
if (self.window) {
|
||||
[self _attach];
|
||||
} else {
|
||||
[self _detach];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_attach
|
||||
{
|
||||
if (_scrollViewComponentView) {
|
||||
[self _detach];
|
||||
}
|
||||
|
||||
_scrollViewComponentView = [RCTScrollViewComponentView findScrollViewComponentViewForView:self];
|
||||
if (!_scrollViewComponentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (@available(macOS 13.0, *)) {
|
||||
_scrollViewComponentView.scrollView.refreshControl = _refreshControl;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_detach
|
||||
{
|
||||
if (!_scrollViewComponentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
// iOS requires to end refreshing before unmounting.
|
||||
[_refreshControl endRefreshing];
|
||||
|
||||
if (@available(macOS 13.0, *)) {
|
||||
_scrollViewComponentView.scrollView.refreshControl = nil;
|
||||
}
|
||||
_scrollViewComponentView = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Native commands
|
||||
|
||||
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
|
||||
{
|
||||
RCTPullToRefreshViewHandleCommand(self, commandName, args);
|
||||
}
|
||||
|
||||
- (void)setNativeRefreshing:(BOOL)refreshing
|
||||
{
|
||||
if (refreshing) {
|
||||
[_refreshControl beginRefreshing];
|
||||
} else {
|
||||
[_refreshControl endRefreshing];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - RCTRefreshableProtocol
|
||||
|
||||
- (void)setRefreshing:(BOOL)refreshing
|
||||
{
|
||||
[self setNativeRefreshing:refreshing];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (NSString *)componentViewName_DO_NOT_USE_THIS_IS_BROKEN
|
||||
{
|
||||
return @"RefreshControl";
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTPullToRefreshViewCls(void)
|
||||
{
|
||||
return RCTPullToRefreshViewComponentView.class;
|
||||
}
|
60
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.h
generated
vendored
Normal file
60
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.h
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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/RCTGenericDelegateSplitter.h>
|
||||
#import <React/RCTScrollableProtocol.h>
|
||||
#import <React/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/*
|
||||
* UIView class for <ScrollView> component.
|
||||
*
|
||||
* By design, the class does not implement any logic that contradicts to the normal behavior of UIScrollView and does
|
||||
* not contain any special/custom support for things like floating headers, pull-to-refresh components,
|
||||
* keyboard-avoiding functionality and so on. All that complexity must be implemented inside those components in order
|
||||
* to keep the complexity of this component manageable.
|
||||
*/
|
||||
@interface RCTScrollViewComponentView : RCTViewComponentView
|
||||
|
||||
/*
|
||||
* Finds and returns the closet RCTScrollViewComponentView component to the given view
|
||||
*/
|
||||
+ (RCTScrollViewComponentView *_Nullable)findScrollViewComponentViewForView:(UIView *)view;
|
||||
|
||||
/*
|
||||
* Returns an actual UIScrollView that this component uses under the hood.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) UIScrollView *scrollView;
|
||||
|
||||
/*
|
||||
* Returns the subview of the scroll view that the component uses to mount all subcomponents into. That's useful to
|
||||
* separate component views from auxiliary views to be able to reliably implement pull-to-refresh- and RTL-related
|
||||
* functionality.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) UIView *containerView;
|
||||
|
||||
/*
|
||||
* Returns a delegate splitter that can be used to subscribe for UIScrollView delegate.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly)
|
||||
RCTGenericDelegateSplitter<id<UIScrollViewDelegate>> *scrollViewDelegateSplitter;
|
||||
|
||||
@end
|
||||
|
||||
/*
|
||||
* RCTScrollableProtocol is a protocol which RCTScrollViewManager uses to communicate with all kinds of `UIScrollView`s.
|
||||
* Until Fabric has own command-execution pipeline we have to support that to some extent. The implementation shouldn't
|
||||
* be perfect though because very soon we will migrate that to the new commands infra and get rid of this.
|
||||
*/
|
||||
@interface RCTScrollViewComponentView (ScrollableProtocol) <RCTScrollableProtocol>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
432
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm
generated
vendored
Normal file
432
node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,432 @@
|
||||
/*
|
||||
* 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 "RCTScrollViewComponentView.h"
|
||||
|
||||
#import <React/RCTAssert.h>
|
||||
#import <React/RCTBridge+Private.h>
|
||||
#import <React/RCTScrollEvent.h>
|
||||
|
||||
#import <react/components/scrollview/RCTComponentViewHelpers.h>
|
||||
#import <react/components/scrollview/ScrollViewComponentDescriptor.h>
|
||||
#import <react/components/scrollview/ScrollViewEventEmitter.h>
|
||||
#import <react/components/scrollview/ScrollViewProps.h>
|
||||
#import <react/components/scrollview/ScrollViewState.h>
|
||||
#import <react/graphics/Geometry.h>
|
||||
|
||||
#import "RCTConversions.h"
|
||||
#import "RCTEnhancedScrollView.h"
|
||||
#import "RCTFabricComponentsPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteger tag)
|
||||
{
|
||||
static uint16_t coalescingKey = 0;
|
||||
RCTScrollEvent *scrollEvent = [[RCTScrollEvent alloc] initWithEventName:@"onScroll"
|
||||
reactTag:[NSNumber numberWithInt:tag]
|
||||
scrollViewContentOffset:scrollView.contentOffset
|
||||
scrollViewContentInset:scrollView.contentInset
|
||||
scrollViewContentSize:scrollView.contentSize
|
||||
scrollViewFrame:scrollView.frame
|
||||
scrollViewZoomScale:scrollView.zoomScale
|
||||
userData:nil
|
||||
coalescingKey:coalescingKey];
|
||||
[[RCTBridge currentBridge].eventDispatcher sendEvent:scrollEvent];
|
||||
}
|
||||
|
||||
@interface RCTScrollViewComponentView () <UIScrollViewDelegate, RCTScrollViewProtocol, RCTScrollableProtocol>
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTScrollViewComponentView {
|
||||
ScrollViewShadowNode::ConcreteState::Shared _state;
|
||||
CGSize _contentSize;
|
||||
NSTimeInterval _lastScrollEventDispatchTime;
|
||||
NSTimeInterval _scrollEventThrottle;
|
||||
// Flag indicating whether the scrolling that is currently happening
|
||||
// is triggered by user or not.
|
||||
// This helps to only update state from `scrollViewDidScroll` in case
|
||||
// some other part of the system scrolls scroll view.
|
||||
BOOL _isUserTriggeredScrolling;
|
||||
}
|
||||
|
||||
+ (RCTScrollViewComponentView *_Nullable)findScrollViewComponentViewForView:(UIView *)view
|
||||
{
|
||||
do {
|
||||
view = view.superview;
|
||||
} while (view != nil && ![view isKindOfClass:[RCTScrollViewComponentView class]]);
|
||||
return (RCTScrollViewComponentView *)view;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static const auto defaultProps = std::make_shared<const ScrollViewProps>();
|
||||
_props = defaultProps;
|
||||
|
||||
_scrollView = [[RCTEnhancedScrollView alloc] initWithFrame:self.bounds];
|
||||
_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
_scrollView.delaysContentTouches = NO;
|
||||
_isUserTriggeredScrolling = NO;
|
||||
[self addSubview:_scrollView];
|
||||
|
||||
_containerView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[_scrollView addSubview:_containerView];
|
||||
|
||||
[self.scrollViewDelegateSplitter addDelegate:self];
|
||||
|
||||
_scrollEventThrottle = INFINITY;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
// Removing all delegates from the splitter nils the actual delegate which prevents a crash on UIScrollView
|
||||
// deallocation.
|
||||
[self.scrollViewDelegateSplitter removeAllDelegates];
|
||||
}
|
||||
|
||||
- (RCTGenericDelegateSplitter<id<UIScrollViewDelegate>> *)scrollViewDelegateSplitter
|
||||
{
|
||||
return ((RCTEnhancedScrollView *)_scrollView).delegateSplitter;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<ScrollViewComponentDescriptor>();
|
||||
}
|
||||
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
const auto &oldScrollViewProps = *std::static_pointer_cast<const ScrollViewProps>(_props);
|
||||
const auto &newScrollViewProps = *std::static_pointer_cast<const ScrollViewProps>(props);
|
||||
|
||||
#define REMAP_PROP(reactName, localName, target) \
|
||||
if (oldScrollViewProps.reactName != newScrollViewProps.reactName) { \
|
||||
target.localName = newScrollViewProps.reactName; \
|
||||
}
|
||||
|
||||
#define REMAP_VIEW_PROP(reactName, localName) REMAP_PROP(reactName, localName, self)
|
||||
#define MAP_VIEW_PROP(name) REMAP_VIEW_PROP(name, name)
|
||||
#define REMAP_SCROLL_VIEW_PROP(reactName, localName) \
|
||||
REMAP_PROP(reactName, localName, ((RCTEnhancedScrollView *)_scrollView))
|
||||
#define MAP_SCROLL_VIEW_PROP(name) REMAP_SCROLL_VIEW_PROP(name, name)
|
||||
|
||||
// FIXME: Commented props are not supported yet.
|
||||
MAP_SCROLL_VIEW_PROP(alwaysBounceHorizontal);
|
||||
MAP_SCROLL_VIEW_PROP(alwaysBounceVertical);
|
||||
MAP_SCROLL_VIEW_PROP(bounces);
|
||||
MAP_SCROLL_VIEW_PROP(bouncesZoom);
|
||||
MAP_SCROLL_VIEW_PROP(canCancelContentTouches);
|
||||
MAP_SCROLL_VIEW_PROP(centerContent);
|
||||
// MAP_SCROLL_VIEW_PROP(automaticallyAdjustContentInsets);
|
||||
MAP_SCROLL_VIEW_PROP(decelerationRate);
|
||||
MAP_SCROLL_VIEW_PROP(directionalLockEnabled);
|
||||
// MAP_SCROLL_VIEW_PROP(indicatorStyle);
|
||||
// MAP_SCROLL_VIEW_PROP(keyboardDismissMode);
|
||||
MAP_SCROLL_VIEW_PROP(maximumZoomScale);
|
||||
MAP_SCROLL_VIEW_PROP(minimumZoomScale);
|
||||
MAP_SCROLL_VIEW_PROP(scrollEnabled);
|
||||
MAP_SCROLL_VIEW_PROP(pagingEnabled);
|
||||
MAP_SCROLL_VIEW_PROP(pinchGestureEnabled);
|
||||
MAP_SCROLL_VIEW_PROP(scrollsToTop);
|
||||
MAP_SCROLL_VIEW_PROP(showsHorizontalScrollIndicator);
|
||||
MAP_SCROLL_VIEW_PROP(showsVerticalScrollIndicator);
|
||||
|
||||
if (oldScrollViewProps.scrollEventThrottle != newScrollViewProps.scrollEventThrottle) {
|
||||
// Zero means "send value only once per significant logical event".
|
||||
// Prop value is in milliseconds.
|
||||
// iOS implementation uses `NSTimeInterval` (in seconds).
|
||||
CGFloat throttleInSeconds = newScrollViewProps.scrollEventThrottle / 1000.0;
|
||||
CGFloat msPerFrame = 1.0 / 60.0;
|
||||
if (throttleInSeconds < 0) {
|
||||
_scrollEventThrottle = INFINITY;
|
||||
} else if (throttleInSeconds <= msPerFrame) {
|
||||
_scrollEventThrottle = 0;
|
||||
} else {
|
||||
_scrollEventThrottle = throttleInSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
MAP_SCROLL_VIEW_PROP(zoomScale);
|
||||
|
||||
if (oldScrollViewProps.contentInset != newScrollViewProps.contentInset) {
|
||||
_scrollView.contentInset = RCTUIEdgeInsetsFromEdgeInsets(newScrollViewProps.contentInset);
|
||||
}
|
||||
|
||||
// MAP_SCROLL_VIEW_PROP(scrollIndicatorInsets);
|
||||
// MAP_SCROLL_VIEW_PROP(snapToInterval);
|
||||
// MAP_SCROLL_VIEW_PROP(snapToAlignment);
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
}
|
||||
|
||||
- (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState
|
||||
{
|
||||
assert(std::dynamic_pointer_cast<ScrollViewShadowNode::ConcreteState const>(state));
|
||||
_state = std::static_pointer_cast<ScrollViewShadowNode::ConcreteState const>(state);
|
||||
|
||||
CGSize contentSize = RCTCGSizeFromSize(_state->getData().getContentSize());
|
||||
|
||||
if (CGSizeEqualToSize(_contentSize, contentSize)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_contentSize = contentSize;
|
||||
_containerView.frame = CGRect{CGPointZero, contentSize};
|
||||
_scrollView.contentSize = contentSize;
|
||||
}
|
||||
|
||||
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
||||
{
|
||||
[_containerView insertSubview:childComponentView atIndex:index];
|
||||
}
|
||||
|
||||
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
||||
{
|
||||
RCTAssert(childComponentView.superview == _containerView, @"Attempt to unmount improperly mounted component view.");
|
||||
[childComponentView removeFromSuperview];
|
||||
}
|
||||
|
||||
- (ScrollViewMetrics)_scrollViewMetrics
|
||||
{
|
||||
ScrollViewMetrics metrics;
|
||||
metrics.contentSize = RCTSizeFromCGSize(_scrollView.contentSize);
|
||||
metrics.contentOffset = RCTPointFromCGPoint(_scrollView.contentOffset);
|
||||
metrics.contentInset = RCTEdgeInsetsFromUIEdgeInsets(_scrollView.contentInset);
|
||||
metrics.containerSize = RCTSizeFromCGSize(_scrollView.bounds.size);
|
||||
metrics.zoomScale = _scrollView.zoomScale;
|
||||
return metrics;
|
||||
}
|
||||
|
||||
- (void)_updateStateWithContentOffset
|
||||
{
|
||||
if (!_state) {
|
||||
return;
|
||||
}
|
||||
auto contentOffset = RCTPointFromCGPoint(_scrollView.contentOffset);
|
||||
_state->updateState([contentOffset](ScrollViewShadowNode::ConcreteState::Data const &data) {
|
||||
auto newData = data;
|
||||
newData.contentOffset = contentOffset;
|
||||
return newData;
|
||||
});
|
||||
}
|
||||
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
_scrollView.contentOffset = CGPointZero;
|
||||
_state.reset();
|
||||
_isUserTriggeredScrolling = NO;
|
||||
[super prepareForRecycle];
|
||||
}
|
||||
|
||||
#pragma mark - UIScrollViewDelegate
|
||||
|
||||
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
|
||||
{
|
||||
if (!_isUserTriggeredScrolling) {
|
||||
[self _updateStateWithContentOffset];
|
||||
}
|
||||
if (!_eventEmitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSTimeInterval now = CACurrentMediaTime();
|
||||
if ((_lastScrollEventDispatchTime == 0) || (now - _lastScrollEventDispatchTime > _scrollEventThrottle)) {
|
||||
_lastScrollEventDispatchTime = now;
|
||||
std::static_pointer_cast<ScrollViewEventEmitter const>(_eventEmitter)->onScroll([self _scrollViewMetrics]);
|
||||
// Once Fabric implements proper NativeAnimationDriver, this should be removed.
|
||||
// This is just a workaround to allow animations based on onScroll event.
|
||||
RCTSendPaperScrollEvent_DEPRECATED(scrollView, self.tag);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
|
||||
{
|
||||
[self scrollViewDidScroll:scrollView];
|
||||
}
|
||||
|
||||
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
|
||||
{
|
||||
_isUserTriggeredScrolling = YES;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView
|
||||
{
|
||||
_isUserTriggeredScrolling = NO;
|
||||
[self _updateStateWithContentOffset];
|
||||
}
|
||||
|
||||
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
|
||||
{
|
||||
[self _forceDispatchNextScrollEvent];
|
||||
|
||||
if (!_eventEmitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::static_pointer_cast<ScrollViewEventEmitter const>(_eventEmitter)->onScrollBeginDrag([self _scrollViewMetrics]);
|
||||
_isUserTriggeredScrolling = YES;
|
||||
}
|
||||
|
||||
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
|
||||
{
|
||||
[self _forceDispatchNextScrollEvent];
|
||||
|
||||
if (!_eventEmitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::static_pointer_cast<ScrollViewEventEmitter const>(_eventEmitter)->onScrollEndDrag([self _scrollViewMetrics]);
|
||||
[self _updateStateWithContentOffset];
|
||||
}
|
||||
|
||||
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
|
||||
{
|
||||
[self _forceDispatchNextScrollEvent];
|
||||
|
||||
if (!_eventEmitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::static_pointer_cast<ScrollViewEventEmitter const>(_eventEmitter)
|
||||
->onMomentumScrollBegin([self _scrollViewMetrics]);
|
||||
}
|
||||
|
||||
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
|
||||
{
|
||||
[self _forceDispatchNextScrollEvent];
|
||||
|
||||
if (!_eventEmitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::static_pointer_cast<ScrollViewEventEmitter const>(_eventEmitter)->onMomentumScrollEnd([self _scrollViewMetrics]);
|
||||
[self _updateStateWithContentOffset];
|
||||
_isUserTriggeredScrolling = NO;
|
||||
}
|
||||
|
||||
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
|
||||
{
|
||||
[self _forceDispatchNextScrollEvent];
|
||||
|
||||
if (!_eventEmitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::static_pointer_cast<ScrollViewEventEmitter const>(_eventEmitter)->onMomentumScrollEnd([self _scrollViewMetrics]);
|
||||
[self _updateStateWithContentOffset];
|
||||
}
|
||||
|
||||
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view
|
||||
{
|
||||
[self _forceDispatchNextScrollEvent];
|
||||
|
||||
if (!_eventEmitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::static_pointer_cast<ScrollViewEventEmitter const>(_eventEmitter)->onScrollBeginDrag([self _scrollViewMetrics]);
|
||||
}
|
||||
|
||||
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale
|
||||
{
|
||||
[self _forceDispatchNextScrollEvent];
|
||||
|
||||
if (!_eventEmitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::static_pointer_cast<ScrollViewEventEmitter const>(_eventEmitter)->onScrollEndDrag([self _scrollViewMetrics]);
|
||||
[self _updateStateWithContentOffset];
|
||||
}
|
||||
|
||||
#pragma mark - UIScrollViewDelegate
|
||||
|
||||
- (void)_forceDispatchNextScrollEvent
|
||||
{
|
||||
_lastScrollEventDispatchTime = 0;
|
||||
}
|
||||
|
||||
#pragma mark - Native commands
|
||||
|
||||
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
|
||||
{
|
||||
RCTScrollViewHandleCommand(self, commandName, args);
|
||||
}
|
||||
|
||||
- (void)flashScrollIndicators
|
||||
{
|
||||
[_scrollView flashScrollIndicators];
|
||||
}
|
||||
|
||||
- (void)scrollTo:(double)x y:(double)y animated:(BOOL)animated
|
||||
{
|
||||
[_scrollView setContentOffset:CGPointMake(x, y) animated:animated];
|
||||
}
|
||||
|
||||
- (void)scrollToEnd:(BOOL)animated
|
||||
{
|
||||
BOOL isHorizontal = _scrollView.contentSize.width > self.frame.size.width;
|
||||
CGPoint offset;
|
||||
if (isHorizontal) {
|
||||
CGFloat offsetX = _scrollView.contentSize.width - _scrollView.bounds.size.width + _scrollView.contentInset.right;
|
||||
offset = CGPointMake(fmax(offsetX, 0), 0);
|
||||
} else {
|
||||
CGFloat offsetY = _scrollView.contentSize.height - _scrollView.bounds.size.height + _scrollView.contentInset.bottom;
|
||||
offset = CGPointMake(0, fmax(offsetY, 0));
|
||||
}
|
||||
|
||||
[_scrollView setContentOffset:offset animated:animated];
|
||||
}
|
||||
|
||||
#pragma mark - RCTScrollableProtocol
|
||||
|
||||
- (CGSize)contentSize
|
||||
{
|
||||
return _contentSize;
|
||||
}
|
||||
|
||||
- (void)scrollToOffset:(CGPoint)offset
|
||||
{
|
||||
[self _forceDispatchNextScrollEvent];
|
||||
[self scrollToOffset:offset animated:YES];
|
||||
}
|
||||
|
||||
- (void)scrollToOffset:(CGPoint)offset animated:(BOOL)animated
|
||||
{
|
||||
[self _forceDispatchNextScrollEvent];
|
||||
[self.scrollView setContentOffset:offset animated:animated];
|
||||
}
|
||||
|
||||
- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated
|
||||
{
|
||||
// Not implemented.
|
||||
}
|
||||
|
||||
- (void)addScrollListener:(NSObject<UIScrollViewDelegate> *)scrollListener
|
||||
{
|
||||
[self.scrollViewDelegateSplitter addDelegate:scrollListener];
|
||||
}
|
||||
|
||||
- (void)removeScrollListener:(NSObject<UIScrollViewDelegate> *)scrollListener
|
||||
{
|
||||
[self.scrollViewDelegateSplitter removeDelegate:scrollListener];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTScrollViewCls(void)
|
||||
{
|
||||
return RCTScrollViewComponentView.class;
|
||||
}
|
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Slider/RCTSliderComponentView.h
generated
vendored
Normal file
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Slider/RCTSliderComponentView.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/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* UIView class for root <Slider> component.
|
||||
*/
|
||||
@interface RCTSliderComponentView : RCTViewComponentView
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
350
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Slider/RCTSliderComponentView.mm
generated
vendored
Normal file
350
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Slider/RCTSliderComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,350 @@
|
||||
/*
|
||||
* 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 "RCTSliderComponentView.h"
|
||||
|
||||
#import <React/RCTImageResponseDelegate.h>
|
||||
#import <React/RCTImageResponseObserverProxy.h>
|
||||
#import <react/components/rncore/EventEmitters.h>
|
||||
#import <react/components/rncore/Props.h>
|
||||
#import <react/components/slider/SliderComponentDescriptor.h>
|
||||
|
||||
#import "FBRCTFabricComponentsPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@interface RCTSliderComponentView () <RCTImageResponseDelegate>
|
||||
@end
|
||||
|
||||
@implementation RCTSliderComponentView {
|
||||
UISlider *_sliderView;
|
||||
float _previousValue;
|
||||
|
||||
UIImage *_trackImage;
|
||||
UIImage *_minimumTrackImage;
|
||||
UIImage *_maximumTrackImage;
|
||||
UIImage *_thumbImage;
|
||||
|
||||
const ImageResponseObserverCoordinator *_trackImageCoordinator;
|
||||
const ImageResponseObserverCoordinator *_minimumTrackImageCoordinator;
|
||||
const ImageResponseObserverCoordinator *_maximumTrackImageCoordinator;
|
||||
const ImageResponseObserverCoordinator *_thumbImageCoordinator;
|
||||
|
||||
RCTImageResponseObserverProxy _trackImageResponseObserverProxy;
|
||||
RCTImageResponseObserverProxy _minimumTrackImageResponseObserverProxy;
|
||||
RCTImageResponseObserverProxy _maximumTrackImageResponseObserverProxy;
|
||||
RCTImageResponseObserverProxy _thumbImageResponseObserverProxy;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static const auto defaultProps = std::make_shared<const SliderProps>();
|
||||
_props = defaultProps;
|
||||
|
||||
_sliderView = [[UISlider alloc] initWithFrame:self.bounds];
|
||||
|
||||
[_sliderView addTarget:self action:@selector(onChange:) forControlEvents:UIControlEventValueChanged];
|
||||
[_sliderView addTarget:self
|
||||
action:@selector(sliderTouchEnd:)
|
||||
forControlEvents:(UIControlEventTouchUpInside | UIControlEventTouchUpOutside | UIControlEventTouchCancel)];
|
||||
|
||||
_sliderView.value = defaultProps->value;
|
||||
|
||||
_trackImageResponseObserverProxy = RCTImageResponseObserverProxy(self);
|
||||
_minimumTrackImageResponseObserverProxy = RCTImageResponseObserverProxy(self);
|
||||
_maximumTrackImageResponseObserverProxy = RCTImageResponseObserverProxy(self);
|
||||
_thumbImageResponseObserverProxy = RCTImageResponseObserverProxy(self);
|
||||
|
||||
self.contentView = _sliderView;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// Recycling still doesn't work 100% properly
|
||||
// TODO: T40099998 implement recycling properly for Fabric Slider component
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
[super prepareForRecycle];
|
||||
|
||||
self.trackImageCoordinator = nullptr;
|
||||
self.minimumTrackImageCoordinator = nullptr;
|
||||
self.maximumTrackImageCoordinator = nullptr;
|
||||
self.thumbImageCoordinator = nullptr;
|
||||
|
||||
// Tint colors will be taken care of when props are set again - we just
|
||||
// need to make sure that image properties are reset here
|
||||
[_sliderView setMinimumTrackImage:nil forState:UIControlStateNormal];
|
||||
[_sliderView setMaximumTrackImage:nil forState:UIControlStateNormal];
|
||||
[_sliderView setThumbImage:nil forState:UIControlStateNormal];
|
||||
|
||||
_trackImage = nil;
|
||||
_minimumTrackImage = nil;
|
||||
_maximumTrackImage = nil;
|
||||
_thumbImage = nil;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
self.trackImageCoordinator = nullptr;
|
||||
self.minimumTrackImageCoordinator = nullptr;
|
||||
self.maximumTrackImageCoordinator = nullptr;
|
||||
self.thumbImageCoordinator = nullptr;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<SliderComponentDescriptor>();
|
||||
}
|
||||
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
const auto &oldSliderProps = *std::static_pointer_cast<const SliderProps>(_props);
|
||||
const auto &newSliderProps = *std::static_pointer_cast<const SliderProps>(props);
|
||||
|
||||
// `value`
|
||||
if (oldSliderProps.value != newSliderProps.value) {
|
||||
_sliderView.value = newSliderProps.value;
|
||||
_previousValue = newSliderProps.value;
|
||||
}
|
||||
|
||||
// `minimumValue`
|
||||
if (oldSliderProps.minimumValue != newSliderProps.minimumValue) {
|
||||
_sliderView.minimumValue = newSliderProps.minimumValue;
|
||||
}
|
||||
|
||||
// `maximumValue`
|
||||
if (oldSliderProps.maximumValue != newSliderProps.maximumValue) {
|
||||
_sliderView.maximumValue = newSliderProps.maximumValue;
|
||||
}
|
||||
|
||||
// `disabled`
|
||||
if (oldSliderProps.disabled != newSliderProps.disabled) {
|
||||
_sliderView.enabled = !newSliderProps.disabled;
|
||||
}
|
||||
|
||||
// `thumbTintColor`
|
||||
if (oldSliderProps.thumbTintColor != newSliderProps.thumbTintColor) {
|
||||
_sliderView.thumbTintColor = [UIColor colorWithCGColor:newSliderProps.thumbTintColor.get()];
|
||||
}
|
||||
|
||||
// `minimumTrackTintColor`
|
||||
if (oldSliderProps.minimumTrackTintColor != newSliderProps.minimumTrackTintColor) {
|
||||
_sliderView.minimumTrackTintColor = [UIColor colorWithCGColor:newSliderProps.minimumTrackTintColor.get()];
|
||||
}
|
||||
|
||||
// `maximumTrackTintColor`
|
||||
if (oldSliderProps.maximumTrackTintColor != newSliderProps.maximumTrackTintColor) {
|
||||
_sliderView.maximumTrackTintColor = [UIColor colorWithCGColor:newSliderProps.maximumTrackTintColor.get()];
|
||||
}
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
}
|
||||
|
||||
- (void)updateState:(facebook::react::State::Shared const &)state
|
||||
oldState:(facebook::react::State::Shared const &)oldState
|
||||
{
|
||||
auto _state = std::static_pointer_cast<SliderShadowNode::ConcreteState const>(state);
|
||||
auto _oldState = std::static_pointer_cast<SliderShadowNode::ConcreteState const>(oldState);
|
||||
|
||||
auto data = _state->getData();
|
||||
|
||||
bool havePreviousData = _oldState != nullptr;
|
||||
|
||||
auto getCoordinator = [](ImageRequest const *request) -> ImageResponseObserverCoordinator const * {
|
||||
if (request) {
|
||||
return &request->getObserverCoordinator();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
if (!havePreviousData || data.getTrackImageSource() != _oldState->getData().getTrackImageSource()) {
|
||||
self.trackImageCoordinator = getCoordinator(&data.getTrackImageRequest());
|
||||
}
|
||||
|
||||
if (!havePreviousData || data.getMinimumTrackImageSource() != _oldState->getData().getMinimumTrackImageSource()) {
|
||||
self.minimumTrackImageCoordinator = getCoordinator(&data.getMinimumTrackImageRequest());
|
||||
}
|
||||
|
||||
if (!havePreviousData || data.getMaximumTrackImageSource() != _oldState->getData().getMaximumTrackImageSource()) {
|
||||
self.maximumTrackImageCoordinator = getCoordinator(&data.getMaximumTrackImageRequest());
|
||||
}
|
||||
|
||||
if (!havePreviousData || data.getThumbImageSource() != _oldState->getData().getThumbImageSource()) {
|
||||
self.thumbImageCoordinator = getCoordinator(&data.getThumbImageRequest());
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setTrackImageCoordinator:(const ImageResponseObserverCoordinator *)coordinator
|
||||
{
|
||||
if (_trackImageCoordinator) {
|
||||
_trackImageCoordinator->removeObserver(_trackImageResponseObserverProxy);
|
||||
}
|
||||
_trackImageCoordinator = coordinator;
|
||||
if (_trackImageCoordinator) {
|
||||
_trackImageCoordinator->addObserver(_trackImageResponseObserverProxy);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setMinimumTrackImageCoordinator:(const ImageResponseObserverCoordinator *)coordinator
|
||||
{
|
||||
if (_minimumTrackImageCoordinator) {
|
||||
_minimumTrackImageCoordinator->removeObserver(_minimumTrackImageResponseObserverProxy);
|
||||
}
|
||||
_minimumTrackImageCoordinator = coordinator;
|
||||
if (_minimumTrackImageCoordinator) {
|
||||
_minimumTrackImageCoordinator->addObserver(_minimumTrackImageResponseObserverProxy);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setMaximumTrackImageCoordinator:(const ImageResponseObserverCoordinator *)coordinator
|
||||
{
|
||||
if (_maximumTrackImageCoordinator) {
|
||||
_maximumTrackImageCoordinator->removeObserver(_maximumTrackImageResponseObserverProxy);
|
||||
}
|
||||
_maximumTrackImageCoordinator = coordinator;
|
||||
if (_maximumTrackImageCoordinator) {
|
||||
_maximumTrackImageCoordinator->addObserver(_maximumTrackImageResponseObserverProxy);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setThumbImageCoordinator:(const ImageResponseObserverCoordinator *)coordinator
|
||||
{
|
||||
if (_thumbImageCoordinator) {
|
||||
_thumbImageCoordinator->removeObserver(_thumbImageResponseObserverProxy);
|
||||
}
|
||||
_thumbImageCoordinator = coordinator;
|
||||
if (_thumbImageCoordinator) {
|
||||
_thumbImageCoordinator->addObserver(_thumbImageResponseObserverProxy);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setTrackImage:(UIImage *)trackImage
|
||||
{
|
||||
if ([trackImage isEqual:_trackImage]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_trackImage = trackImage;
|
||||
_minimumTrackImage = nil;
|
||||
_maximumTrackImage = nil;
|
||||
CGFloat width = trackImage.size.width / 2;
|
||||
UIImage *minimumTrackImage = [trackImage resizableImageWithCapInsets:(UIEdgeInsets){0, width, 0, width}
|
||||
resizingMode:UIImageResizingModeStretch];
|
||||
UIImage *maximumTrackImage = [trackImage resizableImageWithCapInsets:(UIEdgeInsets){0, width, 0, width}
|
||||
resizingMode:UIImageResizingModeStretch];
|
||||
[_sliderView setMinimumTrackImage:minimumTrackImage forState:UIControlStateNormal];
|
||||
[_sliderView setMaximumTrackImage:maximumTrackImage forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
- (void)setMinimumTrackImage:(UIImage *)minimumTrackImage
|
||||
{
|
||||
if ([minimumTrackImage isEqual:_minimumTrackImage] && _trackImage == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
_trackImage = nil;
|
||||
_minimumTrackImage = minimumTrackImage;
|
||||
_minimumTrackImage =
|
||||
[_minimumTrackImage resizableImageWithCapInsets:(UIEdgeInsets){0, _minimumTrackImage.size.width, 0, 0}
|
||||
resizingMode:UIImageResizingModeStretch];
|
||||
[_sliderView setMinimumTrackImage:_minimumTrackImage forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
- (void)setMaximumTrackImage:(UIImage *)maximumTrackImage
|
||||
{
|
||||
if ([maximumTrackImage isEqual:_maximumTrackImage] && _trackImage == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
_trackImage = nil;
|
||||
_maximumTrackImage = maximumTrackImage;
|
||||
_maximumTrackImage =
|
||||
[_maximumTrackImage resizableImageWithCapInsets:(UIEdgeInsets){0, 0, 0, _maximumTrackImage.size.width}
|
||||
resizingMode:UIImageResizingModeStretch];
|
||||
[_sliderView setMaximumTrackImage:_maximumTrackImage forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
- (void)setThumbImage:(UIImage *)thumbImage
|
||||
{
|
||||
if ([thumbImage isEqual:_thumbImage]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_thumbImage = thumbImage;
|
||||
[_sliderView setThumbImage:thumbImage forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
- (void)onChange:(UISlider *)sender
|
||||
{
|
||||
[self onChange:sender withContinuous:YES];
|
||||
}
|
||||
|
||||
- (void)sliderTouchEnd:(UISlider *)sender
|
||||
{
|
||||
[self onChange:sender withContinuous:NO];
|
||||
}
|
||||
|
||||
- (void)onChange:(UISlider *)sender withContinuous:(BOOL)continuous
|
||||
{
|
||||
float value = sender.value;
|
||||
|
||||
const auto &props = *std::static_pointer_cast<const SliderProps>(_props);
|
||||
|
||||
if (props.step > 0 && value <= (props.maximumValue - props.minimumValue)) {
|
||||
value = MAX(
|
||||
props.minimumValue,
|
||||
MIN(props.maximumValue, props.minimumValue + round((value - props.minimumValue) / props.step) * props.step));
|
||||
|
||||
[_sliderView setValue:value animated:YES];
|
||||
}
|
||||
|
||||
if (continuous && _previousValue != value) {
|
||||
std::dynamic_pointer_cast<const SliderEventEmitter>(_eventEmitter)
|
||||
->onValueChange(SliderEventEmitter::OnValueChange{.value = static_cast<Float>(value)});
|
||||
}
|
||||
if (!continuous) {
|
||||
std::dynamic_pointer_cast<const SliderEventEmitter>(_eventEmitter)
|
||||
->onSlidingComplete(SliderEventEmitter::OnSlidingComplete{.value = static_cast<Float>(value)});
|
||||
}
|
||||
|
||||
_previousValue = value;
|
||||
}
|
||||
|
||||
#pragma mark - RCTImageResponseDelegate
|
||||
|
||||
- (void)didReceiveImage:(UIImage *)image fromObserver:(void const *)observer
|
||||
{
|
||||
if (observer == &_trackImageResponseObserverProxy) {
|
||||
self.trackImage = image;
|
||||
} else if (observer == &_minimumTrackImageResponseObserverProxy) {
|
||||
self.minimumTrackImage = image;
|
||||
} else if (observer == &_maximumTrackImageResponseObserverProxy) {
|
||||
self.maximumTrackImage = image;
|
||||
} else if (observer == &_thumbImageResponseObserverProxy) {
|
||||
self.thumbImage = image;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didReceiveProgress:(float)progress fromObserver:(void const *)observer
|
||||
{
|
||||
}
|
||||
|
||||
- (void)didReceiveFailureFromObserver:(void const *)observer
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTSliderCls(void)
|
||||
{
|
||||
return RCTSliderComponentView.class;
|
||||
}
|
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.h
generated
vendored
Normal file
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.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/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* UIView class for root <Switch> component.
|
||||
*/
|
||||
@interface RCTSwitchComponentView : RCTViewComponentView
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
122
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm
generated
vendored
Normal file
122
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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 "RCTSwitchComponentView.h"
|
||||
|
||||
#import <react/components/rncore/ComponentDescriptors.h>
|
||||
#import <react/components/rncore/EventEmitters.h>
|
||||
#import <react/components/rncore/Props.h>
|
||||
#import <react/components/rncore/RCTComponentViewHelpers.h>
|
||||
|
||||
#import "FBRCTFabricComponentsPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@interface RCTSwitchComponentView () <RCTSwitchViewProtocol>
|
||||
@end
|
||||
|
||||
@implementation RCTSwitchComponentView {
|
||||
UISwitch *_switchView;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
_switchView = [[UISwitch alloc] initWithFrame:self.bounds];
|
||||
|
||||
[_switchView addTarget:self action:@selector(onChange:) forControlEvents:UIControlEventValueChanged];
|
||||
|
||||
self.contentView = _switchView;
|
||||
|
||||
[self setPropsToDefault];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setPropsToDefault
|
||||
{
|
||||
static const auto defaultProps = std::make_shared<const SwitchProps>();
|
||||
_props = defaultProps;
|
||||
_switchView.on = defaultProps->value;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
[super prepareForRecycle];
|
||||
[self setPropsToDefault];
|
||||
}
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<SwitchComponentDescriptor>();
|
||||
}
|
||||
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
const auto &oldSwitchProps = *std::static_pointer_cast<const SwitchProps>(_props);
|
||||
const auto &newSwitchProps = *std::static_pointer_cast<const SwitchProps>(props);
|
||||
|
||||
// `value`
|
||||
if (oldSwitchProps.value != newSwitchProps.value) {
|
||||
_switchView.on = newSwitchProps.value;
|
||||
}
|
||||
|
||||
// `disabled`
|
||||
if (oldSwitchProps.disabled != newSwitchProps.disabled) {
|
||||
_switchView.enabled = !newSwitchProps.disabled;
|
||||
}
|
||||
|
||||
// `tintColor`
|
||||
if (oldSwitchProps.tintColor != newSwitchProps.tintColor) {
|
||||
_switchView.tintColor = [UIColor colorWithCGColor:newSwitchProps.tintColor.get()];
|
||||
}
|
||||
|
||||
// `onTintColor
|
||||
if (oldSwitchProps.onTintColor != newSwitchProps.onTintColor) {
|
||||
_switchView.onTintColor = [UIColor colorWithCGColor:newSwitchProps.onTintColor.get()];
|
||||
}
|
||||
|
||||
// `thumbTintColor`
|
||||
if (oldSwitchProps.thumbTintColor != newSwitchProps.thumbTintColor) {
|
||||
_switchView.thumbTintColor = [UIColor colorWithCGColor:newSwitchProps.thumbTintColor.get()];
|
||||
}
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
}
|
||||
|
||||
- (void)onChange:(UISwitch *)sender
|
||||
{
|
||||
const auto &props = *std::static_pointer_cast<const SwitchProps>(_props);
|
||||
if (props.value == sender.on) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::dynamic_pointer_cast<const SwitchEventEmitter>(_eventEmitter)
|
||||
->onChange(SwitchEventEmitter::OnChange{.value = static_cast<bool>(sender.on)});
|
||||
}
|
||||
|
||||
#pragma mark - Native Commands
|
||||
|
||||
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
|
||||
{
|
||||
RCTSwitchHandleCommand(self, commandName, args);
|
||||
}
|
||||
|
||||
- (void)setValue:(BOOL)value
|
||||
{
|
||||
[_switchView setOn:value animated:YES];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTSwitchCls(void)
|
||||
{
|
||||
return RCTSwitchComponentView.class;
|
||||
}
|
27
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.h
generated
vendored
Normal file
27
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.h
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/*
|
||||
* UIView class for <Paragraph> component.
|
||||
*/
|
||||
@interface RCTParagraphComponentView : RCTViewComponentView
|
||||
|
||||
/*
|
||||
* Returns an `NSAttributedString` representing the content of the component.
|
||||
* To be only used by external introspection and debug tools.
|
||||
*/
|
||||
@property (nonatomic, nullable, readonly) NSAttributedString *attributedText;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
171
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm
generated
vendored
Normal file
171
node_modules/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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 "RCTParagraphComponentView.h"
|
||||
|
||||
#import <react/components/text/ParagraphComponentDescriptor.h>
|
||||
#import <react/components/text/ParagraphProps.h>
|
||||
#import <react/components/text/ParagraphState.h>
|
||||
#import <react/components/text/RawTextComponentDescriptor.h>
|
||||
#import <react/components/text/TextComponentDescriptor.h>
|
||||
#import <react/graphics/Geometry.h>
|
||||
#import <react/textlayoutmanager/RCTAttributedTextUtils.h>
|
||||
#import <react/textlayoutmanager/RCTTextLayoutManager.h>
|
||||
#import <react/textlayoutmanager/TextLayoutManager.h>
|
||||
#import <react/utils/ManagedObjectWrapper.h>
|
||||
|
||||
#import "RCTConversions.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@implementation RCTParagraphComponentView {
|
||||
ParagraphShadowNode::ConcreteState::Shared _state;
|
||||
ParagraphAttributes _paragraphAttributes;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static const auto defaultProps = std::make_shared<const ParagraphProps>();
|
||||
_props = defaultProps;
|
||||
|
||||
self.isAccessibilityElement = YES;
|
||||
self.accessibilityTraits |= UIAccessibilityTraitStaticText;
|
||||
self.opaque = NO;
|
||||
self.contentMode = UIViewContentModeRedraw;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
NSString *superDescription = [super description];
|
||||
|
||||
// Cutting the last `>` character.
|
||||
if (superDescription.length > 0 && [superDescription characterAtIndex:superDescription.length - 1] == '>') {
|
||||
superDescription = [superDescription substringToIndex:superDescription.length - 1];
|
||||
}
|
||||
|
||||
return [NSString stringWithFormat:@"%@; attributedText = %@>", superDescription, self.attributedText];
|
||||
}
|
||||
|
||||
- (NSAttributedString *_Nullable)attributedText
|
||||
{
|
||||
if (!_state) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return RCTNSAttributedStringFromAttributedString(_state->getData().attributedString);
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<ParagraphComponentDescriptor>();
|
||||
}
|
||||
|
||||
+ (std::vector<facebook::react::ComponentDescriptorProvider>)supplementalComponentDescriptorProviders
|
||||
{
|
||||
return {concreteComponentDescriptorProvider<RawTextComponentDescriptor>(),
|
||||
concreteComponentDescriptorProvider<TextComponentDescriptor>()};
|
||||
}
|
||||
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
const auto ¶graphProps = std::static_pointer_cast<const ParagraphProps>(props);
|
||||
|
||||
assert(paragraphProps);
|
||||
_paragraphAttributes = paragraphProps->paragraphAttributes;
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
}
|
||||
|
||||
- (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState
|
||||
{
|
||||
_state = std::static_pointer_cast<ParagraphShadowNode::ConcreteState const>(state);
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
[super prepareForRecycle];
|
||||
_state.reset();
|
||||
}
|
||||
|
||||
- (void)drawRect:(CGRect)rect
|
||||
{
|
||||
if (!_state) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto textLayoutManager = _state->getData().layoutManager;
|
||||
assert(textLayoutManager && "TextLayoutManager must not be `nullptr`.");
|
||||
|
||||
if (!textLayoutManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
RCTTextLayoutManager *nativeTextLayoutManager =
|
||||
(RCTTextLayoutManager *)unwrapManagedObject(textLayoutManager->getNativeTextLayoutManager());
|
||||
|
||||
CGRect frame = RCTCGRectFromRect(_layoutMetrics.getContentFrame());
|
||||
|
||||
[nativeTextLayoutManager drawAttributedString:_state->getData().attributedString
|
||||
paragraphAttributes:_paragraphAttributes
|
||||
frame:frame];
|
||||
}
|
||||
|
||||
#pragma mark - Accessibility
|
||||
|
||||
- (NSString *)accessibilityLabel
|
||||
{
|
||||
NSString *superAccessibilityLabel = RCTNSStringFromStringNilIfEmpty(_props->accessibilityLabel);
|
||||
if (superAccessibilityLabel) {
|
||||
return superAccessibilityLabel;
|
||||
}
|
||||
|
||||
if (!_state) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return RCTNSStringFromString(_state->getData().attributedString.getString());
|
||||
}
|
||||
|
||||
- (SharedTouchEventEmitter)touchEventEmitterAtPoint:(CGPoint)point
|
||||
{
|
||||
if (!_state) {
|
||||
return _eventEmitter;
|
||||
}
|
||||
|
||||
auto textLayoutManager = _state->getData().layoutManager;
|
||||
|
||||
assert(textLayoutManager && "TextLayoutManager must not be `nullptr`.");
|
||||
|
||||
if (!textLayoutManager) {
|
||||
return _eventEmitter;
|
||||
}
|
||||
|
||||
RCTTextLayoutManager *nativeTextLayoutManager =
|
||||
(RCTTextLayoutManager *)unwrapManagedObject(textLayoutManager->getNativeTextLayoutManager());
|
||||
CGRect frame = RCTCGRectFromRect(_layoutMetrics.getContentFrame());
|
||||
|
||||
auto eventEmitter = [nativeTextLayoutManager getEventEmitterWithAttributeString:_state->getData().attributedString
|
||||
paragraphAttributes:_paragraphAttributes
|
||||
frame:frame
|
||||
atPoint:point];
|
||||
|
||||
if (!eventEmitter) {
|
||||
return _eventEmitter;
|
||||
}
|
||||
|
||||
assert(std::dynamic_pointer_cast<const TouchEventEmitter>(eventEmitter));
|
||||
return std::static_pointer_cast<const TouchEventEmitter>(eventEmitter);
|
||||
}
|
||||
|
||||
@end
|
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.h
generated
vendored
Normal file
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.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/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* UIView class for <TextInput> component.
|
||||
*/
|
||||
@interface RCTTextInputComponentView : RCTViewComponentView
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
439
node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm
generated
vendored
Normal file
439
node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,439 @@
|
||||
/*
|
||||
* 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 "RCTTextInputComponentView.h"
|
||||
|
||||
#import <react/components/iostextinput/TextInputComponentDescriptor.h>
|
||||
#import <react/graphics/Geometry.h>
|
||||
#import <react/textlayoutmanager/RCTAttributedTextUtils.h>
|
||||
#import <react/textlayoutmanager/TextLayoutManager.h>
|
||||
|
||||
#import <React/RCTBackedTextInputViewProtocol.h>
|
||||
#import <React/RCTUITextField.h>
|
||||
#import <React/RCTUITextView.h>
|
||||
|
||||
#import "RCTConversions.h"
|
||||
#import "RCTTextInputNativeCommands.h"
|
||||
#import "RCTTextInputUtils.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@interface RCTTextInputComponentView () <RCTBackedTextInputDelegate, RCTTextInputViewProtocol>
|
||||
@end
|
||||
|
||||
@implementation RCTTextInputComponentView {
|
||||
TextInputShadowNode::ConcreteState::Shared _state;
|
||||
UIView<RCTBackedTextInputViewProtocol> *_backedTextInputView;
|
||||
NSUInteger _mostRecentEventCount;
|
||||
NSAttributedString *_lastStringStateWasUpdatedWith;
|
||||
|
||||
/*
|
||||
* UIKit uses either UITextField or UITextView as its UIKit element for <TextInput>. UITextField is for single line
|
||||
* entry, UITextView is for multiline entry. There is a problem with order of events when user types a character. In
|
||||
* UITextField (single line text entry), typing a character first triggers `onChange` event and then
|
||||
* onSelectionChange. In UITextView (multi line text entry), typing a character first triggers `onSelectionChange` and
|
||||
* then onChange. JavaScript depends on `onChange` to be called before `onSelectionChange`. This flag keeps state so
|
||||
* if UITextView is backing text input view, inside `-[RCTTextInputComponentView textInputDidChangeSelection]` we make
|
||||
* sure to call `onChange` before `onSelectionChange` and ignore next `-[RCTTextInputComponentView
|
||||
* textInputDidChange]` call.
|
||||
*/
|
||||
BOOL _ignoreNextTextInputCall;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static const auto defaultProps = std::make_shared<TextInputProps const>();
|
||||
_props = defaultProps;
|
||||
auto &props = *defaultProps;
|
||||
|
||||
_backedTextInputView = props.traits.multiline ? [[RCTUITextView alloc] init] : [[RCTUITextField alloc] init];
|
||||
_backedTextInputView.frame = self.bounds;
|
||||
_backedTextInputView.textInputDelegate = self;
|
||||
_ignoreNextTextInputCall = NO;
|
||||
[self addSubview:_backedTextInputView];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<TextInputComponentDescriptor>();
|
||||
}
|
||||
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
auto const &oldTextInputProps = *std::static_pointer_cast<TextInputProps const>(_props);
|
||||
auto const &newTextInputProps = *std::static_pointer_cast<TextInputProps const>(props);
|
||||
|
||||
// Traits:
|
||||
if (newTextInputProps.traits.multiline != oldTextInputProps.traits.multiline) {
|
||||
[self _setMultiline:newTextInputProps.traits.multiline];
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.autocapitalizationType != oldTextInputProps.traits.autocapitalizationType) {
|
||||
_backedTextInputView.autocapitalizationType =
|
||||
RCTUITextAutocapitalizationTypeFromAutocapitalizationType(newTextInputProps.traits.autocapitalizationType);
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.autoCorrect != oldTextInputProps.traits.autoCorrect) {
|
||||
_backedTextInputView.autocorrectionType =
|
||||
RCTUITextAutocorrectionTypeFromOptionalBool(newTextInputProps.traits.autoCorrect);
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.contextMenuHidden != oldTextInputProps.traits.contextMenuHidden) {
|
||||
_backedTextInputView.contextMenuHidden = newTextInputProps.traits.contextMenuHidden;
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.editable != oldTextInputProps.traits.editable) {
|
||||
_backedTextInputView.editable = newTextInputProps.traits.editable;
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.enablesReturnKeyAutomatically !=
|
||||
oldTextInputProps.traits.enablesReturnKeyAutomatically) {
|
||||
_backedTextInputView.enablesReturnKeyAutomatically = newTextInputProps.traits.enablesReturnKeyAutomatically;
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.keyboardAppearance != oldTextInputProps.traits.keyboardAppearance) {
|
||||
_backedTextInputView.keyboardAppearance =
|
||||
RCTUIKeyboardAppearanceFromKeyboardAppearance(newTextInputProps.traits.keyboardAppearance);
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.spellCheck != oldTextInputProps.traits.spellCheck) {
|
||||
_backedTextInputView.spellCheckingType =
|
||||
RCTUITextSpellCheckingTypeFromOptionalBool(newTextInputProps.traits.spellCheck);
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.caretHidden != oldTextInputProps.traits.caretHidden) {
|
||||
_backedTextInputView.caretHidden = newTextInputProps.traits.caretHidden;
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.clearButtonMode != oldTextInputProps.traits.clearButtonMode) {
|
||||
_backedTextInputView.clearButtonMode =
|
||||
RCTUITextFieldViewModeFromTextInputAccessoryVisibilityMode(newTextInputProps.traits.clearButtonMode);
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.scrollEnabled != oldTextInputProps.traits.scrollEnabled) {
|
||||
_backedTextInputView.scrollEnabled = newTextInputProps.traits.scrollEnabled;
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.secureTextEntry != oldTextInputProps.traits.secureTextEntry) {
|
||||
_backedTextInputView.secureTextEntry = newTextInputProps.traits.secureTextEntry;
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.keyboardType != oldTextInputProps.traits.keyboardType) {
|
||||
_backedTextInputView.keyboardType = RCTUIKeyboardTypeFromKeyboardType(newTextInputProps.traits.keyboardType);
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.returnKeyType != oldTextInputProps.traits.returnKeyType) {
|
||||
_backedTextInputView.returnKeyType = RCTUIReturnKeyTypeFromReturnKeyType(newTextInputProps.traits.returnKeyType);
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.textContentType != oldTextInputProps.traits.textContentType) {
|
||||
if (@available(iOS 10.0, *)) {
|
||||
_backedTextInputView.textContentType = RCTUITextContentTypeFromString(newTextInputProps.traits.textContentType);
|
||||
}
|
||||
}
|
||||
|
||||
if (newTextInputProps.traits.passwordRules != oldTextInputProps.traits.passwordRules) {
|
||||
if (@available(iOS 12.0, *)) {
|
||||
_backedTextInputView.passwordRules =
|
||||
RCTUITextInputPasswordRulesFromString(newTextInputProps.traits.passwordRules);
|
||||
}
|
||||
}
|
||||
|
||||
// Traits `blurOnSubmit`, `clearTextOnFocus`, and `selectTextOnFocus` were omitted intentially here
|
||||
// because they are being checked on-demand.
|
||||
|
||||
// Other props:
|
||||
if (newTextInputProps.placeholder != oldTextInputProps.placeholder) {
|
||||
_backedTextInputView.placeholder = RCTNSStringFromString(newTextInputProps.placeholder);
|
||||
}
|
||||
|
||||
if (newTextInputProps.textAttributes != oldTextInputProps.textAttributes) {
|
||||
_backedTextInputView.defaultTextAttributes =
|
||||
RCTNSTextAttributesFromTextAttributes(newTextInputProps.getEffectiveTextAttributes());
|
||||
}
|
||||
|
||||
if (newTextInputProps.selectionColor != oldTextInputProps.selectionColor) {
|
||||
_backedTextInputView.tintColor = RCTUIColorFromSharedColor(newTextInputProps.selectionColor);
|
||||
}
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
}
|
||||
|
||||
- (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState
|
||||
{
|
||||
_state = std::static_pointer_cast<TextInputShadowNode::ConcreteState const>(state);
|
||||
|
||||
if (!_state) {
|
||||
assert(false && "State is `null` for <TextInput> component.");
|
||||
_backedTextInputView.attributedText = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_mostRecentEventCount == _state->getData().mostRecentEventCount) {
|
||||
auto data = _state->getData();
|
||||
[self _setAttributedString:RCTNSAttributedStringFromAttributedStringBox(data.attributedStringBox)];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateLayoutMetrics:(LayoutMetrics const &)layoutMetrics
|
||||
oldLayoutMetrics:(LayoutMetrics const &)oldLayoutMetrics
|
||||
{
|
||||
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
|
||||
|
||||
_backedTextInputView.frame =
|
||||
UIEdgeInsetsInsetRect(self.bounds, RCTUIEdgeInsetsFromEdgeInsets(layoutMetrics.borderWidth));
|
||||
_backedTextInputView.textContainerInset =
|
||||
RCTUIEdgeInsetsFromEdgeInsets(layoutMetrics.contentInsets - layoutMetrics.borderWidth);
|
||||
}
|
||||
|
||||
- (void)_setAttributedString:(NSAttributedString *)attributedString
|
||||
{
|
||||
UITextRange *selectedRange = [_backedTextInputView selectedTextRange];
|
||||
_backedTextInputView.attributedText = attributedString;
|
||||
// Calling `[_backedTextInputView setAttributedText]` results
|
||||
// in `textInputDidChangeSelection` being called but not `textInputDidChange`.
|
||||
// For `_ignoreNextTextInputCall` to have correct value, these calls
|
||||
// need to be balanced, that's why we manually set the flag here.
|
||||
_ignoreNextTextInputCall = NO;
|
||||
if (_lastStringStateWasUpdatedWith.length == attributedString.length) {
|
||||
// Calling `[_backedTextInputView setAttributedText]` moves caret
|
||||
// to the end of text input field. This cancels any selection as well
|
||||
// as position in the text input field. In case the length of string
|
||||
// doesn't change, selection and caret position is maintained.
|
||||
[_backedTextInputView setSelectedTextRange:selectedRange notifyDelegate:NO];
|
||||
}
|
||||
_lastStringStateWasUpdatedWith = attributedString;
|
||||
}
|
||||
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
[super prepareForRecycle];
|
||||
_backedTextInputView.attributedText = [[NSAttributedString alloc] init];
|
||||
_mostRecentEventCount = 0;
|
||||
_state.reset();
|
||||
_lastStringStateWasUpdatedWith = nil;
|
||||
_ignoreNextTextInputCall = NO;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
- (void)_setMultiline:(BOOL)multiline
|
||||
{
|
||||
[_backedTextInputView removeFromSuperview];
|
||||
UIView<RCTBackedTextInputViewProtocol> *backedTextInputView =
|
||||
multiline ? [[RCTUITextView alloc] init] : [[RCTUITextField alloc] init];
|
||||
backedTextInputView.frame = _backedTextInputView.frame;
|
||||
RCTCopyBackedTextInput(_backedTextInputView, backedTextInputView);
|
||||
_backedTextInputView = backedTextInputView;
|
||||
[self addSubview:_backedTextInputView];
|
||||
}
|
||||
|
||||
#pragma mark - RCTBackedTextInputDelegate
|
||||
|
||||
- (BOOL)textInputShouldBeginEditing
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)textInputDidBeginEditing
|
||||
{
|
||||
auto const &props = *std::static_pointer_cast<TextInputProps const>(_props);
|
||||
|
||||
if (props.traits.clearTextOnFocus) {
|
||||
_backedTextInputView.attributedText = [NSAttributedString new];
|
||||
[self textInputDidChange];
|
||||
}
|
||||
|
||||
if (props.traits.selectTextOnFocus) {
|
||||
[_backedTextInputView selectAll:nil];
|
||||
[self textInputDidChangeSelection];
|
||||
}
|
||||
|
||||
if (_eventEmitter) {
|
||||
std::static_pointer_cast<TextInputEventEmitter const>(_eventEmitter)->onFocus([self _textInputMetrics]);
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)textInputShouldEndEditing
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)textInputDidEndEditing
|
||||
{
|
||||
if (_eventEmitter) {
|
||||
std::static_pointer_cast<TextInputEventEmitter const>(_eventEmitter)->onEndEditing([self _textInputMetrics]);
|
||||
std::static_pointer_cast<TextInputEventEmitter const>(_eventEmitter)->onBlur([self _textInputMetrics]);
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)textInputShouldReturn
|
||||
{
|
||||
// We send `submit` event here, in `textInputShouldReturn`
|
||||
// (not in `textInputDidReturn)`, because of semantic of the event:
|
||||
// `onSubmitEditing` is called when "Submit" button
|
||||
// (the blue key on onscreen keyboard) did pressed
|
||||
// (no connection to any specific "submitting" process).
|
||||
|
||||
if (_eventEmitter) {
|
||||
std::static_pointer_cast<TextInputEventEmitter const>(_eventEmitter)->onSubmitEditing([self _textInputMetrics]);
|
||||
}
|
||||
|
||||
auto const &props = *std::static_pointer_cast<TextInputProps const>(_props);
|
||||
return props.traits.blurOnSubmit;
|
||||
}
|
||||
|
||||
- (void)textInputDidReturn
|
||||
{
|
||||
// Does nothing.
|
||||
}
|
||||
|
||||
- (NSString *)textInputShouldChangeText:(NSString *)text inRange:(NSRange)range
|
||||
{
|
||||
if (!_backedTextInputView.textWasPasted) {
|
||||
if (_eventEmitter) {
|
||||
KeyPressMetrics keyPressMetrics;
|
||||
keyPressMetrics.text = RCTStringFromNSString(text);
|
||||
keyPressMetrics.eventCount = _mostRecentEventCount;
|
||||
std::static_pointer_cast<TextInputEventEmitter const>(_eventEmitter)->onKeyPress(keyPressMetrics);
|
||||
}
|
||||
}
|
||||
|
||||
auto const &props = *std::static_pointer_cast<TextInputProps const>(_props);
|
||||
if (props.maxLength) {
|
||||
NSInteger allowedLength = props.maxLength - _backedTextInputView.attributedText.string.length + range.length;
|
||||
|
||||
if (allowedLength <= 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return allowedLength > text.length ? text : [text substringToIndex:allowedLength];
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
- (BOOL)textInputShouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)textInputDidChange
|
||||
{
|
||||
if (_ignoreNextTextInputCall) {
|
||||
_ignoreNextTextInputCall = NO;
|
||||
return;
|
||||
}
|
||||
[self _updateState];
|
||||
|
||||
if (_eventEmitter) {
|
||||
std::static_pointer_cast<TextInputEventEmitter const>(_eventEmitter)->onChange([self _textInputMetrics]);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)textInputDidChangeSelection
|
||||
{
|
||||
auto const &props = *std::static_pointer_cast<TextInputProps const>(_props);
|
||||
if (props.traits.multiline && ![_lastStringStateWasUpdatedWith isEqual:_backedTextInputView.attributedText]) {
|
||||
[self textInputDidChange];
|
||||
_ignoreNextTextInputCall = YES;
|
||||
}
|
||||
|
||||
if (_eventEmitter) {
|
||||
std::static_pointer_cast<TextInputEventEmitter const>(_eventEmitter)->onSelectionChange([self _textInputMetrics]);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Other
|
||||
|
||||
- (TextInputMetrics)_textInputMetrics
|
||||
{
|
||||
TextInputMetrics metrics;
|
||||
metrics.text = RCTStringFromNSString(_backedTextInputView.attributedText.string);
|
||||
metrics.selectionRange = [self _selectionRange];
|
||||
metrics.eventCount = _mostRecentEventCount;
|
||||
return metrics;
|
||||
}
|
||||
|
||||
- (void)_updateState
|
||||
{
|
||||
NSAttributedString *attributedString = _backedTextInputView.attributedText;
|
||||
|
||||
if (!_state) {
|
||||
return;
|
||||
}
|
||||
auto data = _state->getData();
|
||||
_lastStringStateWasUpdatedWith = attributedString;
|
||||
data.attributedStringBox = RCTAttributedStringBoxFromNSAttributedString(attributedString);
|
||||
_mostRecentEventCount += 1;
|
||||
data.mostRecentEventCount = _mostRecentEventCount;
|
||||
_state->updateState(std::move(data));
|
||||
}
|
||||
|
||||
- (AttributedString::Range)_selectionRange
|
||||
{
|
||||
UITextRange *selectedTextRange = _backedTextInputView.selectedTextRange;
|
||||
NSInteger start = [_backedTextInputView offsetFromPosition:_backedTextInputView.beginningOfDocument
|
||||
toPosition:selectedTextRange.start];
|
||||
NSInteger end = [_backedTextInputView offsetFromPosition:_backedTextInputView.beginningOfDocument
|
||||
toPosition:selectedTextRange.end];
|
||||
return AttributedString::Range{(int)start, (int)(end - start)};
|
||||
}
|
||||
|
||||
#pragma mark - Native Commands
|
||||
|
||||
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
|
||||
{
|
||||
RCTTextInputHandleCommand(self, commandName, args);
|
||||
}
|
||||
|
||||
- (void)focus
|
||||
{
|
||||
[_backedTextInputView becomeFirstResponder];
|
||||
}
|
||||
|
||||
- (void)blur
|
||||
{
|
||||
[_backedTextInputView resignFirstResponder];
|
||||
}
|
||||
|
||||
- (void)setTextAndSelection:(NSInteger)eventCount
|
||||
value:(NSString *__nullable)value
|
||||
start:(NSInteger)start
|
||||
end:(NSInteger)end
|
||||
{
|
||||
if (_mostRecentEventCount != eventCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
NSMutableAttributedString *mutableString =
|
||||
[[NSMutableAttributedString alloc] initWithAttributedString:_backedTextInputView.attributedText];
|
||||
[mutableString replaceCharactersInRange:NSMakeRange(0, _backedTextInputView.attributedText.length)
|
||||
withString:value];
|
||||
[self _setAttributedString:mutableString];
|
||||
[self _updateState];
|
||||
}
|
||||
|
||||
UITextPosition *startPosition = [_backedTextInputView positionFromPosition:_backedTextInputView.beginningOfDocument
|
||||
offset:start];
|
||||
UITextPosition *endPosition = [_backedTextInputView positionFromPosition:_backedTextInputView.beginningOfDocument
|
||||
offset:end];
|
||||
|
||||
if (startPosition && endPosition) {
|
||||
UITextRange *range = [_backedTextInputView textRangeFromPosition:startPosition toPosition:endPosition];
|
||||
[_backedTextInputView setSelectedTextRange:range notifyDelegate:NO];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
104
node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputNativeCommands.h
generated
vendored
Normal file
104
node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputNativeCommands.h
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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/RCTDefines.h>
|
||||
#import <React/RCTLog.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol RCTTextInputViewProtocol <NSObject>
|
||||
- (void)focus;
|
||||
- (void)blur;
|
||||
- (void)setTextAndSelection:(NSInteger)eventCount
|
||||
value:(NSString *__nullable)value
|
||||
start:(NSInteger)start
|
||||
end:(NSInteger)end;
|
||||
@end
|
||||
|
||||
RCT_EXTERN inline void
|
||||
RCTTextInputHandleCommand(id<RCTTextInputViewProtocol> componentView, NSString const *commandName, NSArray const *args)
|
||||
{
|
||||
if ([commandName isEqualToString:@"focus"]) {
|
||||
#if RCT_DEBUG
|
||||
if ([args count] != 0) {
|
||||
RCTLogError(
|
||||
@"%@ command %@ received %d arguments, expected %d.", @"TextInput", commandName, (int)[args count], 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
[componentView focus];
|
||||
return;
|
||||
}
|
||||
|
||||
if ([commandName isEqualToString:@"blur"]) {
|
||||
#if RCT_DEBUG
|
||||
if ([args count] != 0) {
|
||||
RCTLogError(
|
||||
@"%@ command %@ received %d arguments, expected %d.", @"TextInput", commandName, (int)[args count], 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
[componentView blur];
|
||||
return;
|
||||
}
|
||||
|
||||
if ([commandName isEqualToString:@"setTextAndSelection"]) {
|
||||
#if RCT_DEBUG
|
||||
if ([args count] != 4) {
|
||||
RCTLogError(
|
||||
@"%@ command %@ received %d arguments, expected %d.", @"TextInput", commandName, (int)[args count], 4);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
NSObject *arg0 = args[0];
|
||||
#if RCT_DEBUG
|
||||
if (!RCTValidateTypeOfViewCommandArgument(arg0, [NSNumber class], @"number", @"TextInput", commandName, @"1st")) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
NSInteger eventCount = [(NSNumber *)arg0 intValue];
|
||||
|
||||
NSObject *arg1 = args[1];
|
||||
#if RCT_DEBUG
|
||||
if (![arg1 isKindOfClass:[NSNull class]] &&
|
||||
!RCTValidateTypeOfViewCommandArgument(arg1, [NSString class], @"string", @"TextInput", commandName, @"2nd")) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
NSString *value = [arg1 isKindOfClass:[NSNull class]] ? nil : (NSString *)arg1;
|
||||
|
||||
NSObject *arg2 = args[2];
|
||||
#if RCT_DEBUG
|
||||
if (!RCTValidateTypeOfViewCommandArgument(arg2, [NSNumber class], @"number", @"TextInput", commandName, @"3rd")) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
NSInteger start = [(NSNumber *)arg2 intValue];
|
||||
|
||||
NSObject *arg3 = args[3];
|
||||
#if RCT_DEBUG
|
||||
if (!RCTValidateTypeOfViewCommandArgument(arg3, [NSNumber class], @"number", @"TextInput", commandName, @"4th")) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
NSInteger end = [(NSNumber *)arg3 intValue];
|
||||
|
||||
[componentView setTextAndSelection:eventCount value:value start:start end:end];
|
||||
return;
|
||||
}
|
||||
|
||||
#if RCT_DEBUG
|
||||
RCTLogError(@"%@ received command %@, which is not a supported command.", @"TextInput", commandName);
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
43
node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.h
generated
vendored
Normal file
43
node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.h
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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/RCTBackedTextInputViewProtocol.h>
|
||||
#import <better/optional.h>
|
||||
#import <react/components/iostextinput/primitives.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
void RCTCopyBackedTextInput(
|
||||
UIView<RCTBackedTextInputViewProtocol> *fromTextInput,
|
||||
UIView<RCTBackedTextInputViewProtocol> *toTextInput);
|
||||
|
||||
UITextAutocorrectionType RCTUITextAutocorrectionTypeFromOptionalBool(facebook::better::optional<bool> autoCorrect);
|
||||
|
||||
UITextAutocapitalizationType RCTUITextAutocapitalizationTypeFromAutocapitalizationType(
|
||||
facebook::react::AutocapitalizationType autocapitalizationType);
|
||||
|
||||
UIKeyboardAppearance RCTUIKeyboardAppearanceFromKeyboardAppearance(
|
||||
facebook::react::KeyboardAppearance keyboardAppearance);
|
||||
|
||||
UITextSpellCheckingType RCTUITextSpellCheckingTypeFromOptionalBool(facebook::better::optional<bool> spellCheck);
|
||||
|
||||
UITextFieldViewMode RCTUITextFieldViewModeFromTextInputAccessoryVisibilityMode(
|
||||
facebook::react::TextInputAccessoryVisibilityMode mode);
|
||||
|
||||
UIKeyboardType RCTUIKeyboardTypeFromKeyboardType(facebook::react::KeyboardType keyboardType);
|
||||
|
||||
UIReturnKeyType RCTUIReturnKeyTypeFromReturnKeyType(facebook::react::ReturnKeyType returnKeyType);
|
||||
|
||||
API_AVAILABLE(ios(10.0))
|
||||
UITextContentType RCTUITextContentTypeFromString(std::string const &contentType);
|
||||
|
||||
API_AVAILABLE(ios(12.0))
|
||||
UITextInputPasswordRules *RCTUITextInputPasswordRulesFromString(std::string const &passwordRules);
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
198
node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm
generated
vendored
Normal file
198
node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm
generated
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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 "RCTTextInputUtils.h"
|
||||
|
||||
#import <React/RCTConversions.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
static NSAttributedString *RCTSanitizeAttributedString(NSAttributedString *attributedString)
|
||||
{
|
||||
// Here we need to remove text attributes specific to particular kind of TextInput on iOS (e.g. limiting line number).
|
||||
// TODO: Implement it properly.
|
||||
return [[NSAttributedString alloc] initWithString:attributedString.string];
|
||||
}
|
||||
|
||||
void RCTCopyBackedTextInput(
|
||||
UIView<RCTBackedTextInputViewProtocol> *fromTextInput,
|
||||
UIView<RCTBackedTextInputViewProtocol> *toTextInput)
|
||||
{
|
||||
toTextInput.attributedText = RCTSanitizeAttributedString(fromTextInput.attributedText);
|
||||
toTextInput.placeholder = fromTextInput.placeholder;
|
||||
toTextInput.placeholderColor = fromTextInput.placeholderColor;
|
||||
toTextInput.textContainerInset = fromTextInput.textContainerInset;
|
||||
toTextInput.inputAccessoryView = fromTextInput.inputAccessoryView;
|
||||
toTextInput.textInputDelegate = fromTextInput.textInputDelegate;
|
||||
toTextInput.placeholderColor = fromTextInput.placeholderColor;
|
||||
toTextInput.defaultTextAttributes = fromTextInput.defaultTextAttributes;
|
||||
toTextInput.autocapitalizationType = fromTextInput.autocapitalizationType;
|
||||
toTextInput.autocorrectionType = fromTextInput.autocorrectionType;
|
||||
toTextInput.contextMenuHidden = fromTextInput.contextMenuHidden;
|
||||
toTextInput.editable = fromTextInput.editable;
|
||||
toTextInput.enablesReturnKeyAutomatically = fromTextInput.enablesReturnKeyAutomatically;
|
||||
toTextInput.keyboardAppearance = fromTextInput.keyboardAppearance;
|
||||
toTextInput.spellCheckingType = fromTextInput.spellCheckingType;
|
||||
toTextInput.caretHidden = fromTextInput.caretHidden;
|
||||
toTextInput.clearButtonMode = fromTextInput.clearButtonMode;
|
||||
toTextInput.scrollEnabled = fromTextInput.scrollEnabled;
|
||||
toTextInput.secureTextEntry = fromTextInput.secureTextEntry;
|
||||
toTextInput.keyboardType = fromTextInput.keyboardType;
|
||||
|
||||
if (@available(iOS 10.0, *)) {
|
||||
toTextInput.textContentType = fromTextInput.textContentType;
|
||||
}
|
||||
|
||||
if (@available(iOS 12.0, *)) {
|
||||
toTextInput.passwordRules = fromTextInput.passwordRules;
|
||||
}
|
||||
|
||||
[toTextInput setSelectedTextRange:fromTextInput.selectedTextRange notifyDelegate:NO];
|
||||
}
|
||||
|
||||
UITextAutocorrectionType RCTUITextAutocorrectionTypeFromOptionalBool(facebook::better::optional<bool> autoCorrect)
|
||||
{
|
||||
return autoCorrect.has_value() ? (*autoCorrect ? UITextAutocorrectionTypeYes : UITextAutocorrectionTypeNo)
|
||||
: UITextAutocorrectionTypeDefault;
|
||||
}
|
||||
|
||||
UITextAutocapitalizationType RCTUITextAutocapitalizationTypeFromAutocapitalizationType(
|
||||
AutocapitalizationType autocapitalizationType)
|
||||
{
|
||||
switch (autocapitalizationType) {
|
||||
case AutocapitalizationType::None:
|
||||
return UITextAutocapitalizationTypeNone;
|
||||
case AutocapitalizationType::Words:
|
||||
return UITextAutocapitalizationTypeWords;
|
||||
case AutocapitalizationType::Sentences:
|
||||
return UITextAutocapitalizationTypeSentences;
|
||||
case AutocapitalizationType::Characters:
|
||||
return UITextAutocapitalizationTypeAllCharacters;
|
||||
}
|
||||
}
|
||||
|
||||
UIKeyboardAppearance RCTUIKeyboardAppearanceFromKeyboardAppearance(KeyboardAppearance keyboardAppearance)
|
||||
{
|
||||
switch (keyboardAppearance) {
|
||||
case KeyboardAppearance::Default:
|
||||
return UIKeyboardAppearanceDefault;
|
||||
case KeyboardAppearance::Light:
|
||||
return UIKeyboardAppearanceLight;
|
||||
case KeyboardAppearance::Dark:
|
||||
return UIKeyboardAppearanceDark;
|
||||
}
|
||||
}
|
||||
|
||||
UITextSpellCheckingType RCTUITextSpellCheckingTypeFromOptionalBool(facebook::better::optional<bool> spellCheck)
|
||||
{
|
||||
return spellCheck.has_value() ? (*spellCheck ? UITextSpellCheckingTypeYes : UITextSpellCheckingTypeNo)
|
||||
: UITextSpellCheckingTypeDefault;
|
||||
}
|
||||
|
||||
UITextFieldViewMode RCTUITextFieldViewModeFromTextInputAccessoryVisibilityMode(
|
||||
facebook::react::TextInputAccessoryVisibilityMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case TextInputAccessoryVisibilityMode::Never:
|
||||
return UITextFieldViewModeNever;
|
||||
case TextInputAccessoryVisibilityMode::WhileEditing:
|
||||
return UITextFieldViewModeWhileEditing;
|
||||
case TextInputAccessoryVisibilityMode::UnlessEditing:
|
||||
return UITextFieldViewModeUnlessEditing;
|
||||
case TextInputAccessoryVisibilityMode::Always:
|
||||
return UITextFieldViewModeAlways;
|
||||
}
|
||||
}
|
||||
|
||||
UIKeyboardType RCTUIKeyboardTypeFromKeyboardType(KeyboardType keyboardType)
|
||||
{
|
||||
switch (keyboardType) {
|
||||
// Universal
|
||||
case KeyboardType::Default:
|
||||
return UIKeyboardTypeDefault;
|
||||
case KeyboardType::EmailAddress:
|
||||
return UIKeyboardTypeEmailAddress;
|
||||
case KeyboardType::Numeric:
|
||||
return UIKeyboardTypeDecimalPad;
|
||||
case KeyboardType::PhonePad:
|
||||
return UIKeyboardTypePhonePad;
|
||||
case KeyboardType::NumberPad:
|
||||
return UIKeyboardTypeNumberPad;
|
||||
case KeyboardType::DecimalPad:
|
||||
return UIKeyboardTypeDecimalPad;
|
||||
// iOS-only
|
||||
case KeyboardType::ASCIICapable:
|
||||
return UIKeyboardTypeASCIICapable;
|
||||
case KeyboardType::NumbersAndPunctuation:
|
||||
return UIKeyboardTypeNumbersAndPunctuation;
|
||||
case KeyboardType::URL:
|
||||
return UIKeyboardTypeURL;
|
||||
case KeyboardType::NamePhonePad:
|
||||
return UIKeyboardTypeNamePhonePad;
|
||||
case KeyboardType::Twitter:
|
||||
return UIKeyboardTypeTwitter;
|
||||
case KeyboardType::WebSearch:
|
||||
return UIKeyboardTypeWebSearch;
|
||||
case KeyboardType::ASCIICapableNumberPad:
|
||||
if (@available(iOS 10.0, *)) {
|
||||
return UIKeyboardTypeASCIICapableNumberPad;
|
||||
} else {
|
||||
return UIKeyboardTypeNumberPad;
|
||||
}
|
||||
// Android-only
|
||||
case KeyboardType::VisiblePassword:
|
||||
return UIKeyboardTypeDefault;
|
||||
}
|
||||
}
|
||||
|
||||
UIReturnKeyType RCTUIReturnKeyTypeFromReturnKeyType(ReturnKeyType returnKeyType)
|
||||
{
|
||||
switch (returnKeyType) {
|
||||
case ReturnKeyType::Default:
|
||||
return UIReturnKeyDefault;
|
||||
case ReturnKeyType::Done:
|
||||
return UIReturnKeyDone;
|
||||
case ReturnKeyType::Go:
|
||||
return UIReturnKeyGo;
|
||||
case ReturnKeyType::Next:
|
||||
return UIReturnKeyNext;
|
||||
case ReturnKeyType::Search:
|
||||
return UIReturnKeySearch;
|
||||
case ReturnKeyType::Send:
|
||||
return UIReturnKeySend;
|
||||
// iOS-only
|
||||
case ReturnKeyType::EmergencyCall:
|
||||
return UIReturnKeyEmergencyCall;
|
||||
case ReturnKeyType::Google:
|
||||
return UIReturnKeyGoogle;
|
||||
case ReturnKeyType::Join:
|
||||
return UIReturnKeyJoin;
|
||||
case ReturnKeyType::Route:
|
||||
return UIReturnKeyRoute;
|
||||
case ReturnKeyType::Yahoo:
|
||||
return UIReturnKeyYahoo;
|
||||
case ReturnKeyType::Continue:
|
||||
return UIReturnKeyContinue;
|
||||
// Android-only
|
||||
case ReturnKeyType::None:
|
||||
case ReturnKeyType::Previous:
|
||||
return UIReturnKeyDefault;
|
||||
}
|
||||
}
|
||||
|
||||
API_AVAILABLE(ios(10.0))
|
||||
UITextContentType RCTUITextContentTypeFromString(std::string const &contentType)
|
||||
{
|
||||
// TODO: Implement properly (T26519801).
|
||||
return RCTNSStringFromStringNilIfEmpty(contentType);
|
||||
}
|
||||
|
||||
API_AVAILABLE(ios(12.0))
|
||||
UITextInputPasswordRules *RCTUITextInputPasswordRulesFromString(std::string const &passwordRules)
|
||||
{
|
||||
return [UITextInputPasswordRules passwordRulesWithDescriptor:RCTNSStringFromStringNilIfEmpty(passwordRules)];
|
||||
}
|
18
node_modules/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedComponent/RCTUnimplementedNativeComponentView.h
generated
vendored
Normal file
18
node_modules/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedComponent/RCTUnimplementedNativeComponentView.h
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RCTUnimplementedNativeComponentView : RCTViewComponentView
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
60
node_modules/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedComponent/RCTUnimplementedNativeComponentView.mm
generated
vendored
Normal file
60
node_modules/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedComponent/RCTUnimplementedNativeComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 "RCTUnimplementedNativeComponentView.h"
|
||||
|
||||
#import <react/components/rncore/ComponentDescriptors.h>
|
||||
#import <react/components/rncore/EventEmitters.h>
|
||||
#import <react/components/rncore/Props.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@implementation RCTUnimplementedNativeComponentView {
|
||||
UILabel *_label;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static const auto defaultProps = std::make_shared<const UnimplementedNativeViewProps>();
|
||||
_props = defaultProps;
|
||||
|
||||
CGRect bounds = self.bounds;
|
||||
_label = [[UILabel alloc] initWithFrame:bounds];
|
||||
_label.backgroundColor = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.3];
|
||||
_label.layoutMargins = UIEdgeInsetsMake(12, 12, 12, 12);
|
||||
_label.lineBreakMode = NSLineBreakByWordWrapping;
|
||||
_label.numberOfLines = 0;
|
||||
_label.textAlignment = NSTextAlignmentCenter;
|
||||
_label.textColor = [UIColor whiteColor];
|
||||
|
||||
self.contentView = _label;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<UnimplementedNativeViewComponentDescriptor>();
|
||||
}
|
||||
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
const auto &oldViewProps = *std::static_pointer_cast<const UnimplementedNativeViewProps>(_props);
|
||||
const auto &newViewProps = *std::static_pointer_cast<const UnimplementedNativeViewProps>(props);
|
||||
|
||||
if (oldViewProps.name != newViewProps.name) {
|
||||
_label.text = [NSString stringWithFormat:@"'%s' is not Fabric compatible yet.", newViewProps.name.c_str()];
|
||||
}
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
}
|
||||
|
||||
@end
|
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.h
generated
vendored
Normal file
21
node_modules/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.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/RCTViewComponentView.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/*
|
||||
* UIView class for all kinds of <UnimplementedView> components.
|
||||
*/
|
||||
@interface RCTUnimplementedViewComponentView : RCTViewComponentView
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
73
node_modules/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm
generated
vendored
Normal file
73
node_modules/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 "RCTUnimplementedViewComponentView.h"
|
||||
|
||||
#import <react/components/rncore/ComponentDescriptors.h>
|
||||
#import <react/components/rncore/EventEmitters.h>
|
||||
#import <react/components/rncore/Props.h>
|
||||
|
||||
#import <react/components/unimplementedview/UnimplementedViewComponentDescriptor.h>
|
||||
#import <react/components/unimplementedview/UnimplementedViewShadowNode.h>
|
||||
|
||||
#import <React/RCTConversions.h>
|
||||
|
||||
#import "FBRCTFabricComponentsPlugins.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@implementation RCTUnimplementedViewComponentView {
|
||||
UILabel *_label;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static auto const defaultProps = std::make_shared<UnimplementedViewProps const>();
|
||||
_props = defaultProps;
|
||||
|
||||
_label = [[UILabel alloc] initWithFrame:self.bounds];
|
||||
_label.backgroundColor = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.3];
|
||||
_label.lineBreakMode = NSLineBreakByCharWrapping;
|
||||
_label.numberOfLines = 0;
|
||||
_label.textAlignment = NSTextAlignmentCenter;
|
||||
_label.textColor = [UIColor whiteColor];
|
||||
_label.allowsDefaultTighteningForTruncation = YES;
|
||||
_label.adjustsFontSizeToFitWidth = YES;
|
||||
|
||||
self.contentView = _label;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<UnimplementedViewComponentDescriptor>();
|
||||
}
|
||||
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
auto const &oldUnimplementedViewProps = *std::static_pointer_cast<UnimplementedViewProps const>(_props);
|
||||
auto const &newUnimplementedViewProps = *std::static_pointer_cast<UnimplementedViewProps const>(props);
|
||||
|
||||
if (oldUnimplementedViewProps.getComponentName() != newUnimplementedViewProps.getComponentName()) {
|
||||
_label.text =
|
||||
[NSString stringWithFormat:@"Unimplemented component: <%s>", newUnimplementedViewProps.getComponentName()];
|
||||
}
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTUnimplementedNativeViewCls(void)
|
||||
{
|
||||
return RCTUnimplementedViewComponentView.class;
|
||||
}
|
90
node_modules/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h
generated
vendored
Normal file
90
node_modules/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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/RCTComponentViewProtocol.h>
|
||||
#import <React/RCTTouchableComponentViewProtocol.h>
|
||||
#import <React/UIView+ComponentViewProtocol.h>
|
||||
#import <react/components/view/ViewEventEmitter.h>
|
||||
#import <react/components/view/ViewProps.h>
|
||||
#import <react/core/EventEmitter.h>
|
||||
#import <react/core/LayoutMetrics.h>
|
||||
#import <react/core/Props.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* UIView class for <View> component.
|
||||
*/
|
||||
@interface RCTViewComponentView : UIView <RCTComponentViewProtocol, RCTTouchableComponentViewProtocol> {
|
||||
@protected
|
||||
facebook::react::LayoutMetrics _layoutMetrics;
|
||||
facebook::react::SharedViewProps _props;
|
||||
facebook::react::SharedViewEventEmitter _eventEmitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the `UIView` instance that is being automatically attached to
|
||||
* the component view and laid out using on `layoutMetrics` (especially `size`
|
||||
* and `padding`) of the component.
|
||||
* This view must not be a component view; it's just a convenient way
|
||||
* to embed/bridge pure native views as component views.
|
||||
* Defaults to `nil`. Assign `nil` to remove view as subview.
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) UIView *contentView;
|
||||
|
||||
/**
|
||||
* Provides access to `nativeId` prop of the component.
|
||||
* It might be used by subclasses (which need to refer to the view from
|
||||
* other platform-specific external views or systems by some id) or
|
||||
* by debugging/inspection tools.
|
||||
* Defaults to `nil`.
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) NSString *nativeId;
|
||||
|
||||
/**
|
||||
* Provides access to `foregroundColor` prop of the component.
|
||||
* Must be used by subclasses only.
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) UIColor *foregroundColor;
|
||||
|
||||
/**
|
||||
* Returns the object - usually (sub)view - which represents this
|
||||
* component view in terms of accessibility.
|
||||
* All accessibility properties will be applied to this object.
|
||||
* May be overridden in subclass which needs to be accessiblitywise
|
||||
* transparent in favour of some subview.
|
||||
* Defaults to `self`.
|
||||
*/
|
||||
@property (nonatomic, strong, nullable, readonly) NSObject *accessibilityElement;
|
||||
|
||||
/**
|
||||
* Insets used when hit testing inside this view.
|
||||
*/
|
||||
@property (nonatomic, assign) UIEdgeInsets hitTestEdgeInsets;
|
||||
|
||||
/**
|
||||
* Enforcing `call super` semantic for overridden methods from `RCTComponentViewProtocol`.
|
||||
* The methods update the instance variables.
|
||||
*/
|
||||
- (void)updateProps:(facebook::react::Props::Shared const &)props
|
||||
oldProps:(facebook::react::Props::Shared const &)oldProps NS_REQUIRES_SUPER;
|
||||
- (void)updateEventEmitter:(facebook::react::EventEmitter::Shared const &)eventEmitter NS_REQUIRES_SUPER;
|
||||
- (void)updateLayoutMetrics:(facebook::react::LayoutMetrics const &)layoutMetrics
|
||||
oldLayoutMetrics:(facebook::react::LayoutMetrics const &)oldLayoutMetrics NS_REQUIRES_SUPER;
|
||||
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask NS_REQUIRES_SUPER;
|
||||
- (void)prepareForRecycle NS_REQUIRES_SUPER;
|
||||
|
||||
/*
|
||||
* This is a fragment of temporary workaround that we need only temporary and will get rid of soon.
|
||||
*/
|
||||
- (NSString *)componentViewName_DO_NOT_USE_THIS_IS_BROKEN;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
585
node_modules/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm
generated
vendored
Normal file
585
node_modules/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm
generated
vendored
Normal file
@ -0,0 +1,585 @@
|
||||
/*
|
||||
* 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 "RCTViewComponentView.h"
|
||||
|
||||
#import <React/RCTAssert.h>
|
||||
#import <React/RCTBorderDrawing.h>
|
||||
#import <objc/runtime.h>
|
||||
#import <react/components/view/ViewComponentDescriptor.h>
|
||||
#import <react/components/view/ViewEventEmitter.h>
|
||||
#import <react/components/view/ViewProps.h>
|
||||
|
||||
#import "RCTConversions.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@implementation RCTViewComponentView {
|
||||
UIColor *_backgroundColor;
|
||||
CALayer *_borderLayer;
|
||||
BOOL _needsInvalidateLayer;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static auto const defaultProps = std::make_shared<ViewProps const>();
|
||||
_props = defaultProps;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (facebook::react::SharedProps)props
|
||||
{
|
||||
return _props;
|
||||
}
|
||||
|
||||
- (void)setContentView:(UIView *)contentView
|
||||
{
|
||||
if (_contentView) {
|
||||
[_contentView removeFromSuperview];
|
||||
}
|
||||
|
||||
_contentView = contentView;
|
||||
|
||||
if (_contentView) {
|
||||
[self addSubview:_contentView];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
// Consider whether using `updateLayoutMetrics:oldLayoutMetrics`
|
||||
// isn't more appropriate for your use case. `layoutSubviews` is called
|
||||
// by UIKit while `updateLayoutMetrics:oldLayoutMetrics` is called
|
||||
// by React Native Renderer within `CATransaction`.
|
||||
// If you are calling `setFrame:` or other methods that cause
|
||||
// `layoutSubviews` to be triggered, `_contentView`'s and `_borderLayout`'s
|
||||
// frames might get out of sync with `self.bounds`.
|
||||
}
|
||||
|
||||
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
if (UIEdgeInsetsEqualToEdgeInsets(self.hitTestEdgeInsets, UIEdgeInsetsZero)) {
|
||||
return [super pointInside:point withEvent:event];
|
||||
}
|
||||
CGRect hitFrame = UIEdgeInsetsInsetRect(self.bounds, self.hitTestEdgeInsets);
|
||||
return CGRectContainsPoint(hitFrame, point);
|
||||
}
|
||||
|
||||
- (UIColor *)backgroundColor
|
||||
{
|
||||
return _backgroundColor;
|
||||
}
|
||||
|
||||
- (void)setBackgroundColor:(UIColor *)backgroundColor
|
||||
{
|
||||
_backgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
RCTAssert(
|
||||
self == [RCTViewComponentView class],
|
||||
@"`+[RCTComponentViewProtocol componentDescriptorProvider]` must be implemented for all subclasses (and `%@` particularly).",
|
||||
NSStringFromClass([self class]));
|
||||
return concreteComponentDescriptorProvider<ViewComponentDescriptor>();
|
||||
}
|
||||
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
#ifndef NS_BLOCK_ASSERTIONS
|
||||
auto propsRawPtr = _props.get();
|
||||
RCTAssert(
|
||||
propsRawPtr &&
|
||||
([self class] == [RCTViewComponentView class] ||
|
||||
typeid(*propsRawPtr).hash_code() != typeid(ViewProps const).hash_code()),
|
||||
@"`RCTViewComponentView` subclasses (and `%@` particularly) must setup `_props`"
|
||||
" instance variable with a default value in the constructor.",
|
||||
NSStringFromClass([self class]));
|
||||
#endif
|
||||
|
||||
auto const &oldViewProps = *std::static_pointer_cast<ViewProps const>(_props);
|
||||
auto const &newViewProps = *std::static_pointer_cast<ViewProps const>(props);
|
||||
|
||||
BOOL needsInvalidateLayer = NO;
|
||||
|
||||
// `opacity`
|
||||
if (oldViewProps.opacity != newViewProps.opacity) {
|
||||
self.layer.opacity = (CGFloat)newViewProps.opacity;
|
||||
needsInvalidateLayer = YES;
|
||||
}
|
||||
|
||||
// `backgroundColor`
|
||||
if (oldViewProps.backgroundColor != newViewProps.backgroundColor) {
|
||||
self.backgroundColor = RCTUIColorFromSharedColor(newViewProps.backgroundColor);
|
||||
needsInvalidateLayer = YES;
|
||||
}
|
||||
|
||||
// `foregroundColor`
|
||||
if (oldViewProps.foregroundColor != newViewProps.foregroundColor) {
|
||||
self.foregroundColor = RCTUIColorFromSharedColor(newViewProps.foregroundColor);
|
||||
}
|
||||
|
||||
// `shadowColor`
|
||||
if (oldViewProps.shadowColor != newViewProps.shadowColor) {
|
||||
CGColorRef shadowColor = RCTCGColorRefFromSharedColor(newViewProps.shadowColor);
|
||||
self.layer.shadowColor = shadowColor;
|
||||
CGColorRelease(shadowColor);
|
||||
needsInvalidateLayer = YES;
|
||||
}
|
||||
|
||||
// `shadowOffset`
|
||||
if (oldViewProps.shadowOffset != newViewProps.shadowOffset) {
|
||||
self.layer.shadowOffset = RCTCGSizeFromSize(newViewProps.shadowOffset);
|
||||
needsInvalidateLayer = YES;
|
||||
}
|
||||
|
||||
// `shadowOpacity`
|
||||
if (oldViewProps.shadowOpacity != newViewProps.shadowOpacity) {
|
||||
self.layer.shadowOpacity = (CGFloat)newViewProps.shadowOpacity;
|
||||
needsInvalidateLayer = YES;
|
||||
}
|
||||
|
||||
// `shadowRadius`
|
||||
if (oldViewProps.shadowRadius != newViewProps.shadowRadius) {
|
||||
self.layer.shadowRadius = (CGFloat)newViewProps.shadowRadius;
|
||||
needsInvalidateLayer = YES;
|
||||
}
|
||||
|
||||
// `backfaceVisibility`
|
||||
if (oldViewProps.backfaceVisibility != newViewProps.backfaceVisibility) {
|
||||
self.layer.doubleSided = newViewProps.backfaceVisibility == BackfaceVisibility::Visible;
|
||||
}
|
||||
|
||||
// `shouldRasterize`
|
||||
if (oldViewProps.shouldRasterize != newViewProps.shouldRasterize) {
|
||||
self.layer.shouldRasterize = newViewProps.shouldRasterize;
|
||||
self.layer.rasterizationScale = newViewProps.shouldRasterize ? [UIScreen mainScreen].scale : 1.0;
|
||||
}
|
||||
|
||||
// `pointerEvents`
|
||||
if (oldViewProps.pointerEvents != newViewProps.pointerEvents) {
|
||||
self.userInteractionEnabled = newViewProps.pointerEvents != PointerEventsMode::None;
|
||||
}
|
||||
|
||||
// `transform`
|
||||
if (oldViewProps.transform != newViewProps.transform) {
|
||||
self.layer.transform = RCTCATransform3DFromTransformMatrix(newViewProps.transform);
|
||||
self.layer.allowsEdgeAntialiasing = newViewProps.transform != Transform::Identity();
|
||||
}
|
||||
|
||||
// `hitSlop`
|
||||
if (oldViewProps.hitSlop != newViewProps.hitSlop) {
|
||||
self.hitTestEdgeInsets = RCTUIEdgeInsetsFromEdgeInsets(newViewProps.hitSlop);
|
||||
}
|
||||
|
||||
// `overflow`
|
||||
if (oldViewProps.getClipsContentToBounds() != newViewProps.getClipsContentToBounds()) {
|
||||
self.clipsToBounds = newViewProps.getClipsContentToBounds();
|
||||
needsInvalidateLayer = YES;
|
||||
}
|
||||
|
||||
// `border`
|
||||
if (oldViewProps.borderStyles != newViewProps.borderStyles || oldViewProps.borderRadii != newViewProps.borderRadii ||
|
||||
oldViewProps.borderColors != newViewProps.borderColors) {
|
||||
needsInvalidateLayer = YES;
|
||||
}
|
||||
|
||||
// `nativeId`
|
||||
if (oldViewProps.nativeId != newViewProps.nativeId) {
|
||||
self.nativeId = RCTNSStringFromStringNilIfEmpty(newViewProps.nativeId);
|
||||
}
|
||||
|
||||
// `accessible`
|
||||
if (oldViewProps.accessible != newViewProps.accessible) {
|
||||
self.accessibilityElement.isAccessibilityElement = newViewProps.accessible;
|
||||
}
|
||||
|
||||
// `accessibilityLabel`
|
||||
if (oldViewProps.accessibilityLabel != newViewProps.accessibilityLabel) {
|
||||
self.accessibilityElement.accessibilityLabel = RCTNSStringFromStringNilIfEmpty(newViewProps.accessibilityLabel);
|
||||
}
|
||||
|
||||
// `accessibilityHint`
|
||||
if (oldViewProps.accessibilityHint != newViewProps.accessibilityHint) {
|
||||
self.accessibilityElement.accessibilityHint = RCTNSStringFromStringNilIfEmpty(newViewProps.accessibilityHint);
|
||||
}
|
||||
|
||||
// `accessibilityViewIsModal`
|
||||
if (oldViewProps.accessibilityViewIsModal != newViewProps.accessibilityViewIsModal) {
|
||||
self.accessibilityElement.accessibilityViewIsModal = newViewProps.accessibilityViewIsModal;
|
||||
}
|
||||
|
||||
// `accessibilityElementsHidden`
|
||||
if (oldViewProps.accessibilityElementsHidden != newViewProps.accessibilityElementsHidden) {
|
||||
self.accessibilityElement.accessibilityElementsHidden = newViewProps.accessibilityElementsHidden;
|
||||
}
|
||||
|
||||
if (oldViewProps.accessibilityTraits != newViewProps.accessibilityTraits) {
|
||||
self.accessibilityElement.accessibilityTraits =
|
||||
RCTUIAccessibilityTraitsFromAccessibilityTraits(newViewProps.accessibilityTraits);
|
||||
}
|
||||
|
||||
// `accessibilityIgnoresInvertColors`
|
||||
if (oldViewProps.accessibilityIgnoresInvertColors != newViewProps.accessibilityIgnoresInvertColors) {
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
|
||||
if (@available(iOS 11.0, *)) {
|
||||
self.accessibilityIgnoresInvertColors = newViewProps.accessibilityIgnoresInvertColors;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
_needsInvalidateLayer = _needsInvalidateLayer || needsInvalidateLayer;
|
||||
|
||||
_props = std::static_pointer_cast<ViewProps const>(props);
|
||||
}
|
||||
|
||||
- (void)updateEventEmitter:(EventEmitter::Shared const &)eventEmitter
|
||||
{
|
||||
assert(std::dynamic_pointer_cast<ViewEventEmitter const>(eventEmitter));
|
||||
_eventEmitter = std::static_pointer_cast<ViewEventEmitter const>(eventEmitter);
|
||||
}
|
||||
|
||||
- (void)updateLayoutMetrics:(LayoutMetrics const &)layoutMetrics
|
||||
oldLayoutMetrics:(LayoutMetrics const &)oldLayoutMetrics
|
||||
{
|
||||
// Using stored `_layoutMetrics` as `oldLayoutMetrics` here to avoid
|
||||
// re-applying individual sub-values which weren't changed.
|
||||
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:_layoutMetrics];
|
||||
|
||||
_layoutMetrics = layoutMetrics;
|
||||
_needsInvalidateLayer = YES;
|
||||
|
||||
if (_borderLayer) {
|
||||
_borderLayer.frame = self.layer.bounds;
|
||||
}
|
||||
|
||||
if (_contentView) {
|
||||
_contentView.frame = RCTCGRectFromRect(_layoutMetrics.getContentFrame());
|
||||
}
|
||||
}
|
||||
|
||||
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask
|
||||
{
|
||||
[super finalizeUpdates:updateMask];
|
||||
if (!_needsInvalidateLayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
_needsInvalidateLayer = NO;
|
||||
[self invalidateLayer];
|
||||
}
|
||||
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
[super prepareForRecycle];
|
||||
_eventEmitter.reset();
|
||||
}
|
||||
|
||||
- (UIView *)betterHitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
// This is a classic textbook implementation of `hitTest:` with a couple of improvements:
|
||||
// * It does not stop algorithm if some touch is outside the view
|
||||
// which does not have `clipToBounds` enabled.
|
||||
// * Taking `layer.zIndex` field into an account is not required because
|
||||
// lists of `ShadowView`s are already sorted based on `zIndex` prop.
|
||||
|
||||
if (!self.userInteractionEnabled || self.hidden || self.alpha < 0.01) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
BOOL isPointInside = [self pointInside:point withEvent:event];
|
||||
|
||||
if (self.clipsToBounds && !isPointInside) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
for (UIView *subview in [self.subviews reverseObjectEnumerator]) {
|
||||
UIView *hitView = [subview hitTest:[subview convertPoint:point fromView:self] withEvent:event];
|
||||
if (hitView) {
|
||||
return hitView;
|
||||
}
|
||||
}
|
||||
|
||||
return isPointInside ? self : nil;
|
||||
}
|
||||
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
switch (_props->pointerEvents) {
|
||||
case PointerEventsMode::Auto:
|
||||
return [self betterHitTest:point withEvent:event];
|
||||
case PointerEventsMode::None:
|
||||
return nil;
|
||||
case PointerEventsMode::BoxOnly:
|
||||
return [self pointInside:point withEvent:event] ? self : nil;
|
||||
case PointerEventsMode::BoxNone:
|
||||
UIView *view = [self betterHitTest:point withEvent:event];
|
||||
return view != self ? view : nil;
|
||||
}
|
||||
}
|
||||
|
||||
static RCTCornerRadii RCTCornerRadiiFromBorderRadii(BorderRadii borderRadii)
|
||||
{
|
||||
return RCTCornerRadii{.topLeft = (CGFloat)borderRadii.topLeft,
|
||||
.topRight = (CGFloat)borderRadii.topRight,
|
||||
.bottomLeft = (CGFloat)borderRadii.bottomLeft,
|
||||
.bottomRight = (CGFloat)borderRadii.bottomRight};
|
||||
}
|
||||
|
||||
static RCTBorderColors RCTBorderColorsFromBorderColors(BorderColors borderColors)
|
||||
{
|
||||
return RCTBorderColors{.left = RCTCGColorRefUnretainedFromSharedColor(borderColors.left),
|
||||
.top = RCTCGColorRefUnretainedFromSharedColor(borderColors.top),
|
||||
.bottom = RCTCGColorRefUnretainedFromSharedColor(borderColors.bottom),
|
||||
.right = RCTCGColorRefUnretainedFromSharedColor(borderColors.right)};
|
||||
}
|
||||
|
||||
static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle)
|
||||
{
|
||||
switch (borderStyle) {
|
||||
case BorderStyle::Solid:
|
||||
return RCTBorderStyleSolid;
|
||||
case BorderStyle::Dotted:
|
||||
return RCTBorderStyleDotted;
|
||||
case BorderStyle::Dashed:
|
||||
return RCTBorderStyleDashed;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)invalidateLayer
|
||||
{
|
||||
CALayer *layer = self.layer;
|
||||
|
||||
if (CGSizeEqualToSize(layer.bounds.size, CGSizeZero)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto const borderMetrics = _props->resolveBorderMetrics(_layoutMetrics);
|
||||
|
||||
// Stage 1. Shadow Path
|
||||
BOOL const layerHasShadow = layer.shadowOpacity > 0 && CGColorGetAlpha(layer.shadowColor) > 0;
|
||||
if (layerHasShadow) {
|
||||
if (CGColorGetAlpha(_backgroundColor.CGColor) > 0.999) {
|
||||
// If view has a solid background color, calculate shadow path from border.
|
||||
RCTCornerInsets const cornerInsets =
|
||||
RCTGetCornerInsets(RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii), UIEdgeInsetsZero);
|
||||
CGPathRef shadowPath = RCTPathCreateWithRoundedRect(self.bounds, cornerInsets, nil);
|
||||
layer.shadowPath = shadowPath;
|
||||
CGPathRelease(shadowPath);
|
||||
} else {
|
||||
// Can't accurately calculate box shadow, so fall back to pixel-based shadow.
|
||||
layer.shadowPath = nil;
|
||||
}
|
||||
} else {
|
||||
layer.shadowPath = nil;
|
||||
}
|
||||
|
||||
// Stage 2. Border Rendering
|
||||
bool const useCoreAnimationBorderRendering =
|
||||
borderMetrics.borderColors.isUniform() && borderMetrics.borderWidths.isUniform() &&
|
||||
borderMetrics.borderStyles.isUniform() && borderMetrics.borderRadii.isUniform() &&
|
||||
borderMetrics.borderStyles.left == BorderStyle::Solid &&
|
||||
(
|
||||
// iOS draws borders in front of the content whereas CSS draws them behind
|
||||
// the content. For this reason, only use iOS border drawing when clipping
|
||||
// or when the border is hidden.
|
||||
borderMetrics.borderWidths.left == 0 ||
|
||||
colorComponentsFromColor(borderMetrics.borderColors.left).alpha == 0 || self.clipsToBounds);
|
||||
|
||||
if (useCoreAnimationBorderRendering) {
|
||||
layer.mask = nil;
|
||||
if (_borderLayer) {
|
||||
[_borderLayer removeFromSuperlayer];
|
||||
_borderLayer = nil;
|
||||
}
|
||||
|
||||
layer.borderWidth = (CGFloat)borderMetrics.borderWidths.left;
|
||||
CGColorRef borderColor = RCTCGColorRefFromSharedColor(borderMetrics.borderColors.left);
|
||||
layer.borderColor = borderColor;
|
||||
CGColorRelease(borderColor);
|
||||
layer.cornerRadius = (CGFloat)borderMetrics.borderRadii.topLeft;
|
||||
layer.backgroundColor = _backgroundColor.CGColor;
|
||||
} else {
|
||||
if (!_borderLayer) {
|
||||
_borderLayer = [[CALayer alloc] init];
|
||||
_borderLayer.zPosition = -1024.0f;
|
||||
_borderLayer.frame = layer.bounds;
|
||||
_borderLayer.magnificationFilter = kCAFilterNearest;
|
||||
[layer addSublayer:_borderLayer];
|
||||
}
|
||||
|
||||
layer.backgroundColor = nil;
|
||||
layer.borderWidth = 0;
|
||||
layer.borderColor = nil;
|
||||
layer.cornerRadius = 0;
|
||||
|
||||
UIImage *image = RCTGetBorderImage(
|
||||
RCTBorderStyleFromBorderStyle(borderMetrics.borderStyles.left),
|
||||
layer.bounds.size,
|
||||
RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii),
|
||||
RCTUIEdgeInsetsFromEdgeInsets(borderMetrics.borderWidths),
|
||||
RCTBorderColorsFromBorderColors(borderMetrics.borderColors),
|
||||
_backgroundColor.CGColor,
|
||||
self.clipsToBounds);
|
||||
|
||||
if (image == nil) {
|
||||
_borderLayer.contents = nil;
|
||||
} else {
|
||||
CGSize imageSize = image.size;
|
||||
UIEdgeInsets imageCapInsets = image.capInsets;
|
||||
CGRect contentsCenter =
|
||||
CGRect{CGPoint{imageCapInsets.left / imageSize.width, imageCapInsets.top / imageSize.height},
|
||||
CGSize{(CGFloat)1.0 / imageSize.width, (CGFloat)1.0 / imageSize.height}};
|
||||
|
||||
_borderLayer.contents = (id)image.CGImage;
|
||||
_borderLayer.contentsScale = image.scale;
|
||||
|
||||
BOOL isResizable = !UIEdgeInsetsEqualToEdgeInsets(image.capInsets, UIEdgeInsetsZero);
|
||||
if (isResizable) {
|
||||
_borderLayer.contentsCenter = contentsCenter;
|
||||
} else {
|
||||
_borderLayer.contentsCenter = CGRect{CGPoint{0.0, 0.0}, CGSize{1.0, 1.0}};
|
||||
}
|
||||
}
|
||||
|
||||
// Stage 2.5. Custom Clipping Mask
|
||||
CAShapeLayer *maskLayer = nil;
|
||||
CGFloat cornerRadius = 0;
|
||||
if (self.clipsToBounds) {
|
||||
if (borderMetrics.borderRadii.isUniform()) {
|
||||
// In this case we can simply use `cornerRadius` exclusively.
|
||||
cornerRadius = borderMetrics.borderRadii.topLeft;
|
||||
} else {
|
||||
// In this case we have to generate masking layer manually.
|
||||
CGPathRef path = RCTPathCreateWithRoundedRect(
|
||||
self.bounds,
|
||||
RCTGetCornerInsets(RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii), UIEdgeInsetsZero),
|
||||
nil);
|
||||
|
||||
maskLayer = [CAShapeLayer layer];
|
||||
maskLayer.path = path;
|
||||
CGPathRelease(path);
|
||||
}
|
||||
}
|
||||
|
||||
layer.cornerRadius = cornerRadius;
|
||||
layer.mask = maskLayer;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Accessibility
|
||||
|
||||
- (NSObject *)accessibilityElement
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
|
||||
{
|
||||
NSMutableString *result = [NSMutableString stringWithString:@""];
|
||||
for (UIView *subview in view.subviews) {
|
||||
NSString *label = subview.accessibilityLabel;
|
||||
if (!label) {
|
||||
label = RCTRecursiveAccessibilityLabel(subview);
|
||||
}
|
||||
if (label && label.length > 0) {
|
||||
if (result.length > 0) {
|
||||
[result appendString:@" "];
|
||||
}
|
||||
[result appendString:label];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString *)accessibilityLabel
|
||||
{
|
||||
NSString *label = super.accessibilityLabel;
|
||||
if (label) {
|
||||
return label;
|
||||
}
|
||||
|
||||
return RCTRecursiveAccessibilityLabel(self);
|
||||
}
|
||||
|
||||
#pragma mark - Accessibility Events
|
||||
|
||||
- (NSArray<UIAccessibilityCustomAction *> *)accessibilityCustomActions
|
||||
{
|
||||
auto const &accessibilityActions = _props->accessibilityActions;
|
||||
|
||||
if (accessibilityActions.size() == 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSMutableArray<UIAccessibilityCustomAction *> *customActions = [NSMutableArray array];
|
||||
for (auto const &accessibilityAction : accessibilityActions) {
|
||||
[customActions
|
||||
addObject:[[UIAccessibilityCustomAction alloc] initWithName:RCTNSStringFromString(accessibilityAction)
|
||||
target:self
|
||||
selector:@selector(didActivateAccessibilityCustomAction:)]];
|
||||
}
|
||||
|
||||
return [customActions copy];
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityActivate
|
||||
{
|
||||
if (_eventEmitter && _props->onAccessibilityTap) {
|
||||
_eventEmitter->onAccessibilityTap();
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityPerformMagicTap
|
||||
{
|
||||
if (_eventEmitter && _props->onAccessibilityMagicTap) {
|
||||
_eventEmitter->onAccessibilityMagicTap();
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityPerformEscape
|
||||
{
|
||||
if (_eventEmitter && _props->onAccessibilityEscape) {
|
||||
_eventEmitter->onAccessibilityEscape();
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)didActivateAccessibilityCustomAction:(UIAccessibilityCustomAction *)action
|
||||
{
|
||||
if (_eventEmitter && _props->onAccessibilityAction) {
|
||||
_eventEmitter->onAccessibilityAction(RCTStringFromNSString(action.name));
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (SharedTouchEventEmitter)touchEventEmitterAtPoint:(CGPoint)point
|
||||
{
|
||||
return _eventEmitter;
|
||||
}
|
||||
|
||||
- (NSString *)componentViewName_DO_NOT_USE_THIS_IS_BROKEN
|
||||
{
|
||||
return RCTNSStringFromString([[self class] componentDescriptorProvider].name);
|
||||
}
|
||||
|
||||
@end
|
Reference in New Issue
Block a user