From e6abf60a3b0768ee4011865dcf7d47e79629af3e Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Mon, 23 Nov 2015 18:56:12 -0800 Subject: [PATCH 01/10] Splitting restartApp into internal and public versions --- CodePush.ios.js | 55 +++++++++++++++++++---------------------------- CodePush.m | 24 ++++++++++++++------- README.md | 10 ++++----- package-mixins.js | 5 +++-- 4 files changed, 46 insertions(+), 48 deletions(-) diff --git a/CodePush.ios.js b/CodePush.ios.js index 449a71f..0ce97aa 100644 --- a/CodePush.ios.js +++ b/CodePush.ios.js @@ -1,10 +1,20 @@ 'use strict'; -var { AlertIOS } = require("react-native"); var NativeCodePush = require("react-native").NativeModules.CodePush; -var packageMixins = require("./package-mixins")(NativeCodePush); var requestFetchAdapter = require("./request-fetch-adapter.js"); var Sdk = require("code-push/script/acquisition-sdk").AcquisitionManager; +var packageMixins = require("./package-mixins")(NativeCodePush); + +var { AlertIOS } = require("react-native"); + +// This function is only used for tests. Replaces the default SDK, configuration and native bridge +function setUpTestDependencies(providedTestSdk, providedTestConfig, testNativeBridge){ + if (providedTestSdk) testSdk = providedTestSdk; + if (providedTestConfig) testConfig = providedTestConfig; + if (testNativeBridge) NativeCodePush = testNativeBridge; +} +var testConfig; +var testSdk; function checkForUpdate() { var config; @@ -51,12 +61,10 @@ function checkForUpdate() { }); } -var isConfigValid = true; - var getConfiguration = (() => { var config; return function getConfiguration() { - if (config && isConfigValid) { + if (config) { return Promise.resolve(config); } else if (testConfig) { return Promise.resolve(testConfig); @@ -64,7 +72,6 @@ var getConfiguration = (() => { return NativeCodePush.getConfiguration() .then((configuration) => { if (!config) config = configuration; - isConfigValid = true; return config; }); } @@ -114,30 +121,6 @@ function log(message) { console.log(`[CodePush] ${message}`) } -function restartApp(rollbackTimeout = 0) { - NativeCodePush.restartApp(rollbackTimeout); -} - -function setDeploymentKey(deploymentKey) { - return NativeCodePush.setDeploymentKey(deploymentKey) - .then(() => { - // Mark the local copy of the config data - // as invalid since we just modified it - // on the native end. - isConfigValid = false; - }); -} - -var testConfig; -var testSdk; - -// This function is only used for tests. Replaces the default SDK, configuration and native bridge -function setUpTestDependencies(providedTestSdk, providedTestConfig, testNativeBridge) { - if (providedTestSdk) testSdk = providedTestSdk; - if (providedTestConfig) testConfig = providedTestConfig; - if (testNativeBridge) NativeCodePush = testNativeBridge; -} - /** * The sync method provides a simple, one-line experience for * incorporating the check, download and application of an update. @@ -231,7 +214,7 @@ function sync(options = {}, syncStatusChangeCallback, downloadProgressCallback) if (typeof syncOptions.updateDialog !== "object") { syncOptions.updateDialog = CodePush.DEFAULT_UPDATE_DIALOG; } else { - syncOptions.updateDialog = Object.assign({}, CodePush.DEFAULT_UPDATE_DIALOG, syncOptions.updateDialog); + syncOptions.updateDialog = Object.assign(CodePush.DEFAULT_UPDATE_DIALOG, syncOptions.updateDialog); } var message = null; @@ -275,6 +258,7 @@ function sync(options = {}, syncStatusChangeCallback, downloadProgressCallback) } }) .catch((error) => { + console.log(error); syncStatusChangeCallback(CodePush.SyncStatus.UNKNOWN_ERROR); reject(error); }) @@ -288,10 +272,15 @@ var CodePush = { getCurrentPackage: getCurrentPackage, log: log, notifyApplicationReady: NativeCodePush.notifyApplicationReady, - restartApp: restartApp, - setDeploymentKey: setDeploymentKey, + restartApp: NativeCodePush.restartApp, + setDeploymentKey: NativeCodePush.setDeploymentKey, setUpTestDependencies: setUpTestDependencies, sync: sync, + AutoSyncMode: { + NONE: NativeCodePush.codePushAutoSyncModeNone, + ON_START: NativeCodePush.codePushAutoSyncModeOnStart, + ON_RESUME: NativeCodePush.codePushAutoSyncModeOnResume + }, InstallMode: { IMMEDIATE: NativeCodePush.codePushInstallModeImmediate, // Restart the app immediately ON_NEXT_RESTART: NativeCodePush.codePushInstallModeOnNextRestart, // Don't artificially restart the app. Allow the update to be "picked up" on the next app restart diff --git a/CodePush.m b/CodePush.m index 0728192..1655e96 100644 --- a/CodePush.m +++ b/CodePush.m @@ -119,7 +119,7 @@ static NSString * const PendingUpdateRollbackTimeoutKey = @"rollbackTimeout"; return @{ @"codePushInstallModeOnNextRestart":@(CodePushInstallModeOnNextRestart), @"codePushInstallModeImmediate": @(CodePushInstallModeImmediate), @"codePushInstallModeOnNextResume": @(CodePushInstallModeOnNextResume) - }; + }; }; - (void)dealloc @@ -326,8 +326,8 @@ RCT_EXPORT_METHOD(isFailedUpdate:(NSString *)packageHash } RCT_EXPORT_METHOD(isFirstRun:(NSString *)packageHash - resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) + resolve:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { NSError *error; BOOL isFirstRun = didUpdate @@ -339,19 +339,27 @@ RCT_EXPORT_METHOD(isFirstRun:(NSString *)packageHash } RCT_EXPORT_METHOD(notifyApplicationReady:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) + rejecter:(RCTPromiseRejectBlock)reject) { [self cancelRollbackTimer]; resolve([NSNull null]); } -RCT_EXPORT_METHOD(restartApp:(int)rollbackTimeout){ +RCT_EXPORT_METHOD(restartApp) +{ + [self checkForPendingUpdate:YES]; +} + +// This version of restart app is exposed solely for immediately installed +// update support, and shouldn't be consumed directly by user code. +RCT_EXPORT_METHOD(restartAppInternal:(int)rollbackTimeout) +{ [self initializeUpdateWithRollbackTimeout:rollbackTimeout needsRestart:YES]; } RCT_EXPORT_METHOD(setDeploymentKey:(NSString *)deploymentKey - resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) + resolve:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { [[CodePushConfig current] setDeploymentKey:deploymentKey]; resolve(nil); @@ -362,4 +370,4 @@ RCT_EXPORT_METHOD(setUsingTestFolder:(BOOL)shouldUseTestFolder) usingTestFolder = shouldUseTestFolder; } -@end +@end \ No newline at end of file diff --git a/README.md b/README.md index 47df67d..0ec3dd9 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ When you require the `react-native-code-push` module, that object provides the f * [checkForUpdate](#codepushcheckforupdate): Queries the CodePush service for an update against the configured deployment. This method returns a promise which resolves to a `RemotePackage` that can be subsequently downloaded. * [getCurrentPackage](#codepushgetcurrentpackage): Gets information about the currently installed package (e.g. description, installation time) * [notifyApplicationReady](#codepushnotifyapplicationready): Notifies the CodePush runtime that an installed update is considered successful. This is an optional API, but is useful when you want to expicitly enable "rollback protection" in the event that an exception occurs in any code that you've deployed to production -* [restartApp](#codepushrestartapp): Installs a pending update by immediately restarting the app. +* [restartApp](#codepushrestartapp): Immediately restarts the app if a previously installed update is pending. * [setDeploymentKey](#codepushsetdeploymentkey): Dynamically updates the deployment key that the CodePush runtime will use to query for app updates. * [sync](#codepushsync): Allows checking for an update, downloading it and installing it, all with a single call. Unless you need custom UI and/or behavior, we recommend most developers to use this method when integrating CodePush into their apps @@ -178,15 +178,15 @@ If the `rollbackTimeout` parameter was not specified, the CodePush runtime will #### codePush.restartApp ```javascript -codePush.restartApp(rollbackTimeout: Number = 0): void; +codePush.restartApp(): void; ``` -Installs the pending update (if applicable) by immediately restarting the app, and optionally starting the rollback timer. This method is for advanced scenarios, and is useful when the following conditions are true: +Installs a pending update (if applicable) by immediately restarting the app, and optionally starting the rollback timer. This method is for advanced scenarios, and is useful when the following conditions are true: -1. Your app is specifying an install mode value of `ON_NEXT_RESTART` when calling `sync` or `LocalPackage.install`, which has the effect of not applying your update until the app has been restarted (by either the end-user or OS) +1. Your app is specifying an install mode value of `ON_NEXT_RESTART` or `ON_NEXT_RESUME` when calling `sync` or `LocalPackage.install`, which has the effect of not applying your update until the app has been restarted (by either the end-user or OS) 2. You have an app-specific user event (e.g. the end-user navigated back to the app's home page) that allows you to apply the update in an unobtrusive way, and potentially gets the update in front of the end-user sooner then waiting until the next restart. -The `rollbackTimeout` parameter has the same behavior as the equivalent in the `sync` and `checkForUpdate` method, and allows your app to have control over the point that an update is installed, while still benefitting from rollback production. +If your app doesn't have a pending update, then calling this method results in a no-op. Otherwise, calling it will restart the app and start the rollback timer based on the timeout value that was specified in the previous call to `sync` or `LocalPackage.install`. #### codePush.setDeploymentKey diff --git a/package-mixins.js b/package-mixins.js index aa0f3de..ff823f6 100644 --- a/package-mixins.js +++ b/package-mixins.js @@ -1,3 +1,4 @@ +var extend = require("extend"); var { NativeAppEventEmitter } = require("react-native"); module.exports = (NativeCodePush) => { @@ -24,7 +25,7 @@ module.exports = (NativeCodePush) => { return NativeCodePush.downloadUpdate(this) .then((downloadedPackage) => { downloadProgressSubscription && downloadProgressSubscription.remove(); - return Object.assign({}, downloadedPackage, local); + return extend({}, downloadedPackage, local); }) .catch((error) => { downloadProgressSubscription && downloadProgressSubscription.remove(); @@ -40,7 +41,7 @@ module.exports = (NativeCodePush) => { .then(function() { updateInstalledCallback && updateInstalledCallback(); if (installMode == NativeCodePush.codePushInstallModeImmediate) { - NativeCodePush.restartApp(rollbackTimeout); + NativeCodePush.restartAppInternal(rollbackTimeout); } }); } From 6f6ed8e8436d261599e2de34d35cb8f5e02ff1c7 Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Mon, 23 Nov 2015 19:06:44 -0800 Subject: [PATCH 02/10] Fixing spacing --- CodePush.ios.js | 48 +++++++++++++++++++++++++++--------------------- CodePush.m | 39 ++++++++++++++++----------------------- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/CodePush.ios.js b/CodePush.ios.js index 0ce97aa..62346ce 100644 --- a/CodePush.ios.js +++ b/CodePush.ios.js @@ -1,20 +1,10 @@ 'use strict'; +var { AlertIOS } = require("react-native"); var NativeCodePush = require("react-native").NativeModules.CodePush; +var packageMixins = require("./package-mixins")(NativeCodePush); var requestFetchAdapter = require("./request-fetch-adapter.js"); var Sdk = require("code-push/script/acquisition-sdk").AcquisitionManager; -var packageMixins = require("./package-mixins")(NativeCodePush); - -var { AlertIOS } = require("react-native"); - -// This function is only used for tests. Replaces the default SDK, configuration and native bridge -function setUpTestDependencies(providedTestSdk, providedTestConfig, testNativeBridge){ - if (providedTestSdk) testSdk = providedTestSdk; - if (providedTestConfig) testConfig = providedTestConfig; - if (testNativeBridge) NativeCodePush = testNativeBridge; -} -var testConfig; -var testSdk; function checkForUpdate() { var config; @@ -61,10 +51,12 @@ function checkForUpdate() { }); } +var isConfigValid = true; + var getConfiguration = (() => { var config; return function getConfiguration() { - if (config) { + if (config && isConfigValid) { return Promise.resolve(config); } else if (testConfig) { return Promise.resolve(testConfig); @@ -72,6 +64,7 @@ var getConfiguration = (() => { return NativeCodePush.getConfiguration() .then((configuration) => { if (!config) config = configuration; + isConfigValid = true; return config; }); } @@ -121,6 +114,26 @@ function log(message) { console.log(`[CodePush] ${message}`) } +function setDeploymentKey(deploymentKey) { + return NativeCodePush.setDeploymentKey(deploymentKey) + .then(() => { + // Mark the local copy of the config data + // as invalid since we just modified it + // on the native end. + isConfigValid = false; + }); +} + +var testConfig; +var testSdk; + +// This function is only used for tests. Replaces the default SDK, configuration and native bridge +function setUpTestDependencies(providedTestSdk, providedTestConfig, testNativeBridge){ + if (providedTestSdk) testSdk = providedTestSdk; + if (providedTestConfig) testConfig = providedTestConfig; + if (testNativeBridge) NativeCodePush = testNativeBridge; +} + /** * The sync method provides a simple, one-line experience for * incorporating the check, download and application of an update. @@ -214,7 +227,7 @@ function sync(options = {}, syncStatusChangeCallback, downloadProgressCallback) if (typeof syncOptions.updateDialog !== "object") { syncOptions.updateDialog = CodePush.DEFAULT_UPDATE_DIALOG; } else { - syncOptions.updateDialog = Object.assign(CodePush.DEFAULT_UPDATE_DIALOG, syncOptions.updateDialog); + syncOptions.updateDialog = Object.assign({}, CodePush.DEFAULT_UPDATE_DIALOG, syncOptions.updateDialog); } var message = null; @@ -258,7 +271,6 @@ function sync(options = {}, syncStatusChangeCallback, downloadProgressCallback) } }) .catch((error) => { - console.log(error); syncStatusChangeCallback(CodePush.SyncStatus.UNKNOWN_ERROR); reject(error); }) @@ -273,14 +285,8 @@ var CodePush = { log: log, notifyApplicationReady: NativeCodePush.notifyApplicationReady, restartApp: NativeCodePush.restartApp, - setDeploymentKey: NativeCodePush.setDeploymentKey, setUpTestDependencies: setUpTestDependencies, sync: sync, - AutoSyncMode: { - NONE: NativeCodePush.codePushAutoSyncModeNone, - ON_START: NativeCodePush.codePushAutoSyncModeOnStart, - ON_RESUME: NativeCodePush.codePushAutoSyncModeOnResume - }, InstallMode: { IMMEDIATE: NativeCodePush.codePushInstallModeImmediate, // Restart the app immediately ON_NEXT_RESTART: NativeCodePush.codePushInstallModeOnNextRestart, // Don't artificially restart the app. Allow the update to be "picked up" on the next app restart diff --git a/CodePush.m b/CodePush.m index 1655e96..e0893a7 100644 --- a/CodePush.m +++ b/CodePush.m @@ -116,10 +116,11 @@ static NSString * const PendingUpdateRollbackTimeoutKey = @"rollbackTimeout"; { // Export the values of the CodePushInstallMode enum // so that the script-side can easily stay in sync - return @{ @"codePushInstallModeOnNextRestart":@(CodePushInstallModeOnNextRestart), + return @{ + @"codePushInstallModeOnNextRestart":@(CodePushInstallModeOnNextRestart), @"codePushInstallModeImmediate": @(CodePushInstallModeImmediate), @"codePushInstallModeOnNextResume": @(CodePushInstallModeOnNextResume) - }; + }; }; - (void)dealloc @@ -243,8 +244,8 @@ static NSString * const PendingUpdateRollbackTimeoutKey = @"rollbackTimeout"; // JavaScript-exported module methods RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage - resolver:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { [CodePushPackage downloadPackage:updatePackage progressCallback:^(long expectedContentLength, long receivedContentLength) { @@ -273,13 +274,13 @@ RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage } RCT_EXPORT_METHOD(getConfiguration:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) + rejecter:(RCTPromiseRejectBlock)reject) { resolve([[CodePushConfig current] configuration]); } RCT_EXPORT_METHOD(getCurrentPackage:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) + rejecter:(RCTPromiseRejectBlock)reject) { dispatch_async(dispatch_get_main_queue(), ^{ NSError *error; @@ -293,10 +294,10 @@ RCT_EXPORT_METHOD(getCurrentPackage:(RCTPromiseResolveBlock)resolve } RCT_EXPORT_METHOD(installUpdate:(NSDictionary*)updatePackage - rollbackTimeout:(int)rollbackTimeout - installMode:(CodePushInstallMode)installMode - resolver:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) + rollbackTimeout:(int)rollbackTimeout + installMode:(CodePushInstallMode)installMode + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSError *error; @@ -318,16 +319,16 @@ RCT_EXPORT_METHOD(installUpdate:(NSDictionary*)updatePackage } RCT_EXPORT_METHOD(isFailedUpdate:(NSString *)packageHash - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject) + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject) { BOOL isFailedHash = [self isFailedHash:packageHash]; resolve(@(isFailedHash)); } RCT_EXPORT_METHOD(isFirstRun:(NSString *)packageHash - resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) + resolve:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { NSError *error; BOOL isFirstRun = didUpdate @@ -339,7 +340,7 @@ RCT_EXPORT_METHOD(isFirstRun:(NSString *)packageHash } RCT_EXPORT_METHOD(notifyApplicationReady:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) + rejecter:(RCTPromiseRejectBlock)reject) { [self cancelRollbackTimer]; resolve([NSNull null]); @@ -357,14 +358,6 @@ RCT_EXPORT_METHOD(restartAppInternal:(int)rollbackTimeout) [self initializeUpdateWithRollbackTimeout:rollbackTimeout needsRestart:YES]; } -RCT_EXPORT_METHOD(setDeploymentKey:(NSString *)deploymentKey - resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) -{ - [[CodePushConfig current] setDeploymentKey:deploymentKey]; - resolve(nil); -} - RCT_EXPORT_METHOD(setUsingTestFolder:(BOOL)shouldUseTestFolder) { usingTestFolder = shouldUseTestFolder; From 8e04d38eb011a05d1e10edbf6ff7002449993417 Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Mon, 23 Nov 2015 19:08:57 -0800 Subject: [PATCH 03/10] Removing setDeploymentKey --- CodePush.ios.js | 10 ---------- package-mixins.js | 3 +-- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/CodePush.ios.js b/CodePush.ios.js index 62346ce..9e4e700 100644 --- a/CodePush.ios.js +++ b/CodePush.ios.js @@ -114,16 +114,6 @@ function log(message) { console.log(`[CodePush] ${message}`) } -function setDeploymentKey(deploymentKey) { - return NativeCodePush.setDeploymentKey(deploymentKey) - .then(() => { - // Mark the local copy of the config data - // as invalid since we just modified it - // on the native end. - isConfigValid = false; - }); -} - var testConfig; var testSdk; diff --git a/package-mixins.js b/package-mixins.js index ff823f6..11c7940 100644 --- a/package-mixins.js +++ b/package-mixins.js @@ -1,4 +1,3 @@ -var extend = require("extend"); var { NativeAppEventEmitter } = require("react-native"); module.exports = (NativeCodePush) => { @@ -25,7 +24,7 @@ module.exports = (NativeCodePush) => { return NativeCodePush.downloadUpdate(this) .then((downloadedPackage) => { downloadProgressSubscription && downloadProgressSubscription.remove(); - return extend({}, downloadedPackage, local); + return Object.assign({}, downloadedPackage, local); }) .catch((error) => { downloadProgressSubscription && downloadProgressSubscription.remove(); From 24d3ef76dd0f17824c742129a845c6637e0ea4e1 Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Mon, 23 Nov 2015 19:16:15 -0800 Subject: [PATCH 04/10] Adding deploymentKey param --- CodePush.ios.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/CodePush.ios.js b/CodePush.ios.js index 9e4e700..4432b29 100644 --- a/CodePush.ios.js +++ b/CodePush.ios.js @@ -6,13 +6,21 @@ var packageMixins = require("./package-mixins")(NativeCodePush); var requestFetchAdapter = require("./request-fetch-adapter.js"); var Sdk = require("code-push/script/acquisition-sdk").AcquisitionManager; -function checkForUpdate() { +function checkForUpdate(deploymentKey) { var config; var sdk; return getConfiguration() .then((configResult) => { config = configResult; + + // If a deployment key was explicitly provided, + // then let's override the one we retrieved + // from the native-side of the app. + if (deploymentKey) { + config.deploymentKey = deploymentKey; + } + return getSdk(); }) .then((sdkResult) => { @@ -51,12 +59,10 @@ function checkForUpdate() { }); } -var isConfigValid = true; - var getConfiguration = (() => { var config; return function getConfiguration() { - if (config && isConfigValid) { + if (config) { return Promise.resolve(config); } else if (testConfig) { return Promise.resolve(testConfig); @@ -64,7 +70,6 @@ var getConfiguration = (() => { return NativeCodePush.getConfiguration() .then((configuration) => { if (!config) config = configuration; - isConfigValid = true; return config; }); } @@ -136,6 +141,7 @@ function setUpTestDependencies(providedTestSdk, providedTestConfig, testNativeBr function sync(options = {}, syncStatusChangeCallback, downloadProgressCallback) { var syncOptions = { + deploymentKey: null, ignoreFailedUpdates: true, installMode: CodePush.InstallMode.ON_NEXT_RESTART, rollbackTimeout: 0, @@ -191,7 +197,7 @@ function sync(options = {}, syncStatusChangeCallback, downloadProgressCallback) return new Promise((resolve, reject) => { syncStatusChangeCallback(CodePush.SyncStatus.CHECKING_FOR_UPDATE); - checkForUpdate() + checkForUpdate(syncOptions.deploymentKey) .then((remotePackage) => { var doDownloadAndInstall = () => { syncStatusChangeCallback(CodePush.SyncStatus.DOWNLOADING_PACKAGE); From 9ee4f0555f3efa84b92ceeade6acd4d57a789b5a Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Mon, 23 Nov 2015 19:22:54 -0800 Subject: [PATCH 05/10] Updating docs --- CodePush.ios.js | 2 +- README.md | 27 +++------------------------ 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/CodePush.ios.js b/CodePush.ios.js index 4432b29..8b474bc 100644 --- a/CodePush.ios.js +++ b/CodePush.ios.js @@ -123,7 +123,7 @@ var testConfig; var testSdk; // This function is only used for tests. Replaces the default SDK, configuration and native bridge -function setUpTestDependencies(providedTestSdk, providedTestConfig, testNativeBridge){ +function setUpTestDependencies(providedTestSdk, providedTestConfig, testNativeBridge) { if (providedTestSdk) testSdk = providedTestSdk; if (providedTestConfig) testConfig = providedTestConfig; if (testNativeBridge) NativeCodePush = testNativeBridge; diff --git a/README.md b/README.md index 0ec3dd9..5cb4ea5 100644 --- a/README.md +++ b/README.md @@ -126,16 +126,15 @@ When you require the `react-native-code-push` module, that object provides the f * [getCurrentPackage](#codepushgetcurrentpackage): Gets information about the currently installed package (e.g. description, installation time) * [notifyApplicationReady](#codepushnotifyapplicationready): Notifies the CodePush runtime that an installed update is considered successful. This is an optional API, but is useful when you want to expicitly enable "rollback protection" in the event that an exception occurs in any code that you've deployed to production * [restartApp](#codepushrestartapp): Immediately restarts the app if a previously installed update is pending. -* [setDeploymentKey](#codepushsetdeploymentkey): Dynamically updates the deployment key that the CodePush runtime will use to query for app updates. * [sync](#codepushsync): Allows checking for an update, downloading it and installing it, all with a single call. Unless you need custom UI and/or behavior, we recommend most developers to use this method when integrating CodePush into their apps #### codePush.checkForUpdate ```javascript -codePush.checkForUpdate(): Promise; +codePush.checkForUpdate(deploymentKey: String): Promise; ``` -Queries the CodePush service for an update against the configured deployment. This method returns a promise which resolves to a `RemotePackage` that can be subsequently downloaded. +Queries the CodePush service for an update from the deployment configured in your `Info.plist` file, or specified using the optional `deploymentKey` parameter. This method returns a promise which resolves to a `RemotePackage` that can be subsequently downloaded. `checkForUpdate` returns a Promise that resolves to one of two values: @@ -188,27 +187,6 @@ Installs a pending update (if applicable) by immediately restarting the app, and If your app doesn't have a pending update, then calling this method results in a no-op. Otherwise, calling it will restart the app and start the rollback timer based on the timeout value that was specified in the previous call to `sync` or `LocalPackage.install`. -#### codePush.setDeploymentKey - -```javascript -codePush.setDeploymentKey(deploymentKey: String): Promise; -``` - -Dynamically updates the deployment key that the CodePush runtime will use to query for app updates. This is beneficial if your app has a default deployment key which you added to your `Info.plist` file, but you want to dynamically change it at runtime based on some app-specific policy (e.g. you want to give early access to certain users, by pointing them at your staging deployment). - -The method simply takes a string representing the new deployment, and returns a `Promise` that will resolve once the specified deployment key has been applied, and calls to `sync` and/or `checkForUpdate` could be successfully called. - -Example Usage: - -```javascript -codePush.setDeploymentKey("SOME_VALID_KEY_VALUE").then(() => { - // The following call to sync with query the updated - // app deployment for an update - codePush.sync(); -}); - -``` - #### codePush.sync ```javascript @@ -226,6 +204,7 @@ If you want to pivot whether you check and/or download an available update based The method accepts an options object that allows you to customize numerous aspects of the default behavior, all of which provide sensible values by default: +* __deploymentKey__ (String) - Specifies the deployment key you want to query for an update against. By default, this value is derived from the `Info.plist` file, but this option allows you to override it from the script-side if you need to dynamically change your app's current deployment. * __ignoreFailedUpdates__ (Boolean) - Indicates whether you would like to automatically ignored updates which are available, but have been previously attemped to install, but failed. Defaults to `true`. * __installMode__ (CodePush.InstallMode) - Indicates whether you would like to restart the app immediately after the update has been installed, or wait until the next app resume or restart. Defaults to `CodePush.InstallMode.ON_NEXT_RESTART` * __rollbackTimeout__ (Number) - The number of seconds that you want the runtime to wait after an update has been installed before considering it failed and rolling it back. Defaults to `0`, which disables rollback protection. From 8495e7d0fd986d057a3fbf5ab5b63958ee8ccf8d Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Mon, 23 Nov 2015 20:24:02 -0800 Subject: [PATCH 06/10] Moving restartApp to LocalPackage --- CodePush.ios.js | 1 - CodePush.m | 12 ++++++------ README.md | 14 -------------- package-mixins.js | 6 +++++- 4 files changed, 11 insertions(+), 22 deletions(-) diff --git a/CodePush.ios.js b/CodePush.ios.js index 8b474bc..ffcce89 100644 --- a/CodePush.ios.js +++ b/CodePush.ios.js @@ -280,7 +280,6 @@ var CodePush = { getCurrentPackage: getCurrentPackage, log: log, notifyApplicationReady: NativeCodePush.notifyApplicationReady, - restartApp: NativeCodePush.restartApp, setUpTestDependencies: setUpTestDependencies, sync: sync, InstallMode: { diff --git a/CodePush.m b/CodePush.m index e0893a7..0be5328 100644 --- a/CodePush.m +++ b/CodePush.m @@ -346,18 +346,18 @@ RCT_EXPORT_METHOD(notifyApplicationReady:(RCTPromiseResolveBlock)resolve resolve([NSNull null]); } -RCT_EXPORT_METHOD(restartApp) -{ - [self checkForPendingUpdate:YES]; -} - // This version of restart app is exposed solely for immediately installed // update support, and shouldn't be consumed directly by user code. -RCT_EXPORT_METHOD(restartAppInternal:(int)rollbackTimeout) +RCT_EXPORT_METHOD(restartForImmedidateUpdate:(int)rollbackTimeout) { [self initializeUpdateWithRollbackTimeout:rollbackTimeout needsRestart:YES]; } +RCT_EXPORT_METHOD(restartForPendingUpdate) +{ + [self checkForPendingUpdate:YES]; +} + RCT_EXPORT_METHOD(setUsingTestFolder:(BOOL)shouldUseTestFolder) { usingTestFolder = shouldUseTestFolder; diff --git a/README.md b/README.md index 5cb4ea5..b357a8a 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,6 @@ When you require the `react-native-code-push` module, that object provides the f * [checkForUpdate](#codepushcheckforupdate): Queries the CodePush service for an update against the configured deployment. This method returns a promise which resolves to a `RemotePackage` that can be subsequently downloaded. * [getCurrentPackage](#codepushgetcurrentpackage): Gets information about the currently installed package (e.g. description, installation time) * [notifyApplicationReady](#codepushnotifyapplicationready): Notifies the CodePush runtime that an installed update is considered successful. This is an optional API, but is useful when you want to expicitly enable "rollback protection" in the event that an exception occurs in any code that you've deployed to production -* [restartApp](#codepushrestartapp): Immediately restarts the app if a previously installed update is pending. * [sync](#codepushsync): Allows checking for an update, downloading it and installing it, all with a single call. Unless you need custom UI and/or behavior, we recommend most developers to use this method when integrating CodePush into their apps #### codePush.checkForUpdate @@ -174,19 +173,6 @@ Notifies the CodePush runtime that an update is considered successful, and there If the `rollbackTimeout` parameter was not specified, the CodePush runtime will not enforce any automatic rollback behavior, and therefore, calling this function is not required and will result in a no-op. -#### codePush.restartApp - -```javascript -codePush.restartApp(): void; -``` - -Installs a pending update (if applicable) by immediately restarting the app, and optionally starting the rollback timer. This method is for advanced scenarios, and is useful when the following conditions are true: - -1. Your app is specifying an install mode value of `ON_NEXT_RESTART` or `ON_NEXT_RESUME` when calling `sync` or `LocalPackage.install`, which has the effect of not applying your update until the app has been restarted (by either the end-user or OS) -2. You have an app-specific user event (e.g. the end-user navigated back to the app's home page) that allows you to apply the update in an unobtrusive way, and potentially gets the update in front of the end-user sooner then waiting until the next restart. - -If your app doesn't have a pending update, then calling this method results in a no-op. Otherwise, calling it will restart the app and start the rollback timer based on the timeout value that was specified in the previous call to `sync` or `LocalPackage.install`. - #### codePush.sync ```javascript diff --git a/package-mixins.js b/package-mixins.js index 11c7940..ddd51cb 100644 --- a/package-mixins.js +++ b/package-mixins.js @@ -40,7 +40,11 @@ module.exports = (NativeCodePush) => { .then(function() { updateInstalledCallback && updateInstalledCallback(); if (installMode == NativeCodePush.codePushInstallModeImmediate) { - NativeCodePush.restartAppInternal(rollbackTimeout); + NativeCodePush.restartImmedidateUpdate(rollbackTimeout); + } else { + this.restart = function () { + NaviteCodePush.restartForPendingUpdate(); + } } }); } From 7f21bae33a31d6db6ffd46047552de5d893fe6f2 Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Mon, 23 Nov 2015 20:30:48 -0800 Subject: [PATCH 07/10] Fixing function name --- package-mixins.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-mixins.js b/package-mixins.js index ddd51cb..2d34046 100644 --- a/package-mixins.js +++ b/package-mixins.js @@ -40,7 +40,7 @@ module.exports = (NativeCodePush) => { .then(function() { updateInstalledCallback && updateInstalledCallback(); if (installMode == NativeCodePush.codePushInstallModeImmediate) { - NativeCodePush.restartImmedidateUpdate(rollbackTimeout); + NativeCodePush.restartForImmedidateUpdate(rollbackTimeout); } else { this.restart = function () { NaviteCodePush.restartForPendingUpdate(); From 292359a20161c2fe629542ebff02ca5e146b171e Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Mon, 23 Nov 2015 21:32:36 -0800 Subject: [PATCH 08/10] Renaming restartPendingUpdate --- CodePush.ios.js | 5 ++++- CodePush.m | 6 +++--- README.md | 6 +++--- package-mixins.js | 8 ++------ 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/CodePush.ios.js b/CodePush.ios.js index ffcce89..6599bf6 100644 --- a/CodePush.ios.js +++ b/CodePush.ios.js @@ -6,7 +6,7 @@ var packageMixins = require("./package-mixins")(NativeCodePush); var requestFetchAdapter = require("./request-fetch-adapter.js"); var Sdk = require("code-push/script/acquisition-sdk").AcquisitionManager; -function checkForUpdate(deploymentKey) { +function checkForUpdate(deploymentKey = null) { var config; var sdk; @@ -274,12 +274,15 @@ function sync(options = {}, syncStatusChangeCallback, downloadProgressCallback) }); }; +codePush.installPendingUpdate(); + var CodePush = { checkForUpdate: checkForUpdate, getConfiguration: getConfiguration, getCurrentPackage: getCurrentPackage, log: log, notifyApplicationReady: NativeCodePush.notifyApplicationReady, + restartPendingUpdate: NativeCodePush.restartPendingUpdate, setUpTestDependencies: setUpTestDependencies, sync: sync, InstallMode: { diff --git a/CodePush.m b/CodePush.m index 0be5328..d0eaa5f 100644 --- a/CodePush.m +++ b/CodePush.m @@ -346,14 +346,14 @@ RCT_EXPORT_METHOD(notifyApplicationReady:(RCTPromiseResolveBlock)resolve resolve([NSNull null]); } -// This version of restart app is exposed solely for immediately installed +// This function is exposed solely for immediately installed // update support, and shouldn't be consumed directly by user code. -RCT_EXPORT_METHOD(restartForImmedidateUpdate:(int)rollbackTimeout) +RCT_EXPORT_METHOD(restartImmedidateUpdate:(int)rollbackTimeout) { [self initializeUpdateWithRollbackTimeout:rollbackTimeout needsRestart:YES]; } -RCT_EXPORT_METHOD(restartForPendingUpdate) +RCT_EXPORT_METHOD(restartPendingUpdate) { [self checkForPendingUpdate:YES]; } diff --git a/README.md b/README.md index b357a8a..50bd138 100644 --- a/README.md +++ b/README.md @@ -124,16 +124,16 @@ When you require the `react-native-code-push` module, that object provides the f * [checkForUpdate](#codepushcheckforupdate): Queries the CodePush service for an update against the configured deployment. This method returns a promise which resolves to a `RemotePackage` that can be subsequently downloaded. * [getCurrentPackage](#codepushgetcurrentpackage): Gets information about the currently installed package (e.g. description, installation time) -* [notifyApplicationReady](#codepushnotifyapplicationready): Notifies the CodePush runtime that an installed update is considered successful. This is an optional API, but is useful when you want to expicitly enable "rollback protection" in the event that an exception occurs in any code that you've deployed to production +* [notifyApplicationReady](#codepushnotifyapplicationready): Notifies the CodePush runtime that an installed update is considered successful. This is an optional API, but is useful when you want to expicitly enable "rollback protection" in the event that an exception occurs in any code that you've deployed to production. * [sync](#codepushsync): Allows checking for an update, downloading it and installing it, all with a single call. Unless you need custom UI and/or behavior, we recommend most developers to use this method when integrating CodePush into their apps #### codePush.checkForUpdate ```javascript -codePush.checkForUpdate(deploymentKey: String): Promise; +codePush.checkForUpdate(deploymentKey: String = null): Promise; ``` -Queries the CodePush service for an update from the deployment configured in your `Info.plist` file, or specified using the optional `deploymentKey` parameter. This method returns a promise which resolves to a `RemotePackage` that can be subsequently downloaded. +Queries the CodePush service for an update using the deployment configured either in your `Info.plist` file or specified using the optional `deploymentKey` parameter. This method returns a promise which resolves to a `RemotePackage` that can be subsequently downloaded. `checkForUpdate` returns a Promise that resolves to one of two values: diff --git a/package-mixins.js b/package-mixins.js index 2d34046..6416bae 100644 --- a/package-mixins.js +++ b/package-mixins.js @@ -40,12 +40,8 @@ module.exports = (NativeCodePush) => { .then(function() { updateInstalledCallback && updateInstalledCallback(); if (installMode == NativeCodePush.codePushInstallModeImmediate) { - NativeCodePush.restartForImmedidateUpdate(rollbackTimeout); - } else { - this.restart = function () { - NaviteCodePush.restartForPendingUpdate(); - } - } + NativeCodePush.restartImmedidateUpdate(rollbackTimeout); + }; }); } }; From 219c6795c1456cccb9eb8f66e44f9fb6e21b5cf5 Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Mon, 23 Nov 2015 21:37:05 -0800 Subject: [PATCH 09/10] Fixing typo --- CodePush.ios.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/CodePush.ios.js b/CodePush.ios.js index 6599bf6..cf58aa5 100644 --- a/CodePush.ios.js +++ b/CodePush.ios.js @@ -274,8 +274,6 @@ function sync(options = {}, syncStatusChangeCallback, downloadProgressCallback) }); }; -codePush.installPendingUpdate(); - var CodePush = { checkForUpdate: checkForUpdate, getConfiguration: getConfiguration, From b668f742396807fad9b3966216052a5969b629c5 Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Tue, 24 Nov 2015 08:50:14 -0800 Subject: [PATCH 10/10] Adding in docs --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 50bd138..332a413 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,7 @@ When you require the `react-native-code-push` module, that object provides the f * [checkForUpdate](#codepushcheckforupdate): Queries the CodePush service for an update against the configured deployment. This method returns a promise which resolves to a `RemotePackage` that can be subsequently downloaded. * [getCurrentPackage](#codepushgetcurrentpackage): Gets information about the currently installed package (e.g. description, installation time) * [notifyApplicationReady](#codepushnotifyapplicationready): Notifies the CodePush runtime that an installed update is considered successful. This is an optional API, but is useful when you want to expicitly enable "rollback protection" in the event that an exception occurs in any code that you've deployed to production. +* [restartPendingUpdate](#codepushrestartPendingUpdate): Conditionally restarts the app if a previously installed update is currently pending (e.g. it was installed using the `ON_NEXT_RESTART` or `ON_NEXT_RESUME` modes, and the user hasn't restarted or resumed the app yet). * [sync](#codepushsync): Allows checking for an update, downloading it and installing it, all with a single call. Unless you need custom UI and/or behavior, we recommend most developers to use this method when integrating CodePush into their apps #### codePush.checkForUpdate @@ -173,6 +174,19 @@ Notifies the CodePush runtime that an update is considered successful, and there If the `rollbackTimeout` parameter was not specified, the CodePush runtime will not enforce any automatic rollback behavior, and therefore, calling this function is not required and will result in a no-op. +#### codePush.restartPendingUpdate + +```javascript +codePush.restartPendingUpdate(): void; +``` + +Installs the pending update (if applicable) by immediately restarting the app, and optionally starting the rollback timer. This method is for advanced scenarios, and is only useful when the following conditions are true: + +1. Your app is specifying an install mode value of `ON_NEXT_RESTART` or `ON_NEXT_RESUME` when calling the `sync` or `LocalPackage.install` methods. This has the effect of not applying your update until the app has been restarted (by either the end-user or OS) or resumed, and therefore, the update won't be immediately displayed to the end-user . +2. You have an app-specific user event (e.g. the end-user navigated back to the app's home route) that allows you to apply the update in an unobtrusive way, and potentially gets the update in front of the end-user sooner then waiting until the next restart or resume. + +If you call this method, and there isn't a pending update, it will result in a no-op. Otherwise, the app will be restarted in order to display the update to the end-user. + #### codePush.sync ```javascript