From 2c3903bfb96f3c197c56cbf33029dd46d963915a Mon Sep 17 00:00:00 2001 From: Djordje Dimitrijev Date: Mon, 19 Aug 2024 15:09:46 +0200 Subject: [PATCH 1/3] Fix script for creating demo code push apps --- Examples/create-app.js | 93 +++++++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 33 deletions(-) diff --git a/Examples/create-app.js b/Examples/create-app.js index 6ca346fb9..26327527c 100644 --- a/Examples/create-app.js +++ b/Examples/create-app.js @@ -1,6 +1,9 @@ /* The script serves to generate CodePushified React Native app to reproduce issues or for testing purposes. +NOTE: Use CodePushDemoApp and CodePushDemoAppCpp as reference how to implement CodePush in your app. For creating a working demo app +follow steps bellow. + Requirements: 1. npm i -g react-native-cli 2. npm i -g appcenter-cli @@ -28,19 +31,11 @@ const execSync = child_process.execSync; const args = process.argv.slice(2); const appName = args[0] || 'CodePushDemoAppTest'; - if (fs.existsSync(appName)) { console.error(`Folder with name "${appName}" already exists! Please delete`); process.exit(); } -// Checking if yarn is installed -try { - execCommand('yarn bin'); -} catch (err) { - console.error(`You must install 'yarn' to use this script!`); - process.exit(); -} const appNameAndroid = `${appName}-android`; const appNameIOS = `${appName}-ios`; @@ -48,7 +43,7 @@ let owner = null; const reactNativeVersion = args[1] || `react-native@${execCommand('npm view react-native version')}`.trim(); const reactNativeVersionIsLowerThanV049 = isReactNativeVersionLowerThan(49); const reactNativeCodePushVersion = args[2] || `react-native-code-push@${execCommand('npm view react-native-code-push version')}`.trim(); - +const reactNativeVersionIsLowerThanV073 = isReactNativeVersionLowerThan(73) if (!isReactNativeVersionLowerThan(60) && process.platform === "darwin") { try { console.log("Verify that CocoaPods installed"); @@ -89,8 +84,8 @@ function createCodePushApp(name, os) { const app = JSON.parse(appResult); owner = app.owner.name; console.log(`App "${name}" has been created \n`); - } catch(e) { - console.error(`Error: Unable to create CodePush app. Please check that you haven't application with "${name}" name on portal.`, ); + } catch (e) { + console.error(`Error: Unable to create CodePush app. Please check that you haven't application with "${name}" name on portal.`,); console.error("Error: ", e.toString()); } execCommand(`appcenter codepush deployment add -a ${owner}/${name} Staging`); @@ -128,7 +123,7 @@ function generatePlainReactNativeApp(appName, reactNativeVersion) { function installCodePush(reactNativeCodePushVersion) { console.log(`Installing React Native Module for CodePush...`); - execCommand(`yarn add ${reactNativeCodePushVersion}`); + execCommand(`npm i ${reactNativeCodePushVersion}`); console.log(`React Native Module for CodePush has been installed \n`); } @@ -213,8 +208,8 @@ function optimizeToTestInDebugMode() { const rnXcodeShPath = `node_modules/react-native/${rnXcodeShLocationFolder}/react-native-xcode.sh`; // Replace "if [[ "$PLATFORM_NAME" == *simulator ]]; then" with "if false; then" to force bundling execCommand(`sed -ie 's/if \\[\\[ "\$PLATFORM_NAME" == \\*simulator \\]\\]; then/if false; then/' ${rnXcodeShPath}`); - execCommand(`perl -i -p0e 's/#ifdef DEBUG.*?#endif/jsCodeLocation = [CodePush bundleURL];/s' ios/${appName}/AppDelegate.m`); - execCommand(`sed -ie 's/targetName.toLowerCase().contains("release")/true/' node_modules/react-native/react.gradle`); + execCommand(`perl -i -p0e 's/#ifdef DEBUG.*?#endif/jsCodeLocation = [CodePush bundleURL];/s' ios/${appName}/${getAppDelegateName()}`); + reactNativeVersionIsLowerThanV073 && execCommand(`sed -ie 's/targetName.toLowerCase().contains("release")/true/' node_modules/react-native/react.gradle`); } function grantAccess(folderPath) { @@ -250,7 +245,8 @@ function isReactNativeVersionLowerThan(version) { function androidSetup() { const buildGradlePath = path.join('android', 'app', 'build.gradle'); const settingsGradlePath = path.join('android', 'settings.gradle'); - const mainApplicationPath = path.join('android', 'app', 'src', 'main', 'java', 'com', appName, 'MainApplication.java'); + const mainApplicationType = reactNativeVersionIsLowerThanV073 ? 'java' : 'kt'; + const mainApplicationPath = path.join('android', 'app', 'src', 'main', 'java', 'com', appName, `MainApplication.${mainApplicationType}`); const stringsResourcesPath = path.join('android', 'app', 'src', 'main', 'res', 'values', 'strings.xml'); let stringsResourcesContent = fs.readFileSync(stringsResourcesPath, "utf8"); @@ -260,47 +256,78 @@ function androidSetup() { fs.writeFileSync(stringsResourcesPath, stringsResourcesContent); let buildGradleContents = fs.readFileSync(buildGradlePath, "utf8"); - const reactGradleLink = buildGradleContents.match(/\napply from: ["'].*?react\.gradle["']/)[0]; + const reactGradleLink = buildGradleContents.match(/\napply from: ["'].*?react\.gradle["']/); const codePushGradleLink = `\napply from: "../../node_modules/react-native-code-push/android/codepush.gradle"`; - buildGradleContents = buildGradleContents.replace(reactGradleLink, - `${reactGradleLink}${codePushGradleLink}`); - fs.writeFileSync(buildGradlePath, buildGradleContents); + if (reactGradleLink != null) { + buildGradleContents = buildGradleContents.replace(reactGradleLink[0], + `${reactGradleLink[0]}${codePushGradleLink}`); + fs.writeFileSync(buildGradlePath, buildGradleContents); + } + // react.gradle script removed from 0.71 thus this workaround + else { + const appPluginLastLine = buildGradleContents.match(/apply plugin: "com.facebook.react"/)[0]; + buildGradleContents = buildGradleContents.replace(appPluginLastLine, `${appPluginLastLine}${codePushGradleLink}`) + fs.writeFileSync(buildGradlePath, buildGradleContents); + } let settingsGradleContents = fs.readFileSync(settingsGradlePath, "utf8"); const settingsGradleInclude = "include \':app\'"; - const codePushProjectImport= `':react-native-code-push'\nproject(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')`; + const codePushProjectImport = `':react-native-code-push'\nproject(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')`; settingsGradleContents = settingsGradleContents.replace(settingsGradleInclude, `${settingsGradleInclude}, ${codePushProjectImport}`); fs.writeFileSync(settingsGradlePath, settingsGradleContents); - const getJSBundleFileOverride = ` - @Override - protected String getJSBundleFile(){ - return CodePush.getJSBundleFile(); - } - `; + let importCodePush = `\nimport com.microsoft.codepush.react.CodePush;`; + let reactNativeHostInstantiationImport = "import android.app.Application;"; let mainApplicationContents = fs.readFileSync(mainApplicationPath, "utf8"); - const reactNativeHostInstantiation = "new ReactNativeHost(this) {"; + let getJSBundleFileOverride = ""; + let reactNativeHostInstantiation = ""; + + // handle react-native version with java + if (reactNativeVersionIsLowerThanV073) { + reactNativeHostInstantiation = "new ReactNativeHost(this) {"; + + getJSBundleFileOverride = ` + @Override + protected String getJSBundleFile(){ + return CodePush.getJSBundleFile(); + } + `; + } + // handle react-native version with kotlin + else { + reactNativeHostInstantiation = "object : DefaultReactNativeHost(this) {" + getJSBundleFileOverride = ` + override fun getJSBundleFile(): String { + return CodePush.getJSBundleFile() + } + `; + importCodePush = importCodePush.replace(';', ''); + reactNativeHostInstantiationImport = reactNativeHostInstantiationImport.replace(';', ''); + } mainApplicationContents = mainApplicationContents.replace(reactNativeHostInstantiation, `${reactNativeHostInstantiation}${getJSBundleFileOverride}`); - const importCodePush = `\nimport com.microsoft.codepush.react.CodePush;`; - const reactNativeHostInstantiationImport = "import android.app.Application;"; mainApplicationContents = mainApplicationContents.replace(reactNativeHostInstantiationImport, `${reactNativeHostInstantiationImport}${importCodePush}`); fs.writeFileSync(mainApplicationPath, mainApplicationContents); } +function getAppDelegateName() { return fs.readdirSync(path.join('ios', appName)).find(file => file.endsWith('mm') || file.endsWith('m')) }; + // Configuring ios applications for react-native version higher than 0.60 function iosSetup() { const plistPath = path.join('ios', appName, 'Info.plist'); - const appDelegatePath = path.join('ios', appName, 'AppDelegate.m'); + + const appDelegatePath = path.join('ios', appName, getAppDelegateName()); let plistContents = fs.readFileSync(plistPath, "utf8"); - const falseInfoPlist = ``; + + const dictPlistTag = `\n`; + const codePushDeploymentKey = iosStagingDeploymentKey || 'deployment-key-here'; - plistContents = plistContents.replace(falseInfoPlist, - `${falseInfoPlist}\n\tCodePushDeploymentKey\n\t${codePushDeploymentKey}`); + plistContents = plistContents.replace(dictPlistTag, + `\tCodePushDeploymentKey\n\t${codePushDeploymentKey}${dictPlistTag}`); fs.writeFileSync(plistPath, plistContents); let appDelegateContents = fs.readFileSync(appDelegatePath, "utf8"); From 81ab712974c1a979416e2ee53402afde073019a8 Mon Sep 17 00:00:00 2001 From: Djordje Dimitrijev Date: Tue, 20 Aug 2024 13:23:12 +0200 Subject: [PATCH 2/3] Bump versions in ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 33dc8c104..a0b74fc79 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -16,7 +16,7 @@ What actually happens? ### Reproducible Demo -* Download https://github.com/microsoft/react-native-code-push/archive/master.zip and unzip. From `Examples` folder run `node create-app.js appName react-native@0.61.5 react-native-code-push@6.0.0` command to generate plain CodePushified React Native app. Please see description on top of `create-app.js` file content if needed +* Download https://github.com/microsoft/react-native-code-push/archive/master.zip and unzip. From `Examples` folder run `node create-app.js appName react-native@0.71.19 react-native-code-push@8.3.1` command to generate plain CodePushified React Native app. Please see description on top of `create-app.js` file content if needed * If you can't reproduce the bug on it, provide us as much info as possible about your project ### Environment From d97a62ce695f6abc403bdb0acd8eabd55f978099 Mon Sep 17 00:00:00 2001 From: Djordje Dimitrijev Date: Tue, 20 Aug 2024 16:55:11 +0200 Subject: [PATCH 3/3] Update changes after review --- Examples/create-app.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Examples/create-app.js b/Examples/create-app.js index 26327527c..0b527cee2 100644 --- a/Examples/create-app.js +++ b/Examples/create-app.js @@ -31,6 +31,7 @@ const execSync = child_process.execSync; const args = process.argv.slice(2); const appName = args[0] || 'CodePushDemoAppTest'; + if (fs.existsSync(appName)) { console.error(`Folder with name "${appName}" already exists! Please delete`); process.exit(); @@ -43,6 +44,7 @@ let owner = null; const reactNativeVersion = args[1] || `react-native@${execCommand('npm view react-native version')}`.trim(); const reactNativeVersionIsLowerThanV049 = isReactNativeVersionLowerThan(49); const reactNativeCodePushVersion = args[2] || `react-native-code-push@${execCommand('npm view react-native-code-push version')}`.trim(); + const reactNativeVersionIsLowerThanV073 = isReactNativeVersionLowerThan(73) if (!isReactNativeVersionLowerThan(60) && process.platform === "darwin") { try { @@ -313,7 +315,7 @@ function androidSetup() { fs.writeFileSync(mainApplicationPath, mainApplicationContents); } -function getAppDelegateName() { return fs.readdirSync(path.join('ios', appName)).find(file => file.endsWith('mm') || file.endsWith('m')) }; +function getAppDelegateName() { return fs.readdirSync(path.join('ios', appName)).find(file => file === ('AppDelegate.mm') || file === 'AppDelegate.m') }; // Configuring ios applications for react-native version higher than 0.60 function iosSetup() {