@appzung/react-native-code-push 7.1.1 → 8.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,104 @@
1
+ trigger:
2
+ - master
3
+
4
+ pr:
5
+ - master
6
+
7
+ resources:
8
+ repositories:
9
+ - repository: 1ESPipelineTemplates
10
+ type: git
11
+ name: 1ESPipelineTemplates/1ESPipelineTemplates
12
+ ref: refs/tags/release
13
+ name: $(Build.SourceBranchName)_$(date:yyyyMMdd)$(rev:.r)
14
+
15
+ extends:
16
+ ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}:
17
+ template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates
18
+ ${{ else }}:
19
+ template: v1/1ES.Unofficial.PipelineTemplate.yml@1ESPipelineTemplates
20
+ parameters:
21
+ pool:
22
+ name: 1ES-PT-CBL-Mariner-2.0-Gen2
23
+ os: linux
24
+ customBuildTags:
25
+ - ES365AIMigrationTooling-BulkMigrated
26
+ sdl:
27
+ sourceAnalysisPool: 1ES-PT-Windows-2022
28
+ credscan:
29
+ suppressionsFile: $(Build.SourcesDirectory)/.config/CredScanSuppressions.json
30
+ stages:
31
+ - stage: Stage
32
+ jobs:
33
+ - job: HostJob
34
+ templateContext:
35
+ outputs:
36
+ - output: pipelineArtifact
37
+ displayName: "Publish Artifact: artifacts"
38
+ path: '$(Build.ArtifactStagingDirectory)/npm'
39
+ artifactName: npm
40
+
41
+ steps:
42
+ - task: NodeTool@0
43
+ inputs:
44
+ versionSpec: '14.x'
45
+ displayName: 'Install Node.js'
46
+
47
+ - script: |
48
+ npm pack
49
+ npm install -g react-native-code-push*.tgz
50
+ displayName: 'Package react-native-code-push'
51
+ workingDirectory: $(Build.SourcesDirectory)
52
+
53
+ - task: DeleteFiles@1
54
+ inputs:
55
+ contents: node_modules
56
+ displayName: 'Delete node_modules'
57
+
58
+ - task: ArchiveFiles@2
59
+ inputs:
60
+ rootFolderOrFile: '$(Build.SourcesDirectory)'
61
+ includeRootFolder: false
62
+ archiveType: 'tar'
63
+ archiveFile: '$(Build.ArtifactStagingDirectory)/npm/$(Build.BuildId).tgz'
64
+ replaceExistingArchive: true
65
+ verbose: true
66
+ displayName: 'Prepare npm artifact'
67
+
68
+ - stage: APIScan
69
+ dependsOn: Stage
70
+ pool:
71
+ name: 1ES-PT-Windows-2022
72
+ os: windows
73
+ variables:
74
+ "agent.source.skip": true
75
+ jobs:
76
+ - job: APIScan
77
+ steps:
78
+ - task: DownloadPipelineArtifact@2
79
+ displayName: Download Build Artifacts for APIScan
80
+ inputs:
81
+ artifactName: npm
82
+ targetPath: '$(Agent.BuildDirectory)/npm'
83
+ - task: ExtractFiles@1
84
+ inputs:
85
+ archiveFilePatterns: '$(Agent.BuildDirectory)/npm/*.tgz'
86
+ destinationFolder: '$(Agent.BuildDirectory)/npm_extracted'
87
+ - task: AzureKeyVault@2
88
+ inputs:
89
+ azureSubscription: 'AC - Dev Infra & Build Pool'
90
+ KeyVaultName: 'mobile-center-sdk'
91
+ SecretsFilter: 'appcenter-sdk-managed-identity-clientid'
92
+ RunAsPreJob: false
93
+ - task: APIScan@2
94
+ displayName: 'Run APIScan'
95
+ inputs:
96
+ softwareFolder: '$(Agent.BuildDirectory)\npm_extracted'
97
+ softwareName: 'react-native-code-push'
98
+ softwareVersionNum: '$(Build.BuildId)'
99
+ isLargeApp: false
100
+ toolVersion: 'Latest'
101
+ verbosityLevel: verbose
102
+ condition: and(succeeded(), ne(variables['DisableAPIScan'], 'true'))
103
+ env:
104
+ AzureServicesAuthConnectionString: 'runAs=App;AppId=$(appcenter-sdk-managed-identity-clientid)'
@@ -0,0 +1,94 @@
1
+ trigger:
2
+ - master
3
+
4
+ pr:
5
+ - master
6
+
7
+ variables:
8
+ - name: api-level
9
+ value: '27'
10
+
11
+ pool:
12
+ vmImage: 'macOS-12'
13
+
14
+ stages:
15
+ - stage: RunTests
16
+ displayName: 'Run Android & IOS tests'
17
+ jobs:
18
+ - job: TestAndroid
19
+ timeoutInMinutes: 120
20
+ displayName: 'Test android'
21
+ steps:
22
+
23
+ - script: |
24
+ adb devices
25
+ displayName: 'Start adb server'
26
+
27
+ - script: |
28
+ $ANDROID_HOME/tools/bin/sdkmanager "system-images;android-$(api-level);google_apis;x86"
29
+ displayName: 'Download system image'
30
+
31
+ - script: |
32
+ $ANDROID_HOME/tools/bin/avdmanager create avd --force --name TestEmulator --abi google_apis/x86 --package 'system-images;android-$(api-level);google_apis;x86' --device "Nexus 6P"
33
+ displayName: 'Creating Android emulator'
34
+
35
+ - script: |
36
+ $ANDROID_HOME/emulator/emulator -avd TestEmulator -noaudio -no-window -no-snapshot-save -no-boot-anim -memory 6144 &
37
+ displayName: 'Start Android emulator'
38
+
39
+ - script: |
40
+ $ANDROID_HOME/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]]; do sleep 1; done'
41
+ displayName: 'Wait for emulator to boot'
42
+
43
+ - script: |
44
+ adb shell settings put global window_animation_scale 0.0
45
+ displayName: 'Disable animations and transitions'
46
+
47
+ - script: |
48
+ adb shell settings put global transition_animation_scale 0.0
49
+ displayName: 'Disable animations and transitions'
50
+
51
+ - script: |
52
+ adb shell settings put global animator_duration_scale 0.0
53
+ displayName: 'Disable animations and transitions'
54
+
55
+
56
+ - task: JavaToolInstaller@0
57
+ inputs:
58
+ versionSpec: '11'
59
+ jdkArchitectureOption: 'x64'
60
+ jdkSourceOption: 'PreInstalled'
61
+ displayName: 'Change Java version'
62
+
63
+ - script: |
64
+ npm install
65
+ displayName: 'Package Installation'
66
+
67
+ - script: |
68
+ npm run build:tests && npm run test:setup:android
69
+ displayName: 'Setup Android tests'
70
+
71
+ - script: |
72
+ npm run test:fast:android
73
+ displayName: 'Run Android test'
74
+
75
+ - job: TestIOS
76
+ timeoutInMinutes: 120
77
+ displayName: 'Test IOS'
78
+ steps:
79
+
80
+ - script: |
81
+ npm install
82
+ displayName: 'Install dependencies'
83
+
84
+ - script: |
85
+ npm run build:tests && npm run test:setup:ios
86
+ displayName: 'Setup iOS tests'
87
+
88
+ - script: |
89
+ npm run test:fast:ios
90
+ displayName: 'Run tests'
91
+
92
+
93
+
94
+
@@ -0,0 +1,14 @@
1
+ {
2
+ "tool": "Credential Scanner",
3
+ "suppressions": [
4
+ {
5
+ "file": "/Examples/CodePushDemoApp/android/app/debug.keystore",
6
+ "_justification": "Used only in DemoApp"
7
+ },
8
+ {
9
+ "file": "/Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/CodePushDemoAppCpp_TemporaryKey.pfx",
10
+ "_justification": "Used only in DemoApp"
11
+ }
12
+ ]
13
+ }
14
+
package/CONTRIBUTING.md CHANGED
@@ -37,10 +37,10 @@ Follow these steps to test your modifications to the plugin manually:
37
37
 
38
38
  First, make sure you have installed the dependencies for the plugin by following the steps above.
39
39
 
40
- Then, make sure you have installed `react-native-cli`.
40
+ Then, make sure you have installed `react-native`.
41
41
 
42
42
  ```
43
- npm install -g react-native-cli
43
+ npm install -g react-native
44
44
  ```
45
45
 
46
46
  To run Android tests, make sure you have `sdk\tools`, `sdk\emulator` and `sdk\platform-tools` in your PATH.
@@ -131,4 +131,4 @@ To run the core unit tests on Android and pull the plugin from NPM:
131
131
  NPM=true CORE=true npm run test:android
132
132
  ```
133
133
 
134
- ...and so on!
134
+ ...and so on!
package/CodePush.js CHANGED
@@ -531,42 +531,41 @@ function codePushify(options = {}) {
531
531
  );
532
532
  }
533
533
 
534
- var decorator = (RootComponent) => {
535
- const extended = class CodePushComponent extends React.Component {
534
+ const decorator = (RootComponent) => {
535
+ class CodePushComponent extends React.Component {
536
+ constructor(props) {
537
+ super(props);
538
+ this.rootComponentRef = React.createRef();
539
+ }
540
+
536
541
  componentDidMount() {
537
542
  if (options.checkFrequency === CodePush.CheckFrequency.MANUAL) {
538
543
  CodePush.notifyAppReady();
539
544
  } else {
540
- let rootComponentInstance = this.refs.rootComponent;
545
+ const rootComponentInstance = this.rootComponentRef.current;
541
546
 
542
547
  let syncStatusCallback;
543
548
  if (rootComponentInstance && rootComponentInstance.codePushStatusDidChange) {
544
- syncStatusCallback = rootComponentInstance.codePushStatusDidChange;
545
- if (rootComponentInstance instanceof React.Component) {
546
- syncStatusCallback = syncStatusCallback.bind(rootComponentInstance);
547
- }
549
+ syncStatusCallback = rootComponentInstance.codePushStatusDidChange.bind(rootComponentInstance);
548
550
  }
549
551
 
550
552
  let downloadProgressCallback;
551
553
  if (rootComponentInstance && rootComponentInstance.codePushDownloadDidProgress) {
552
- downloadProgressCallback = rootComponentInstance.codePushDownloadDidProgress;
553
- if (rootComponentInstance instanceof React.Component) {
554
- downloadProgressCallback = downloadProgressCallback.bind(rootComponentInstance);
555
- }
554
+ downloadProgressCallback = rootComponentInstance.codePushDownloadDidProgress.bind(rootComponentInstance);
556
555
  }
557
556
 
558
557
  let handleBinaryVersionMismatchCallback;
559
558
  if (rootComponentInstance && rootComponentInstance.codePushOnBinaryVersionMismatch) {
560
- handleBinaryVersionMismatchCallback = rootComponentInstance.codePushOnBinaryVersionMismatch;
561
- if (rootComponentInstance instanceof React.Component) {
562
- handleBinaryVersionMismatchCallback = handleBinaryVersionMismatchCallback.bind(rootComponentInstance);
563
- }
559
+ handleBinaryVersionMismatchCallback = rootComponentInstance.codePushOnBinaryVersionMismatch.bind(rootComponentInstance);
564
560
  }
565
561
 
566
562
  CodePush.sync(options, syncStatusCallback, downloadProgressCallback, handleBinaryVersionMismatchCallback);
563
+
567
564
  if (options.checkFrequency === CodePush.CheckFrequency.ON_APP_RESUME) {
568
565
  ReactNative.AppState.addEventListener("change", (newState) => {
569
- newState === "active" && CodePush.sync(options, syncStatusCallback, downloadProgressCallback);
566
+ if (newState === "active") {
567
+ CodePush.sync(options, syncStatusCallback, downloadProgressCallback);
568
+ }
570
569
  });
571
570
  }
572
571
  }
@@ -575,17 +574,17 @@ function codePushify(options = {}) {
575
574
  render() {
576
575
  const props = {...this.props};
577
576
 
578
- // we can set ref property on class components only (not stateless)
579
- // check it by render method
580
- if (RootComponent.prototype.render) {
581
- props.ref = "rootComponent";
577
+ // We can set ref property on class components only (not stateless)
578
+ // Check it by render method
579
+ if (RootComponent.prototype && RootComponent.prototype.render) {
580
+ props.ref = this.rootComponentRef;
582
581
  }
583
582
 
584
583
  return <RootComponent {...props} />
585
584
  }
586
585
  }
587
586
 
588
- return hoistStatics(extended, RootComponent);
587
+ return hoistStatics(CodePushComponent, RootComponent);
589
588
  }
590
589
 
591
590
  if (typeof options === "function") {
package/README.md CHANGED
@@ -75,7 +75,8 @@ We try our best to maintain backwards compatibility of our plugin with previous
75
75
  | v0.59 | v5.6+ *(RN refactored js bundle loader code)* |
76
76
  | v0.60-v0.61 | v6.0+ *(RN migrated to Autolinking)* |
77
77
  | v0.62-v0.64 | v6.2+ *(RN removed LiveReload)* |
78
- | v0.65-v0.69 | v7.2+ *(RN updated iPhone-target-version)* |
78
+ | v0.65-v0.70 | v7.0+ *(RN updated iPhone-target-version)* |
79
+ | v0.71 | v8.0+ *(RN moved to react-native-gradle-plugin)* |
79
80
 
80
81
  *NOTE: `react-native-code-push` versions lower than **[v5.7.0](https://github.com/microsoft/react-native-code-push/releases/tag/v5.7.0)** will stop working in the near future. You can find more information in our [documentation](https://github.com/microsoft/code-push/blob/master/migration-notice.md).*
81
82
 
@@ -276,7 +277,7 @@ Once your app is configured and distributed to your users, and you have made som
276
277
 
277
278
  *NOTE: Before you can start releasing updates, please log into App Center by running the `appcenter login` command.*
278
279
 
279
- In it's the most basic form, this command only requires one parameter: your owner name + "/" + app name.
280
+ In its most basic form, this command only requires one parameter: your owner name + "/" + app name.
280
281
 
281
282
  ```shell
282
283
  appcenter codepush release-react -a <ownerName>/<appName>
@@ -387,7 +388,6 @@ The React Native community has graciously created some awesome open source apps
387
388
 
388
389
  Additionally, if you're looking to get started with React Native + CodePush, and are looking for an awesome starter kit, you should check out the following:
389
390
 
390
- * [Native Starter Pro](http://strapmobile.com/native-starter-pro/)
391
391
  * [Pepperoni](http://getpepperoni.com/)
392
392
 
393
393
  *Note: If you've developed a React Native app using CodePush, that is also open-source, please let us know. We would love to add it to this list!*
@@ -432,7 +432,7 @@ In addition to being able to use the CodePush CLI to "manually" release updates,
432
432
  * [Visual Studio Team Services](https://marketplace.visualstudio.com/items?itemName=ms-vsclient.code-push) - *NOTE: VSTS also has extensions for publishing to [HockeyApp](https://marketplace.visualstudio.com/items?itemName=ms.hockeyapp) and the [Google Play](https://github.com/microsoft/google-play-vsts-extension) store, so it provides a pretty great mobile CD solution in general.*
433
433
  * [Travis CI](https://github.com/mondora/code-push-travis-cli)
434
434
 
435
- Additionally, if you'd like more details of what a complete mobile CI/CD workflow can look like, which includes CodePush, check out this [excellent article](https://zeemee.engineering/zeemee-engineering-and-the-quest-for-the-holy-mobile-dev-grail-1310be4953d1#.zfwaxtbco) by the [ZeeMee engineering team](https://zeemee.engineering).
435
+ Additionally, if you'd like more details of what a complete mobile CI/CD workflow can look like, which includes CodePush, check out this [excellent article](https://medium.com/zeemee-engineering/zeemee-engineering-and-the-quest-for-the-holy-mobile-dev-grail-1310be4953d1) by the [ZeeMee engineering team](https://www.zeemee.com/).
436
436
 
437
437
  ### TypeScript Consumption
438
438
 
@@ -27,5 +27,5 @@ android {
27
27
 
28
28
  dependencies {
29
29
  implementation "com.facebook.react:react-native:+"
30
- implementation 'com.nimbusds:nimbus-jose-jwt:5.1'
30
+ implementation 'com.nimbusds:nimbus-jose-jwt:9.37.3'
31
31
  }
@@ -3,8 +3,4 @@
3
3
 
4
4
  <uses-permission android:name="android.permission.INTERNET" />
5
5
 
6
- <application>
7
- <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
8
- </application>
9
-
10
- </manifest>
6
+ </manifest>
@@ -10,8 +10,8 @@ import com.facebook.react.ReactPackage;
10
10
  import com.facebook.react.bridge.JavaScriptModule;
11
11
  import com.facebook.react.bridge.NativeModule;
12
12
  import com.facebook.react.bridge.ReactApplicationContext;
13
- import com.facebook.react.devsupport.DevInternalSettings;
14
13
  import com.facebook.react.devsupport.interfaces.DevSupportManager;
14
+ import com.facebook.react.modules.debug.interfaces.DeveloperSettings;
15
15
  import com.facebook.react.uimanager.ViewManager;
16
16
 
17
17
  import org.json.JSONException;
@@ -152,12 +152,12 @@ public class CodePush implements ReactPackage {
152
152
  if (instanceManager != null) {
153
153
  DevSupportManager devSupportManager = instanceManager.getDevSupportManager();
154
154
  if (devSupportManager != null) {
155
- DevInternalSettings devInternalSettings = (DevInternalSettings)devSupportManager.getDevSettings();
156
- Method[] methods = devInternalSettings.getClass().getMethods();
155
+ DeveloperSettings devSettings = devSupportManager.getDevSettings();
156
+ Method[] methods = devSettings.getClass().getMethods();
157
157
  for (Method m : methods) {
158
158
  if (m.getName().equals("isReloadOnJSChangeEnabled")) {
159
159
  try {
160
- return (boolean) m.invoke(devInternalSettings);
160
+ return (boolean) m.invoke(devSettings);
161
161
  } catch (Exception x) {
162
162
  return false;
163
163
  }
@@ -295,7 +295,16 @@ public class CodePush implements ReactPackage {
295
295
 
296
296
  JSONObject pendingUpdate = mSettingsManager.getPendingUpdate();
297
297
  if (pendingUpdate != null) {
298
- JSONObject packageMetadata = this.mUpdateManager.getCurrentPackage();
298
+ JSONObject packageMetadata = null;
299
+
300
+ try {
301
+ packageMetadata = this.mUpdateManager.getCurrentPackage();
302
+ } catch (CodePushMalformedDataException e) {
303
+ // We need to recover the app in case 'codepush.json' is corrupted
304
+ CodePushUtils.log(e);
305
+ clearUpdates();
306
+ return;
307
+ }
299
308
  if (packageMetadata == null || !isPackageBundleLatest(packageMetadata) && hasBinaryVersionChanged(packageMetadata)) {
300
309
  CodePushUtils.log("Skipping initializeUpdateAfterRestart(), binary version is newer");
301
310
  return;
@@ -31,4 +31,5 @@ public class CodePushConstants {
31
31
  public static final String LATEST_ROLLBACK_PACKAGE_HASH_KEY = "packageHash";
32
32
  public static final String LATEST_ROLLBACK_TIME_KEY = "time";
33
33
  public static final String LATEST_ROLLBACK_COUNT_KEY = "count";
34
+ public static final String CLIENT_UNIQUE_ID_KEY = "clientUniqueId";
34
35
  }
@@ -1,6 +1,7 @@
1
1
  package com.microsoft.codepush.react;
2
2
 
3
3
  import android.app.Activity;
4
+ import android.content.SharedPreferences;
4
5
  import android.os.AsyncTask;
5
6
  import android.os.Handler;
6
7
  import android.os.Looper;
@@ -34,6 +35,7 @@ import java.util.Date;
34
35
  import java.util.HashMap;
35
36
  import java.util.List;
36
37
  import java.util.Map;
38
+ import java.util.UUID;
37
39
 
38
40
  public class CodePushNativeModule extends ReactContextBaseJavaModule {
39
41
  private String mBinaryContentsHash = null;
@@ -60,7 +62,13 @@ public class CodePushNativeModule extends ReactContextBaseJavaModule {
60
62
 
61
63
  // Initialize module state while we have a reference to the current context.
62
64
  mBinaryContentsHash = CodePushUpdateUtils.getHashForBinaryContents(reactContext, mCodePush.isDebugMode());
63
- mClientUniqueId = Settings.Secure.getString(reactContext.getContentResolver(), Settings.Secure.ANDROID_ID);
65
+
66
+ SharedPreferences preferences = codePush.getContext().getSharedPreferences(CodePushConstants.CODE_PUSH_PREFERENCES, 0);
67
+ mClientUniqueId = preferences.getString(CodePushConstants.CLIENT_UNIQUE_ID_KEY, null);
68
+ if (mClientUniqueId == null) {
69
+ mClientUniqueId = UUID.randomUUID().toString();
70
+ preferences.edit().putString(CodePushConstants.CLIENT_UNIQUE_ID_KEY, mClientUniqueId).apply();
71
+ }
64
72
  }
65
73
 
66
74
  @Override
@@ -3,11 +3,12 @@ package com.microsoft.codepush.react;
3
3
  import android.content.Context;
4
4
  import android.util.Base64;
5
5
 
6
+ import com.nimbusds.jose.JWSVerifier;
7
+ import com.nimbusds.jose.crypto.RSASSAVerifier;
8
+ import com.nimbusds.jwt.SignedJWT;
9
+
6
10
  import java.security.interfaces.*;
7
11
 
8
- import com.nimbusds.jose.*;
9
- import com.nimbusds.jose.crypto.*;
10
- import com.nimbusds.jwt.*;
11
12
 
12
13
  import org.json.JSONArray;
13
14
  import org.json.JSONException;
@@ -97,7 +98,7 @@ public class CodePushUpdateUtils {
97
98
  }
98
99
 
99
100
  public static void copyNecessaryFilesFromCurrentPackage(String diffManifestFilePath, String currentPackageFolderPath, String newPackageFolderPath) throws IOException {
100
- FileUtils.copyDirectoryContents(currentPackageFolderPath, newPackageFolderPath);
101
+ FileUtils.copyDirectoryContents(currentPackageFolderPath, newPackageFolderPath);
101
102
  JSONObject diffManifest = CodePushUtils.getJsonObjectFromFile(diffManifestFilePath);
102
103
  try {
103
104
  JSONArray deletedFiles = diffManifest.getJSONArray("deletedFiles");
@@ -67,7 +67,9 @@ public class CodePushUtils {
67
67
  String key = it.next();
68
68
  Object obj = null;
69
69
  try {
70
- obj = jsonObj.get(key);
70
+ if (!jsonObj.isNull(key)) {
71
+ obj = jsonObj.get(key);
72
+ }
71
73
  } catch (JSONException jsonException) {
72
74
  // Should not happen.
73
75
  throw new CodePushUnknownException("Key " + key + " should exist in " + jsonObj.toString() + ".", jsonException);
@@ -2,7 +2,8 @@
2
2
 
3
3
  buildscript {
4
4
  repositories {
5
- jcenter()
5
+ google()
6
+ mavenCentral()
6
7
  }
7
8
  dependencies {
8
9
  classpath 'com.android.tools.build:gradle:1.3.0'
@@ -15,6 +16,6 @@ buildscript {
15
16
  allprojects {
16
17
  repositories {
17
18
  mavenLocal()
18
- jcenter()
19
+ mavenCentral()
19
20
  }
20
21
  }
@@ -2,8 +2,8 @@
2
2
 
3
3
  import java.nio.file.Paths;
4
4
 
5
- def config = project.hasProperty("react") ? project.react : [];
6
- def bundleAssetName = config.bundleAssetName ?: "index.android.bundle"
5
+ def config = project.extensions.findByName("react") ?: [:]
6
+ def bundleAssetName = config.bundleAssetName ? config.bundleAssetName.get() : "index.android.bundle"
7
7
 
8
8
  // because elvis operator
9
9
  def elvisFile(thing) {
@@ -17,21 +17,61 @@ void runBefore(String dependentTaskName, Task task) {
17
17
  }
18
18
  }
19
19
 
20
+ /**
21
+ * Finds the path of the installed npm package with the given name using Node's
22
+ * module resolution algorithm, which searches "node_modules" directories up to
23
+ * the file system root. This handles various cases, including:
24
+ *
25
+ * - Working in the open-source RN repo:
26
+ * Gradle: /path/to/react-native/ReactAndroid
27
+ * Node module: /path/to/react-native/node_modules/[package]
28
+ *
29
+ * - Installing RN as a dependency of an app and searching for hoisted
30
+ * dependencies:
31
+ * Gradle: /path/to/app/node_modules/react-native/ReactAndroid
32
+ * Node module: /path/to/app/node_modules/[package]
33
+ *
34
+ * - Working in a larger repo (e.g., Facebook) that contains RN:
35
+ * Gradle: /path/to/repo/path/to/react-native/ReactAndroid
36
+ * Node module: /path/to/repo/node_modules/[package]
37
+ *
38
+ * The search begins at the given base directory (a File object). The returned
39
+ * path is a string.
40
+ */
41
+ static def findNodeModulePath(baseDir, packageName) {
42
+ def basePath = baseDir.toPath().normalize()
43
+ // Node's module resolution algorithm searches up to the root directory,
44
+ // after which the base path will be null
45
+ while (basePath) {
46
+ def candidatePath = Paths.get(basePath.toString(), "node_modules", packageName)
47
+ if (candidatePath.toFile().exists()) {
48
+ return candidatePath.toString()
49
+ }
50
+ basePath = basePath.getParent()
51
+ }
52
+ return null
53
+ }
54
+
20
55
  android.buildTypes.each { buildType ->
21
56
  // to prevent incorrect long value restoration from strings.xml we need to wrap it with double quotes
22
57
  // https://github.com/microsoft/cordova-plugin-code-push/issues/264
23
58
  buildType.resValue 'string', "CODE_PUSH_APK_BUILD_TIME", String.format("\"%d\"", System.currentTimeMillis())
24
59
  }
25
60
 
26
- gradle.projectsEvaluated {
61
+ gradle.projectsEvaluated {
62
+ def debuggableVariants = config.debuggableVariants ? config.debuggableVariants.get() : ['debug']
63
+
27
64
  android.applicationVariants.all { variant ->
65
+ // No code push for debuggable variants
66
+ if (debuggableVariants.contains(variant.name)) {
67
+ return;
68
+ }
69
+
28
70
  def nodeModulesPath;
29
- if (config.root) {
30
- nodeModulesPath = Paths.get(config.root, "/node_modules");
31
- } else if (project.hasProperty('nodeModulesPath')) {
32
- nodeModulesPath = project.nodeModulesPath
71
+ if (project.hasProperty('nodeModulesPath')) {
72
+ nodeModulesPath = "${project.nodeModulesPath}/react-native-code-push"
33
73
  } else {
34
- nodeModulesPath = "../../node_modules";
74
+ nodeModulesPath = findNodeModulePath(projectDir, "react-native-code-push")
35
75
  }
36
76
 
37
77
  def targetName = variant.name.capitalize()
@@ -42,40 +82,45 @@ gradle.projectsEvaluated {
42
82
  def jsBundleFile;
43
83
 
44
84
  // Additional node commandline arguments
45
- def nodeExecutableAndArgs = config.nodeExecutableAndArgs ?: ["node"]
46
- def extraPackagerArgs = config.extraPackagerArgs ?: []
85
+ def nodeExecutableAndArgs = config.nodeExecutableAndArgs ? config.nodeExecutableAndArgs.get(): ["node"]
86
+ def extraPackagerArgs = config.extraPackagerArgs ? config.extraPackagerArgs.get() : []
47
87
 
48
88
  // Make this task run right after the bundle task
49
89
  def generateBundledResourcesHash;
50
90
 
51
- if (variant.hasProperty("bundleJsAndAssets")) {
52
- def reactBundleTask = variant.bundleJsAndAssets
53
- jsBundleDir = reactBundleTask.generatedAssetsFolders[0].absolutePath
54
- resourcesDir = reactBundleTask.generatedResFolders[0].absolutePath
91
+ def reactBundleTask = tasks.findByName("createBundle${targetName}JsAndAssets")
92
+ if (reactBundleTask) {
93
+ jsBundleDir = reactBundleTask.property('jsBundleDir').asFile.get()
94
+ resourcesDir = reactBundleTask.property('resourcesDir').asFile.get()
95
+
96
+ // mitigates Resource and asset merger: Duplicate resources error
97
+ project.delete(files("${jsBundleDir}"))
98
+
99
+ jsBundleDir.mkdirs()
100
+ resourcesDir.mkdirs()
101
+
55
102
  jsBundleFile = file("$jsBundleDir/$bundleAssetName")
56
103
 
57
104
  generateBundledResourcesHash = tasks.create(
58
105
  name: "generateBundledResourcesHash${targetName}",
59
106
  type: Exec) {
60
- commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/react-native-code-push/scripts/generateBundledResourcesHash.js", resourcesDir, jsBundleFile, jsBundleDir)
107
+ commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/scripts/generateBundledResourcesHash.js", resourcesDir, jsBundleFile, jsBundleDir)
61
108
 
62
- enabled config."bundleIn${targetName}" ||
63
- config."bundleIn${variant.buildType.name.capitalize()}" ?:
64
- targetName.toLowerCase().contains("release")
109
+ enabled !debuggableVariants.contains(variant.name) ?: targetName.toLowerCase().contains("release")
65
110
  }
66
-
111
+
67
112
  runBefore("merge${targetName}Resources", generateBundledResourcesHash)
68
- runBefore("merge${targetName}Assets", generateBundledResourcesHash)
113
+ runBefore("merge${targetName}Assets", generateBundledResourcesHash)
69
114
  } else {
70
115
  def jsBundleDirConfigName = "jsBundleDir${targetName}"
71
- jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?:
116
+ jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ? elvisFile(config."$jsBundleDirConfigName").get():
72
117
  file("$buildDir/intermediates/assets/${targetPath}")
73
118
 
74
119
  def resourcesDirConfigName = "resourcesDir${targetName}"
75
- resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?:
120
+ resourcesDir = elvisFile(config."${resourcesDirConfigName}") ? elvisFile(config."${resourcesDirConfigName}").get():
76
121
  file("$buildDir/intermediates/res/merged/${targetPath}")
77
122
 
78
- // In case version of 'Android Plugin for Gradle'' is lower than 1.3.0
123
+ // In case version of 'Android Plugin for Gradle'' is lower than 1.3.0
79
124
  // '$buildDir' has slightly different structure - 'merged' folder
80
125
  // does not exists so '${targetPath}' folder contains directly in 'res' folder.
81
126
  if (!resourcesDir.exists() && file("$buildDir/intermediates/res/${targetPath}").exists()) {
@@ -89,14 +134,14 @@ gradle.projectsEvaluated {
89
134
  generateBundledResourcesHash = tasks.create(
90
135
  name: "generateBundledResourcesHash${targetName}",
91
136
  type: Exec) {
92
- commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/react-native-code-push/scripts/generateBundledResourcesHash.js", resourcesDir, jsBundleFile, jsBundleDir, resourcesMapTempFileName)
137
+ commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/scripts/generateBundledResourcesHash.js", resourcesDir, jsBundleFile, jsBundleDir, resourcesMapTempFileName)
93
138
  }
94
139
 
95
140
  // Make this task run right before the bundle task
96
141
  def recordFilesBeforeBundleCommand = tasks.create(
97
142
  name: "recordFilesBeforeBundleCommand${targetName}",
98
143
  type: Exec) {
99
- commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/react-native-code-push/scripts/recordFilesBeforeBundleCommand.js", resourcesDir, resourcesMapTempFileName)
144
+ commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/scripts/recordFilesBeforeBundleCommand.js", resourcesDir, resourcesMapTempFileName)
100
145
  }
101
146
 
102
147
  recordFilesBeforeBundleCommand.dependsOn("merge${targetName}Resources")
@@ -107,7 +152,8 @@ gradle.projectsEvaluated {
107
152
  generateBundledResourcesHash.dependsOn("recordFilesBeforeBundleCommand${targetName}")
108
153
  }
109
154
 
110
- generateBundledResourcesHash.dependsOn("bundle${targetName}JsAndAssets")
155
+ generateBundledResourcesHash.dependsOn("createBundle${targetName}JsAndAssets")
156
+
111
157
  runBefore("processArmeabi-v7a${targetName}Resources", generateBundledResourcesHash)
112
158
  runBefore("processX86${targetName}Resources", generateBundledResourcesHash)
113
159
  runBefore("processUniversal${targetName}Resources", generateBundledResourcesHash)
package/docs/api-js.md CHANGED
@@ -128,7 +128,7 @@ The `codePush` decorator accepts an "options" object that allows you to customiz
128
128
 
129
129
  * __minimumBackgroundDuration__ *(Number)* - Specifies the minimum number of seconds that the app needs to have been in the background before restarting the app. This property only applies to updates which are installed using `InstallMode.ON_NEXT_RESUME` or `InstallMode.ON_NEXT_SUSPEND`, and can be useful for getting your update in front of end users sooner, without being too obtrusive. Defaults to `0`, which has the effect of applying the update immediately after a resume or unless the app suspension is long enough to not matter, regardless how long it was in the background.
130
130
 
131
- * __updateDialog__ *(UpdateDialogOptions)* - An "options" object used to determine whether a confirmation dialog should be displayed to the end user when an update is available, and if so, what strings to use. Defaults to `null`, which has the effect of disabling the dialog completely. Setting this to any truthy value will enable the dialog with the default strings, and passing an object to this parameter allows enabling the dialog as well as overriding one or more of the default strings. Before enabling this option within an App Store-distributed app, please refer to [this note](https://github.com/microsoft/react-native-code-push#user-content-apple-note).
131
+ * __updateDialog__ *(UpdateDialogOptions)* - An "options" object used to determine whether a confirmation dialog should be displayed to the end user when an update is available, and if so, what strings to use. Defaults to `null`, which has the effect of disabling the dialog completely. Setting this to any truthy value will enable the dialog with the default strings, and passing an object to this parameter allows enabling the dialog as well as overriding one or more of the default strings. Before enabling this option within an App Store-distributed app, please refer to [this note](https://github.com/microsoft/react-native-code-push#app-store).
132
132
 
133
133
  The following list represents the available options and their defaults:
134
134
 
@@ -27,16 +27,40 @@ In order to integrate CodePush into your Android project, please perform the fol
27
27
  project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')
28
28
  ```
29
29
 
30
- 2. In your `android/app/build.gradle` file, add the `codepush.gradle` file as an additional build task definition underneath `react.gradle`:
30
+ 2. In your `android/app/build.gradle` file, add the `codepush.gradle` file as an additional build task definition to the end of the file:
31
31
 
32
32
  ```gradle
33
33
  ...
34
- apply from: "../../node_modules/react-native/react.gradle"
35
34
  apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
36
35
  ...
37
36
  ```
38
37
 
39
- 3. Update the `MainApplication.java` file to use CodePush via the following changes:
38
+ 3. Update the `MainApplication` file to use CodePush via the following changes:
39
+
40
+ For React Native 0.73 and above: update the `MainApplication.kt`
41
+
42
+ ```kotlin
43
+ ...
44
+ // 1. Import the plugin class.
45
+ import com.microsoft.codepush.react.CodePush
46
+
47
+ class MainApplication : Application(), ReactApplication {
48
+
49
+ override val reactNativeHost: ReactNativeHost =
50
+ object : DefaultReactNativeHost(this) {
51
+ ...
52
+
53
+ // 2. Override the getJSBundleFile method in order to let
54
+ // the CodePush runtime determine where to get the JS
55
+ // bundle location from on each app start
56
+ override fun getJSBundleFile(): String {
57
+ return CodePush.getJSBundleFile()
58
+ }
59
+ };
60
+ }
61
+ ```
62
+
63
+ For React Native 0.72 and below: update the `MainApplication.java`
40
64
 
41
65
  ```java
42
66
  ...
package/docs/setup-ios.md CHANGED
@@ -35,7 +35,7 @@ Once you've acquired the CodePush plugin, you need to integrate it into the Xcod
35
35
  - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
36
36
  {
37
37
  #if DEBUG
38
- return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
38
+ return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
39
39
  #else
40
40
  return [CodePush bundleURL];
41
41
  #endif
@@ -33,6 +33,29 @@ void App::OnLaunched(activation::LaunchActivatedEventArgs const& e)
33
33
  ...
34
34
  ```
35
35
 
36
+ #### Plugin Configuration (Windows) C#
37
+
38
+ 1. add name space `Microsoft.CodePush` to `App.xaml.cs`
39
+
40
+ 2. add app version and deployment key to `configMap` at the start of your app's `OnLaunched` method in `App.xaml.cs`.
41
+
42
+ ```c#
43
+ using Microsoft.CodePush;
44
+
45
+ ...
46
+ protected override void OnLaunched(LaunchActivatedEventArgs e)
47
+ {
48
+ Microsoft.CodePush.ReactNative.CodePushConfig.SetHost(Host);
49
+ IDictionary<string, string> configMap = new Dictionary<string, string>();
50
+ configMap.Add("appVersion", "1.0.0");
51
+ configMap.Add("deploymentKey", "deployment key");
52
+ Microsoft.CodePush.ReactNative.CodePushConfig.Init(configMap);
53
+ ...
54
+ }
55
+ ...
56
+ ```
57
+
58
+
36
59
  ### Plugin Installation and Configuration for React Native Windows lower than 0.60
37
60
 
38
61
  #### Plugin Installation (Windows)
@@ -1,5 +1,9 @@
1
1
  #import "CodePush.h"
2
+ #if __has_include(<SSZipArchive/SSZipArchive.h>)
3
+ #import <SSZipArchive/SSZipArchive.h>
4
+ #else
2
5
  #import "SSZipArchive.h"
6
+ #endif
3
7
 
4
8
  @implementation CodePushPackage
5
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appzung/react-native-code-push",
3
- "version": "7.1.1",
3
+ "version": "8.3.2",
4
4
  "description": "React Native plugin for the CodePush service",
5
5
  "main": "CodePush.js",
6
6
  "typings": "typings/react-native-code-push.d.ts",
@@ -25,7 +25,7 @@
25
25
  "tslint": "tslint -c tslint.json test/**/*.ts"
26
26
  },
27
27
  "dependencies": {
28
- "code-push": "^4.1.0",
28
+ "code-push": "^4.2.2",
29
29
  "glob": "^7.1.7",
30
30
  "hoist-non-react-statics": "^3.3.2",
31
31
  "inquirer": "^8.1.5",
@@ -134,7 +134,7 @@ export interface SyncOptions {
134
134
  * value will enable the dialog with the default strings, and passing an object to this parameter allows enabling the dialog as well as
135
135
  * overriding one or more of the default strings.
136
136
  */
137
- updateDialog?: UpdateDialog;
137
+ updateDialog?: UpdateDialog | true;
138
138
 
139
139
  /**
140
140
  * The rollback retry mechanism allows the application to attempt to reinstall an update that was previously rolled back (with the restrictions
@@ -14,8 +14,8 @@
14
14
  <AppContainerApplication>true</AppContainerApplication>
15
15
  <ApplicationType>Windows Store</ApplicationType>
16
16
  <ApplicationTypeRevision>10.0</ApplicationTypeRevision>
17
- <WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18362.0</WindowsTargetPlatformVersion>
18
- <WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
17
+ <WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0</WindowsTargetPlatformVersion>
18
+ <WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
19
19
  </PropertyGroup>
20
20
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
21
21
  <PropertyGroup Label="ReactNativeWindowsProps">
@@ -57,7 +57,6 @@
57
57
  </ItemGroup>
58
58
  <PropertyGroup Label="Configuration">
59
59
  <ConfigurationType>DynamicLibrary</ConfigurationType>
60
- <PlatformToolset>v140</PlatformToolset>
61
60
  <PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset>
62
61
  <PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset>
63
62
  <CharacterSet>Unicode</CharacterSet>
@@ -50,8 +50,8 @@
50
50
  <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
51
51
  </PropertyGroup>
52
52
  <ItemGroup>
53
- <Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
54
- <HintPath>$(SolutionDir)\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
53
+ <Reference Include="Newtonsoft.Json, Version=13.0.1.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
54
+ <HintPath>$(SolutionDir)\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
55
55
  <Private>True</Private>
56
56
  </Reference>
57
57
  <Reference Include="PCLStorage, Version=1.0.2.0, Culture=neutral, PublicKeyToken=286fe515a2c35b64, processorArchitecture=MSIL">
@@ -71,9 +71,9 @@
71
71
  <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
72
72
  </PropertyGroup>
73
73
  <ItemGroup>
74
- <Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
74
+ <Reference Include="Newtonsoft.Json, Version=13.0.1.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
75
75
  <SpecificVersion>False</SpecificVersion>
76
- <HintPath>..\..\Examples\CodePushDemoApp\windows\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
76
+ <HintPath>..\..\Examples\CodePushDemoApp\windows\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
77
77
  <Private>True</Private>
78
78
  </Reference>
79
79
  <Reference Include="System" />