@capgo/capacitor-updater 8.50.2 → 8.51.1

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.
@@ -40,7 +40,7 @@ public class DelayCondition {
40
40
  public boolean equals(Object o) {
41
41
  if (this == o) return true;
42
42
  if (!(o instanceof DelayCondition that)) return false;
43
- return (getKind() == that.getKind() && Objects.equals(getValue(), that.getValue()));
43
+ return getKind() == that.getKind() && Objects.equals(getValue(), that.getValue());
44
44
  }
45
45
 
46
46
  @Override
@@ -51,6 +51,6 @@ public class DelayCondition {
51
51
  @NonNull
52
52
  @Override
53
53
  public String toString() {
54
- return ("DelayCondition{" + "kind=" + kind + ", value='" + value + '\'' + '}');
54
+ return "DelayCondition{" + "kind=" + kind + ", value='" + value + '\'' + '}';
55
55
  }
56
56
  }
@@ -174,7 +174,9 @@ public class DownloadService extends Worker {
174
174
  }
175
175
 
176
176
  static File resolveManifestBuiltinFile(final File builtinFolder, final String fileName) throws IOException {
177
- return CapgoUpdater.resolvePathInsideDirectory(builtinFolder, fileName);
177
+ final boolean isBrotli = fileName.endsWith(".br");
178
+ final String resolvedName = isBrotli ? fileName.substring(0, fileName.length() - 3) : fileName;
179
+ return CapgoUpdater.resolvePathInsideDirectory(builtinFolder, resolvedName);
178
180
  }
179
181
 
180
182
  private String getInputString(String key, String fallback) {
@@ -642,14 +644,29 @@ public class DownloadService extends Worker {
642
644
  }
643
645
 
644
646
  private void copyFile(File source, File dest) throws IOException {
647
+ final File parent = dest.getParentFile();
648
+ if (parent != null && !parent.exists() && !parent.mkdirs()) {
649
+ throw new IOException("Failed to create parent directory: " + parent.getAbsolutePath());
650
+ }
651
+
652
+ final File tempFile = new File(parent, dest.getName() + ".capgo_tmp");
645
653
  try (
646
654
  FileInputStream inStream = new FileInputStream(source);
647
- FileOutputStream outStream = new FileOutputStream(dest);
655
+ FileOutputStream outStream = new FileOutputStream(tempFile);
648
656
  FileChannel inChannel = inStream.getChannel();
649
657
  FileChannel outChannel = outStream.getChannel()
650
658
  ) {
651
659
  inChannel.transferTo(0, inChannel.size(), outChannel);
652
660
  }
661
+
662
+ try {
663
+ Files.move(tempFile.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
664
+ } catch (IOException e) {
665
+ if (tempFile.exists()) {
666
+ tempFile.delete();
667
+ }
668
+ throw e;
669
+ }
653
670
  }
654
671
 
655
672
  private void downloadAndVerify(
@@ -22,7 +22,7 @@ public class InternalUtils {
22
22
  public static String getPackageName(PackageManager pm, String packageName) {
23
23
  try {
24
24
  PackageInfo pInfo = getPackageInfoInternal(pm, packageName);
25
- return (pInfo != null) ? pInfo.packageName : null;
25
+ return pInfo != null ? pInfo.packageName : null;
26
26
  } catch (PackageManager.NameNotFoundException e) {
27
27
  // Exception is handled internally, and null is returned to indicate the package name could not be retrieved
28
28
  return null;
@@ -13,6 +13,7 @@ import android.hardware.SensorManager;
13
13
  import android.text.Editable;
14
14
  import android.text.TextWatcher;
15
15
  import android.widget.ArrayAdapter;
16
+ import android.widget.Button;
16
17
  import android.widget.EditText;
17
18
  import android.widget.LinearLayout;
18
19
  import android.widget.ListView;
@@ -117,65 +118,8 @@ public class ShakeMenu implements ShakeDetector.Listener, ThreeFingerPinchDetect
117
118
  isShowing = false;
118
119
  return;
119
120
  }
120
- if (Boolean.TRUE.equals(plugin.shakeChannelSelectorEnabled)) {
121
- showCombinedPreviewMenu();
122
- return;
123
- }
124
- String appName = activity.getPackageManager().getApplicationLabel(activity.getApplicationInfo()).toString();
125
- String title = "Preview " + appName + " Menu";
126
- String message = "Reload, switch, or leave the current preview.";
127
- List<String> actions = new ArrayList<>();
128
- actions.add("Reload preview");
129
- if (plugin.previewMenuPreviews().length() > 0) {
130
- actions.add("Switch preview");
131
- }
132
- actions.add("Leave test app");
133
- final boolean[] openingNestedSelector = { false };
134
- final boolean[] previewActionRunning = { false };
135
121
 
136
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
137
- builder.setTitle(title);
138
- builder.setMessage(message);
139
- builder.setItems(actions.toArray(new String[0]), (dialogInterface, which) -> {
140
- AlertDialog dialog = (AlertDialog) dialogInterface;
141
- String action = actions.get(which);
142
- if ("Reload preview".equals(action)) {
143
- previewActionRunning[0] = true;
144
- logger.info("Reloading webview");
145
- runPreviewMenuAction(dialog, "Could not reload the test app.", "Error reloading test app: ", () ->
146
- plugin.reloadPreviewSessionFromShakeMenu()
147
- );
148
- } else if ("Switch preview".equals(action)) {
149
- openingNestedSelector[0] = true;
150
- dialog.dismiss();
151
- showPreviewSelector();
152
- } else {
153
- previewActionRunning[0] = true;
154
- runPreviewMenuAction(dialog, "Could not leave the test app.", "Error leaving test app: ", () ->
155
- plugin.leavePreviewSessionFromShakeMenu()
156
- );
157
- }
158
- });
159
-
160
- // Cancel button
161
- builder.setNegativeButton(
162
- "Close menu",
163
- new DialogInterface.OnClickListener() {
164
- public void onClick(DialogInterface dialog, int id) {
165
- logger.info("Shake menu cancelled");
166
- dialog.dismiss();
167
- isShowing = false;
168
- }
169
- }
170
- );
171
-
172
- AlertDialog dialog = builder.create();
173
- dialog.setOnDismissListener((dialogInterface) -> {
174
- if (!openingNestedSelector[0] && !previewActionRunning[0]) {
175
- isShowing = false;
176
- }
177
- });
178
- dialog.show();
122
+ showPreviewActionsMenu(Boolean.TRUE.equals(plugin.shakeChannelSelectorEnabled));
179
123
  } catch (Exception e) {
180
124
  logger.error("Error showing shake menu: " + e.getMessage());
181
125
  isShowing = false;
@@ -183,65 +127,95 @@ public class ShakeMenu implements ShakeDetector.Listener, ThreeFingerPinchDetect
183
127
  });
184
128
  }
185
129
 
186
- private void showCombinedPreviewMenu() {
187
- try {
188
- String appName = activity.getPackageManager().getApplicationLabel(activity.getApplicationInfo()).toString();
189
- String title = "Preview " + appName + " Menu";
190
- String message = "Reload, switch, or leave the current preview.";
191
- List<String> actions = new ArrayList<>();
192
- actions.add("Reload preview");
193
- if (plugin.previewMenuPreviews().length() > 0) {
194
- actions.add("Switch preview");
195
- }
196
- actions.add("Leave test app");
197
- actions.add("Switch channel");
198
- final boolean[] openingNestedSelector = { false };
199
- final boolean[] previewActionRunning = { false };
130
+ private void showPreviewActionsMenu(boolean includeChannelSelector) {
131
+ String appName = activity.getPackageManager().getApplicationLabel(activity.getApplicationInfo()).toString();
132
+ String title = "Preview " + appName + " Menu";
133
+ String message = "Reload, switch, or leave the current preview.";
134
+ final boolean[] openingNestedSelector = { false };
135
+ final boolean[] previewActionRunning = { false };
136
+ final AlertDialog[] dialogRef = { null };
137
+ List<Button> buttons = new ArrayList<>();
138
+
139
+ LinearLayout layout = new LinearLayout(activity);
140
+ layout.setOrientation(LinearLayout.VERTICAL);
141
+ int horizontalPadding = dpToPx(16);
142
+ int verticalPadding = dpToPx(8);
143
+ layout.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding);
144
+
145
+ addPreviewMenuButton(layout, buttons, "Reload preview", () -> {
146
+ AlertDialog dialog = dialogRef[0];
147
+ previewActionRunning[0] = true;
148
+ setPreviewMenuButtonsEnabled(buttons, false);
149
+ logger.info("Reloading webview");
150
+ runPreviewMenuAction(dialog, "Could not reload the test app.", "Error reloading test app: ", () ->
151
+ plugin.reloadPreviewSessionFromShakeMenu()
152
+ );
153
+ });
200
154
 
201
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
202
- builder.setTitle(title);
203
- builder.setMessage(message);
204
- builder.setItems(actions.toArray(new String[0]), (dialogInterface, which) -> {
205
- AlertDialog dialog = (AlertDialog) dialogInterface;
206
- String action = actions.get(which);
207
- if ("Reload preview".equals(action)) {
208
- previewActionRunning[0] = true;
209
- logger.info("Reloading webview");
210
- runPreviewMenuAction(dialog, "Could not reload the test app.", "Error reloading test app: ", () ->
211
- plugin.reloadPreviewSessionFromShakeMenu()
212
- );
213
- } else if ("Leave test app".equals(action)) {
214
- previewActionRunning[0] = true;
215
- runPreviewMenuAction(dialog, "Could not leave the test app.", "Error leaving test app: ", () ->
216
- plugin.leavePreviewSessionFromShakeMenu()
217
- );
218
- } else if ("Switch preview".equals(action)) {
219
- openingNestedSelector[0] = true;
220
- dialog.dismiss();
221
- showPreviewSelector();
222
- } else {
223
- openingNestedSelector[0] = true;
224
- dialog.dismiss();
225
- showChannelSelector();
226
- }
227
- });
228
- builder.setNegativeButton("Close menu", (dialog, id) -> {
229
- logger.info("Shake menu cancelled");
155
+ if (plugin.previewMenuPreviews().length() > 0) {
156
+ addPreviewMenuButton(layout, buttons, "Switch preview", () -> {
157
+ AlertDialog dialog = dialogRef[0];
158
+ openingNestedSelector[0] = true;
230
159
  dialog.dismiss();
231
- isShowing = false;
160
+ showPreviewSelector();
232
161
  });
162
+ }
233
163
 
234
- AlertDialog dialog = builder.create();
235
- dialog.setOnDismissListener((dialogInterface) -> {
236
- if (!openingNestedSelector[0] && !previewActionRunning[0]) {
237
- isShowing = false;
238
- }
164
+ if (includeChannelSelector) {
165
+ addPreviewMenuButton(layout, buttons, "Switch channel", () -> {
166
+ AlertDialog dialog = dialogRef[0];
167
+ openingNestedSelector[0] = true;
168
+ dialog.dismiss();
169
+ showChannelSelector();
239
170
  });
240
- dialog.show();
241
- } catch (Exception e) {
242
- logger.error("Error showing combined shake menu: " + e.getMessage());
243
- isShowing = false;
244
171
  }
172
+
173
+ addPreviewMenuButton(layout, buttons, "Leave test app", () -> {
174
+ AlertDialog dialog = dialogRef[0];
175
+ previewActionRunning[0] = true;
176
+ setPreviewMenuButtonsEnabled(buttons, false);
177
+ runPreviewMenuAction(dialog, "Could not leave the test app.", "Error leaving test app: ", () ->
178
+ plugin.leavePreviewSessionFromShakeMenu()
179
+ );
180
+ });
181
+
182
+ addPreviewMenuButton(layout, buttons, "Close menu", () -> {
183
+ AlertDialog dialog = dialogRef[0];
184
+ if (dialog != null) {
185
+ logger.info("Shake menu cancelled");
186
+ dialog.dismiss();
187
+ isShowing = false;
188
+ }
189
+ });
190
+
191
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
192
+ builder.setTitle(title);
193
+ builder.setMessage(message);
194
+ builder.setView(layout);
195
+
196
+ AlertDialog dialog = builder.create();
197
+ dialogRef[0] = dialog;
198
+ dialog.setOnDismissListener((dialogInterface) -> {
199
+ if (!openingNestedSelector[0] && !previewActionRunning[0]) {
200
+ isShowing = false;
201
+ }
202
+ });
203
+ dialog.show();
204
+ }
205
+
206
+ private void addPreviewMenuButton(LinearLayout layout, List<Button> buttons, String title, Runnable action) {
207
+ Button button = new Button(activity);
208
+ button.setAllCaps(false);
209
+ button.setText(title);
210
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
211
+ LinearLayout.LayoutParams.MATCH_PARENT,
212
+ LinearLayout.LayoutParams.WRAP_CONTENT
213
+ );
214
+ params.setMargins(0, 0, 0, dpToPx(8));
215
+ button.setLayoutParams(params);
216
+ button.setOnClickListener((view) -> action.run());
217
+ buttons.add(button);
218
+ layout.addView(button);
245
219
  }
246
220
 
247
221
  private void runPreviewMenuAction(AlertDialog dialog, String failureMessage, String errorPrefix, PreviewMenuAction action) {
@@ -262,10 +236,10 @@ public class ShakeMenu implements ShakeDetector.Listener, ThreeFingerPinchDetect
262
236
  }).start();
263
237
  }
264
238
 
265
- private void setPreviewMenuButtonsEnabled(AlertDialog dialog, boolean enabled) {
266
- dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(enabled);
267
- dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setEnabled(enabled);
268
- dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setEnabled(enabled);
239
+ private void setPreviewMenuButtonsEnabled(List<Button> buttons, boolean enabled) {
240
+ for (Button button : buttons) {
241
+ button.setEnabled(enabled);
242
+ }
269
243
  }
270
244
 
271
245
  private void showPreviewSelector() {
@@ -299,7 +273,7 @@ public class ShakeMenu implements ShakeDetector.Listener, ThreeFingerPinchDetect
299
273
  String name = preview.optString("name", "");
300
274
  JSObject bundle = preview.getJSObject("bundle");
301
275
  String version = bundle == null ? "" : bundle.optString("version", "");
302
- String label = !name.isEmpty() ? name : (!version.isEmpty() ? version : preview.optString("id", "Preview"));
276
+ String label = !name.isEmpty() ? name : !version.isEmpty() ? version : preview.optString("id", "Preview");
303
277
  if (preview.optBoolean("isActive", false)) {
304
278
  label += " (current)";
305
279
  }
package/dist/docs.json CHANGED
@@ -156,7 +156,7 @@
156
156
  "text": "{Error} If the download fails or the bundle is invalid."
157
157
  }
158
158
  ],
159
- "docs": "Download a new bundle from the provided URL for later installation.\n\nThe downloaded bundle is stored locally but not activated. To use it:\n- Call {@link next} to set it for installation on next app backgrounding/restart\n- Call {@link set} to activate it immediately (destroys current JavaScript context)\n\nThe URL should point to a zip file containing either:\n- Your app files directly in the zip root, or\n- A single folder containing all your app files\n\nThe bundle must include an `index.html` file at the root level.\n\nFor encrypted bundles, provide the `sessionKey` and `checksum` parameters.\nFor multi-file delta updates, provide the `manifest` array.\n\n**Android Background Runner note:** `@capacitor/background-runner` loads its\nconfigured runner script from native APK assets. Live updates cannot replace\nthat runner script. Keep it stable across OTA updates and ship a native app\nupdate when the runner code changes.",
159
+ "docs": "Download a new bundle from the provided URL for later installation.\n\nThe downloaded bundle is stored locally but not activated. To use it:\n- Call {@link next} to set it for installation on next app backgrounding/restart\n- Call {@link set} to activate it immediately (destroys current JavaScript context)\n\nThe URL should point to a zip file containing either:\n- Your app files directly in the zip root, or\n- A single folder containing all your app files\n\nThe bundle must include an `index.html` file at the root level.\n\nFor encrypted bundles, provide the `sessionKey` and `checksum` parameters.\nFor multi-file delta updates, provide the `manifest` array.\n\n**Android Background Runner note:** `@capacitor/background-runner` loads its\nconfigured runner script from native APK assets. Live updates cannot replace\nthat runner script. Keep it stable across OTA updates and ship a native app\nupdate when the runner code changes. When a bundle switch happens, Capacitor\nUpdater cancels and reschedules configured Background Runner WorkManager jobs\nand syncs the bundled runner script into native `public/` storage when present.",
160
160
  "complexTypes": [
161
161
  "BundleInfo",
162
162
  "DownloadOptions"
@@ -4468,6 +4468,14 @@
4468
4468
  {
4469
4469
  "text": "'downloading'",
4470
4470
  "complexTypes": []
4471
+ },
4472
+ {
4473
+ "text": "'deleted'",
4474
+ "complexTypes": []
4475
+ },
4476
+ {
4477
+ "text": "'deleting'",
4478
+ "complexTypes": []
4471
4479
  }
4472
4480
  ]
4473
4481
  },
@@ -4623,7 +4631,7 @@
4623
4631
  "name": "example"
4624
4632
  }
4625
4633
  ],
4626
- "docs": "Configure how the plugin checks for, downloads, and applies live updates.\n\nThe plugin checks for updates when the app moves to the foreground and, if\n{@link periodCheckDelay} is set, on a repeating timer while the app stays open.\n\nBoolean values keep their existing behavior:\n- `true`: Same as `\"atBackground\"`.\n- `false`: Same as `\"off\"`.\n\nString values merge the previous Auto Update and Direct Update configuration:\n- `\"off\"`: Disable automatic update checks.\n- `\"atBackground\"`: Check and download automatically on each foreground check, then apply the update the next time the app moves to background.\n- `\"atInstall\"`: Apply immediately only after a fresh install or native app store update; otherwise use `\"atBackground\"` behavior.\n- `\"onLaunch\"`: Apply immediately only when the app is brought to the foreground from a killed state (cold start). After that first check, fall back to `\"atBackground\"` behavior.\n- `\"always\"`: Check on every foreground transition and apply immediately whenever an update is available.\n- `\"onlyDownload\"`: Check and download automatically, emit `updateAvailable`, and never set the next bundle or apply an update automatically.\n\nOnly available for Android and iOS.",
4634
+ "docs": "Configure how the plugin checks for, downloads, and applies live updates.\n\nThe plugin checks for updates when the app moves to the foreground. When\n{@link periodCheckDelay} is greater than 0, it also checks on a repeating timer\nwhile the app stays open.\n\nBoolean values keep their existing behavior:\n- `true`: Same as `\"atBackground\"`.\n- `false`: Same as `\"off\"`.\n\nString values merge the previous Auto Update and Direct Update configuration:\n- `\"off\"`: Disable automatic update checks.\n- `\"atBackground\"`: Check and download automatically on each foreground check, then apply the update the next time the app moves to background.\n- `\"atInstall\"`: Apply immediately only after a fresh install or native app store update; otherwise use `\"atBackground\"` behavior.\n- `\"onLaunch\"`: Apply immediately only when the app is brought to the foreground from a killed state (cold start). After that first check, fall back to `\"atBackground\"` behavior.\n- `\"always\"`: Check on every foreground transition and apply immediately whenever an update is available.\n- `\"onlyDownload\"`: Check and download automatically, emit `updateAvailable`, and never set the next bundle or apply an update automatically.\n\nOnly available for Android and iOS.",
4627
4635
  "complexTypes": [],
4628
4636
  "type": "boolean | 'always' | 'off' | 'atBackground' | 'atInstall' | 'onLaunch' | 'onlyDownload' | undefined"
4629
4637
  },
@@ -4687,7 +4695,7 @@
4687
4695
  "name": "example"
4688
4696
  }
4689
4697
  ],
4690
- "docs": "Configure the URL / endpoint to which update statistics are sent.\n\nOnly available for Android and iOS. Set to \"\" to disable stats reporting.\nNative stats include update lifecycle events, app health signals such as crashes,\nAndroid ANRs, low-memory exits, iOS memory warnings, and WebView health signals\nsuch as JavaScript errors, unhandled promise rejections, resource load failures,\nWebView renderer exits, and unclean WebView restarts when available.",
4698
+ "docs": "Configure the URL / endpoint to which update statistics are sent.\n\nOnly available for Android and iOS. Set to \"\" to disable stats reporting.\nNative stats include update lifecycle events, app health signals such as crashes,\nAndroid ANRs, low-memory exits, iOS memory warnings, and WebView health signals\nsuch as JavaScript errors, unhandled promise rejections, resource load failures,\nWebView renderer exits, unclean WebView restarts, app launch readiness timing,\nand WebView load milestones when available.",
4691
4699
  "complexTypes": [],
4692
4700
  "type": "string | undefined"
4693
4701
  },
@@ -4727,7 +4735,7 @@
4727
4735
  "name": "directUpdate",
4728
4736
  "tags": [
4729
4737
  {
4730
- "text": "Use {@link PluginsConfig.CapacitorUpdater.autoUpdate} string modes instead.\nWorks well for apps less than 10MB and with uploads done using --delta flag.\nZip or apps more than 10MB will be relatively slow for users to update.\n- false: Never do direct updates (use default behavior: download on foreground check, apply when backgrounded)\n- atInstall: Direct update only after app install or native app store update, otherwise act as directUpdate = false\n- onLaunch: Direct update only when the app is brought to the foreground from a killed state, otherwise act as directUpdate = false\n- always: Direct update on every foreground check whenever an update is available, never act as directUpdate = false\n- true: (deprecated) Same as \"always\" for backward compatibility\n\nActivate this flag will automatically make the CLI upload delta in CICD envs and will ask for confirmation in local uploads.\nOnly available for Android and iOS.",
4738
+ "text": "Use {@link PluginsConfig.CapacitorUpdater.autoUpdate} string modes instead.\nWorks well for apps less than 10MB and with uploads done using --delta flag.\nZip or apps more than 10MB will be relatively slow for users to update.\n- false: Never do direct updates\n- atInstall: Same as `\"atInstall\"` for {@link autoUpdate}\n- onLaunch: Same as `\"onLaunch\"` for {@link autoUpdate}\n- always: Same as `\"always\"` for {@link autoUpdate}\n- true: (deprecated) Same as \"always\" for backward compatibility\n\nActivate this flag will automatically make the CLI upload delta in CICD envs and will ask for confirmation in local uploads.\nOnly available for Android and iOS.",
4731
4739
  "name": "deprecated"
4732
4740
  },
4733
4741
  {
@@ -4807,7 +4815,7 @@
4807
4815
  "name": "example"
4808
4816
  }
4809
4817
  ],
4810
- "docs": "Configure the delay period for period update check. the unit is in seconds.\n\nOnly available for Android and iOS.\nCannot be less than 600 seconds (10 minutes).",
4818
+ "docs": "Configure the interval in seconds for repeating update checks while the app stays open.\nForeground checks still run when this is 0. Values below 600 are normalized to 600.\n\nOnly available for Android and iOS.\nCannot be less than 600 seconds (10 minutes).",
4811
4819
  "complexTypes": [],
4812
4820
  "type": "number | undefined"
4813
4821
  },
@@ -44,8 +44,9 @@ declare module '@capacitor/cli' {
44
44
  /**
45
45
  * Configure how the plugin checks for, downloads, and applies live updates.
46
46
  *
47
- * The plugin checks for updates when the app moves to the foreground and, if
48
- * {@link periodCheckDelay} is set, on a repeating timer while the app stays open.
47
+ * The plugin checks for updates when the app moves to the foreground. When
48
+ * {@link periodCheckDelay} is greater than 0, it also checks on a repeating timer
49
+ * while the app stays open.
49
50
  *
50
51
  * Boolean values keep their existing behavior:
51
52
  * - `true`: Same as `"atBackground"`.
@@ -99,7 +100,8 @@ declare module '@capacitor/cli' {
99
100
  * Native stats include update lifecycle events, app health signals such as crashes,
100
101
  * Android ANRs, low-memory exits, iOS memory warnings, and WebView health signals
101
102
  * such as JavaScript errors, unhandled promise rejections, resource load failures,
102
- * WebView renderer exits, and unclean WebView restarts when available.
103
+ * WebView renderer exits, unclean WebView restarts, app launch readiness timing,
104
+ * and WebView load milestones when available.
103
105
  *
104
106
  * @default https://plugin.capgo.app/stats
105
107
  * @example https://example.com/api/stats
@@ -130,10 +132,10 @@ declare module '@capacitor/cli' {
130
132
  * @deprecated Use {@link PluginsConfig.CapacitorUpdater.autoUpdate} string modes instead.
131
133
  * Works well for apps less than 10MB and with uploads done using --delta flag.
132
134
  * Zip or apps more than 10MB will be relatively slow for users to update.
133
- * - false: Never do direct updates (use default behavior: download on foreground check, apply when backgrounded)
134
- * - atInstall: Direct update only after app install or native app store update, otherwise act as directUpdate = false
135
- * - onLaunch: Direct update only when the app is brought to the foreground from a killed state, otherwise act as directUpdate = false
136
- * - always: Direct update on every foreground check whenever an update is available, never act as directUpdate = false
135
+ * - false: Never do direct updates
136
+ * - atInstall: Same as `"atInstall"` for {@link autoUpdate}
137
+ * - onLaunch: Same as `"onLaunch"` for {@link autoUpdate}
138
+ * - always: Same as `"always"` for {@link autoUpdate}
137
139
  * - true: (deprecated) Same as "always" for backward compatibility
138
140
  *
139
141
  * Activate this flag will automatically make the CLI upload delta in CICD envs and will ask for confirmation in local uploads.
@@ -181,7 +183,8 @@ declare module '@capacitor/cli' {
181
183
  */
182
184
  autoSplashscreenTimeout?: number;
183
185
  /**
184
- * Configure the delay period for period update check. the unit is in seconds.
186
+ * Configure the interval in seconds for repeating update checks while the app stays open.
187
+ * Foreground checks still run when this is 0. Values below 600 are normalized to 600.
185
188
  *
186
189
  * Only available for Android and iOS.
187
190
  * Cannot be less than 600 seconds (10 minutes).
@@ -485,7 +488,9 @@ export interface CapacitorUpdaterPlugin {
485
488
  * **Android Background Runner note:** `@capacitor/background-runner` loads its
486
489
  * configured runner script from native APK assets. Live updates cannot replace
487
490
  * that runner script. Keep it stable across OTA updates and ship a native app
488
- * update when the runner code changes.
491
+ * update when the runner code changes. When a bundle switch happens, Capacitor
492
+ * Updater cancels and reschedules configured Background Runner WorkManager jobs
493
+ * and syncs the bundled runner script into native `public/` storage when present.
489
494
  *
490
495
  * @example
491
496
  * const bundle = await CapacitorUpdater.download({
@@ -1599,7 +1604,7 @@ export interface CapacitorUpdaterPlugin {
1599
1604
  * success: The bundle has been downloaded and is ready to be **SET** as the next bundle.
1600
1605
  * error: The bundle has failed to download.
1601
1606
  */
1602
- export type BundleStatus = 'success' | 'error' | 'pending' | 'downloading';
1607
+ export type BundleStatus = 'success' | 'error' | 'pending' | 'downloading' | 'deleted' | 'deleting';
1603
1608
  export type DelayUntilNext = 'background' | 'kill' | 'nativeVersion' | 'date';
1604
1609
  /**
1605
1610
  * Classification for update-check responses that do not provide a downloadable bundle.