diff --git a/ios/HingeInteraction.h b/ios/HingeInteraction.h new file mode 100644 index 0000000..f937155 --- /dev/null +++ b/ios/HingeInteraction.h @@ -0,0 +1,10 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^HingesUpdateHandler)(NSArray *hinges); + +/// Returns nil when the SDK or runtime has no UIHingeInteraction. +id _Nullable HingesMakeInteraction(HingesUpdateHandler handler); + +NS_ASSUME_NONNULL_END diff --git a/ios/HingeInteraction.mm b/ios/HingeInteraction.mm new file mode 100644 index 0000000..3271471 --- /dev/null +++ b/ios/HingeInteraction.mm @@ -0,0 +1,26 @@ +#import "HingeInteraction.h" + +id HingesMakeInteraction(HingesUpdateHandler handler) +{ +#if defined(__IPHONE_27_1) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_27_1 + if (@available(iOS 27.1, *)) { + return [[UIHingeInteraction alloc] + initWithUpdateHandler:^(UIHingeInteraction *interaction, UIHingeInteractionUpdate *update) { + UIHinge *hinge = update.hinge; + if (hinge == nil) { + handler(@[]); + return; + } + NSString *status = @"unknown"; + switch (hinge.status) { + case UIHingeStatusClosed: status = @"closed"; break; + case UIHingeStatusPartiallyOpen: status = @"partiallyOpen"; break; + case UIHingeStatusFullyOpen: status = @"fullyOpen"; break; + case UIHingeStatusUnknown: break; + } + handler(@[@{@"status": status, @"angle": @(hinge.angle), @"hasAngle": @YES}]); + }]; + } +#endif + return nil; +} diff --git a/ios/HingesModule.mm b/ios/HingesModule.mm index 3a6edbe..cdb74c1 100644 --- a/ios/HingesModule.mm +++ b/ios/HingesModule.mm @@ -1,5 +1,7 @@ #import "HingesModule.h" +#import "HingeInteraction.h" + #import #import #import @@ -88,35 +90,20 @@ - (void)startObserving:(double)rootTag if (observation.interaction == nil) { UIView *view = [self->_surfacePresenter surfaceForRootTag:tag.integerValue].view; observation.view = view; -#if defined(__IPHONE_27_1) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_27_1 - if (@available(iOS 27.1, *)) { - if (view != nil) { - __weak HingesModule *weakSelf = self; - __weak HingeRootObservation *weakObservation = observation; - UIHingeInteraction *interaction = [[UIHingeInteraction alloc] - initWithUpdateHandler:^(UIHingeInteraction *interaction, UIHingeInteractionUpdate *update) { - HingesModule *strongSelf = weakSelf; - HingeRootObservation *strongObservation = weakObservation; - if (strongSelf == nil || strongObservation == nil) return; - UIHinge *hinge = update.hinge; - NSArray *hinges = @[]; - if (hinge != nil) { - NSString *status = @"unknown"; - switch (hinge.status) { - case UIHingeStatusClosed: status = @"closed"; break; - case UIHingeStatusPartiallyOpen: status = @"partiallyOpen"; break; - case UIHingeStatusFullyOpen: status = @"fullyOpen"; break; - case UIHingeStatusUnknown: break; - } - hinges = @[@{@"status": status, @"angle": @(hinge.angle), @"hasAngle": @YES}]; - } - [strongSelf updateRoot:tag observation:strongObservation hinges:hinges]; - }]; + if (view != nil) { + __weak HingesModule *weakSelf = self; + __weak HingeRootObservation *weakObservation = observation; + id interaction = HingesMakeInteraction(^(NSArray *hinges) { + HingesModule *strongSelf = weakSelf; + HingeRootObservation *strongObservation = weakObservation; + if (strongSelf == nil || strongObservation == nil) return; + [strongSelf updateRoot:tag observation:strongObservation hinges:hinges]; + }); + if (interaction != nil) { observation.interaction = interaction; [view addInteraction:interaction]; } } -#endif } [self emitSnapshotForRoot:tag hinges:[self getSnapshot:rootTag][@"hinges"]]; }); diff --git a/ios/HingesObserverView.mm b/ios/HingesObserverView.mm index c8386a0..82649d2 100644 --- a/ios/HingesObserverView.mm +++ b/ios/HingesObserverView.mm @@ -1,5 +1,7 @@ #import "HingesObserverView.h" +#import "HingeInteraction.h" + #import #import #import @@ -26,31 +28,21 @@ - (instancetype)initWithFrame:(CGRect)frame if (self = [super initWithFrame:frame]) { static const auto defaultProps = std::make_shared(); _props = defaultProps; -#if defined(__IPHONE_27_1) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_27_1 - if (@available(iOS 27.1, *)) { - __weak HingesObserverView *weakSelf = self; - UIHingeInteraction *interaction = [[UIHingeInteraction alloc] - initWithUpdateHandler:^(UIHingeInteraction *interaction, UIHingeInteractionUpdate *update) { - HingesObserverView *strongSelf = weakSelf; - if (strongSelf == nil) return; - HingesObserverViewEventEmitter::OnHingesChange snapshot; - UIHinge *hinge = update.hinge; - if (hinge != nil) { - std::string status = "unknown"; - switch (hinge.status) { - case UIHingeStatusClosed: status = "closed"; break; - case UIHingeStatusPartiallyOpen: status = "partiallyOpen"; break; - case UIHingeStatusFullyOpen: status = "fullyOpen"; break; - case UIHingeStatusUnknown: break; - } - snapshot.hinges.push_back({status, hinge.angle, true}); - } - strongSelf->_snapshot = std::move(snapshot); - [strongSelf emitSnapshot]; - }]; + __weak HingesObserverView *weakSelf = self; + id interaction = HingesMakeInteraction(^(NSArray *hinges) { + HingesObserverView *strongSelf = weakSelf; + if (strongSelf == nil) return; + HingesObserverViewEventEmitter::OnHingesChange snapshot; + for (NSDictionary *hinge in hinges) { + snapshot.hinges.push_back( + {[hinge[@"status"] UTF8String], [hinge[@"angle"] doubleValue], [hinge[@"hasAngle"] boolValue]}); + } + strongSelf->_snapshot = std::move(snapshot); + [strongSelf emitSnapshot]; + }); + if (interaction != nil) { [self addInteraction:interaction]; } -#endif } return self; }