From e53e362502ba96da7c7e10b3f7978f5c38e6e9bd Mon Sep 17 00:00:00 2001 From: Nathan Sankbeil Date: Tue, 24 Sep 2019 11:03:18 -0400 Subject: [PATCH] fix(flagship): Make android namespace match package name The namespace for native android code was always set to com.brandingbrand.reactnative.and.{config.name}, rather than using the defined ID. This lead to some issues with starting activities and imports. BREAKING CHANGE: If anything hard codes the android native project path (ie. android/app/src/main/java/com/brandingbrand/reactnative/and/project-name), it will need to be updated to account for the dynamic package name. Flagship now exports its own modules, so `flagship.path.android.nativeProjectPath(config)` can be used to get the directory without hard coding a path. --- packages/flagship/android/app/BUCK | 4 +- packages/flagship/android/app/build.gradle | 2 +- .../android/app/src/main/AndroidManifest.xml | 2 +- .../reactnative/and/flagship/EnvSwitcher.java | 4 +- .../and/flagship/EnvSwitcherPackage.java | 4 +- .../and/flagship/MainActivity.java | 4 +- .../and/flagship/MainApplication.java | 2 +- .../and/flagship/NativeConstants.java | 4 +- .../and/flagship/NativeConstantsPackage.java | 4 +- .../flagship/ThreadSafeUIImplementation.java | 2 +- packages/flagship/src/commands/init.ts | 9 ++ packages/flagship/src/index.ts | 33 +++++++ packages/flagship/src/lib/fs.ts | 4 +- packages/flagship/src/lib/path.ts | 10 +-- packages/flagship/src/lib/rename.ts | 89 +++++++++++++++---- yarn.lock | 31 ++++++- 16 files changed, 169 insertions(+), 39 deletions(-) create mode 100644 packages/flagship/src/index.ts diff --git a/packages/flagship/android/app/BUCK b/packages/flagship/android/app/BUCK index bf6d8d8e33..c78d12fafa 100644 --- a/packages/flagship/android/app/BUCK +++ b/packages/flagship/android/app/BUCK @@ -35,13 +35,13 @@ android_library( android_build_config( name = 'build_config', - package = 'com.brandingbrand.reactnative.and.flagship', + package = 'CONFIG_BUNDLE_ID', ) android_resource( name = 'res', res = 'src/main/res', - package = 'com.brandingbrand.reactnative.and.flagship', + package = 'CONFIG_BUNDLE_ID', ) android_binary( diff --git a/packages/flagship/android/app/build.gradle b/packages/flagship/android/app/build.gradle index 4e69acba75..618b69145d 100644 --- a/packages/flagship/android/app/build.gradle +++ b/packages/flagship/android/app/build.gradle @@ -107,7 +107,7 @@ android { defaultConfig { multiDexEnabled true - applicationId "com.brandingbrand.reactnative.and.flagship" + applicationId "CONFIG_BUNDLE_ID" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionName project.VERSION_NAME diff --git a/packages/flagship/android/app/src/main/AndroidManifest.xml b/packages/flagship/android/app/src/main/AndroidManifest.xml index c23f710ac0..ba389c1dc9 100644 --- a/packages/flagship/android/app/src/main/AndroidManifest.xml +++ b/packages/flagship/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="CONFIG_BUNDLE_ID"> diff --git a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/EnvSwitcher.java b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/EnvSwitcher.java index d612510d7f..bba9713f0f 100644 --- a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/EnvSwitcher.java +++ b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/EnvSwitcher.java @@ -1,4 +1,4 @@ -package com.brandingbrand.reactnative.and.flagship; +package CONFIG_BUNDLE_ID; import android.annotation.SuppressLint; import android.content.Context; @@ -44,4 +44,4 @@ public void setEnv(String name, Promise promise) { promise.resolve(null); } -} \ No newline at end of file +} diff --git a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/EnvSwitcherPackage.java b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/EnvSwitcherPackage.java index ca4047ae56..f3b9bff525 100644 --- a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/EnvSwitcherPackage.java +++ b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/EnvSwitcherPackage.java @@ -1,4 +1,4 @@ -package com.brandingbrand.reactnative.and.flagship; +package CONFIG_BUNDLE_ID; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; @@ -21,4 +21,4 @@ public List createNativeModules(final ReactApplicationContext reac add(new EnvSwitcher(reactContext)); }}; } -} \ No newline at end of file +} diff --git a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/MainActivity.java b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/MainActivity.java index 44c61a12f3..e13b86005b 100644 --- a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/MainActivity.java +++ b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/MainActivity.java @@ -1,4 +1,4 @@ -package com.brandingbrand.reactnative.and.flagship; +package CONFIG_BUNDLE_ID; import com.reactnativenavigation.controllers.SplashActivity; @@ -7,4 +7,4 @@ public class MainActivity extends SplashActivity { public int getSplashLayout() { return R.layout.splash; } -} \ No newline at end of file +} diff --git a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/MainApplication.java b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/MainApplication.java index 4abca74b5a..5dbf807000 100644 --- a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/MainApplication.java +++ b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/MainApplication.java @@ -1,4 +1,4 @@ -package com.brandingbrand.reactnative.and.flagship; +package CONFIG_BUNDLE_ID; import android.app.Application; diff --git a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/NativeConstants.java b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/NativeConstants.java index 1313005777..9995072d1b 100644 --- a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/NativeConstants.java +++ b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/NativeConstants.java @@ -1,4 +1,4 @@ -package com.brandingbrand.reactnative.and.flagship; +package CONFIG_BUNDLE_ID; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; @@ -24,4 +24,4 @@ public Map getConstants() { return constants; } -} \ No newline at end of file +} diff --git a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/NativeConstantsPackage.java b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/NativeConstantsPackage.java index a6df7218b6..89e9cdd00b 100644 --- a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/NativeConstantsPackage.java +++ b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/NativeConstantsPackage.java @@ -1,4 +1,4 @@ -package com.brandingbrand.reactnative.and.flagship; +package CONFIG_BUNDLE_ID; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; @@ -21,4 +21,4 @@ public List createNativeModules(final ReactApplicationContext reac add(new NativeConstants(reactContext)); }}; } -} \ No newline at end of file +} diff --git a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/ThreadSafeUIImplementation.java b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/ThreadSafeUIImplementation.java index 055217a13b..e9582a106f 100644 --- a/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/ThreadSafeUIImplementation.java +++ b/packages/flagship/android/app/src/main/java/com/brandingbrand/reactnative/and/flagship/ThreadSafeUIImplementation.java @@ -1,4 +1,4 @@ -package com.brandingbrand.reactnative.and.flagship; +package CONFIG_BUNDLE_ID; import android.support.annotation.Nullable; diff --git a/packages/flagship/src/commands/init.ts b/packages/flagship/src/commands/init.ts index ce109cd1ee..fae8dd98d5 100644 --- a/packages/flagship/src/commands/init.ts +++ b/packages/flagship/src/commands/init.ts @@ -31,6 +31,8 @@ export interface HandlerArgs { env: string; } +const TEMPLATE_ANDROID_PACKAGE = 'com.brandingbrand.reactnative.and.flagship'; + export const command = 'init [platform]'; export const describe = 'initialize FLAGSHIP for [platform]'; @@ -127,8 +129,15 @@ function initAndroid( // Clone the boilerplate into the project fs.clone('android'); + // The id should be defined, but set it to a default if it's not for compatibility reasons + const pkgId = configuration.bundleIds && configuration.bundleIds.android ? + configuration.bundleIds.android.toLowerCase() : + `com.brandingbrand.reactnative.and.${configuration.name.toLowerCase()}`; + // Rename the boilerplate project with the app name rename.source('FLAGSHIP', configuration.name, 'android'); + rename.source('CONFIG_BUNDLE_ID', pkgId, 'android'); + rename.pkgDirectory(TEMPLATE_ANDROID_PACKAGE, pkgId, path.android.mainPath(), 'java'); rename.files('FLAGSHIP', configuration.name, 'android'); fastlane.configure(path.android.fastfilePath(), configuration); // Update Fastfile diff --git a/packages/flagship/src/index.ts b/packages/flagship/src/index.ts new file mode 100644 index 0000000000..f6014ed9da --- /dev/null +++ b/packages/flagship/src/index.ts @@ -0,0 +1,33 @@ +import * as android from './lib/android'; +import * as cocoapods from './lib/cocoapods'; +import * as deeplinking from './lib/deeplinking'; +import * as env from './lib/env'; +import * as fastlane from './lib/fastlane'; +import * as fs from './lib/fs'; +import * as ios from './lib/ios'; +import * as link from './lib/link'; +import * as modules from './lib/modules'; +import * as nativeConstants from './lib/native-constants'; +import * as os from './lib/os'; +import * as path from './lib/path'; +import * as rename from './lib/rename'; +import * as version from './lib/version'; +import * as web from './lib/web'; + +export { + android, + cocoapods, + deeplinking, + env, + fastlane, + fs, + ios, + link, + modules, + nativeConstants, + os, + path, + rename, + version, + web +}; diff --git a/packages/flagship/src/lib/fs.ts b/packages/flagship/src/lib/fs.ts index 63902c7189..f50ee55dd2 100644 --- a/packages/flagship/src/lib/fs.ts +++ b/packages/flagship/src/lib/fs.ts @@ -2,6 +2,7 @@ import { copySync, ensureDirSync, ensureSymlinkSync, + moveSync, pathExistsSync, readdirSync, readFileSync, @@ -18,7 +19,8 @@ export { ensureDirSync, renameSync, pathExistsSync, - ensureSymlinkSync + ensureSymlinkSync, + moveSync }; import * as helpers from '../helpers'; diff --git a/packages/flagship/src/lib/path.ts b/packages/flagship/src/lib/path.ts index 1065fb5520..702afb29cf 100644 --- a/packages/flagship/src/lib/path.ts +++ b/packages/flagship/src/lib/path.ts @@ -169,14 +169,14 @@ function getManifestPath(): string { * @returns {string} The path to the native project. */ function getNativeProjectPathAndriod(configuration: Config): string { + const pkgId = configuration.bundleIds && configuration.bundleIds.android ? + configuration.bundleIds.android : + `com.brandingbrand.reactnative.and.${configuration.name}`; + return resolvePathFromProject( getMainPath(), 'java', - 'com', - 'brandingbrand', - 'reactnative', - 'and', - configuration.name.toLowerCase() + ...pkgId.toLowerCase().split('.') ); } diff --git a/packages/flagship/src/lib/rename.ts b/packages/flagship/src/lib/rename.ts index 6a98364b73..e0fe77a634 100644 --- a/packages/flagship/src/lib/rename.ts +++ b/packages/flagship/src/lib/rename.ts @@ -34,6 +34,54 @@ export function source(oldName: string, newName: string, ...pathComponents: stri logInfo(`renamed project within source in ${directory}`); } +/** + * Updates the directory structure to match a new namespace + * + * @param {string} oldPkg The old package name to replace. + * @param {string} newPkg The new package name to use. + * @param {...string} pathComponents Path components to the directory in which to + * replace the project name. + */ +export function pkgDirectory(oldPkg: string, newPkg: string, ...pathComponents: string[]): void { + const directory = path.project.resolve(...pathComponents); + const oldPathPart = oldPkg.replace(/\./g, '/'); + const newPathPart = newPkg.replace(/\./g, '/'); + + try { + const results = getMatchingFiles(directory, oldPathPart); + + // Rename matching paths + results.forEach(oldPath => { + const newPath = oldPath.replace(oldPathPart, newPathPart).toLowerCase(); + fs.moveSync(oldPath, newPath); + }); + + // since we only moved the bottom-most directory, traverse through the old + // package directories to delete any empty package folders + oldPkg + .split('.') + .reduce((parts, part, index, arr) => { + const pattern = [...arr.slice(0, index), part].join('/'); + parts.push(...getMatchingFiles(directory, pattern)); + return parts; + }, []) + .reverse() + .forEach(dir => { + const contents = fs.pathExistsSync(dir) && fs.readdirSync(dir); + if (Array.isArray(contents) && contents.length === 0) { + fs.removeSync(dir); + } + }); + + } catch (err) { + logError('renaming project files', err); + process.exit(1); + } + + logInfo(`renamed project files in ${directory}`); +} + + /** * Replaces the project name within boilerplate file names. * @@ -46,21 +94,7 @@ export function files(oldName: string, newName: string, ...pathComponents: strin const directory = path.project.resolve(...pathComponents); try { - const globOptions = { - nosort: true, - dot: true - }; - - // Find files/directories to be renamed - const results = [ - ...sync(directory + '/**/*' + oldName + '*', globOptions), - ...sync(directory + '/**/*' + oldName.toLocaleLowerCase() + '*', globOptions) - ]; - - // Sort the results so highest depth paths are replaced first - results.sort((a, b) => { - return b.length - a.length; - }); + const results = getMatchingFiles(directory, oldName); // Rename each path results.forEach(oldPath => { @@ -79,5 +113,28 @@ export function files(oldName: string, newName: string, ...pathComponents: strin process.exit(1); } - logInfo(`renaming project files in ${directory}`); + logInfo(`renamed project files in ${directory}`); +} + +function getMatchingFiles(directory: string, oldName: string): string[] { + const globOptions = { + nosort: true, + dot: true + }; + + // Find files/directories to be renamed + const results = [ + ...sync(directory + '/**/*' + oldName + '*', globOptions), + ...sync(directory + '/**/*' + oldName.toLocaleLowerCase() + '*', globOptions) + ]; + + // Remove duplicate paths from the results array + const uniqueResults = Array.from(new Set(results)); + + // Sort the results so highest depth paths are replaced first + uniqueResults.sort((a, b) => { + return b.length - a.length; + }); + + return uniqueResults; } diff --git a/yarn.lock b/yarn.lock index da3ff3577c..477e5f1df4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15952,7 +15952,36 @@ webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^4.16.5, webpack@^4.23.1: +webpack@4.39.3: + version "4.39.3" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.39.3.tgz#a02179d1032156b713b6ec2da7e0df9d037def50" + integrity sha512-BXSI9M211JyCVc3JxHWDpze85CvjC842EvpRsVTc/d15YJGlox7GIDd38kJgWrb3ZluyvIjgenbLDMBQPDcxYQ== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-module-context" "1.8.5" + "@webassemblyjs/wasm-edit" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + acorn "^6.2.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" + enhanced-resolve "^4.1.0" + eslint-scope "^4.0.3" + json-parse-better-errors "^1.0.2" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.1" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" + schema-utils "^1.0.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.1" + watchpack "^1.6.0" + webpack-sources "^1.4.1" + +webpack@^4.23.1: version "4.39.1" resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.39.1.tgz#60ed9fb2b72cd60f26ea526c404d2a4cc97a1bd8" integrity sha512-/LAb2TJ2z+eVwisldp3dqTEoNhzp/TLCZlmZm3GGGAlnfIWDgOEE758j/9atklNLfRyhKbZTCOIoPqLJXeBLbQ==