diff --git a/autolink/fixtures/rn72/MainActivity.java.template b/autolink/fixtures/rn72/MainActivity.java.template new file mode 100644 index 00000000000..3cbe89b48fa --- /dev/null +++ b/autolink/fixtures/rn72/MainActivity.java.template @@ -0,0 +1,32 @@ +package com.app; + +import com.facebook.react.ReactActivity; +import com.facebook.react.ReactActivityDelegate; +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; +import com.facebook.react.defaults.DefaultReactActivityDelegate; + +public class MainActivity extends ReactActivity { + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + @Override + protected String getMainComponentName() { + return "App"; + } + + /** + * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link + * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React + * (aka React 18) with two boolean flags. + */ + @Override + protected ReactActivityDelegate createReactActivityDelegate() { + return new DefaultReactActivityDelegate( + this, + getMainComponentName(), + // If you opted-in for the New Architecture, we enable the Fabric Renderer. + DefaultNewArchitectureEntryPoint.getFabricEnabled()); + } +} diff --git a/autolink/fixtures/rn72/MainApplication.java.template b/autolink/fixtures/rn72/MainApplication.java.template new file mode 100644 index 00000000000..659f3a0a643 --- /dev/null +++ b/autolink/fixtures/rn72/MainApplication.java.template @@ -0,0 +1,62 @@ +package com.app; + +import android.app.Application; +import com.facebook.react.PackageList; +import com.facebook.react.ReactApplication; +import com.facebook.react.ReactNativeHost; +import com.facebook.react.ReactPackage; +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; +import com.facebook.react.defaults.DefaultReactNativeHost; +import com.facebook.soloader.SoLoader; +import java.util.List; + +public class MainApplication extends Application implements ReactApplication { + + private final ReactNativeHost mReactNativeHost = + new DefaultReactNativeHost(this) { + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List getPackages() { + @SuppressWarnings("UnnecessaryLocalVariable") + List packages = new PackageList(this).getPackages(); + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + return packages; + } + + @Override + protected String getJSMainModuleName() { + return "index"; + } + + @Override + protected boolean isNewArchEnabled() { + return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + } + + @Override + protected Boolean isHermesEnabled() { + return BuildConfig.IS_HERMES_ENABLED; + } + }; + + @Override + public ReactNativeHost getReactNativeHost() { + return mReactNativeHost; + } + + @Override + public void onCreate() { + super.onCreate(); + SoLoader.init(this, /* native exopackage */ false); + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + DefaultNewArchitectureEntryPoint.load(); + } + ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + } +} diff --git a/autolink/fixtures/rn73/MainActivity.kt.template b/autolink/fixtures/rn73/MainActivity.kt.template new file mode 100644 index 00000000000..5345a1d439a --- /dev/null +++ b/autolink/fixtures/rn73/MainActivity.kt.template @@ -0,0 +1,22 @@ +package com.app + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +class MainActivity : ReactActivity() { + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + override fun getMainComponentName(): String = "App" + + /** + * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] + * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] + */ + override fun createReactActivityDelegate(): ReactActivityDelegate = + DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) +} diff --git a/autolink/fixtures/rn73/MainApplication.kt.template b/autolink/fixtures/rn73/MainApplication.kt.template new file mode 100644 index 00000000000..4b77eb58830 --- /dev/null +++ b/autolink/fixtures/rn73/MainApplication.kt.template @@ -0,0 +1,45 @@ +package com.app + +import android.app.Application +import com.facebook.react.PackageList +import com.facebook.react.ReactApplication +import com.facebook.react.ReactHost +import com.facebook.react.ReactNativeHost +import com.facebook.react.ReactPackage +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load +import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost +import com.facebook.react.defaults.DefaultReactNativeHost +import com.facebook.react.flipper.ReactNativeFlipper +import com.facebook.soloader.SoLoader + +class MainApplication : Application(), ReactApplication { + + override val reactNativeHost: ReactNativeHost = + object : DefaultReactNativeHost(this) { + override fun getPackages(): List = + PackageList(this).packages.apply { + // Packages that cannot be autolinked yet can be added manually here, for example: + // add(MyReactNativePackage()) + } + + override fun getJSMainModuleName(): String = "index" + + override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG + + override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED + } + + override val reactHost: ReactHost + get() = getDefaultReactHost(this.applicationContext, reactNativeHost) + + override fun onCreate() { + super.onCreate() + SoLoader.init(this, false) + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + load() + } + ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager) + } +} diff --git a/autolink/postlink/__snapshots__/activityLinker.test.js.snap b/autolink/postlink/__snapshots__/activityLinker.test.js.snap index c08caa6e5b6..42023ace473 100644 --- a/autolink/postlink/__snapshots__/activityLinker.test.js.snap +++ b/autolink/postlink/__snapshots__/activityLinker.test.js.snap @@ -67,7 +67,6 @@ public class MainActivity extends NavigationActivity { " `; - exports[`activityLinker should work for RN 0.71 1`] = ` "package com.app; @@ -81,6 +80,40 @@ public class MainActivity extends NavigationActivity { +} +" +`; + +exports[`activityLinker should work for RN 0.72 1`] = ` +"package com.app; + +import com.reactnativenavigation.NavigationActivity; +import com.facebook.react.ReactActivityDelegate; +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; +import com.facebook.react.defaults.DefaultReactActivityDelegate; + +public class MainActivity extends NavigationActivity { + + + + +} +" +`; + +exports[`activityLinker should work for RN 0.73 1`] = ` +"package com.app + +import com.reactnativenavigation.NavigationActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +class MainActivity : NavigationActivity() { + + + + } " `; diff --git a/autolink/postlink/__snapshots__/applicationLinker.test.js.snap b/autolink/postlink/__snapshots__/applicationLinker.test.js.snap new file mode 100644 index 00000000000..76d901979f3 --- /dev/null +++ b/autolink/postlink/__snapshots__/applicationLinker.test.js.snap @@ -0,0 +1,118 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`applicationLinker should work for RN 0.72 1`] = ` +"package com.app; + +import android.app.Application; +import com.facebook.react.PackageList; +import com.reactnativenavigation.NavigationApplication; +import com.facebook.react.ReactNativeHost; +import com.facebook.react.ReactPackage; +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; +import com.facebook.react.defaults.DefaultReactNativeHost; +import com.reactnativenavigation.react.NavigationReactNativeHost; +import com.facebook.soloader.SoLoader; +import java.util.List; + +public class MainApplication extends NavigationApplication { + + private final ReactNativeHost mReactNativeHost = + new NavigationReactNativeHost(this) { + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List getPackages() { + @SuppressWarnings(\\"UnnecessaryLocalVariable\\") + List packages = new PackageList(this).getPackages(); + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + return packages; + } + + @Override + protected String getJSMainModuleName() { + return \\"index\\"; + } + + @Override + protected boolean isNewArchEnabled() { + return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + } + + @Override + protected Boolean isHermesEnabled() { + return BuildConfig.IS_HERMES_ENABLED; + } + }; + + @Override + public ReactNativeHost getReactNativeHost() { + return mReactNativeHost; + } + + @Override + public void onCreate() { + super.onCreate(); + + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + DefaultNewArchitectureEntryPoint.load(); + } + ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + } +} +" +`; + +exports[`applicationLinker should work for RN 0.73 1`] = ` +"package com.app + +import android.app.Application +import com.facebook.react.PackageList +import com.reactnativenavigation.NavigationApplication +import com.facebook.react.ReactHost +import com.facebook.react.ReactNativeHost +import com.facebook.react.ReactPackage +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load +import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost +import com.facebook.react.defaults.DefaultReactNativeHost +import com.reactnativenavigation.react.NavigationReactNativeHost +import com.facebook.react.flipper.ReactNativeFlipper +import com.facebook.soloader.SoLoader + +class MainApplication : NavigationApplication() { + + override val reactNativeHost: ReactNativeHost = + object : NavigationReactNativeHost(this) { + override fun getPackages(): List = + PackageList(this).packages.apply { + // Packages that cannot be autolinked yet can be added manually here, for example: + // add(MyReactNativePackage()) + } + + override fun getJSMainModuleName(): String = \\"index\\" + + override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG + + override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED + } + + override val reactHost: ReactHost + get() = getDefaultReactHost(this.applicationContext, reactNativeHost) + + override fun onCreate() { + super.onCreate() + + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + load() + } + ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager) + } +} +" +`; diff --git a/autolink/postlink/activityLinker.js b/autolink/postlink/activityLinker.js index 47215492be1..e2c7c986bdc 100644 --- a/autolink/postlink/activityLinker.js +++ b/autolink/postlink/activityLinker.js @@ -54,16 +54,20 @@ class ActivityLinker { } _removeGetMainComponentName(contents) { - var match = /\/\*\*\s*\n([^\*]|(\*(?!\/)))*\*\/\s*@Override\s*protected\s*String\s*getMainComponentName\s*\(\)\s*{\s*return.+\s*\}/.exec( - contents - ); - if (match) { - debugn(' Removing getMainComponentName function'); - return contents.replace( - /\/\*\*\s*\n([^\*]|(\*(?!\/)))*\*\/\s*@Override\s*protected\s*String\s*getMainComponentName\s*\(\)\s*{\s*return.+\s*\}/, - '' - ); + var javaRegex = /\/\*\*\s*\n([^\*]|(\*(?!\/)))*\*\/\s*@Override\s*protected\s*String\s*getMainComponentName\s*\(\)\s*{\s*return.+\s*\}/; + var javaMatch = javaRegex.exec(contents); + if (javaMatch) { + debugn(' [Java] Removing getMainComponentName function'); + return contents.replace(javaRegex, ''); + } + + var kotlinRegex = /\/\*\*\s*\n([^\*]|(\*(?!\/)))*\*\/\s*override\sfun\sgetMainComponentName\(\):\sString\s=\s.+/; + var kotlinMatch = kotlinRegex.exec(contents); + if (kotlinMatch) { + debugn(' [Kotlin] Removing getMainComponentName function'); + return contents.replace(kotlinRegex, ''); } + warnn(' getMainComponentName function was not found.'); return contents; } @@ -78,13 +82,20 @@ class ActivityLinker { debugn(' Extending NavigationActivity'); return activityContent .replace(/extends\s+ReactActivity\s*/, 'extends NavigationActivity ') + .replace(/ReactActivity\(\)/, 'NavigationActivity()') .replace( /public\s+MainActivityDelegate\s*\(\s*ReactActivity\s+activity,\s*String\s+mainComponentName\s*\)/, 'public MainActivityDelegate(NavigationActivity activity, String mainComponentName)' ) .replace( + // Java 'import com.facebook.react.ReactActivity;', 'import com.reactnativenavigation.NavigationActivity;' + ) + .replace( + // Kotlin + /import\scom\.facebook\.react\.ReactActivity\n/, + 'import com.reactnativenavigation.NavigationActivity\n' ); } @@ -94,30 +105,34 @@ class ActivityLinker { } _doesActivityExtendReactActivity(activityContent) { - return /public\s+class\s+MainActivity\s+extends\s+ReactActivity\s*/.test(activityContent); + return ( + /public\s+class\s+MainActivity\s+extends\s+ReactActivity\s*/.test(activityContent) || + /class\sMainActivity\s?:\s?ReactActivity\(\)/.test(activityContent) + ); } _hasAlreadyExtendNavigationActivity(activityContent) { - return /public\s+class\s+MainActivity\s+extends\s+NavigationActivity\s*/.test(activityContent); + return ( + /public\s+class\s+MainActivity\s+extends\s+NavigationActivity\s*/.test(activityContent) || + /class\sMainActivity\s:\sNavigationActivity\(\)\s\{/.test(activityContent) + ); } _removeCreateReactActivityDelegate(activityContent) { - if (this._hasCreateReactActivityDelegate(activityContent)) { - debugn(' Removing createReactActivityDelegate function'); - return activityContent.replace( - /\/\*\*\s*\n([^\*]|(\*(?!\/)))*\*\/\s*@Override\s*protected\s*ReactActivityDelegate\s*createReactActivityDelegate\s*\(\)\s*{\s*return((.|\r|\s)*?)}/, - '' - ); - } else { - warnn(' createReactActivityDelegate is already not defined in MainActivity'); - return activityContent; + var javaRegex = /\/\*\*\s*\n([^\*]|(\*(?!\/)))*\*\/\s*@Override\s*protected\s*ReactActivityDelegate\s*createReactActivityDelegate\s*\(\)\s*{\s*return((.|\r|\s)*?)}/; + if (javaRegex.test(activityContent)) { + debugn(' [Java] Removing createReactActivityDelegate function'); + return activityContent.replace(javaRegex, ''); } - } - _hasCreateReactActivityDelegate(activityContent) { - return /\/\*\*\s*\n([^\*]|(\*(?!\/)))*\*\/\s*@Override\s*protected\s*ReactActivityDelegate\s*createReactActivityDelegate\s*\(\)\s*{\s*return((.|\r|\s)*?)}/.test( - activityContent - ); + var kotlinRegex = /\/\*\*\s*\n([^\*]|(\*(?!\/)))*\*\/\s*override\sfun\screateReactActivityDelegate\(\):\sReactActivityDelegate\s=\s+DefaultReactActivityDelegate\(this,\smainComponentName,\sfabricEnabled\)/; + if (kotlinRegex.test(activityContent)) { + debugn(' [Kotlin] Removing createReactActivityDelegate function'); + return activityContent.replace(kotlinRegex, ''); + } + + warnn(' createReactActivityDelegate is already not defined in MainActivity'); + return activityContent; } } diff --git a/autolink/postlink/activityLinker.test.js b/autolink/postlink/activityLinker.test.js index 4e771139b46..65c029ef18b 100644 --- a/autolink/postlink/activityLinker.test.js +++ b/autolink/postlink/activityLinker.test.js @@ -100,4 +100,56 @@ describe('activityLinker', () => { const mainActivityContent = fs.readFileSync(linker.activityPath, 'utf8'); expect(mainActivityContent).toMatchSnapshot(); }); + + it('should work for RN 0.72', () => { + jest.mock('../postlink/path', () => { + const { copyFileSync } = require('fs'); + const { tmpdir } = require('os'); + const path = require('path'); + + const tmpMainActivityPath = path.resolve(tmpdir(), 'rnn-tests_MainActivity.java'); + + copyFileSync( + path.resolve('autolink/fixtures/rn72/MainActivity.java.template'), + tmpMainActivityPath + ); + + return { + mainActivityJava: tmpMainActivityPath, + }; + }); + + const ActivityLinker = require('./activityLinker'); + const linker = new ActivityLinker(); + + linker.link(); + const mainActivityContent = fs.readFileSync(linker.activityPath, 'utf8'); + expect(mainActivityContent).toMatchSnapshot(); + }); + + it('should work for RN 0.73', () => { + jest.mock('../postlink/path', () => { + const { copyFileSync } = require('fs'); + const { tmpdir } = require('os'); + const path = require('path'); + + const tmpMainActivityPath = path.resolve(tmpdir(), 'rnn-tests_MainActivity.kt'); + + copyFileSync( + path.resolve('autolink/fixtures/rn73/MainActivity.kt.template'), + tmpMainActivityPath + ); + + return { + mainActivityJava: tmpMainActivityPath, + }; + }); + + const ActivityLinker = require('./activityLinker'); + const linker = new ActivityLinker(); + + linker.link(); + const mainActivityContent = fs.readFileSync(linker.activityPath, 'utf8'); + expect(mainActivityContent).toMatchSnapshot(); + }); }); diff --git a/autolink/postlink/applicationLinker.js b/autolink/postlink/applicationLinker.js index 5d65b320e06..c7495271cbb 100644 --- a/autolink/postlink/applicationLinker.js +++ b/autolink/postlink/applicationLinker.js @@ -71,9 +71,16 @@ class ApplicationLinker { /extends\s+Application\s+implements\s+ReactApplication/gi, 'extends NavigationApplication' ) + .replace(/:\sApplication\(\),\sReactApplication/, ': NavigationApplication()') .replace( + // Java 'import com.facebook.react.ReactApplication;', 'import com.reactnativenavigation.NavigationApplication;' + ) + .replace( + // Kotlin + 'import com.facebook.react.ReactApplication', + 'import com.reactnativenavigation.NavigationApplication' ); } @@ -88,13 +95,18 @@ class ApplicationLinker { } _doesExtendApplication(applicationContent) { - return /\s+MainApplication\s+extends\s+Application\s+implements\s+ReactApplication\s+/.test( - applicationContent + return ( + /\s+MainApplication\s+extends\s+Application\s+implements\s+ReactApplication\s+/.test( + applicationContent + ) || /class\sMainApplication\s:\sApplication\(\),\sReactApplication/.test(applicationContent) ); } _hasAlreadyLinkedApplication(applicationContent) { - return /\s+extends\s+NavigationApplication\s+/.test(applicationContent); + return ( + /\s+extends\s+NavigationApplication\s+/.test(applicationContent) || + /class\sMainApplication\s:\sNavigationApplication\(\)/.test(applicationContent) + ); } _extendNavigationHost(applicationContent) { @@ -114,10 +126,17 @@ class ApplicationLinker { } else if (this._doesExtendDefaultReactNativeHost(applicationContent)) { debugn(' Changing host implementation to NavigationReactNativeHost'); return applicationContent - .replace('new DefaultReactNativeHost(this)', 'new NavigationReactNativeHost(this)') + .replace('new DefaultReactNativeHost(this)', 'new NavigationReactNativeHost(this)') // Java + .replace('DefaultReactNativeHost(this)', 'NavigationReactNativeHost(this)') // Kotlin .replace( + // Java 'import com.facebook.react.defaults.DefaultReactNativeHost;', 'import com.facebook.react.defaults.DefaultReactNativeHost;\nimport com.reactnativenavigation.react.NavigationReactNativeHost;' + ) + .replace( + // Kotlin + /import\scom\.facebook\.react\.defaults\.DefaultReactNativeHost\n/, + 'import com.facebook.react.defaults.DefaultReactNativeHost\nimport com.reactnativenavigation.react.NavigationReactNativeHost\n' ); } @@ -129,27 +148,43 @@ class ApplicationLinker { } _doesExtendDefaultReactNativeHost(applicationContent) { - return /\s*new DefaultReactNativeHost\(this\)\s*/.test(applicationContent); + return ( + /\s*new DefaultReactNativeHost\(this\)\s*/.test(applicationContent) || + /DefaultReactNativeHost\(this\)/.test(applicationContent) + ); } _hasAlreadyLinkedNavigationHost(applicationContent) { - return /\s*new NavigationReactNativeHost\(this\)\s*/.test(applicationContent); + return ( + /\s*new NavigationReactNativeHost\(this\)\s*/.test(applicationContent) || + /NavigationReactNativeHost\(this\)/.test(applicationContent) + ); } _removeSOLoaderInit(applicationContent) { if (this._isSOLoaderInitCalled(applicationContent)) { debugn(' Removing call to SOLoader.init()'); - return applicationContent.replace( - /SoLoader.init\(\s*this\s*,\s*[/* native exopackage */]*\s*false\s*\);/, - '' - ); + return applicationContent + .replace( + // Java + /SoLoader.init\(\s*this\s*,\s*[/* native exopackage */]*\s*false\s*\);/, + '' + ) + .replace( + // Kotlin + /SoLoader\.init\(this,\sfalse\)/, + '' + ); } warnn(' SOLoader.init() is not called, skipping.'); return applicationContent; } _isSOLoaderInitCalled(applicationContent) { - return /SoLoader.init\(this,\s*[/* native exopackage */]*\s*false\);/.test(applicationContent); + return ( + /SoLoader.init\(this,\s*[/* native exopackage */]*\s*false\);/.test(applicationContent) || + /SoLoader\.init\(this,\sfalse\)/.test(applicationContent) + ); } } diff --git a/autolink/postlink/applicationLinker.test.js b/autolink/postlink/applicationLinker.test.js new file mode 100644 index 00000000000..96be2416cb8 --- /dev/null +++ b/autolink/postlink/applicationLinker.test.js @@ -0,0 +1,75 @@ +import fs from 'fs'; + +/** + * Mocks + */ + +jest.mock('../postlink/log', () => ({ + log: console.log, + logn: console.log, + warn: console.log, + warnn: console.log, + info: console.log, + infon: console.log, + debug: console.log, + debugn: console.log, + errorn: console.log, +})); + +/** + * Tests + */ + +describe('applicationLinker', () => { + it('should work for RN 0.72', () => { + jest.mock('../postlink/path', () => { + const { copyFileSync } = require('fs'); + const { tmpdir } = require('os'); + const path = require('path'); + + const tmpApplicationJavaPath = path.resolve(tmpdir(), 'rnn-tests_MainApplication.java'); + + copyFileSync( + path.resolve('autolink/fixtures/rn72/MainApplication.java.template'), + tmpApplicationJavaPath + ); + + return { + mainApplicationJava: tmpApplicationJavaPath, + }; + }); + + const ApplicationLinker = require('./applicationLinker'); + const linker = new ApplicationLinker(); + + linker.link(); + const mainActivityContent = fs.readFileSync(linker.applicationPath, 'utf8'); + expect(mainActivityContent).toMatchSnapshot(); + }); + + it('should work for RN 0.73', () => { + jest.mock('../postlink/path', () => { + const { copyFileSync } = require('fs'); + const { tmpdir } = require('os'); + const path = require('path'); + + const tmpApplicationJavaPath = path.resolve(tmpdir(), 'rnn-tests_MainApplication.kt'); + + copyFileSync( + path.resolve('autolink/fixtures/rn73/MainApplication.kt.template'), + tmpApplicationJavaPath + ); + + return { + mainApplicationJava: tmpApplicationJavaPath, + }; + }); + + const ApplicationLinker = require('./applicationLinker'); + const linker = new ApplicationLinker(); + + linker.link(); + const mainActivityContent = fs.readFileSync(linker.applicationPath, 'utf8'); + expect(mainActivityContent).toMatchSnapshot(); + }); +}); diff --git a/autolink/postlink/gradleLinker.js b/autolink/postlink/gradleLinker.js index 520539591bb..c80d55c1f14 100644 --- a/autolink/postlink/gradleLinker.js +++ b/autolink/postlink/gradleLinker.js @@ -173,7 +173,7 @@ class GradleLinker { * @param {string} contents */ _isKotlinPluginDeclared(contents) { - return /org.jetbrains.kotlin:kotlin-gradle-plugin:/.test(contents); + return /org\.jetbrains\.kotlin:kotlin-gradle-plugin:?/.test(contents); } } diff --git a/autolink/postlink/path.js b/autolink/postlink/path.js index 3b5055b0098..c58fab2f833 100644 --- a/autolink/postlink/path.js +++ b/autolink/postlink/path.js @@ -3,11 +3,13 @@ var ignoreFolders = { ignore: ['node_modules/**', '**/build/**', '**/Build/**', '**/DerivedData/**', '**/*-tvOS*/**'], }; -exports.mainActivityJava = glob.sync('**/MainActivity.java', ignoreFolders)[0]; -exports.mainActivityKotlin = glob.sync('**/MainActivity.kt', ignoreFolders)[0]; -var mainApplicationJava = glob.sync('**/MainApplication.java', ignoreFolders)[0]; +exports.mainActivityJava = glob.sync('**/MainActivity.{java,kt}', ignoreFolders)[0]; +var mainApplicationJava = glob.sync('**/MainApplication.{java,kt}', ignoreFolders)[0]; exports.mainApplicationJava = mainApplicationJava; -exports.rootGradle = mainApplicationJava.replace(/android\/app\/.*\.java/, 'android/build.gradle'); +exports.rootGradle = mainApplicationJava.replace( + /android\/app\/.*\.(java|kt)/, + 'android/build.gradle' +); var reactNativeVersion = require('../../../react-native/package.json').version; exports.appDelegate = glob.sync(