120 lines
3.5 KiB
Plaintext
120 lines
3.5 KiB
Plaintext
|
#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;
|
||
|
}
|
||
|
|
||
|
- (instancetype)initWithFrame:(CGRect)frame
|
||
|
{
|
||
|
if (self = [super initWithFrame:frame]) {
|
||
|
static const auto defaultProps = std::make_shared<const RNCSafeAreaProviderProps>();
|
||
|
_props = defaultProps;
|
||
|
|
||
|
#if !TARGET_OS_TV
|
||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||
|
selector:@selector(invalidateSafeAreaInsets)
|
||
|
name:UIKeyboardDidShowNotification
|
||
|
object:nil];
|
||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||
|
selector:@selector(invalidateSafeAreaInsets)
|
||
|
name:UIKeyboardDidHideNotification
|
||
|
object:nil];
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
- (void)safeAreaInsetsDidChange
|
||
|
{
|
||
|
[self invalidateSafeAreaInsets];
|
||
|
}
|
||
|
|
||
|
- (void)invalidateSafeAreaInsets
|
||
|
{
|
||
|
// 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:nil];
|
||
|
|
||
|
if (_initialInsetsSent &&
|
||
|
UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale()) &&
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
@end
|
||
|
|
||
|
Class<RCTComponentViewProtocol> RNCSafeAreaProviderCls(void)
|
||
|
{
|
||
|
return RNCSafeAreaProviderComponentView.class;
|
||
|
}
|