145 lines
3.9 KiB
Plaintext
145 lines
3.9 KiB
Plaintext
#import "RNSStackScreenComponentView.h"
|
|
#import <React/RCTConversions.h>
|
|
#import <React/RCTMountingTransactionObserving.h>
|
|
#import <react/renderer/components/rnscreens/ComponentDescriptors.h>
|
|
#import <react/renderer/components/rnscreens/EventEmitters.h>
|
|
#import <react/renderer/components/rnscreens/Props.h>
|
|
#import <react/renderer/components/rnscreens/RCTComponentViewHelpers.h>
|
|
|
|
#import "RNSConversions-Stack.h"
|
|
#import "RNSStackHostComponentView.h"
|
|
|
|
#import "Swift-Bridging.h"
|
|
|
|
namespace react = facebook::react;
|
|
|
|
@interface RNSStackScreenComponentView () <RCTMountingTransactionObserving>
|
|
@end
|
|
|
|
#pragma mark - View implementation
|
|
|
|
@implementation RNSStackScreenComponentView {
|
|
RNSStackScreenController *_Nonnull _controller;
|
|
RNSStackScreenComponentEventEmitter *_Nonnull _reactEventEmitter;
|
|
|
|
// Flags
|
|
BOOL _hasUpdatedActivityMode;
|
|
}
|
|
|
|
- (instancetype)initWithFrame:(CGRect)frame
|
|
{
|
|
if (self = [super initWithFrame:frame]) {
|
|
[self initState];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)initState
|
|
{
|
|
[self resetProps];
|
|
[self setupController];
|
|
|
|
_reactEventEmitter = [RNSStackScreenComponentEventEmitter new];
|
|
|
|
_hasUpdatedActivityMode = NO;
|
|
}
|
|
|
|
- (void)resetProps
|
|
{
|
|
static const auto defaultProps = std::make_shared<const react::RNSScreenStackProps>();
|
|
_props = defaultProps;
|
|
|
|
// container state
|
|
_screenKey = nil;
|
|
_activityMode = RNSStackScreenActivityModeDetached;
|
|
}
|
|
|
|
- (void)setupController
|
|
{
|
|
_controller = [[RNSStackScreenController alloc] initWithComponentView:self];
|
|
_controller.view = self;
|
|
}
|
|
|
|
- (void)invalidateImpl
|
|
{
|
|
// We want to run after container updates are performed (transitions etc.)
|
|
__weak auto weakSelf = self;
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
auto strongSelf = weakSelf;
|
|
if (strongSelf) {
|
|
strongSelf->_controller = nil;
|
|
}
|
|
});
|
|
}
|
|
|
|
#pragma mark - Events
|
|
|
|
- (nonnull RNSStackScreenComponentEventEmitter *)reactEventEmitter
|
|
{
|
|
RCTAssert(_reactEventEmitter != nil, @"[RNScreens] Attempt to access uninitialized _reactEventEmitter");
|
|
return _reactEventEmitter;
|
|
}
|
|
|
|
#pragma mark - RCTComponentViewProtocol
|
|
|
|
- (void)updateProps:(const facebook::react::Props::Shared &)props
|
|
oldProps:(const facebook::react::Props::Shared &)oldProps
|
|
{
|
|
const auto &oldComponentProps = *std::static_pointer_cast<const react::RNSStackScreenProps>(_props);
|
|
const auto &newComponentProps = *std::static_pointer_cast<const react::RNSStackScreenProps>(props);
|
|
|
|
if (oldComponentProps.activityMode != newComponentProps.activityMode) {
|
|
_activityMode = rnscreens::conversion::convert<RNSStackScreenActivityMode>(newComponentProps.activityMode);
|
|
_hasUpdatedActivityMode = YES;
|
|
}
|
|
|
|
if (oldComponentProps.screenKey != newComponentProps.screenKey) {
|
|
RCTAssert(_screenKey == nil, @"[RNScreens] ScreenController cannot change its screenKey");
|
|
_screenKey = RCTNSStringFromStringNilIfEmpty(newComponentProps.screenKey);
|
|
}
|
|
|
|
[super updateProps:props oldProps:oldProps];
|
|
}
|
|
|
|
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask
|
|
{
|
|
if (_hasUpdatedActivityMode) {
|
|
_hasUpdatedActivityMode = NO;
|
|
[self.stackHost stackScreenChangedActivityMode:self];
|
|
}
|
|
|
|
[super finalizeUpdates:updateMask];
|
|
}
|
|
|
|
- (void)updateEventEmitter:(const facebook::react::EventEmitter::Shared &)eventEmitter
|
|
{
|
|
[super updateEventEmitter:eventEmitter];
|
|
[_reactEventEmitter
|
|
updateEventEmitter:std::static_pointer_cast<const react::RNSStackScreenEventEmitter>(eventEmitter)];
|
|
}
|
|
|
|
+ (react::ComponentDescriptorProvider)componentDescriptorProvider
|
|
{
|
|
return react::concreteComponentDescriptorProvider<react::RNSStackScreenComponentDescriptor>();
|
|
}
|
|
|
|
+ (BOOL)shouldBeRecycled
|
|
{
|
|
// There won't be tens of instances of this component usually & it's easier for now.
|
|
// We could consider enabling it someday though.
|
|
return NO;
|
|
}
|
|
|
|
- (void)invalidate
|
|
{
|
|
[self invalidateImpl];
|
|
}
|
|
|
|
@end
|
|
|
|
Class<RCTComponentViewProtocol> RNSStackScreenCls(void)
|
|
{
|
|
return RNSStackScreenComponentView.class;
|
|
}
|