first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#elif TARGET_OS_OSX
#import <AppKit/AppKit.h>
#endif
#import <React/RCTViewComponentView.h>
NS_ASSUME_NONNULL_BEGIN
@interface RNCSafeAreaProviderComponentView : RCTViewComponentView
extern NSString *const RNCSafeAreaDidChange;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,154 @@
#import "RNCSafeAreaProviderComponentView.h"
#import <react/renderer/components/safeareacontext/ComponentDescriptors.h>
#import <react/renderer/components/safeareacontext/EventEmitters.h>
#import <react/renderer/components/safeareacontext/Props.h>
#import <react/renderer/components/safeareacontext/RCTComponentViewHelpers.h>
#import <React/RCTFabricComponentsPlugins.h>
#import "RNCSafeAreaUtils.h"
using namespace facebook::react;
@interface RNCSafeAreaProviderComponentView () <RCTRNCSafeAreaProviderViewProtocol>
@end
@implementation RNCSafeAreaProviderComponentView {
UIEdgeInsets _currentSafeAreaInsets;
CGRect _currentFrame;
BOOL _initialInsetsSent;
BOOL _registeredNotifications;
}
// Needed because of this: https://github.com/facebook/react-native/pull/37274
+ (void)load
{
[super load];
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const RNCSafeAreaProviderProps>();
_props = defaultProps;
}
return self;
}
#if !TARGET_OS_OSX
- (void)willMoveToSuperview:(UIView *)newSuperView
{
[super willMoveToSuperview:newSuperView];
if (newSuperView != nil && !_registeredNotifications) {
_registeredNotifications = YES;
[self registerNotifications];
}
}
#endif
- (void)registerNotifications
{
#if !TARGET_OS_TV && !TARGET_OS_OSX
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(invalidateSafeAreaInsets)
name:UIKeyboardDidShowNotification
object:nil];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(invalidateSafeAreaInsets)
name:UIKeyboardDidHideNotification
object:nil];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(invalidateSafeAreaInsets)
name:UIKeyboardDidChangeFrameNotification
object:nil];
#endif
}
- (void)safeAreaInsetsDidChange
{
[self invalidateSafeAreaInsets];
}
- (void)invalidateSafeAreaInsets
{
if (self.superview == nil) {
return;
}
// This gets called before the view size is set by react-native so
// make sure to wait so we don't set wrong insets to JS.
if (CGSizeEqualToSize(self.frame.size, CGSizeZero)) {
return;
}
UIEdgeInsets safeAreaInsets = self.safeAreaInsets;
CGRect frame = [self convertRect:self.bounds toView:RNCParentViewController(self).view];
if (_initialInsetsSent &&
#if TARGET_OS_IPHONE
UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale()) &&
#elif TARGET_OS_OSX
NSEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale()) &&
#endif
CGRectEqualToRect(frame, _currentFrame)) {
return;
}
_initialInsetsSent = YES;
_currentSafeAreaInsets = safeAreaInsets;
_currentFrame = frame;
[NSNotificationCenter.defaultCenter postNotificationName:RNCSafeAreaDidChange object:self userInfo:nil];
if (_eventEmitter) {
RNCSafeAreaProviderEventEmitter::OnInsetsChange event = {
.insets =
{
.top = safeAreaInsets.top,
.left = safeAreaInsets.left,
.bottom = safeAreaInsets.bottom,
.right = safeAreaInsets.right,
},
.frame =
{
.x = frame.origin.x,
.y = frame.origin.y,
.width = frame.size.width,
.height = frame.size.height,
},
};
std::static_pointer_cast<RNCSafeAreaProviderEventEmitter const>(_eventEmitter)->onInsetsChange(event);
}
}
- (void)layoutSubviews
{
[super layoutSubviews];
[self invalidateSafeAreaInsets];
}
#pragma mark - RCTComponentViewProtocol
+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<RNCSafeAreaProviderComponentDescriptor>();
}
- (void)prepareForRecycle
{
[super prepareForRecycle];
_currentSafeAreaInsets = UIEdgeInsetsZero;
_currentFrame = CGRectZero;
_initialInsetsSent = NO;
[NSNotificationCenter.defaultCenter removeObserver:self];
_registeredNotifications = NO;
}
@end
Class<RCTComponentViewProtocol> RNCSafeAreaProviderCls(void)
{
return RNCSafeAreaProviderComponentView.class;
}

View File

@@ -0,0 +1,15 @@
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#elif TARGET_OS_OSX
#import <AppKit/AppKit.h>
#endif
#import <React/RCTViewComponentView.h>
NS_ASSUME_NONNULL_BEGIN
@interface RNCSafeAreaViewComponentView : RCTViewComponentView
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,175 @@
#import "RNCSafeAreaViewComponentView.h"
#import <react/renderer/components/safeareacontext/EventEmitters.h>
#import <react/renderer/components/safeareacontext/Props.h>
#import <react/renderer/components/safeareacontext/RCTComponentViewHelpers.h>
#import <react/renderer/components/safeareacontext/RNCSafeAreaViewComponentDescriptor.h>
#import <react/renderer/components/safeareacontext/RNCSafeAreaViewShadowNode.h>
#import <React/RCTConversions.h>
#import <React/RCTFabricComponentsPlugins.h>
#import "RNCSafeAreaProviderComponentView.h"
#import "RNCSafeAreaUtils.h"
using namespace facebook::react;
@interface RNCSafeAreaViewComponentView () <RCTRNCSafeAreaViewViewProtocol>
@end
@implementation RNCSafeAreaViewComponentView {
RNCSafeAreaViewShadowNode::ConcreteState::Shared _state;
UIEdgeInsets _currentSafeAreaInsets;
__weak UIView *_Nullable _providerView;
}
// Needed because of this: https://github.com/facebook/react-native/pull/37274
+ (void)load
{
[super load];
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const RNCSafeAreaViewProps>();
_props = defaultProps;
}
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];
}
#if TARGET_OS_IPHONE
NSString *providerViewSafeAreaInsetsString = NSStringFromUIEdgeInsets(_providerView.safeAreaInsets);
NSString *currentSafeAreaInsetsString = NSStringFromUIEdgeInsets(_currentSafeAreaInsets);
#elif TARGET_OS_OSX
NSString *providerViewSafeAreaInsetsString = [NSString stringWithFormat:@"{%f,%f,%f,%f}",
_providerView.safeAreaInsets.top,
_providerView.safeAreaInsets.left,
_providerView.safeAreaInsets.bottom,
_providerView.safeAreaInsets.right];
NSString *currentSafeAreaInsetsString = [NSString stringWithFormat:@"{%f,%f,%f,%f}",
_currentSafeAreaInsets.top,
_currentSafeAreaInsets.left,
_currentSafeAreaInsets.bottom,
_currentSafeAreaInsets.right];
#endif
return [NSString stringWithFormat:@"%@; RNCSafeAreaInsets = %@; appliedRNCSafeAreaInsets = %@>",
superDescription,
providerViewSafeAreaInsetsString,
currentSafeAreaInsetsString];
}
- (void)didMoveToWindow
{
UIView *previousProviderView = _providerView;
_providerView = [self findNearestProvider];
[self updateStateIfNecessary];
if (previousProviderView != _providerView) {
[NSNotificationCenter.defaultCenter removeObserver:self name:RNCSafeAreaDidChange object:previousProviderView];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(safeAreaProviderInsetsDidChange:)
name:RNCSafeAreaDidChange
object:_providerView];
}
}
- (void)safeAreaProviderInsetsDidChange:(NSNotification *)notification
{
[self updateStateIfNecessary];
}
- (void)updateStateIfNecessary
{
if (_providerView == nil) {
return;
}
#if TARGET_OS_IPHONE
UIEdgeInsets safeAreaInsets = _providerView.safeAreaInsets;
if (UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale())) {
return;
}
#elif TARGET_OS_OSX
NSEdgeInsets safeAreaInsets = _providerView.safeAreaInsets;
if (NSEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale())) {
return;
}
#endif
_currentSafeAreaInsets = safeAreaInsets;
[self updateState];
}
- (UIView *)findNearestProvider
{
UIView *current = self.superview;
while (current != nil) {
if ([current isKindOfClass:RNCSafeAreaProviderComponentView.class]) {
return current;
}
current = current.superview;
}
return self;
}
- (void)updateState
{
if (!_state) {
return;
}
_state->updateState(
[=](RNCSafeAreaViewShadowNode::ConcreteState::Data const &oldData)
-> RNCSafeAreaViewShadowNode::ConcreteState::SharedData {
auto newData = oldData;
newData.insets = RCTEdgeInsetsFromUIEdgeInsets(_currentSafeAreaInsets);
return std::make_shared<RNCSafeAreaViewShadowNode::ConcreteState::Data const>(newData);
});
}
#pragma mark - RCTComponentViewProtocol
+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<RNCSafeAreaViewComponentDescriptor>();
}
- (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState
{
_state = std::static_pointer_cast<RNCSafeAreaViewShadowNode::ConcreteState const>(state);
}
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask
{
[super finalizeUpdates:updateMask];
[self updateStateIfNecessary];
}
- (void)prepareForRecycle
{
[super prepareForRecycle];
[NSNotificationCenter.defaultCenter removeObserver:self];
_state.reset();
_providerView = nil;
_currentSafeAreaInsets = UIEdgeInsetsZero;
}
@end
Class<RCTComponentViewProtocol> RNCSafeAreaViewCls(void)
{
return RNCSafeAreaViewComponentView.class;
}