@capawesome/capacitor-live-update 6.1.0 → 6.2.0-dev.0a2a6a5.1722676620
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.
- package/README.md +24 -10
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdate.java +39 -17
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdateConfig.java +12 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePlugin.java +17 -3
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePreferences.java +17 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/GetBundleResult.java +2 -1
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/ReadyResult.java +32 -0
- package/dist/docs.json +79 -3
- package/dist/esm/definitions.d.ts +37 -1
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +2 -2
- package/dist/esm/web.js.map +1 -1
- package/ios/Plugin/Classes/Results/GetBundleResult.swift +1 -1
- package/ios/Plugin/Classes/Results/ReadyResult.swift +22 -0
- package/ios/Plugin/LiveUpdate.swift +33 -11
- package/ios/Plugin/LiveUpdateConfig.swift +1 -0
- package/ios/Plugin/LiveUpdatePlugin.swift +12 -3
- package/ios/Plugin/LiveUpdatePreferences.swift +14 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Capacitor plugin to update your app remotely in real-time.
|
|
|
7
7
|
- 🔋 Supports **Android and iOS**
|
|
8
8
|
- ⚡️ **Capacitor 6** support
|
|
9
9
|
- 📦 **Bundle Management**: Download, set, and delete bundles.
|
|
10
|
-
- ☁️ **Cloud Support**: Use the [Capawesome Cloud](https://capawesome.io/cloud) to manage your app updates.
|
|
10
|
+
- ☁️ **Cloud Support**: Use the [Capawesome Cloud](https://capawesome.io/cloud/live-updates/) to manage your app updates.
|
|
11
11
|
- 📺 **Channel Support**: Set a channel for the app to manage different versions.
|
|
12
12
|
- 🔄 **Auto Update**: Automatically download and set the latest bundle for the app.
|
|
13
13
|
- 🛟 **Rollback**: Reset the app to the default bundle if an incompatible bundle has been set.
|
|
@@ -65,14 +65,15 @@ We recommend to declare [`CA92.1`](https://developer.apple.com/documentation/bun
|
|
|
65
65
|
<docgen-config>
|
|
66
66
|
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
67
67
|
|
|
68
|
-
| Prop | Type
|
|
69
|
-
| ----------------------- |
|
|
70
|
-
| **`appId`** | <code>string</code>
|
|
71
|
-
| **`autoDeleteBundles`** | <code>boolean</code>
|
|
72
|
-
| **`enabled`** | <code>boolean</code>
|
|
73
|
-
| **`
|
|
74
|
-
| **`
|
|
75
|
-
| **`
|
|
68
|
+
| Prop | Type | Description | Default | Since |
|
|
69
|
+
| ----------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- |
|
|
70
|
+
| **`appId`** | <code>string</code> | The app ID is used to identify the app when using [Capawesome Cloud](https://capawesome.io/cloud). | | 5.0.0 |
|
|
71
|
+
| **`autoDeleteBundles`** | <code>boolean</code> | Whether or not to automatically delete unused bundles. When enabled, the plugin will automatically delete unused bundles after calling `ready()`. | <code>false</code> | 5.0.0 |
|
|
72
|
+
| **`enabled`** | <code>boolean</code> | Whether or not the plugin is enabled. | <code>true</code> | 5.0.0 |
|
|
73
|
+
| **`location`** | <code>'us' \| 'eu'</code> | The location of the server to use when using [Capawesome Cloud](https://capawesome.io/cloud). | <code>'us'</code> | 6.2.0 |
|
|
74
|
+
| **`publicKey`** | <code>string</code> | The public key to verify the integrity of the bundle. The public key must be a PEM-encoded RSA public key. | | 6.1.0 |
|
|
75
|
+
| **`readyTimeout`** | <code>number</code> | The timeout in milliseconds to wait for the app to be ready before resetting to the default bundle. | <code>10000</code> | 5.0.0 |
|
|
76
|
+
| **`resetOnUpdate`** | <code>boolean</code> | Whether or not the app should be reset to the default bundle during an update. | <code>true</code> | 5.0.0 |
|
|
76
77
|
|
|
77
78
|
### Examples
|
|
78
79
|
|
|
@@ -85,6 +86,7 @@ In `capacitor.config.json`:
|
|
|
85
86
|
"appId": '4100e356-e851-47fe-9d3c-b411eb325a99',
|
|
86
87
|
"autoDeleteBundles": undefined,
|
|
87
88
|
"enabled": undefined,
|
|
89
|
+
"location": 'eu',
|
|
88
90
|
"publicKey": '-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDodf1SD0OOn6hIlDuKBza0Ed0OqtwyVJwiyjmE9BJaZ7y8ZUfcF+SKmd0l2cDPM45XIg2tAFux5n29uoKyHwSt+6tCi5CJA5Z1/1eZruRRqABLonV77KS3HUtvOgqRLDnKSV89dYZkM++NwmzOPgIF422mvc+VukcVOBfc8/AHQIDAQAB-----END PUBLIC KEY-----',
|
|
89
91
|
"readyTimeout": undefined,
|
|
90
92
|
"resetOnUpdate": undefined
|
|
@@ -106,6 +108,7 @@ const config: CapacitorConfig = {
|
|
|
106
108
|
appId: '4100e356-e851-47fe-9d3c-b411eb325a99',
|
|
107
109
|
autoDeleteBundles: undefined,
|
|
108
110
|
enabled: undefined,
|
|
111
|
+
location: 'eu',
|
|
109
112
|
publicKey: '-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDodf1SD0OOn6hIlDuKBza0Ed0OqtwyVJwiyjmE9BJaZ7y8ZUfcF+SKmd0l2cDPM45XIg2tAFux5n29uoKyHwSt+6tCi5CJA5Z1/1eZruRRqABLonV77KS3HUtvOgqRLDnKSV89dYZkM++NwmzOPgIF422mvc+VukcVOBfc8/AHQIDAQAB-----END PUBLIC KEY-----',
|
|
110
113
|
readyTimeout: undefined,
|
|
111
114
|
resetOnUpdate: undefined,
|
|
@@ -398,7 +401,7 @@ Only available on Android and iOS.
|
|
|
398
401
|
### ready()
|
|
399
402
|
|
|
400
403
|
```typescript
|
|
401
|
-
ready() => Promise<
|
|
404
|
+
ready() => Promise<ReadyResult>
|
|
402
405
|
```
|
|
403
406
|
|
|
404
407
|
Notify the plugin that the app is ready to use and no rollback is needed.
|
|
@@ -408,6 +411,8 @@ to prevent the app from being reset to the default bundle.
|
|
|
408
411
|
|
|
409
412
|
Only available on Android and iOS.
|
|
410
413
|
|
|
414
|
+
**Returns:** <code>Promise<<a href="#readyresult">ReadyResult</a>></code>
|
|
415
|
+
|
|
411
416
|
**Since:** 5.0.0
|
|
412
417
|
|
|
413
418
|
--------------------
|
|
@@ -591,6 +596,15 @@ Only available on Android and iOS.
|
|
|
591
596
|
| **`versionName`** | <code>string</code> | The version name of the app. On **Android**, this is the `versionName` from the `android/app/build.gradle` file. On **iOS**, this is the `CFBundleShortVersionString` from the `Info.plist` file. | 5.0.0 |
|
|
592
597
|
|
|
593
598
|
|
|
599
|
+
#### ReadyResult
|
|
600
|
+
|
|
601
|
+
| Prop | Type | Description | Since |
|
|
602
|
+
| ---------------------- | --------------------------- | --------------------------------------------------------------------------------------- | ----- |
|
|
603
|
+
| **`previousBundleId`** | <code>string \| null</code> | The identifier of the previous bundle used. If `null`, the default bundle was used. | 7.0.0 |
|
|
604
|
+
| **`currentBundleId`** | <code>string \| null</code> | The identifier of the current bundle used. If `null`, the default bundle is being used. | 7.0.0 |
|
|
605
|
+
| **`rollback`** | <code>boolean</code> | Whether or not the app was reset to the default bundle. | 7.0.0 |
|
|
606
|
+
|
|
607
|
+
|
|
594
608
|
#### SetBundleOptions
|
|
595
609
|
|
|
596
610
|
| Prop | Type | Description | Since |
|
|
@@ -9,6 +9,7 @@ import android.os.Handler;
|
|
|
9
9
|
import android.util.Base64;
|
|
10
10
|
import androidx.annotation.NonNull;
|
|
11
11
|
import androidx.annotation.Nullable;
|
|
12
|
+
import com.getcapacitor.Bridge;
|
|
12
13
|
import com.getcapacitor.Logger;
|
|
13
14
|
import com.getcapacitor.plugin.WebView;
|
|
14
15
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.api.GetLatestBundleResponse;
|
|
@@ -24,6 +25,7 @@ import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetCustomIdR
|
|
|
24
25
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetDeviceIdResult;
|
|
25
26
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetVersionCodeResult;
|
|
26
27
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetVersionNameResult;
|
|
28
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.ReadyResult;
|
|
27
29
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.SyncResult;
|
|
28
30
|
import io.capawesome.capacitorjs.plugins.liveupdate.interfaces.EmptyCallback;
|
|
29
31
|
import io.capawesome.capacitorjs.plugins.liveupdate.interfaces.NonEmptyCallback;
|
|
@@ -54,11 +56,11 @@ import org.json.JSONObject;
|
|
|
54
56
|
|
|
55
57
|
public class LiveUpdate {
|
|
56
58
|
|
|
59
|
+
public static final String DEFAULT_WEB_ASSET_DIR = Bridge.DEFAULT_WEB_ASSET_DIR;
|
|
60
|
+
|
|
57
61
|
@NonNull
|
|
58
62
|
private final LiveUpdateConfig config;
|
|
59
63
|
|
|
60
|
-
private final String defaultWebAssetDir;
|
|
61
|
-
|
|
62
64
|
@NonNull
|
|
63
65
|
private final LiveUpdatePlugin plugin;
|
|
64
66
|
|
|
@@ -71,9 +73,10 @@ public class LiveUpdate {
|
|
|
71
73
|
private final String bundlesDirectory = "_capacitor_live_update_bundles";
|
|
72
74
|
private final Handler rollbackHandler = new Handler();
|
|
73
75
|
|
|
76
|
+
private boolean rollbackPerformed = false;
|
|
77
|
+
|
|
74
78
|
public LiveUpdate(@NonNull LiveUpdateConfig config, @NonNull LiveUpdatePlugin plugin) throws PackageManager.NameNotFoundException {
|
|
75
79
|
this.config = config;
|
|
76
|
-
this.defaultWebAssetDir = plugin.getBridge().DEFAULT_WEB_ASSET_DIR;
|
|
77
80
|
this.plugin = plugin;
|
|
78
81
|
this.preferences = new LiveUpdatePreferences(plugin.getContext());
|
|
79
82
|
this.webViewSettingsEditor = plugin.getContext().getSharedPreferences(WebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE).edit();
|
|
@@ -119,9 +122,6 @@ public class LiveUpdate {
|
|
|
119
122
|
|
|
120
123
|
public void getBundle(@NonNull NonEmptyCallback callback) {
|
|
121
124
|
String bundleId = getCurrentBundleId();
|
|
122
|
-
if (bundleId.equals(defaultWebAssetDir)) {
|
|
123
|
-
bundleId = null;
|
|
124
|
-
}
|
|
125
125
|
GetBundleResult result = new GetBundleResult(bundleId);
|
|
126
126
|
callback.success(result);
|
|
127
127
|
}
|
|
@@ -162,12 +162,18 @@ public class LiveUpdate {
|
|
|
162
162
|
callback.success(result);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
public void ready() {
|
|
165
|
+
public void ready(@NonNull NonEmptyCallback callback) {
|
|
166
166
|
Logger.debug(LiveUpdatePlugin.TAG, "App is ready.");
|
|
167
167
|
stopRollbackTimer();
|
|
168
168
|
if (config.getAutoDeleteBundles()) {
|
|
169
169
|
deleteUnusedBundles();
|
|
170
170
|
}
|
|
171
|
+
String currentBundleId = getCurrentBundleId();
|
|
172
|
+
String previousBundleId = getPreviousBundleId();
|
|
173
|
+
ReadyResult result = new ReadyResult(currentBundleId, previousBundleId, rollbackPerformed);
|
|
174
|
+
callback.success(result);
|
|
175
|
+
setPreviousBundleId(currentBundleId);
|
|
176
|
+
rollbackPerformed = false;
|
|
171
177
|
}
|
|
172
178
|
|
|
173
179
|
public void reload() {
|
|
@@ -472,9 +478,13 @@ public class LiveUpdate {
|
|
|
472
478
|
@Nullable
|
|
473
479
|
private void fetchLatestBundle(@NonNull NonEmptyCallback<GetLatestBundleResponse> callback)
|
|
474
480
|
throws PackageManager.NameNotFoundException {
|
|
481
|
+
String host = "api.cloud.capawesome.io";
|
|
482
|
+
if (config.getLocation() != null && config.getLocation().equals("eu")) {
|
|
483
|
+
host = "api.cloud.capawesome.eu";
|
|
484
|
+
}
|
|
475
485
|
HttpUrl url = new HttpUrl.Builder()
|
|
476
486
|
.scheme("https")
|
|
477
|
-
.host(
|
|
487
|
+
.host(host)
|
|
478
488
|
.addPathSegment("v1")
|
|
479
489
|
.addPathSegment("apps")
|
|
480
490
|
.addPathSegment(config.getAppId())
|
|
@@ -554,8 +564,8 @@ public class LiveUpdate {
|
|
|
554
564
|
*/
|
|
555
565
|
private String getCurrentBundleId() {
|
|
556
566
|
String currentPath = getCurrentCapacitorServerPath();
|
|
557
|
-
if (currentPath.equals(
|
|
558
|
-
return
|
|
567
|
+
if (currentPath.equals(DEFAULT_WEB_ASSET_DIR)) {
|
|
568
|
+
return DEFAULT_WEB_ASSET_DIR;
|
|
559
569
|
}
|
|
560
570
|
return new File(currentPath).getName();
|
|
561
571
|
}
|
|
@@ -583,8 +593,8 @@ public class LiveUpdate {
|
|
|
583
593
|
@NonNull
|
|
584
594
|
private String getNextBundleId() {
|
|
585
595
|
String nextPath = getNextCapacitorServerPath();
|
|
586
|
-
if (nextPath.equals(
|
|
587
|
-
return
|
|
596
|
+
if (nextPath.equals(DEFAULT_WEB_ASSET_DIR)) {
|
|
597
|
+
return DEFAULT_WEB_ASSET_DIR;
|
|
588
598
|
}
|
|
589
599
|
return new File(nextPath).getName();
|
|
590
600
|
}
|
|
@@ -597,7 +607,12 @@ public class LiveUpdate {
|
|
|
597
607
|
return plugin
|
|
598
608
|
.getContext()
|
|
599
609
|
.getSharedPreferences(WebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE)
|
|
600
|
-
.getString(WebView.CAP_SERVER_PATH,
|
|
610
|
+
.getString(WebView.CAP_SERVER_PATH, DEFAULT_WEB_ASSET_DIR);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
@Nullable
|
|
614
|
+
private String getPreviousBundleId() {
|
|
615
|
+
return preferences.getPreviousBundleId();
|
|
601
616
|
}
|
|
602
617
|
|
|
603
618
|
private boolean hasBundle(@NonNull String bundleId) {
|
|
@@ -612,7 +627,10 @@ public class LiveUpdate {
|
|
|
612
627
|
}
|
|
613
628
|
|
|
614
629
|
private void rollback() {
|
|
615
|
-
|
|
630
|
+
rollbackPerformed = true;
|
|
631
|
+
String currentBundleId = getCurrentBundleId();
|
|
632
|
+
setPreviousBundleId(currentBundleId);
|
|
633
|
+
if (currentBundleId.equals(DEFAULT_WEB_ASSET_DIR)) {
|
|
616
634
|
Logger.debug(LiveUpdatePlugin.TAG, "App is not ready. Default bundle is already in use.");
|
|
617
635
|
return;
|
|
618
636
|
}
|
|
@@ -652,7 +670,7 @@ public class LiveUpdate {
|
|
|
652
670
|
}
|
|
653
671
|
|
|
654
672
|
private void setCurrentCapacitorServerPath(@NonNull String path) {
|
|
655
|
-
if (path.equals(
|
|
673
|
+
if (path.equals(DEFAULT_WEB_ASSET_DIR)) {
|
|
656
674
|
this.plugin.getBridge().setServerAssetPath(path);
|
|
657
675
|
} else {
|
|
658
676
|
this.plugin.getBridge().setServerBasePath(path);
|
|
@@ -661,7 +679,7 @@ public class LiveUpdate {
|
|
|
661
679
|
}
|
|
662
680
|
|
|
663
681
|
private void setCurrentCapacitorServerPathToDefaultWebAssetDir() {
|
|
664
|
-
setCurrentCapacitorServerPath(
|
|
682
|
+
setCurrentCapacitorServerPath(DEFAULT_WEB_ASSET_DIR);
|
|
665
683
|
}
|
|
666
684
|
|
|
667
685
|
private void setNextBundle(@NonNull String bundleId) {
|
|
@@ -675,7 +693,11 @@ public class LiveUpdate {
|
|
|
675
693
|
}
|
|
676
694
|
|
|
677
695
|
private void setNextCapacitorServerPathToDefaultWebAssetDir() {
|
|
678
|
-
setNextCapacitorServerPath(
|
|
696
|
+
setNextCapacitorServerPath(DEFAULT_WEB_ASSET_DIR);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
private void setPreviousBundleId(@Nullable String bundleId) {
|
|
700
|
+
preferences.setPreviousBundleId(bundleId);
|
|
679
701
|
}
|
|
680
702
|
|
|
681
703
|
private void startRollbackTimer() {
|
package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdateConfig.java
CHANGED
|
@@ -11,6 +11,9 @@ public class LiveUpdateConfig {
|
|
|
11
11
|
private boolean autoDeleteBundles = false;
|
|
12
12
|
private boolean enabled = true;
|
|
13
13
|
|
|
14
|
+
@Nullable
|
|
15
|
+
private String location = null;
|
|
16
|
+
|
|
14
17
|
@Nullable
|
|
15
18
|
private String publicKey = null;
|
|
16
19
|
|
|
@@ -30,6 +33,11 @@ public class LiveUpdateConfig {
|
|
|
30
33
|
return enabled;
|
|
31
34
|
}
|
|
32
35
|
|
|
36
|
+
@Nullable
|
|
37
|
+
public String getLocation() {
|
|
38
|
+
return location;
|
|
39
|
+
}
|
|
40
|
+
|
|
33
41
|
@Nullable
|
|
34
42
|
public String getPublicKey() {
|
|
35
43
|
return publicKey;
|
|
@@ -55,6 +63,10 @@ public class LiveUpdateConfig {
|
|
|
55
63
|
this.enabled = enabled;
|
|
56
64
|
}
|
|
57
65
|
|
|
66
|
+
public void setLocation(@Nullable String location) {
|
|
67
|
+
this.location = location;
|
|
68
|
+
}
|
|
69
|
+
|
|
58
70
|
public void setPublicKey(@Nullable String publicKey) {
|
|
59
71
|
this.publicKey = publicKey;
|
|
60
72
|
}
|
package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePlugin.java
CHANGED
|
@@ -19,7 +19,7 @@ import io.capawesome.capacitorjs.plugins.liveupdate.interfaces.Result;
|
|
|
19
19
|
public class LiveUpdatePlugin extends Plugin {
|
|
20
20
|
|
|
21
21
|
public static final String TAG = "LiveUpdate";
|
|
22
|
-
public static final String VERSION = "6.
|
|
22
|
+
public static final String VERSION = "6.2.0-dev.0a2a6a5.1722676620";
|
|
23
23
|
public static final String SHARED_PREFERENCES_NAME = "CapawesomeLiveUpdate"; // DO NOT CHANGE
|
|
24
24
|
public static final String ERROR_APP_ID_MISSING = "appId must be configured.";
|
|
25
25
|
public static final String ERROR_BUNDLE_EXISTS = "bundle already exists.";
|
|
@@ -280,8 +280,20 @@ public class LiveUpdatePlugin extends Plugin {
|
|
|
280
280
|
@PluginMethod
|
|
281
281
|
public void ready(PluginCall call) {
|
|
282
282
|
try {
|
|
283
|
-
|
|
284
|
-
|
|
283
|
+
NonEmptyCallback<Result> callback = new NonEmptyCallback<>() {
|
|
284
|
+
@Override
|
|
285
|
+
public void success(Result result) {
|
|
286
|
+
call.resolve(result.toJSObject());
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
@Override
|
|
290
|
+
public void error(Exception exception) {
|
|
291
|
+
Logger.error(TAG, exception.getMessage(), exception);
|
|
292
|
+
call.reject(exception.getMessage());
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
implementation.ready(callback);
|
|
285
297
|
} catch (Exception exception) {
|
|
286
298
|
Logger.error(TAG, exception.getMessage(), exception);
|
|
287
299
|
call.reject(exception.getMessage());
|
|
@@ -433,6 +445,8 @@ public class LiveUpdatePlugin extends Plugin {
|
|
|
433
445
|
config.setAutoDeleteBundles(autoDeleteBundles);
|
|
434
446
|
boolean enabled = getConfig().getBoolean("enabled", config.getEnabled());
|
|
435
447
|
config.setEnabled(enabled);
|
|
448
|
+
String location = getConfig().getString("location", config.getLocation());
|
|
449
|
+
config.setLocation(location);
|
|
436
450
|
String publicKey = getConfig().getString("publicKey", config.getPublicKey());
|
|
437
451
|
config.setPublicKey(publicKey);
|
|
438
452
|
int readyTimeout = getConfig().getInt("readyTimeout", config.getReadyTimeout());
|
|
@@ -19,6 +19,7 @@ public class LiveUpdatePreferences {
|
|
|
19
19
|
private final String deviceIdKey = "deviceId"; // DO NOT CHANGE
|
|
20
20
|
private final String customIdKey = "customId"; // DO NOT CHANGE
|
|
21
21
|
private final String lastVersionCodeKey = "lastVersionCode"; // DO NOT CHANGE
|
|
22
|
+
private final String previousBundleIdKey = "previousBundleId"; // DO NOT CHANGE
|
|
22
23
|
|
|
23
24
|
public LiveUpdatePreferences(@NonNull Context context) {
|
|
24
25
|
this.context = context;
|
|
@@ -52,6 +53,13 @@ public class LiveUpdatePreferences {
|
|
|
52
53
|
return context.getSharedPreferences(LiveUpdatePlugin.SHARED_PREFERENCES_NAME, Activity.MODE_PRIVATE).getInt(lastVersionCodeKey, 0);
|
|
53
54
|
}
|
|
54
55
|
|
|
56
|
+
@Nullable
|
|
57
|
+
public String getPreviousBundleId() {
|
|
58
|
+
return context
|
|
59
|
+
.getSharedPreferences(LiveUpdatePlugin.SHARED_PREFERENCES_NAME, Activity.MODE_PRIVATE)
|
|
60
|
+
.getString(previousBundleIdKey, null);
|
|
61
|
+
}
|
|
62
|
+
|
|
55
63
|
public void setChannel(@Nullable String channel) {
|
|
56
64
|
if (channel == null) {
|
|
57
65
|
settingsEditor.remove(channelKey);
|
|
@@ -83,4 +91,13 @@ public class LiveUpdatePreferences {
|
|
|
83
91
|
settingsEditor.putInt(lastVersionCodeKey, lastVersionCode);
|
|
84
92
|
settingsEditor.apply();
|
|
85
93
|
}
|
|
94
|
+
|
|
95
|
+
public void setPreviousBundleId(@Nullable String bundleId) {
|
|
96
|
+
if (bundleId == null) {
|
|
97
|
+
settingsEditor.remove(previousBundleIdKey);
|
|
98
|
+
} else {
|
|
99
|
+
settingsEditor.putString(previousBundleIdKey, bundleId);
|
|
100
|
+
}
|
|
101
|
+
settingsEditor.apply();
|
|
102
|
+
}
|
|
86
103
|
}
|
|
@@ -4,6 +4,7 @@ import androidx.annotation.NonNull;
|
|
|
4
4
|
import androidx.annotation.Nullable;
|
|
5
5
|
import com.getcapacitor.JSArray;
|
|
6
6
|
import com.getcapacitor.JSObject;
|
|
7
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.LiveUpdate;
|
|
7
8
|
import io.capawesome.capacitorjs.plugins.liveupdate.interfaces.Result;
|
|
8
9
|
import org.json.JSONObject;
|
|
9
10
|
|
|
@@ -18,7 +19,7 @@ public class GetBundleResult implements Result {
|
|
|
18
19
|
|
|
19
20
|
public JSObject toJSObject() {
|
|
20
21
|
JSObject result = new JSObject();
|
|
21
|
-
result.put("bundleId", bundleId
|
|
22
|
+
result.put("bundleId", bundleId.equals(LiveUpdate.DEFAULT_WEB_ASSET_DIR) ? JSONObject.NULL : bundleId);
|
|
22
23
|
return result;
|
|
23
24
|
}
|
|
24
25
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.liveupdate.classes.results;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.Nullable;
|
|
4
|
+
import com.getcapacitor.JSObject;
|
|
5
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.LiveUpdate;
|
|
6
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.interfaces.Result;
|
|
7
|
+
import org.json.JSONObject;
|
|
8
|
+
|
|
9
|
+
public class ReadyResult implements Result {
|
|
10
|
+
|
|
11
|
+
@Nullable
|
|
12
|
+
private String currentBundleId;
|
|
13
|
+
|
|
14
|
+
@Nullable
|
|
15
|
+
private String previousBundleId;
|
|
16
|
+
|
|
17
|
+
private boolean rollback;
|
|
18
|
+
|
|
19
|
+
public ReadyResult(@Nullable String currentBundleId, @Nullable String previousBundleId, boolean rollback) {
|
|
20
|
+
this.currentBundleId = currentBundleId;
|
|
21
|
+
this.previousBundleId = previousBundleId;
|
|
22
|
+
this.rollback = rollback;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public JSObject toJSObject() {
|
|
26
|
+
JSObject result = new JSObject();
|
|
27
|
+
result.put("currentBundleId", currentBundleId.equals(LiveUpdate.DEFAULT_WEB_ASSET_DIR) ? JSONObject.NULL : currentBundleId);
|
|
28
|
+
result.put("previousBundleId", previousBundleId.equals(LiveUpdate.DEFAULT_WEB_ASSET_DIR) ? JSONObject.NULL : previousBundleId);
|
|
29
|
+
result.put("rollback", rollback);
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
}
|
package/dist/docs.json
CHANGED
|
@@ -172,9 +172,9 @@
|
|
|
172
172
|
},
|
|
173
173
|
{
|
|
174
174
|
"name": "ready",
|
|
175
|
-
"signature": "() => Promise<
|
|
175
|
+
"signature": "() => Promise<ReadyResult>",
|
|
176
176
|
"parameters": [],
|
|
177
|
-
"returns": "Promise<
|
|
177
|
+
"returns": "Promise<ReadyResult>",
|
|
178
178
|
"tags": [
|
|
179
179
|
{
|
|
180
180
|
"name": "since",
|
|
@@ -182,7 +182,9 @@
|
|
|
182
182
|
}
|
|
183
183
|
],
|
|
184
184
|
"docs": "Notify the plugin that the app is ready to use and no rollback is needed.\n\n**Attention**: This method should be called as soon as the app is ready to use\nto prevent the app from being reset to the default bundle.\n\nOnly available on Android and iOS.",
|
|
185
|
-
"complexTypes": [
|
|
185
|
+
"complexTypes": [
|
|
186
|
+
"ReadyResult"
|
|
187
|
+
],
|
|
186
188
|
"slug": "ready"
|
|
187
189
|
},
|
|
188
190
|
{
|
|
@@ -598,6 +600,56 @@
|
|
|
598
600
|
}
|
|
599
601
|
]
|
|
600
602
|
},
|
|
603
|
+
{
|
|
604
|
+
"name": "ReadyResult",
|
|
605
|
+
"slug": "readyresult",
|
|
606
|
+
"docs": "",
|
|
607
|
+
"tags": [
|
|
608
|
+
{
|
|
609
|
+
"text": "7.0.0",
|
|
610
|
+
"name": "since"
|
|
611
|
+
}
|
|
612
|
+
],
|
|
613
|
+
"methods": [],
|
|
614
|
+
"properties": [
|
|
615
|
+
{
|
|
616
|
+
"name": "previousBundleId",
|
|
617
|
+
"tags": [
|
|
618
|
+
{
|
|
619
|
+
"text": "7.0.0",
|
|
620
|
+
"name": "since"
|
|
621
|
+
}
|
|
622
|
+
],
|
|
623
|
+
"docs": "The identifier of the previous bundle used.\n\nIf `null`, the default bundle was used.",
|
|
624
|
+
"complexTypes": [],
|
|
625
|
+
"type": "string | null"
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
"name": "currentBundleId",
|
|
629
|
+
"tags": [
|
|
630
|
+
{
|
|
631
|
+
"text": "7.0.0",
|
|
632
|
+
"name": "since"
|
|
633
|
+
}
|
|
634
|
+
],
|
|
635
|
+
"docs": "The identifier of the current bundle used.\n\nIf `null`, the default bundle is being used.",
|
|
636
|
+
"complexTypes": [],
|
|
637
|
+
"type": "string | null"
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
"name": "rollback",
|
|
641
|
+
"tags": [
|
|
642
|
+
{
|
|
643
|
+
"text": "7.0.0",
|
|
644
|
+
"name": "since"
|
|
645
|
+
}
|
|
646
|
+
],
|
|
647
|
+
"docs": "Whether or not the app was reset to the default bundle.",
|
|
648
|
+
"complexTypes": [],
|
|
649
|
+
"type": "boolean"
|
|
650
|
+
}
|
|
651
|
+
]
|
|
652
|
+
},
|
|
601
653
|
{
|
|
602
654
|
"name": "SetBundleOptions",
|
|
603
655
|
"slug": "setbundleoptions",
|
|
@@ -762,6 +814,30 @@
|
|
|
762
814
|
"complexTypes": [],
|
|
763
815
|
"type": "boolean | undefined"
|
|
764
816
|
},
|
|
817
|
+
{
|
|
818
|
+
"name": "location",
|
|
819
|
+
"tags": [
|
|
820
|
+
{
|
|
821
|
+
"text": "6.2.0",
|
|
822
|
+
"name": "since"
|
|
823
|
+
},
|
|
824
|
+
{
|
|
825
|
+
"text": "'us'",
|
|
826
|
+
"name": "default"
|
|
827
|
+
},
|
|
828
|
+
{
|
|
829
|
+
"text": "'eu'",
|
|
830
|
+
"name": "example"
|
|
831
|
+
},
|
|
832
|
+
{
|
|
833
|
+
"text": "https ://capawesome.io/cloud/live-updates/advanced/privacy/",
|
|
834
|
+
"name": "see"
|
|
835
|
+
}
|
|
836
|
+
],
|
|
837
|
+
"docs": "The location of the server to use when using [Capawesome Cloud](https://capawesome.io/cloud).",
|
|
838
|
+
"complexTypes": [],
|
|
839
|
+
"type": "'us' | 'eu' | undefined"
|
|
840
|
+
},
|
|
765
841
|
{
|
|
766
842
|
"name": "publicKey",
|
|
767
843
|
"tags": [
|
|
@@ -24,6 +24,15 @@ declare module '@capacitor/cli' {
|
|
|
24
24
|
* @default true
|
|
25
25
|
*/
|
|
26
26
|
enabled?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* The location of the server to use when using [Capawesome Cloud](https://capawesome.io/cloud).
|
|
29
|
+
*
|
|
30
|
+
* @since 6.2.0
|
|
31
|
+
* @default 'us'
|
|
32
|
+
* @example 'eu'
|
|
33
|
+
* @see https://capawesome.io/cloud/live-updates/advanced/privacy/
|
|
34
|
+
*/
|
|
35
|
+
location?: 'us' | 'eu';
|
|
27
36
|
/**
|
|
28
37
|
* The public key to verify the integrity of the bundle.
|
|
29
38
|
*
|
|
@@ -133,7 +142,7 @@ export interface LiveUpdatePlugin {
|
|
|
133
142
|
*
|
|
134
143
|
* @since 5.0.0
|
|
135
144
|
*/
|
|
136
|
-
ready(): Promise<
|
|
145
|
+
ready(): Promise<ReadyResult>;
|
|
137
146
|
/**
|
|
138
147
|
* Reload the app to apply the new bundle.
|
|
139
148
|
*
|
|
@@ -327,6 +336,33 @@ export interface GetCustomIdResult {
|
|
|
327
336
|
*/
|
|
328
337
|
customId: string | null;
|
|
329
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* @since 7.0.0
|
|
341
|
+
*/
|
|
342
|
+
export interface ReadyResult {
|
|
343
|
+
/**
|
|
344
|
+
* The identifier of the previous bundle used.
|
|
345
|
+
*
|
|
346
|
+
* If `null`, the default bundle was used.
|
|
347
|
+
*
|
|
348
|
+
* @since 7.0.0
|
|
349
|
+
*/
|
|
350
|
+
previousBundleId: string | null;
|
|
351
|
+
/**
|
|
352
|
+
* The identifier of the current bundle used.
|
|
353
|
+
*
|
|
354
|
+
* If `null`, the default bundle is being used.
|
|
355
|
+
*
|
|
356
|
+
* @since 7.0.0
|
|
357
|
+
*/
|
|
358
|
+
currentBundleId: string | null;
|
|
359
|
+
/**
|
|
360
|
+
* Whether or not the app was reset to the default bundle.
|
|
361
|
+
*
|
|
362
|
+
* @since 7.0.0
|
|
363
|
+
*/
|
|
364
|
+
rollback: boolean;
|
|
365
|
+
}
|
|
330
366
|
/**
|
|
331
367
|
* @since 5.0.0
|
|
332
368
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,wCAAwC","sourcesContent":["/// <reference types=\"@capacitor/cli\" />\n\ndeclare module '@capacitor/cli' {\n export interface PluginsConfig {\n LiveUpdate?: {\n /**\n * The app ID is used to identify the app when using [Capawesome Cloud](https://capawesome.io/cloud).\n *\n * @since 5.0.0\n * @example '4100e356-e851-47fe-9d3c-b411eb325a99'\n */\n appId?: string;\n /**\n * Whether or not to automatically delete unused bundles.\n *\n * When enabled, the plugin will automatically delete unused bundles after calling `ready()`.\n *\n * @since 5.0.0\n * @default false\n */\n autoDeleteBundles?: boolean;\n /**\n * Whether or not the plugin is enabled.\n *\n * @since 5.0.0\n * @default true\n */\n enabled?: boolean;\n /**\n * The public key to verify the integrity of the bundle.\n *\n * The public key must be a PEM-encoded RSA public key.\n *\n * @since 6.1.0\n * @example '-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDodf1SD0OOn6hIlDuKBza0Ed0OqtwyVJwiyjmE9BJaZ7y8ZUfcF+SKmd0l2cDPM45XIg2tAFux5n29uoKyHwSt+6tCi5CJA5Z1/1eZruRRqABLonV77KS3HUtvOgqRLDnKSV89dYZkM++NwmzOPgIF422mvc+VukcVOBfc8/AHQIDAQAB-----END PUBLIC KEY-----'\n */\n publicKey?: string;\n /**\n * The timeout in milliseconds to wait for the app to be ready before resetting to the default bundle.\n *\n * @since 5.0.0\n * @default 10000\n */\n readyTimeout?: number;\n /**\n * Whether or not the app should be reset to the default bundle during an update.\n *\n * @since 5.0.0\n * @default true\n */\n resetOnUpdate?: boolean;\n };\n }\n}\n\nexport interface LiveUpdatePlugin {\n /**\n * Delete a bundle from the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n deleteBundle(options: DeleteBundleOptions): Promise<void>;\n /**\n * Download a bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n downloadBundle(options: DownloadBundleOptions): Promise<void>;\n /**\n * Get the active bundle identifier.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getBundle(): Promise<GetBundleResult>;\n /**\n * Get all available bundle identifiers.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getBundles(): Promise<GetBundlesResult>;\n /**\n * Get the channel of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getChannel(): Promise<GetChannelResult>;\n /**\n * Get the custom identifier of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getCustomId(): Promise<GetCustomIdResult>;\n /**\n * Get the device identifier of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getDeviceId(): Promise<GetDeviceIdResult>;\n /**\n * Get the version code of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getVersionCode(): Promise<GetVersionCodeResult>;\n /**\n * Get the version name of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getVersionName(): Promise<GetVersionNameResult>;\n /**\n * Notify the plugin that the app is ready to use and no rollback is needed.\n *\n * **Attention**: This method should be called as soon as the app is ready to use\n * to prevent the app from being reset to the default bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n ready(): Promise<void>;\n /**\n * Reload the app to apply the new bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n reload(): Promise<void>;\n /**\n * Reset the app to the default bundle.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n reset(): Promise<void>;\n /**\n * Set the next bundle to use for the app.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setBundle(options: SetBundleOptions): Promise<void>;\n /**\n * Set the channel of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setChannel(options: SetChannelOptions): Promise<void>;\n /**\n * Set the custom identifier of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setCustomId(options: SetCustomIdOptions): Promise<void>;\n /**\n * Automatically download and set the latest bundle for the app using the [Capawesome Cloud](https://capawesome.io/cloud/).\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n sync(): Promise<SyncResult>;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface DeleteBundleOptions {\n /**\n * The unique identifier of the bundle to delete.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\nexport interface DownloadBundleOptions {\n /**\n * The unique identifier of the bundle.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n /**\n * The checksum of the bundle to verify the integrity of the ZIP file.\n *\n * Must be a SHA-256 hash in hexadecimal format.\n *\n * @since 6.1.0\n * @example 'aab8e0a312e807c8eaeb923e2bdccd7731c5508869c62ad8e6e43ee881414c84'\n */\n checksum?: string;\n /**\n * The URL of the bundle to download.\n *\n * The bundle must be a ZIP file containing at least a `index.html` file.\n *\n * @since 5.0.0\n * @example 'https://example.com/bundle.zip'\n */\n url: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetBundleResult {\n /**\n * The unique identifier of the active bundle.\n *\n * If `null`, the default bundle is being used.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetBundlesResult {\n /**\n * An array of unique identifiers of all available bundles.\n *\n * @since 5.0.0\n */\n bundleIds: string[];\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetChannelResult {\n /**\n * The channel of the app.\n *\n * If `null`, the app is using the default channel.\n *\n * @since 5.0.0\n * @example 'production'\n */\n channel: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetDeviceIdResult {\n /**\n * The unique identifier of the device.\n *\n * On iOS, [`identifierForVendor`](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor) is used.\n * The value of this property is the same for apps that come from the same vendor running on the same device.\n *\n * @since 5.0.0\n *\n * @example '50d2a548-80b7-4dad-adc7-97c0e79d8a89'\n */\n deviceId: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetVersionCodeResult {\n /**\n * The version code of the app.\n *\n * On **Android**, this is the `versionCode` from the `android/app/build.gradle` file.\n * On **iOS**, this is the `CFBundleVersion` from the `Info.plist` file.\n *\n * @since 5.0.0\n * @example \"1\"\n */\n versionCode: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetVersionNameResult {\n /**\n * The version name of the app.\n *\n * On **Android**, this is the `versionName` from the `android/app/build.gradle` file.\n * On **iOS**, this is the `CFBundleShortVersionString` from the `Info.plist` file.\n *\n * @since 5.0.0\n * @example \"1.0.0\"\n */\n versionName: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetCustomIdResult {\n /**\n * The custom identifier of the app.\n *\n * If `null`, no custom identifier is set.\n *\n * @since 5.0.0\n * @example '50d2a548-80b7-4dad-adc7-97c0e79d8a89'\n */\n customId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetBundleOptions {\n /**\n * The unique identifier of the bundle to use.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetChannelOptions {\n /**\n * The channel of the app.\n *\n * Set `null` to remove the channel.\n *\n * @since 5.0.0\n */\n channel: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetCustomIdOptions {\n /**\n * The custom identifier of the app.\n *\n * Set `null` to remove the custom identifier.\n *\n * @since 5.0.0\n */\n customId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SyncResult {\n /**\n * The identifier of the next bundle to use.\n *\n * If `null`, the app is up-to-date and no new bundle is available.\n *\n * @since 5.0.0\n */\n nextBundleId: string | null;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,wCAAwC","sourcesContent":["/// <reference types=\"@capacitor/cli\" />\n\ndeclare module '@capacitor/cli' {\n export interface PluginsConfig {\n LiveUpdate?: {\n /**\n * The app ID is used to identify the app when using [Capawesome Cloud](https://capawesome.io/cloud).\n *\n * @since 5.0.0\n * @example '4100e356-e851-47fe-9d3c-b411eb325a99'\n */\n appId?: string;\n /**\n * Whether or not to automatically delete unused bundles.\n *\n * When enabled, the plugin will automatically delete unused bundles after calling `ready()`.\n *\n * @since 5.0.0\n * @default false\n */\n autoDeleteBundles?: boolean;\n /**\n * Whether or not the plugin is enabled.\n *\n * @since 5.0.0\n * @default true\n */\n enabled?: boolean;\n /**\n * The location of the server to use when using [Capawesome Cloud](https://capawesome.io/cloud).\n *\n * @since 6.2.0\n * @default 'us'\n * @example 'eu'\n * @see https://capawesome.io/cloud/live-updates/advanced/privacy/\n */\n location?: 'us' | 'eu';\n /**\n * The public key to verify the integrity of the bundle.\n *\n * The public key must be a PEM-encoded RSA public key.\n *\n * @since 6.1.0\n * @example '-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDodf1SD0OOn6hIlDuKBza0Ed0OqtwyVJwiyjmE9BJaZ7y8ZUfcF+SKmd0l2cDPM45XIg2tAFux5n29uoKyHwSt+6tCi5CJA5Z1/1eZruRRqABLonV77KS3HUtvOgqRLDnKSV89dYZkM++NwmzOPgIF422mvc+VukcVOBfc8/AHQIDAQAB-----END PUBLIC KEY-----'\n */\n publicKey?: string;\n /**\n * The timeout in milliseconds to wait for the app to be ready before resetting to the default bundle.\n *\n * @since 5.0.0\n * @default 10000\n */\n readyTimeout?: number;\n /**\n * Whether or not the app should be reset to the default bundle during an update.\n *\n * @since 5.0.0\n * @default true\n */\n resetOnUpdate?: boolean;\n };\n }\n}\n\nexport interface LiveUpdatePlugin {\n /**\n * Delete a bundle from the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n deleteBundle(options: DeleteBundleOptions): Promise<void>;\n /**\n * Download a bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n downloadBundle(options: DownloadBundleOptions): Promise<void>;\n /**\n * Get the active bundle identifier.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getBundle(): Promise<GetBundleResult>;\n /**\n * Get all available bundle identifiers.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getBundles(): Promise<GetBundlesResult>;\n /**\n * Get the channel of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getChannel(): Promise<GetChannelResult>;\n /**\n * Get the custom identifier of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getCustomId(): Promise<GetCustomIdResult>;\n /**\n * Get the device identifier of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getDeviceId(): Promise<GetDeviceIdResult>;\n /**\n * Get the version code of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getVersionCode(): Promise<GetVersionCodeResult>;\n /**\n * Get the version name of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getVersionName(): Promise<GetVersionNameResult>;\n /**\n * Notify the plugin that the app is ready to use and no rollback is needed.\n *\n * **Attention**: This method should be called as soon as the app is ready to use\n * to prevent the app from being reset to the default bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n ready(): Promise<ReadyResult>;\n /**\n * Reload the app to apply the new bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n reload(): Promise<void>;\n /**\n * Reset the app to the default bundle.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n reset(): Promise<void>;\n /**\n * Set the next bundle to use for the app.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setBundle(options: SetBundleOptions): Promise<void>;\n /**\n * Set the channel of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setChannel(options: SetChannelOptions): Promise<void>;\n /**\n * Set the custom identifier of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setCustomId(options: SetCustomIdOptions): Promise<void>;\n /**\n * Automatically download and set the latest bundle for the app using the [Capawesome Cloud](https://capawesome.io/cloud/).\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n sync(): Promise<SyncResult>;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface DeleteBundleOptions {\n /**\n * The unique identifier of the bundle to delete.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\nexport interface DownloadBundleOptions {\n /**\n * The unique identifier of the bundle.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n /**\n * The checksum of the bundle to verify the integrity of the ZIP file.\n *\n * Must be a SHA-256 hash in hexadecimal format.\n *\n * @since 6.1.0\n * @example 'aab8e0a312e807c8eaeb923e2bdccd7731c5508869c62ad8e6e43ee881414c84'\n */\n checksum?: string;\n /**\n * The URL of the bundle to download.\n *\n * The bundle must be a ZIP file containing at least a `index.html` file.\n *\n * @since 5.0.0\n * @example 'https://example.com/bundle.zip'\n */\n url: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetBundleResult {\n /**\n * The unique identifier of the active bundle.\n *\n * If `null`, the default bundle is being used.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetBundlesResult {\n /**\n * An array of unique identifiers of all available bundles.\n *\n * @since 5.0.0\n */\n bundleIds: string[];\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetChannelResult {\n /**\n * The channel of the app.\n *\n * If `null`, the app is using the default channel.\n *\n * @since 5.0.0\n * @example 'production'\n */\n channel: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetDeviceIdResult {\n /**\n * The unique identifier of the device.\n *\n * On iOS, [`identifierForVendor`](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor) is used.\n * The value of this property is the same for apps that come from the same vendor running on the same device.\n *\n * @since 5.0.0\n *\n * @example '50d2a548-80b7-4dad-adc7-97c0e79d8a89'\n */\n deviceId: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetVersionCodeResult {\n /**\n * The version code of the app.\n *\n * On **Android**, this is the `versionCode` from the `android/app/build.gradle` file.\n * On **iOS**, this is the `CFBundleVersion` from the `Info.plist` file.\n *\n * @since 5.0.0\n * @example \"1\"\n */\n versionCode: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetVersionNameResult {\n /**\n * The version name of the app.\n *\n * On **Android**, this is the `versionName` from the `android/app/build.gradle` file.\n * On **iOS**, this is the `CFBundleShortVersionString` from the `Info.plist` file.\n *\n * @since 5.0.0\n * @example \"1.0.0\"\n */\n versionName: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetCustomIdResult {\n /**\n * The custom identifier of the app.\n *\n * If `null`, no custom identifier is set.\n *\n * @since 5.0.0\n * @example '50d2a548-80b7-4dad-adc7-97c0e79d8a89'\n */\n customId: string | null;\n}\n\n/**\n * @since 7.0.0\n */\nexport interface ReadyResult {\n /**\n * The identifier of the previous bundle used.\n *\n * If `null`, the default bundle was used.\n *\n * @since 7.0.0\n */\n previousBundleId: string | null;\n /**\n * The identifier of the current bundle used.\n *\n * If `null`, the default bundle is being used.\n *\n * @since 7.0.0\n */\n currentBundleId: string | null;\n /**\n * Whether or not the app was reset to the default bundle.\n *\n * @since 7.0.0\n */\n rollback: boolean;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetBundleOptions {\n /**\n * The unique identifier of the bundle to use.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetChannelOptions {\n /**\n * The channel of the app.\n *\n * Set `null` to remove the channel.\n *\n * @since 5.0.0\n */\n channel: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetCustomIdOptions {\n /**\n * The custom identifier of the app.\n *\n * Set `null` to remove the custom identifier.\n *\n * @since 5.0.0\n */\n customId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SyncResult {\n /**\n * The identifier of the next bundle to use.\n *\n * If `null`, the app is up-to-date and no new bundle is available.\n *\n * @since 5.0.0\n */\n nextBundleId: string | null;\n}\n"]}
|
package/dist/esm/web.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WebPlugin } from '@capacitor/core';
|
|
2
|
-
import type { DeleteBundleOptions, DownloadBundleOptions, GetBundleResult, GetBundlesResult, GetChannelResult, GetCustomIdResult, GetDeviceIdResult, GetVersionCodeResult, GetVersionNameResult, LiveUpdatePlugin, SetBundleOptions, SetChannelOptions, SetCustomIdOptions, SyncResult } from './definitions';
|
|
2
|
+
import type { DeleteBundleOptions, DownloadBundleOptions, GetBundleResult, GetBundlesResult, GetChannelResult, GetCustomIdResult, GetDeviceIdResult, GetVersionCodeResult, GetVersionNameResult, LiveUpdatePlugin, ReadyResult, SetBundleOptions, SetChannelOptions, SetCustomIdOptions, SyncResult } from './definitions';
|
|
3
3
|
export declare class LiveUpdateWeb extends WebPlugin implements LiveUpdatePlugin {
|
|
4
4
|
deleteBundle(_options: DeleteBundleOptions): Promise<void>;
|
|
5
5
|
downloadBundle(_options: DownloadBundleOptions): Promise<void>;
|
|
@@ -10,7 +10,7 @@ export declare class LiveUpdateWeb extends WebPlugin implements LiveUpdatePlugin
|
|
|
10
10
|
getDeviceId(): Promise<GetDeviceIdResult>;
|
|
11
11
|
getVersionCode(): Promise<GetVersionCodeResult>;
|
|
12
12
|
getVersionName(): Promise<GetVersionNameResult>;
|
|
13
|
-
ready(): Promise<
|
|
13
|
+
ready(): Promise<ReadyResult>;
|
|
14
14
|
reload(): Promise<void>;
|
|
15
15
|
reset(): Promise<void>;
|
|
16
16
|
setBundle(_options: SetBundleOptions): Promise<void>;
|
package/dist/esm/web.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAoB5C,MAAM,OAAO,aAAc,SAAQ,SAAS;IACnC,KAAK,CAAC,YAAY,CAAC,QAA6B;QACrD,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,cAAc,CAAC,QAA+B;QACzD,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,SAAS;QACpB,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,UAAU;QACrB,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,UAAU;QACrB,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,WAAW;QACtB,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,WAAW;QACtB,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,cAAc;QACzB,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,cAAc;QACzB,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,KAAK;QAChB,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,MAAM;QACjB,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,KAAK;QAChB,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,SAAS,CAAC,QAA0B;QAC/C,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,QAA2B;QACjD,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,QAA4B;QACnD,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAEO,uBAAuB;QAC7B,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type {\n DeleteBundleOptions,\n DownloadBundleOptions,\n GetBundleResult,\n GetBundlesResult,\n GetChannelResult,\n GetCustomIdResult,\n GetDeviceIdResult,\n GetVersionCodeResult,\n GetVersionNameResult,\n LiveUpdatePlugin,\n ReadyResult,\n SetBundleOptions,\n SetChannelOptions,\n SetCustomIdOptions,\n SyncResult,\n} from './definitions';\n\nexport class LiveUpdateWeb extends WebPlugin implements LiveUpdatePlugin {\n public async deleteBundle(_options: DeleteBundleOptions): Promise<void> {\n this.throwUnimplementedError();\n }\n\n public async downloadBundle(_options: DownloadBundleOptions): Promise<void> {\n this.throwUnimplementedError();\n }\n\n public async getBundle(): Promise<GetBundleResult> {\n this.throwUnimplementedError();\n }\n\n public async getBundles(): Promise<GetBundlesResult> {\n this.throwUnimplementedError();\n }\n\n public async getChannel(): Promise<GetChannelResult> {\n this.throwUnimplementedError();\n }\n\n public async getCustomId(): Promise<GetCustomIdResult> {\n this.throwUnimplementedError();\n }\n\n public async getDeviceId(): Promise<GetDeviceIdResult> {\n this.throwUnimplementedError();\n }\n\n public async getVersionCode(): Promise<GetVersionCodeResult> {\n this.throwUnimplementedError();\n }\n\n public async getVersionName(): Promise<GetVersionNameResult> {\n this.throwUnimplementedError();\n }\n\n public async ready(): Promise<ReadyResult> {\n this.throwUnimplementedError();\n }\n\n public async reload(): Promise<void> {\n this.throwUnimplementedError();\n }\n\n public async reset(): Promise<void> {\n this.throwUnimplementedError();\n }\n\n public async setBundle(_options: SetBundleOptions): Promise<void> {\n this.throwUnimplementedError();\n }\n\n public async setChannel(_options: SetChannelOptions): Promise<void> {\n this.throwUnimplementedError();\n }\n\n public async setCustomId(_options: SetCustomIdOptions): Promise<void> {\n this.throwUnimplementedError();\n }\n\n public async sync(): Promise<SyncResult> {\n this.throwUnimplementedError();\n }\n\n private throwUnimplementedError(): never {\n throw this.unimplemented('Not implemented on web.');\n }\n}\n"]}
|
|
@@ -10,7 +10,7 @@ import Capacitor
|
|
|
10
10
|
|
|
11
11
|
public func toJSObject() -> AnyObject {
|
|
12
12
|
var result = JSObject()
|
|
13
|
-
result["bundleId"] = bundleId ==
|
|
13
|
+
result["bundleId"] = bundleId == LiveUpdate.defaultWebAssetDir ? NSNull() : bundleId
|
|
14
14
|
return result as AnyObject
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc public class ReadyResult: NSObject, Result {
|
|
5
|
+
let currentBundleId: String?
|
|
6
|
+
let previousBundleId: String?
|
|
7
|
+
let rollback: Bool
|
|
8
|
+
|
|
9
|
+
init(currentBundleId: String?, previousBundleId: String?, rollback: Bool) {
|
|
10
|
+
self.currentBundleId = currentBundleId
|
|
11
|
+
self.previousBundleId = previousBundleId
|
|
12
|
+
self.rollback = rollback
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public func toJSObject() -> AnyObject {
|
|
16
|
+
var result = JSObject()
|
|
17
|
+
result["currentBundleId"] = currentBundleId == LiveUpdate.defaultWebAssetDir ? NSNull() : currentBundleId
|
|
18
|
+
result["previousBundleId"] = previousBundleId == LiveUpdate.defaultWebAssetDir ? NSNull() : previousBundleId
|
|
19
|
+
result["rollback"] = rollback
|
|
20
|
+
return result as AnyObject
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -7,9 +7,10 @@ import CommonCrypto
|
|
|
7
7
|
|
|
8
8
|
// swiftlint:disable type_body_length
|
|
9
9
|
@objc public class LiveUpdate: NSObject {
|
|
10
|
+
public static let defaultWebAssetDir = "public" // DO NOT CHANGE (See https://dub.sh/Buvz4yj)
|
|
11
|
+
|
|
10
12
|
private let cachesDirectoryUrl = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
|
|
11
13
|
private let config: LiveUpdateConfig
|
|
12
|
-
private let defaultWebAssetDir = "public" // DO NOT CHANGE (See https://dub.sh/Buvz4yj)
|
|
13
14
|
private let defaultServerPathKey = "serverBasePath" // DO NOT CHANGE (See https://dub.sh/ceDl0zT)
|
|
14
15
|
private let libraryDirectoryUrl = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!
|
|
15
16
|
private let plugin: LiveUpdatePlugin
|
|
@@ -17,6 +18,7 @@ import CommonCrypto
|
|
|
17
18
|
private let preferences: LiveUpdatePreferences
|
|
18
19
|
|
|
19
20
|
private var rollbackDispatchWorkItem: DispatchWorkItem?
|
|
21
|
+
private var rollbackPerformed = false
|
|
20
22
|
|
|
21
23
|
init(config: LiveUpdateConfig, plugin: LiveUpdatePlugin) {
|
|
22
24
|
self.config = config
|
|
@@ -74,10 +76,7 @@ import CommonCrypto
|
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
@objc public func getBundle(completion: @escaping (Result?, Error?) -> Void) {
|
|
77
|
-
|
|
78
|
-
if bundleId == defaultWebAssetDir {
|
|
79
|
-
bundleId = nil
|
|
80
|
-
}
|
|
79
|
+
let bundleId = getCurrentBundleId()
|
|
81
80
|
let result = GetBundleResult(bundleId: bundleId)
|
|
82
81
|
completion(result, nil)
|
|
83
82
|
}
|
|
@@ -119,12 +118,18 @@ import CommonCrypto
|
|
|
119
118
|
completion(result, nil)
|
|
120
119
|
}
|
|
121
120
|
|
|
122
|
-
@objc public func ready() {
|
|
121
|
+
@objc public func ready(completion: @escaping (Result?, Error?) -> Void) {
|
|
123
122
|
CAPLog.print("[", LiveUpdatePlugin.tag, "] ", "App is ready.")
|
|
124
123
|
stopRollbackTimer()
|
|
125
124
|
if config.autoDeleteBundles {
|
|
126
125
|
deleteUnusedBundles()
|
|
127
126
|
}
|
|
127
|
+
let currentBundleId = getCurrentBundleId()
|
|
128
|
+
let previousBundleId = getPreviousBundleId()
|
|
129
|
+
let result = ReadyResult(currentBundleId: currentBundleId, previousBundleId: previousBundleId, rollback: rollbackPerformed)
|
|
130
|
+
completion(result, nil)
|
|
131
|
+
setPreviousBundleId(bundleId: currentBundleId)
|
|
132
|
+
rollbackPerformed = false
|
|
128
133
|
}
|
|
129
134
|
|
|
130
135
|
@objc public func reload() {
|
|
@@ -378,7 +383,13 @@ import CommonCrypto
|
|
|
378
383
|
parameters["osVersion"] = UIDevice.current.systemVersion
|
|
379
384
|
parameters["platform"] = "1"
|
|
380
385
|
parameters["pluginVersion"] = LiveUpdatePlugin.version
|
|
381
|
-
|
|
386
|
+
var host = "api.cloud.capawesome.io"
|
|
387
|
+
if let location = config.location {
|
|
388
|
+
if location == "eu" {
|
|
389
|
+
host = "api.cloud.capawesome.eu"
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
let url = URL(string: "https://\(host)/v1/apps/\(config.appId ?? "")/bundles/latest")!
|
|
382
393
|
AF.request(url, method: .get, parameters: parameters).validate().responseDecodable(of: GetLatestBundleResponse.self) { response in
|
|
383
394
|
CAPLog.print("[", LiveUpdatePlugin.tag, "] Fetching latest bundle from ", response.request?.url?.absoluteString ?? "")
|
|
384
395
|
if let error = response.error {
|
|
@@ -450,20 +461,27 @@ import CommonCrypto
|
|
|
450
461
|
|
|
451
462
|
/// - Returns: The absolute path to the next bundle directory.
|
|
452
463
|
private func getNextCapacitorServerPath() -> String {
|
|
453
|
-
let defaultCapacitorServerPath = buildCapacitorServerPathFor(bundleId: defaultWebAssetDir)
|
|
464
|
+
let defaultCapacitorServerPath = buildCapacitorServerPathFor(bundleId: LiveUpdate.defaultWebAssetDir)
|
|
454
465
|
if let path = KeyValueStore.standard[self.defaultServerPathKey, as: String.self] {
|
|
455
466
|
return path.isEmpty ? defaultCapacitorServerPath : path
|
|
456
467
|
}
|
|
457
468
|
return defaultCapacitorServerPath
|
|
458
469
|
}
|
|
459
470
|
|
|
471
|
+
private func getPreviousBundleId() -> String? {
|
|
472
|
+
return preferences.getPreviousBundleId()
|
|
473
|
+
}
|
|
474
|
+
|
|
460
475
|
private func hasBundle(bundleId: String) -> Bool {
|
|
461
476
|
let path = buildBundlePathFor(bundleId: bundleId)
|
|
462
477
|
return FileManager.default.fileExists(atPath: path)
|
|
463
478
|
}
|
|
464
479
|
|
|
465
480
|
private func rollback() {
|
|
466
|
-
|
|
481
|
+
rollbackPerformed = true
|
|
482
|
+
let currentBundleId = getCurrentBundleId()
|
|
483
|
+
setPreviousBundleId(bundleId: currentBundleId)
|
|
484
|
+
if currentBundleId == LiveUpdate.defaultWebAssetDir {
|
|
467
485
|
CAPLog.print("[", LiveUpdatePlugin.tag, "] ", "App is not ready. Default bundle is already in use.")
|
|
468
486
|
return
|
|
469
487
|
}
|
|
@@ -497,7 +515,7 @@ import CommonCrypto
|
|
|
497
515
|
}
|
|
498
516
|
|
|
499
517
|
private func setCurrentCapacitorServerPathToDefaultWebAssetDir() {
|
|
500
|
-
let path = buildCapacitorServerPathFor(bundleId: defaultWebAssetDir)
|
|
518
|
+
let path = buildCapacitorServerPathFor(bundleId: LiveUpdate.defaultWebAssetDir)
|
|
501
519
|
setCurrentCapacitorServerPath(path: path)
|
|
502
520
|
}
|
|
503
521
|
|
|
@@ -517,10 +535,14 @@ import CommonCrypto
|
|
|
517
535
|
}
|
|
518
536
|
|
|
519
537
|
private func setNextCapacitorServerPathToDefaultWebAssetDir() {
|
|
520
|
-
let path = buildCapacitorServerPathFor(bundleId: defaultWebAssetDir)
|
|
538
|
+
let path = buildCapacitorServerPathFor(bundleId: LiveUpdate.defaultWebAssetDir)
|
|
521
539
|
setNextCapacitorServerPath(path: path)
|
|
522
540
|
}
|
|
523
541
|
|
|
542
|
+
private func setPreviousBundleId(bundleId: String?) {
|
|
543
|
+
preferences.setPreviousBundleId(bundleId)
|
|
544
|
+
}
|
|
545
|
+
|
|
524
546
|
private func startRollbackTimer() {
|
|
525
547
|
stopRollbackTimer()
|
|
526
548
|
rollbackDispatchWorkItem = DispatchWorkItem { [weak self] in
|
|
@@ -8,7 +8,7 @@ import Capacitor
|
|
|
8
8
|
@objc(LiveUpdatePlugin)
|
|
9
9
|
public class LiveUpdatePlugin: CAPPlugin {
|
|
10
10
|
public static let tag = "LiveUpdate"
|
|
11
|
-
public static let version = "6.
|
|
11
|
+
public static let version = "6.2.0-dev.0a2a6a5.1722676620"
|
|
12
12
|
public static let userDefaultsPrefix = "CapawesomeLiveUpdate" // DO NOT CHANGE
|
|
13
13
|
|
|
14
14
|
private var config: LiveUpdateConfig?
|
|
@@ -152,8 +152,16 @@ public class LiveUpdatePlugin: CAPPlugin {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
@objc func ready(_ call: CAPPluginCall) {
|
|
155
|
-
implementation?.ready(
|
|
156
|
-
|
|
155
|
+
implementation?.ready(completion: { result, error in
|
|
156
|
+
if let error = error {
|
|
157
|
+
CAPLog.print("[", LiveUpdatePlugin.tag, "] ", error)
|
|
158
|
+
call.reject(error.localizedDescription)
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
if let result = result?.toJSObject() as? JSObject {
|
|
162
|
+
call.resolve(result)
|
|
163
|
+
}
|
|
164
|
+
})
|
|
157
165
|
}
|
|
158
166
|
|
|
159
167
|
@objc func reload(_ call: CAPPluginCall) {
|
|
@@ -240,6 +248,7 @@ public class LiveUpdatePlugin: CAPPlugin {
|
|
|
240
248
|
config.appId = getConfig().getString("appId", config.appId)
|
|
241
249
|
config.autoDeleteBundles = getConfig().getBoolean("autoDeleteBundles", config.autoDeleteBundles)
|
|
242
250
|
config.enabled = getConfig().getBoolean("enabled", config.enabled)
|
|
251
|
+
config.location = getConfig().getString("location", config.location)
|
|
243
252
|
config.publicKey = getConfig().getString("publicKey", config.publicKey)
|
|
244
253
|
config.readyTimeout = getConfig().getInt("readyTimeout", config.readyTimeout)
|
|
245
254
|
config.resetOnUpdate = getConfig().getBoolean("resetOnUpdate", config.resetOnUpdate)
|
|
@@ -4,6 +4,7 @@ public class LiveUpdatePreferences: NSObject {
|
|
|
4
4
|
private let channelKey = "channel" // DO NOT CHANGE
|
|
5
5
|
private let customIdKey = "customId" // DO NOT CHANGE
|
|
6
6
|
private let lastBundleVersionKey = "lastBundleVersion" // DO NOT CHANGE
|
|
7
|
+
private let previousBundleIdKey = "previousBundleIdKey" // DO NOT CHANGE
|
|
7
8
|
|
|
8
9
|
public func getChannel() -> String? {
|
|
9
10
|
return UserDefaults.standard.string(forKey: applyPrefix(to: channelKey))
|
|
@@ -17,6 +18,10 @@ public class LiveUpdatePreferences: NSObject {
|
|
|
17
18
|
return UserDefaults.standard.string(forKey: applyPrefix(to: lastBundleVersionKey))
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
public func getPreviousBundleId() -> String? {
|
|
22
|
+
return UserDefaults.standard.string(forKey: applyPrefix(to: previousBundleIdKey))
|
|
23
|
+
}
|
|
24
|
+
|
|
20
25
|
public func setChannel(_ value: String?) {
|
|
21
26
|
if let value = value {
|
|
22
27
|
UserDefaults.standard.set(value, forKey: applyPrefix(to: channelKey))
|
|
@@ -36,6 +41,15 @@ public class LiveUpdatePreferences: NSObject {
|
|
|
36
41
|
UserDefaults.standard.synchronize()
|
|
37
42
|
}
|
|
38
43
|
|
|
44
|
+
public func setPreviousBundleId(_ value: String?) {
|
|
45
|
+
if let value = value {
|
|
46
|
+
UserDefaults.standard.set(value, forKey: applyPrefix(to: previousBundleIdKey))
|
|
47
|
+
} else {
|
|
48
|
+
UserDefaults.standard.removeObject(forKey: applyPrefix(to: previousBundleIdKey))
|
|
49
|
+
}
|
|
50
|
+
UserDefaults.standard.synchronize()
|
|
51
|
+
}
|
|
52
|
+
|
|
39
53
|
private func applyPrefix(to key: String) -> String {
|
|
40
54
|
return LiveUpdatePlugin.userDefaultsPrefix + "." + key
|
|
41
55
|
}
|
package/package.json
CHANGED