Skip to content

refactor: share one UIHingeInteraction factory across the iOS module and view - #12

Merged
janicduplessis merged 1 commit into
mainfrom
@janic/ios-hinge-interaction-helper
Sep 21, 2026
Merged

janicduplessis merged 1 commit into
mainfrom
@janic/ios-hinge-interaction-helper

Conversation

@janicduplessis

Copy link
Copy Markdown
Contributor

Description

The iOS TurboModule and the Fabric observer view each built their own UIHingeInteraction. Both carried the same __IPHONE_27_1 compile guard, the same @available(iOS 27.1, *) check, and the same UIHinge.status to string mapping, so any change to the hinge mapping had to be made twice and kept in sync by hand. Android already routes both of its consumers through a single HingeSource.

Solution

ios/HingeInteraction.mm now owns the SDK guard, the availability check, the interaction construction and the status/angle mapping, and hands the caller a plain payload array. Call sites just supply a handler. HingesMakeInteraction returns nil when the feature is unavailable, from an old SDK or a pre-27.1 runtime; both call sites then attach nothing and keep an empty snapshot, exactly as the module already behaved when it had no root view.

No behavior change.

Not covered: the only iOS reading available here is closed at 0 degrees, so the rest of the status mapping stays exercised only by the Android end to end check. No real foldable device, and no changing angle.

Test plan

iPhone Duo simulator on the iOS 27.1 runtime, built with Xcode 27.1 beta, Sensor lab:

  • the NATIVE HINGE pill and NATIVE ANGLE 0.0° / closed come from the Fabric view path
  • React hook: 0.000 rad · Observer: 0.000 rad comes from the TurboModule path, covering both the useHinges hook and a standalone createHingeObserver

Compile guard: built the Hinges pod target against the iOS 27.0 SDK with the default Xcode for generic/platform=iOS Simulator. It compiles clean, and nm -u on HingeInteraction.o lists only _objc_storeStrong, so nothing links against UIHingeInteraction when the SDK lacks it.

…and view

The TurboModule and the Fabric observer view each carried their own SDK compile guard, iOS 27.1 availability check, UIHingeInteraction construction and UIHinge status mapping. A new HingesMakeInteraction helper owns all of that and hands each call site the same payload shape, matching how Android shares HingeSource. Behavior is unchanged.
Comment thread ios/HingeInteraction.h
typedef void (^HingesUpdateHandler)(NSArray<NSDictionary *> *hinges);

/// Returns nil when the SDK or runtime has no UIHingeInteraction.
id<UIInteraction> _Nullable HingesMakeInteraction(HingesUpdateHandler handler);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning id<UIInteraction> rather than UIHingeInteraction * keeps this header buildable on SDKs that have no UIHingeInteraction declaration, so the guard stays confined to the .mm.

@janicduplessis
janicduplessis marked this pull request as ready for review September 21, 2026 13:45
@janicduplessis
janicduplessis merged commit f38954e into main Sep 21, 2026
3 checks passed
@janicduplessis
janicduplessis deleted the @janic/ios-hinge-interaction-helper branch September 21, 2026 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant