Skip to content

Commit

Permalink
Added sync sample and updated the documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
unknown authored and unknown committed Oct 30, 2015
1 parent ae48c39 commit ad20e57
Show file tree
Hide file tree
Showing 22 changed files with 423 additions and 65 deletions.
57 changes: 55 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ A Cordova application's assets (HTML, JavaScript, CSS files and other resources)

CodePush is here to simplify this process by allowing you to instantly update your application's assets without having to submit a new update to the store. We do this by packaging the application assets in a zip archive and sending it to the CodePush server. In the application, we install and persist the update. Then, since these are all web assets, the application will just reload from the updated package location. We store the update packages in the internal storage of the device.

For an easy way to get started, please see our [sample application](/sample) and our [getting started guide](#getting-started).
For an easy way to get started, please see our [sample applications](/samples) and our [getting started guide](#getting-started).

## Compiling sources & contributing

Expand All @@ -31,10 +31,12 @@ The JavaScript code in this plugin is compiled from TypeScript. Please see [this
- __[checkForUpdate](#codepushcheckforupdate)__: Checks the server for update packages.
- __[notifyApplicationReady](#codepushnotifyapplicationready)__: Notifies the plugin that the update operation succeeded.
- __[getCurrentPackage](#codepushgetcurrentpackage)__: Gets information about the currently applied package.
- __[sync](#codepushsync)__: Convenience function for installing updates in one call.

## Objects
- __[LocalPackage](#localpackage)__: Contains information about a locally installed package.
- __[RemotePackage](#remotepackage)__: Contains information about an update package available for download.
- __[SyncStatus](#syncStatus)__: Defines the possible result statuses of the [sync](#codepushsync) operation.

## Getting started
- Add the plugin to your application.
Expand All @@ -57,7 +59,7 @@ The JavaScript code in this plugin is compiled from TypeScript. Please see [this
```xml
<meta http-equiv="Content-Security-Policy" content="default-src https://codepush.azurewebsites.net/ 'self' ... ">
```
- You are now ready to use the plugin in the application code. See the sample app for an example and the methods description for more details.
- You are now ready to use the plugin in the application code. See the [sample applications](/samples) for a examples and the methods description for more details.

## Create an application update package
You can create an update by simply zipping and deploying your platform's www folder. The [CodePush CLI](https://github.com/Microsoft/code-push/tree/master/cli) has a ```deploy``` command for this.
Expand Down Expand Up @@ -167,6 +169,14 @@ Contains details about an update package that is available for download.
```
- __abortDownload(abortSuccess, abortError)__: Aborts the current download session, if any.

## SyncStatus
Defines the possible result statuses of the [sync](#codepushsync) operation.
### Properties
- __UP_TO_DATE__: The application is up to date. (number)
- __APPLY_SUCCESS__: An update is available, it has been downloaded, unzipped and copied to the deployment folder. After the completion of the callback invoked with SyncStatus.APPLY_SUCCESS, the application will be reloaded with the updated code and resources.
- __UPDATE_IGNORED__: An optional update is available, but the user declined to install it. The update was not downloaded.
- __ERROR__: An error happened during the sync operation. This might be an error while communicating with the server, downloading or unziping the update. The console logs should contain more information about what happened. No update has been applied in this case.

## codePush.checkForUpdate
Queries the CodePush server for updates.
```javascript
Expand Down Expand Up @@ -276,3 +286,46 @@ var app = {
}
}
```

## codePush.sync
```javascript
codePush.sync(syncCallback, syncOptions);
```
Convenience method for installing updates in one method call.
This method is provided for simplicity, and its behavior can be replicated by using window.codePush.checkForUpdate(), RemotePackage's download() and LocalPackage's apply() methods.
The algorithm of this method is the following:
- Checks for an update on the CodePush server.
- If an update is available
- If the update is mandatory and the alertMessage is set in options, the user will be informed that the application will be updated to the latest version.
The update package will then be downloaded and applied.
- If the update is not mandatory and the confirmMessage is set in options, the user will be asked if they want to update to the latest version.
If they decline, the syncCallback will be invoked with SyncStatus.UPDATE_IGNORED.
- Otherwise, the update package will be downloaded and applied with no user interaction.
- If no update is available on the server, the syncCallback will be invoked with the SyncStatus.UP_TO_DATE.
- If an error ocurrs during checking for update, downloading or applying it, the syncCallback will be invoked with the SyncStatus.ERROR.

- __syncCallback__: Optional callback to be called with the status of the sync operation. The callback will be called only once, and the possible statuses are defined by the SyncStatus enum.
- __syncOptions__: Optional SyncOptions parameter configuring the behavior of the sync operation.

### Example
```javascript
window.codePush.sync(function (syncStatus) {
switch (syncStatus) {
case SyncStatus.APPLY_SUCCESS:
console.log("The update was applied successfully. This is the last callback before the application is reloaded with the updated content.");
/* Don't continue app initialization, the application will refresh after this return. */
return;
case SyncStatus.UP_TO_DATE:
app.displayMessage("The application is up to date.");
break;
case SyncStatus.UPDATE_IGNORED:
app.displayMessage("The user decided not to install the optional update.");
break;
case SyncStatus.ERROR:
app.displayMessage("An error ocurred while checking for updates");
break;
}

// continue application initialization
}
```
38 changes: 24 additions & 14 deletions bin/www/codePush.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,19 @@ var CodePush = (function () {
syncOptions = this.getDefaultSyncOptions();
}
if (syncOptions.mandatoryUpdateMessage) {
syncOptions.mandatoryUpdateContinueButtonLabel = syncOptions.mandatoryUpdateContinueButtonLabel || this.getDefaultSyncOptions().mandatoryUpdateContinueButtonLabel;
syncOptions.dialogTitle = syncOptions.dialogTitle || this.getDefaultSyncOptions().dialogTitle;
syncOptions.mandatoryContinueButtonLabel = syncOptions.mandatoryContinueButtonLabel || this.getDefaultSyncOptions().mandatoryContinueButtonLabel;
syncOptions.updateTitle = syncOptions.updateTitle || this.getDefaultSyncOptions().updateTitle;
}
if (syncOptions.optionalUpdateMessage) {
syncOptions.optionalUpdateConfirmButtonLabel = syncOptions.optionalUpdateConfirmButtonLabel || this.getDefaultSyncOptions().optionalUpdateConfirmButtonLabel;
syncOptions.optionalUpdateCancelButtonLabel = syncOptions.optionalUpdateCancelButtonLabel || this.getDefaultSyncOptions().optionalUpdateCancelButtonLabel;
syncOptions.dialogTitle = syncOptions.dialogTitle || this.getDefaultSyncOptions().dialogTitle;
syncOptions.optionalInstallButtonLabel = syncOptions.optionalInstallButtonLabel || this.getDefaultSyncOptions().optionalInstallButtonLabel;
syncOptions.optionalIgnoreButtonLabel = syncOptions.optionalIgnoreButtonLabel || this.getDefaultSyncOptions().optionalIgnoreButtonLabel;
syncOptions.updateTitle = syncOptions.updateTitle || this.getDefaultSyncOptions().updateTitle;
}
if (typeof syncOptions.ignoreFailedUpdates !== typeof true) {
syncOptions.ignoreFailedUpdates = true;
}
if (syncOptions.appendReleaseDescription && !syncOptions.descriptionPrefix) {
syncOptions.descriptionPrefix = this.getDefaultSyncOptions().descriptionPrefix;
}
window.codePush.notifyApplicationReady();
var onError = function (error) {
Expand All @@ -117,21 +123,23 @@ var CodePush = (function () {
}
else {
if (remotePackage.isMandatory && syncOptions.mandatoryUpdateMessage) {
navigator.notification.alert(syncOptions.mandatoryUpdateMessage, function () { downloadAndInstallUpdate(remotePackage); }, syncOptions.dialogTitle, syncOptions.mandatoryUpdateContinueButtonLabel);
var message = syncOptions.appendReleaseDescription ? syncOptions.mandatoryUpdateMessage + syncOptions.descriptionPrefix + remotePackage.description : syncOptions.mandatoryUpdateMessage;
navigator.notification.alert(message, function () { downloadAndInstallUpdate(remotePackage); }, syncOptions.updateTitle, syncOptions.mandatoryContinueButtonLabel);
}
else if (!remotePackage.isMandatory && syncOptions && syncOptions.optionalUpdateMessage) {
else if (!remotePackage.isMandatory && syncOptions.optionalUpdateMessage) {
var optionalUpdateCallback = function (buttonIndex) {
switch (buttonIndex) {
case 1:
downloadAndInstallUpdate(remotePackage);
break;
case 2:
default:
syncCallback && syncCallback(SyncStatus.USER_DECLINED);
syncCallback && syncCallback(SyncStatus.UPDATE_IGNORED);
break;
}
};
navigator.notification.confirm(syncOptions.optionalUpdateMessage, optionalUpdateCallback, syncOptions.dialogTitle, [syncOptions.optionalUpdateConfirmButtonLabel, syncOptions.optionalUpdateCancelButtonLabel]);
var message = syncOptions.appendReleaseDescription ? syncOptions.optionalUpdateMessage + syncOptions.descriptionPrefix + remotePackage.description : syncOptions.optionalUpdateMessage;
navigator.notification.confirm(message, optionalUpdateCallback, syncOptions.updateTitle, [syncOptions.optionalInstallButtonLabel, syncOptions.optionalIgnoreButtonLabel]);
}
else {
downloadAndInstallUpdate(remotePackage);
Expand All @@ -143,14 +151,16 @@ var CodePush = (function () {
CodePush.prototype.getDefaultSyncOptions = function () {
if (!CodePush.DefaultSyncOptions) {
CodePush.DefaultSyncOptions = {
dialogTitle: "Update",
updateTitle: "Update",
mandatoryUpdateMessage: "You will be updated to the latest version.",
mandatoryUpdateContinueButtonLabel: "Continue",
mandatoryContinueButtonLabel: "Continue",
optionalUpdateMessage: "An update is available. Would you like to install it?",
optionalUpdateConfirmButtonLabel: "Install",
optionalUpdateCancelButtonLabel: "Cancel",
optionalInstallButtonLabel: "Install",
optionalIgnoreButtonLabel: "Ignore",
rollbackTimeout: 0,
ignoreFailedUpdates: true
ignoreFailedUpdates: true,
appendReleaseDescription: false,
descriptionPrefix: " Description: "
};
}
return CodePush.DefaultSyncOptions;
Expand Down
2 changes: 1 addition & 1 deletion bin/www/syncStatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var SyncStatus;
(function (SyncStatus) {
SyncStatus[SyncStatus["UP_TO_DATE"] = 0] = "UP_TO_DATE";
SyncStatus[SyncStatus["APPLY_SUCCESS"] = 1] = "APPLY_SUCCESS";
SyncStatus[SyncStatus["USER_DECLINED"] = 2] = "USER_DECLINED";
SyncStatus[SyncStatus["UPDATE_IGNORED"] = 2] = "UPDATE_IGNORED";
SyncStatus[SyncStatus["ERROR"] = 3] = "ERROR";
})(SyncStatus || (SyncStatus = {}));
module.exports = SyncStatus;
4 changes: 2 additions & 2 deletions sample/README.md → samples/advanced/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Cordova CodePush Sample App
# Cordova CodePush Sample App - Advanced

This is a sample application demonstrating one way you could integrate CodePush in your Cordova application. All the CodePush specific code is found in [index.js](/sample/www/js/index.js). The CodePush configuration is found in [config.xml](/sample/config.xml).
This is a sample application demonstrating a more advanced way you could integrate CodePush in your Cordova application. All the CodePush specific code is found in [index.js](/sample/www/js/index.js). The CodePush configuration is found in [config.xml](/sample/config.xml).

When the application loads, on the `deviceready` event, we poll the CodePush server for an update. If an update is available, we prompt the user to install it. If the user approves it, the update is installed and the application is reloaded.

Expand Down
38 changes: 38 additions & 0 deletions samples/advanced/config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version='1.0' encoding='utf-8'?>
<widget id="io.cordova.hellocodepush.advanced" version="1.0.1-beta" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>CodePushAdvanced</name>
<description>
A sample Apache Cordova application that uses the CodePush service.
</description>

<!-- The contents of the main page can change between Code-Push updates, but not the name. -->
<content src="index.html" />

<plugin name="cordova-plugin-whitelist" version="1" />
<plugin name="cordova-plugin-code-push" version="1.0.1-beta" />
<plugin name="cordova-plugin-dialogs" version="1.1.1" />

<!-- This sample application can communicate with any external domain.
If you want to restrict this, don't forget to enable communication with the Code-Push server URL as well. -->
<access origin="*" />

<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />

<platform name="android">
<allow-intent href="market:*" />
<!-- CodePush deployment key for the Android platform. -->
<preference name="CodePushDeploymentKey" value="TODO_ADD_ANDROID_DEPLOYMENT_KEY" />
</platform>

<platform name="ios">
<allow-intent href="itms:*" />
<allow-intent href="itms-apps:*" />
<!-- CodePush deployment key for the iOS platform. -->
<preference name="CodePushDeploymentKey" value="TODO_ADD_IOS_DEPLOYMENT_KEY" />
</platform>
</widget>
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
7 changes: 7 additions & 0 deletions samples/basic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Cordova CodePush Sample App - Basic

This is a sample application demonstrating the CodePush sync operation. All the CodePush specific code is found in [index.js](/sample/www/js/index.js). The CodePush configuration is found in [config.xml](/sample/config.xml).

When the application loads, on the `deviceready` event, we invoke sync. This checks for an update, and if one is available, the user will be prompted to install it. Once the user accepts it, the update is installed and the application reloaded. See SyncOptions in our documentation for customizing the sync behavior.

For more information on how to get started see our [Getting Started](https://github.com/Microsoft/cordova-plugin-code-push#getting-started) section.
4 changes: 2 additions & 2 deletions sample/config.xml → samples/basic/config.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='utf-8'?>
<widget id="io.cordova.hellocodepush" version="1.0.1-beta" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>HelloCodePush</name>
<widget id="io.cordova.hellocodepush.basic" version="1.0.1-beta" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>CodePushBasic</name>
<description>
A sample Apache Cordova application that uses the CodePush service.
</description>
Expand Down
115 changes: 115 additions & 0 deletions samples/basic/www/css/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
* {
-webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */
}

body {
-webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */
-webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */
-webkit-user-select: none; /* prevent copy paste, to allow, change 'none' to 'text' */
background-color:#E4E4E4;
background-image:linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
background-image:-webkit-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
background-image:-ms-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
background-image:-webkit-gradient(
linear,
left top,
left bottom,
color-stop(0, #A7A7A7),
color-stop(0.51, #E4E4E4)
);
background-attachment:fixed;
font-family:'HelveticaNeue-Light', 'HelveticaNeue', Helvetica, Arial, sans-serif;
font-size:12px;
height:100%;
margin:0px;
padding:0px;
text-transform:uppercase;
width:100%;
}

/* Portrait layout (default) */
.app {
background:url(../img/logo.png) no-repeat center top; /* 170px x 200px */
position:absolute; /* position in the center of the screen */
left:50%;
top:50%;
height:50px; /* text area height */
width:225px; /* text area width */
text-align:center;
padding:180px 0px 0px 0px; /* image height is 200px (bottom 20px are overlapped with text) */
margin:-115px 0px 0px -112px; /* offset vertical: half of image height and text area height */
/* offset horizontal: half of text area width */
}

/* Landscape layout (with min-width) */
@media screen and (min-aspect-ratio: 1/1) and (min-width:400px) {
.app {
background-position:left center;
padding:75px 0px 75px 170px; /* padding-top + padding-bottom + text area = image height */
margin:-90px 0px 0px -198px; /* offset vertical: half of image height */
/* offset horizontal: half of image width and text area width */
}
}

h1 {
font-size:24px;
font-weight:normal;
margin:0px;
overflow:visible;
padding:0px;
text-align:center;
}

.event {
border-radius:4px;
-webkit-border-radius:4px;
color:#FFFFFF;
font-size:12px;
margin:0px 30px;
padding:2px 0px;
}

.event.listening {
background-color:#333333;
display:block;
}

.event.received {
background-color:#4B946A;
display:none;
}

@keyframes fade {
from { opacity: 1.0; }
50% { opacity: 0.4; }
to { opacity: 1.0; }
}

@-webkit-keyframes fade {
from { opacity: 1.0; }
50% { opacity: 0.4; }
to { opacity: 1.0; }
}

.blink {
animation:fade 3000ms infinite;
-webkit-animation:fade 3000ms infinite;
}
Binary file added samples/basic/www/img/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit ad20e57

Please sign in to comment.