From 7a3d6aa0df46cf8a66d9c386d60d3ddb3ed2f88b Mon Sep 17 00:00:00 2001 From: Tushar Varshney Date: Wed, 3 Aug 2022 23:12:56 +0100 Subject: [PATCH 1/6] Add kotlin examples in new-architecture-app-modules-android.md --- docs/new-architecture-app-modules-android.md | 171 ++++++++++++++++++- 1 file changed, 169 insertions(+), 2 deletions(-) diff --git a/docs/new-architecture-app-modules-android.md b/docs/new-architecture-app-modules-android.md index 23a2a129e5a..3d6be11213c 100644 --- a/docs/new-architecture-app-modules-android.md +++ b/docs/new-architecture-app-modules-android.md @@ -4,6 +4,8 @@ title: Enabling TurboModule on Android --- import NewArchitectureWarning from './\_markdown-new-architecture-warning.mdx'; +import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +import constants from '@site/core/TabsConstants'; @@ -18,7 +20,7 @@ You can mitigate this by following the approach described in [Speeding up your B ::: -The code-gen will output some Java and some C++ code that now we need to build. +The code-gen will output some Java/Kotlin and some C++ code that now we need to build. Let’s edit your **module level** `build.gradle` to include the **two** `externalNativeBuild` blocks detailed below inside the `android{}` block: @@ -135,11 +137,14 @@ You can now verify that everything works correctly by running your android app: yarn react-native run-android ``` -## 2. Java - Provide a `ReactPackageTurboModuleManagerDelegate` +## 2. Java/Kotlin - Provide a `ReactPackageTurboModuleManagerDelegate` Now is time to actually use the TurboModule. First, we will need to create a `ReactPackageTurboModuleManagerDelegate` subclass, like the following: + + + ```java package com.awesomeproject; @@ -179,6 +184,52 @@ public class MyApplicationTurboModuleManagerDelegate extends ReactPackageTurboMo } ``` + + + + +```kotlin +package com.awesomeproject; + +import com.facebook.jni.HybridData +import com.facebook.react.ReactPackage +import com.facebook.react.ReactPackageTurboModuleManagerDelegate +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.soloader.SoLoader + +class MyApplicationTurboModuleManagerDelegate protected constructor( + reactApplicationContext: ReactApplicationContext?, + packages: List? +) : + ReactPackageTurboModuleManagerDelegate(reactApplicationContext, packages) { + protected external fun initHybrid(): HybridData? + class Builder : ReactPackageTurboModuleManagerDelegate.Builder() { + protected fun build( + context: ReactApplicationContext?, packages: List? + ): MyApplicationTurboModuleManagerDelegate { + return MyApplicationTurboModuleManagerDelegate(context, packages) + } + } + + @Synchronized + protected fun maybeLoadOtherSoLibraries() { + // Prevents issues with initializer interruptions. + if (!sIsSoLibraryLoaded) { + SoLoader.loadLibrary("myapplication_appmodules") + sIsSoLibraryLoaded = true + } + } + + companion object { + @Volatile + private var sIsSoLibraryLoaded = false + } +} +``` + + + + Please note that the `SoLoader.loadLibrary` parameter (in this case `"myapplication_appmodules")` should be the same as the one specified for `LOCAL_MODULE :=` inside the `Android.mk` file you created before. This class will then be responsible of loading the TurboModules and will take care of loading the native library build with the NDK at runtime. @@ -189,6 +240,9 @@ Then, you can provide the class you created to your `ReactNativeHost`. You can l Once you located it, you need to add the `getReactPackageTurboModuleManagerDelegateBuilder` method as from the snippet below: + + + ```java public class MyApplication extends Application implements ReactApplication { @@ -212,10 +266,39 @@ public class MyApplication extends Application implements ReactApplication { } ``` + + + +```kotlin +class MyApplication : Application(), ReactApplication { + private val mReactNativeHost: ReactNativeHost = object : ReactNativeHost(this) { + /* ... */ + val useDeveloperSupport: Boolean + get() { /* ... */ } + + /* ... */ + protected val packages: List + protected get() { /* ... */ } + + /* ... */ + protected val jSMainModuleName: String + protected get() { /* ... */ } + protected val reactPackageTurboModuleManagerDelegateBuilder: ReactPackageTurboModuleManagerDelegate.Builder + protected get() = Builder() + } +} +``` + + + + ## 4. Extend the `getPackages()` from your `ReactNativeHost` to use the TurboModule Still on the `ReactNativeHost` , we need to extend the the `getPackages()` method to include the newly created TurboModule. Update the method to include the following: + + + ```java public class MyApplication extends Application implements ReactApplication { @@ -272,8 +355,72 @@ public class MyApplication extends Application implements ReactApplication { return new MyApplicationTurboModuleManagerDelegate.Builder(); } }; +} +``` + + + + +```kotlin +class MyApplication() : Application(), ReactApplication { + private val mReactNativeHost: ReactNativeHost = object : ReactNativeHost(this) { + /* ... */ + val useDeveloperSupport: Boolean + get() { /* ... */ } + + val packages: List + protected get() { + val packages: MutableList = PackageList(this).getPackages() + + // Add those lines + packages.add(object : TurboReactPackage() { + @Nullable + fun getModule( + name: String, + reactContext: ReactApplicationContext? + ): NativeModule? { + if ((name == NativeAwesomeManager.NAME)) { + return NativeAwesomeManager(reactContext) + } else { + return null + } + } + + val reactModuleInfoProvider: ReactModuleInfoProvider + get() = ReactModuleInfoProvider { + val moduleInfos: MutableMap = + HashMap() + moduleInfos.put( + NativeAwesomeManager.NAME, + ReactModuleInfo( + NativeAwesomeManager.NAME, + "NativeAwesomeManager", + false, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + true // isTurboModule + ) + ) + moduleInfos + } + }) + return packages + } + + protected fun getJSMainModuleName(): String { /* ... */ + } + + protected fun getReactPackageTurboModuleManagerDelegateBuilder(): ReactPackageTurboModuleManagerDelegate.Builder { + return Builder() + } + } +} ``` + + + ## 5. C++ Provide a native implementation for the methods in your `*TurboModuleDelegate` class If you take a closer look at the class `MyApplicationTurboModuleManagerDelegate` that you created before, you will notice how some of the methods are `native`. @@ -422,6 +569,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { Now you can finally enable the `TurboModule `support in your Application. To do so, you need to turn on the `useTurboModule` flag inside your Application `onCreate` method. + + + ```java public class MyApplication extends Application implements ReactApplication { @@ -430,8 +580,25 @@ public class MyApplication extends Application implements ReactApplication { ReactFeatureFlags.useTurboModules = true; //... } +} +``` + + + + + +```kotlin +class MyApplication : Application(), ReactApplication { + fun onCreate() { + ReactFeatureFlags.useTurboModules = true + //... + } +} ``` + + + It’s now time to run again your Android app to verify that everything works correctly: ```bash From 8b2f0e9522c8d683a3e341b45c50230c1491a9cd Mon Sep 17 00:00:00 2001 From: Tushar Varshney Date: Wed, 3 Aug 2022 23:28:07 +0100 Subject: [PATCH 2/6] Format all kotlin classes using https://facebookincubator.github.io/ktfmt/ --- docs/new-architecture-app-modules-android.md | 154 ++++++++++--------- 1 file changed, 84 insertions(+), 70 deletions(-) diff --git a/docs/new-architecture-app-modules-android.md b/docs/new-architecture-app-modules-android.md index 3d6be11213c..4a547828fba 100644 --- a/docs/new-architecture-app-modules-android.md +++ b/docs/new-architecture-app-modules-android.md @@ -189,7 +189,7 @@ public class MyApplicationTurboModuleManagerDelegate extends ReactPackageTurboMo ```kotlin -package com.awesomeproject; +package com.awesomeproject import com.facebook.jni.HybridData import com.facebook.react.ReactPackage @@ -197,15 +197,16 @@ import com.facebook.react.ReactPackageTurboModuleManagerDelegate import com.facebook.react.bridge.ReactApplicationContext import com.facebook.soloader.SoLoader -class MyApplicationTurboModuleManagerDelegate protected constructor( +class MyApplicationTurboModuleManagerDelegate +protected constructor( reactApplicationContext: ReactApplicationContext?, packages: List? -) : - ReactPackageTurboModuleManagerDelegate(reactApplicationContext, packages) { +) : ReactPackageTurboModuleManagerDelegate(reactApplicationContext, packages) { protected external fun initHybrid(): HybridData? class Builder : ReactPackageTurboModuleManagerDelegate.Builder() { protected fun build( - context: ReactApplicationContext?, packages: List? + context: ReactApplicationContext?, + packages: List? ): MyApplicationTurboModuleManagerDelegate { return MyApplicationTurboModuleManagerDelegate(context, packages) } @@ -221,8 +222,7 @@ class MyApplicationTurboModuleManagerDelegate protected constructor( } companion object { - @Volatile - private var sIsSoLibraryLoaded = false + @Volatile private var sIsSoLibraryLoaded = false } } ``` @@ -271,21 +271,29 @@ public class MyApplication extends Application implements ReactApplication { ```kotlin class MyApplication : Application(), ReactApplication { - private val mReactNativeHost: ReactNativeHost = object : ReactNativeHost(this) { - /* ... */ - val useDeveloperSupport: Boolean - get() { /* ... */ } - - /* ... */ - protected val packages: List - protected get() { /* ... */ } - - /* ... */ - protected val jSMainModuleName: String - protected get() { /* ... */ } - protected val reactPackageTurboModuleManagerDelegateBuilder: ReactPackageTurboModuleManagerDelegate.Builder - protected get() = Builder() - } + private val mReactNativeHost: ReactNativeHost = + object : ReactNativeHost(this) { + /* ... */ + val useDeveloperSupport: Boolean + get() { + /* ... */ + } + + /* ... */ + protected val packages: List + protected get() { + /* ... */ + } + + /* ... */ + protected val jSMainModuleName: String + protected get() { + /* ... */ + } + protected val reactPackageTurboModuleManagerDelegateBuilder: + ReactPackageTurboModuleManagerDelegate.Builder + protected get() = Builder() + } } ``` @@ -363,58 +371,64 @@ public class MyApplication extends Application implements ReactApplication { ```kotlin class MyApplication() : Application(), ReactApplication { - private val mReactNativeHost: ReactNativeHost = object : ReactNativeHost(this) { - /* ... */ - val useDeveloperSupport: Boolean - get() { /* ... */ } - - val packages: List - protected get() { - val packages: MutableList = PackageList(this).getPackages() - - // Add those lines - packages.add(object : TurboReactPackage() { - @Nullable - fun getModule( - name: String, - reactContext: ReactApplicationContext? - ): NativeModule? { - if ((name == NativeAwesomeManager.NAME)) { - return NativeAwesomeManager(reactContext) - } else { - return null + private val mReactNativeHost: ReactNativeHost = + object : ReactNativeHost(this) { + /* ... */ + val useDeveloperSupport: Boolean + get() { + /* ... */ + } + + val packages: List + protected get() { + val packages: MutableList = PackageList(this).getPackages() + + // Add those lines + packages.add( + object : TurboReactPackage() { + @Nullable + fun getModule( + name: String, + reactContext: ReactApplicationContext? + ): NativeModule? { + if ((name == NativeAwesomeManager.NAME)) { + return NativeAwesomeManager(reactContext) + } else { + return null + } + } + + val reactModuleInfoProvider: ReactModuleInfoProvider + get() = ReactModuleInfoProvider { + val moduleInfos: MutableMap = HashMap() + moduleInfos.put( + NativeAwesomeManager.NAME, + ReactModuleInfo( + NativeAwesomeManager.NAME, + "NativeAwesomeManager", + false, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + true // isTurboModule + ) + ) + moduleInfos + } } - } + ) + return packages + } - val reactModuleInfoProvider: ReactModuleInfoProvider - get() = ReactModuleInfoProvider { - val moduleInfos: MutableMap = - HashMap() - moduleInfos.put( - NativeAwesomeManager.NAME, - ReactModuleInfo( - NativeAwesomeManager.NAME, - "NativeAwesomeManager", - false, // canOverrideExistingModule - false, // needsEagerInit - true, // hasConstants - false, // isCxxModule - true // isTurboModule - ) - ) - moduleInfos - } - }) - return packages + protected fun getJSMainModuleName(): String { + /* ... */ } - protected fun getJSMainModuleName(): String { /* ... */ - } - - protected fun getReactPackageTurboModuleManagerDelegateBuilder(): ReactPackageTurboModuleManagerDelegate.Builder { - return Builder() + protected fun getReactPackageTurboModuleManagerDelegateBuilder(): + ReactPackageTurboModuleManagerDelegate.Builder { + return Builder() + } } - } } ``` @@ -591,7 +605,7 @@ public class MyApplication extends Application implements ReactApplication { class MyApplication : Application(), ReactApplication { fun onCreate() { ReactFeatureFlags.useTurboModules = true - //... + // ... } } ``` From 8472488e3e4c3896c652a788afa1d45300a4ebc4 Mon Sep 17 00:00:00 2001 From: Tushar Varshney Date: Thu, 4 Aug 2022 17:05:16 +0100 Subject: [PATCH 3/6] Fixed code review comments in kotlin files --- docs/new-architecture-app-modules-android.md | 145 +++++++++---------- 1 file changed, 68 insertions(+), 77 deletions(-) diff --git a/docs/new-architecture-app-modules-android.md b/docs/new-architecture-app-modules-android.md index 4a547828fba..5f9c23970ac 100644 --- a/docs/new-architecture-app-modules-android.md +++ b/docs/new-architecture-app-modules-android.md @@ -20,7 +20,7 @@ You can mitigate this by following the approach described in [Speeding up your B ::: -The code-gen will output some Java/Kotlin and some C++ code that now we need to build. +The code-gen will output some Java and some C++ code that now we need to build. Let’s edit your **module level** `build.gradle` to include the **two** `externalNativeBuild` blocks detailed below inside the `android{}` block: @@ -199,14 +199,14 @@ import com.facebook.soloader.SoLoader class MyApplicationTurboModuleManagerDelegate protected constructor( - reactApplicationContext: ReactApplicationContext?, - packages: List? + reactApplicationContext: ReactApplicationContext, + packages: List ) : ReactPackageTurboModuleManagerDelegate(reactApplicationContext, packages) { protected external fun initHybrid(): HybridData? class Builder : ReactPackageTurboModuleManagerDelegate.Builder() { protected fun build( - context: ReactApplicationContext?, - packages: List? + context: ReactApplicationContext, + packages: List ): MyApplicationTurboModuleManagerDelegate { return MyApplicationTurboModuleManagerDelegate(context, packages) } @@ -246,7 +246,7 @@ Once you located it, you need to add the `getReactPackageTurboModuleManagerDeleg ```java public class MyApplication extends Application implements ReactApplication { - private final ReactNativeHost mReactNativeHost = + private final ReactNativeHost reactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { /* ... */ } @@ -271,28 +271,26 @@ public class MyApplication extends Application implements ReactApplication { ```kotlin class MyApplication : Application(), ReactApplication { - private val mReactNativeHost: ReactNativeHost = + private val reactNativeHost: ReactNativeHost = object : ReactNativeHost(this) { - /* ... */ - val useDeveloperSupport: Boolean - get() { - /* ... */ - } - - /* ... */ - protected val packages: List - protected get() { - /* ... */ - } - - /* ... */ - protected val jSMainModuleName: String - protected get() { - /* ... */ - } - protected val reactPackageTurboModuleManagerDelegateBuilder: - ReactPackageTurboModuleManagerDelegate.Builder - protected get() = Builder() + + override fun getUseDeveloperSupport(): Boolean { + /* ... */ + } + + override fun getPackages(): List? { + /* ... */ + } + + override fun getJSMainModuleName(): String? { + /* ... */ + } + + @NonNull + override fun getReactPackageTurboModuleManagerDelegateBuilder(): + ReactPackageTurboModuleManagerDelegate.Builder? { + return Builder() + } } } ``` @@ -310,7 +308,7 @@ Still on the `ReactNativeHost` , we need to extend the the `getPackages()` metho ```java public class MyApplication extends Application implements ReactApplication { - private final ReactNativeHost mReactNativeHost = + private final ReactNativeHost reactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { /* ... */ } @@ -371,61 +369,54 @@ public class MyApplication extends Application implements ReactApplication { ```kotlin class MyApplication() : Application(), ReactApplication { - private val mReactNativeHost: ReactNativeHost = + private val reactNativeHost: ReactNativeHost = object : ReactNativeHost(this) { - /* ... */ - val useDeveloperSupport: Boolean - get() { - /* ... */ - } - - val packages: List - protected get() { - val packages: MutableList = PackageList(this).getPackages() - - // Add those lines - packages.add( - object : TurboReactPackage() { - @Nullable - fun getModule( - name: String, - reactContext: ReactApplicationContext? - ): NativeModule? { - if ((name == NativeAwesomeManager.NAME)) { - return NativeAwesomeManager(reactContext) - } else { - return null - } + override fun getUseDeveloperSupport(): Boolean { + /* ... */ + } + + override protected fun getPackages(): List? { + val packages: MutableList = PackageList(this).getPackages() + + // Add those lines + packages.add( + object : TurboReactPackage() { + @Nullable + override fun getModule( + name: String, + reactContext: ReactApplicationContext? + ): NativeModule? = + if ((name == NativeAwesomeManager.NAME)) { + NativeAwesomeManager(reactContext) + } else { + null } - val reactModuleInfoProvider: ReactModuleInfoProvider - get() = ReactModuleInfoProvider { - val moduleInfos: MutableMap = HashMap() - moduleInfos.put( - NativeAwesomeManager.NAME, - ReactModuleInfo( - NativeAwesomeManager.NAME, - "NativeAwesomeManager", - false, // canOverrideExistingModule - false, // needsEagerInit - true, // hasConstants - false, // isCxxModule - true // isTurboModule - ) - ) - moduleInfos - } - } - ) - return packages - } + override fun getReactModuleInfoProvider() = + mutableMapOf( + NativeAwesomeManager.NAME, + ReactModuleInfo( + NativeAwesomeManager.NAME, + "NativeAwesomeManager", + false, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + true // isTurboModule + ) + ) + } + ) + return packages + } - protected fun getJSMainModuleName(): String { + override protected fun getJSMainModuleName(): String? { /* ... */ } - protected fun getReactPackageTurboModuleManagerDelegateBuilder(): - ReactPackageTurboModuleManagerDelegate.Builder { + @NonNull + override protected fun getReactPackageTurboModuleManagerDelegateBuilder(): + ReactPackageTurboModuleManagerDelegate.Builder? { return Builder() } } @@ -603,7 +594,7 @@ public class MyApplication extends Application implements ReactApplication { ```kotlin class MyApplication : Application(), ReactApplication { - fun onCreate() { + override fun onCreate() { ReactFeatureFlags.useTurboModules = true // ... } From ee3a105d7a0d461126fa3c8aac6625ecf8aba2d3 Mon Sep 17 00:00:00 2001 From: Tushar Varshney Date: Thu, 4 Aug 2022 18:20:49 +0100 Subject: [PATCH 4/6] Add override in MyApplicationTurboModuleManagerDelegate methods in kotlin class --- docs/new-architecture-app-modules-android.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/new-architecture-app-modules-android.md b/docs/new-architecture-app-modules-android.md index 5f9c23970ac..1d17b05417c 100644 --- a/docs/new-architecture-app-modules-android.md +++ b/docs/new-architecture-app-modules-android.md @@ -202,9 +202,9 @@ protected constructor( reactApplicationContext: ReactApplicationContext, packages: List ) : ReactPackageTurboModuleManagerDelegate(reactApplicationContext, packages) { - protected external fun initHybrid(): HybridData? + override protected external fun initHybrid(): HybridData? class Builder : ReactPackageTurboModuleManagerDelegate.Builder() { - protected fun build( + override protected fun build( context: ReactApplicationContext, packages: List ): MyApplicationTurboModuleManagerDelegate { @@ -213,7 +213,7 @@ protected constructor( } @Synchronized - protected fun maybeLoadOtherSoLibraries() { + override protected fun maybeLoadOtherSoLibraries() { // Prevents issues with initializer interruptions. if (!sIsSoLibraryLoaded) { SoLoader.loadLibrary("myapplication_appmodules") From 18841027c758af3014722f268589f5ab50bb394d Mon Sep 17 00:00:00 2001 From: Tushar Varshney Date: Fri, 5 Aug 2022 11:59:32 +0100 Subject: [PATCH 5/6] Fixed code comments, Format the code according to the java/kotlin guidelines --- docs/new-architecture-app-modules-android.md | 22 +++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/docs/new-architecture-app-modules-android.md b/docs/new-architecture-app-modules-android.md index 1d17b05417c..b25fafad849 100644 --- a/docs/new-architecture-app-modules-android.md +++ b/docs/new-architecture-app-modules-android.md @@ -202,27 +202,27 @@ protected constructor( reactApplicationContext: ReactApplicationContext, packages: List ) : ReactPackageTurboModuleManagerDelegate(reactApplicationContext, packages) { + override protected external fun initHybrid(): HybridData? class Builder : ReactPackageTurboModuleManagerDelegate.Builder() { override protected fun build( context: ReactApplicationContext, packages: List - ): MyApplicationTurboModuleManagerDelegate { - return MyApplicationTurboModuleManagerDelegate(context, packages) - } + ): MyApplicationTurboModuleManagerDelegate = + MyApplicationTurboModuleManagerDelegate(context, packages) } @Synchronized override protected fun maybeLoadOtherSoLibraries() { // Prevents issues with initializer interruptions. - if (!sIsSoLibraryLoaded) { + if (!isSoLibraryLoaded) { SoLoader.loadLibrary("myapplication_appmodules") - sIsSoLibraryLoaded = true + isSoLibraryLoaded = true } } companion object { - @Volatile private var sIsSoLibraryLoaded = false + @Volatile private var isSoLibraryLoaded = false } } ``` @@ -246,7 +246,7 @@ Once you located it, you need to add the `getReactPackageTurboModuleManagerDeleg ```java public class MyApplication extends Application implements ReactApplication { - private final ReactNativeHost reactNativeHost = + private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { /* ... */ } @@ -287,10 +287,8 @@ class MyApplication : Application(), ReactApplication { } @NonNull - override fun getReactPackageTurboModuleManagerDelegateBuilder(): - ReactPackageTurboModuleManagerDelegate.Builder? { - return Builder() - } + override fun getReactPackageTurboModuleManagerDelegateBuilder() = + ReactPackageTurboModuleManagerDelegate.Builder() } } ``` @@ -308,7 +306,7 @@ Still on the `ReactNativeHost` , we need to extend the the `getPackages()` metho ```java public class MyApplication extends Application implements ReactApplication { - private final ReactNativeHost reactNativeHost = + private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { /* ... */ } From db640801f29a6779b039e89ddd16200feae2cf4d Mon Sep 17 00:00:00 2001 From: Tushar Varshney Date: Fri, 5 Aug 2022 12:11:59 +0100 Subject: [PATCH 6/6] Add inline space around functions --- docs/new-architecture-app-modules-android.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/new-architecture-app-modules-android.md b/docs/new-architecture-app-modules-android.md index b25fafad849..4891fd9690e 100644 --- a/docs/new-architecture-app-modules-android.md +++ b/docs/new-architecture-app-modules-android.md @@ -367,6 +367,7 @@ public class MyApplication extends Application implements ReactApplication { ```kotlin class MyApplication() : Application(), ReactApplication { + private val reactNativeHost: ReactNativeHost = object : ReactNativeHost(this) { override fun getUseDeveloperSupport(): Boolean { @@ -592,6 +593,7 @@ public class MyApplication extends Application implements ReactApplication { ```kotlin class MyApplication : Application(), ReactApplication { + override fun onCreate() { ReactFeatureFlags.useTurboModules = true // ...