voize-gmbh / reakt-native-toolkit

Combine React Native with Kotlin Multiplatform (KMP)
Apache License 2.0
124 stars 4 forks source link

View manager props #67

Closed erksch closed 2 weeks ago

erksch commented 3 weeks ago

This MR adds the capability to annotate Compose function parameters with @ReactNativeProp to make them settable from React Native.

Android

For Android, supporting props is straight-forward. Each prop gets a setter annotated with @ReactProp in the generated SimpleViewManager<ComposeView> subclass (see React Native docs on this). The setter emits a value into shared flow which is passed into the compose function.

For callback parameters of the compose function we generate implementations of the callback according to the React Native Android view manager event docs.

By generating all this into the view manager everything works out of the box.

iOS

On iOS, this is much more tricky.

Firstly, React Native requires the that you add RCT_EXPORT_VIEW_PROPERTY on your RCTViewManager implementation which under hood creates a class method propConfig_<name>. There is no way to write a Kotlin class in ios source sets so that it has class methods so we need to get rid of the Kotlin subclassing of RCTViewManager (and remove the interop) and instead generate the subclass in Objective-C code so we can set the class methods properly.

Secondly, when React Native picked which props exist via the RCT_EXPORT_VIEW_PROPERTY methods it calls the method directly the UIView returned by the view manager (you can circumvent this using RCT_CUSTOM_VIEW_PROPERTY but it is true at least for callback props). Now we run into the second Kotlin / Objective-C interop problem: We can not create a class in Kotlin ios source sets that subclasses an Objective-C type (UIView in this case) and add methods to it that are callable from Objective-C. So we also need to generate the UIView subclass as Objective-C code and add the Compose view as a subview to it.

So on iOS we have 3 components:

We generate all Objecitve-C code in one header and one implementation file that the library user has to include in their XCode project.

Future work

erksch commented 3 weeks ago

https://github.com/user-attachments/assets/c454320c-ddb1-4108-ba61-aca606d64fe3

https://github.com/user-attachments/assets/ebcb9d09-8aa5-480e-89a2-5b2e2a71a280