codeplay-common 4.9.3 → 4.9.4

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.
@@ -1,3 +1,4 @@
1
+ // Version 6.5: recreate failed WebViews, defer background recovery, and suppress foreground recovery toasts.
1
2
  const fs = require('fs');
2
3
  const path = require('path');
3
4
  const plist = require('plist');
@@ -1191,6 +1192,8 @@ if (!fs.existsSync(bridgeWebViewClientFilePath)) {
1191
1192
  }
1192
1193
 
1193
1194
  let fileContent = fs.readFileSync(bridgeWebViewClientFilePath, 'utf8');
1195
+ const bridgeWebViewLineEnding = fileContent.includes('\r\n') ? '\r\n' : '\n';
1196
+ fileContent = fileContent.replace(/\r\n/g, '\n');
1194
1197
 
1195
1198
  // Define old and new code
1196
1199
  const oldCodeStart = `@Override
@@ -1208,7 +1211,8 @@ const oldCodeStart = `@Override
1208
1211
  return result;
1209
1212
  }`;
1210
1213
 
1211
- const newCode = `@Override
1214
+ // Match the previous patch so existing projects migrate without reinstalling Capacitor.
1215
+ const legacyReloadCode = `@Override
1212
1216
  public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) {
1213
1217
  super.onRenderProcessGone(view, detail);
1214
1218
 
@@ -1244,15 +1248,104 @@ const newCode = `@Override
1244
1248
  return result;
1245
1249
  }`;
1246
1250
 
1247
- // Step 1: Update method if needed
1251
+ const newCode = `// Codeplay WebView renderer recovery (before-build 6.5).
1252
+ private boolean codeplayRendererRecoveryPending = false;
1253
+ private static long codeplayRendererRecoveryWindowStart = -1L;
1254
+ private static int codeplayRendererRecoveryCount = 0;
1255
+
1256
+ @Override
1257
+ public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) {
1258
+ if (codeplayRendererRecoveryPending) return true;
1259
+
1260
+ boolean handled = false;
1261
+ List<WebViewListener> webViewListeners = bridge.getWebViewListeners();
1262
+ if (webViewListeners != null) {
1263
+ for (WebViewListener listener : webViewListeners) {
1264
+ handled = listener.onRenderProcessGone(view, detail) || handled;
1265
+ }
1266
+ }
1267
+ if (handled) return true;
1268
+
1269
+ codeplayRendererRecoveryPending = true;
1270
+ final androidx.appcompat.app.AppCompatActivity activity = bridge.getActivity();
1271
+ final boolean wasInForeground = activity != null && activity.getLifecycle()
1272
+ .getCurrentState().isAtLeast(androidx.lifecycle.Lifecycle.State.STARTED);
1273
+
1274
+ // A terminated renderer's WebView must never be loaded or reloaded again.
1275
+ if (view.getParent() instanceof android.view.ViewGroup) {
1276
+ ((android.view.ViewGroup) view.getParent()).removeView(view);
1277
+ }
1278
+ view.destroy();
1279
+
1280
+ if (activity == null || activity.isFinishing() || activity.isDestroyed()) return true;
1281
+
1282
+ final android.os.Handler mainHandler = new android.os.Handler(android.os.Looper.getMainLooper());
1283
+ final Runnable recover = () -> {
1284
+ if (activity.isFinishing() || activity.isDestroyed()) return;
1285
+
1286
+ // Static counters survive Activity recreation and prevent an automatic restart loop.
1287
+ long now = android.os.SystemClock.elapsedRealtime();
1288
+ if (codeplayRendererRecoveryWindowStart < 0L ||
1289
+ now - codeplayRendererRecoveryWindowStart >= 60000L) {
1290
+ codeplayRendererRecoveryWindowStart = now;
1291
+ codeplayRendererRecoveryCount = 0;
1292
+ }
1293
+
1294
+ if (codeplayRendererRecoveryCount >= 3) {
1295
+ new android.app.AlertDialog.Builder(activity)
1296
+ .setTitle("Unable to restore the app")
1297
+ .setMessage("The app could not recover automatically. Please try again.")
1298
+ .setCancelable(false)
1299
+ .setPositiveButton("Try again", (dialog, which) -> {
1300
+ codeplayRendererRecoveryWindowStart = -1L;
1301
+ codeplayRendererRecoveryCount = 0;
1302
+ if (!activity.isFinishing() && !activity.isDestroyed()) activity.recreate();
1303
+ })
1304
+ .setNegativeButton("Close", (dialog, which) -> activity.finish())
1305
+ .show();
1306
+ return;
1307
+ }
1308
+
1309
+ codeplayRendererRecoveryCount++;
1310
+ if (!wasInForeground) {
1311
+ Toast.makeText(activity.getApplicationContext(), "Restoring your app…", Toast.LENGTH_SHORT).show();
1312
+ }
1313
+ activity.recreate();
1314
+ };
1315
+
1316
+ if (wasInForeground) {
1317
+ mainHandler.post(recover);
1318
+ } else {
1319
+ // Do not allocate another renderer while the app is hidden and memory may still be low.
1320
+ activity.getLifecycle().addObserver(new androidx.lifecycle.LifecycleEventObserver() {
1321
+ @Override
1322
+ public void onStateChanged(
1323
+ androidx.lifecycle.LifecycleOwner source,
1324
+ androidx.lifecycle.Lifecycle.Event event
1325
+ ) {
1326
+ if (event == androidx.lifecycle.Lifecycle.Event.ON_RESUME) {
1327
+ source.getLifecycle().removeObserver(this);
1328
+ mainHandler.post(recover);
1329
+ } else if (event == androidx.lifecycle.Lifecycle.Event.ON_DESTROY) {
1330
+ source.getLifecycle().removeObserver(this);
1331
+ }
1332
+ }
1333
+ });
1334
+ }
1335
+ return true;
1336
+ }`;
1337
+
1338
+ // Step 1: Update the stock method or migrate the previous reload-based patch.
1248
1339
  let updated = false;
1249
1340
 
1250
- if (fileContent.includes(oldCodeStart)) {
1251
- console.log('✅ Found old onRenderProcessGone method. Replacing it...');
1341
+ if (fileContent.includes(newCode)) {
1342
+ console.log('ℹ️ Method already updated. No changes needed in "BridgeWebViewClient.java".');
1343
+ } else if (fileContent.includes(legacyReloadCode)) {
1344
+ fileContent = fileContent.replace(legacyReloadCode, newCode);
1345
+ updated = true;
1346
+ } else if (fileContent.includes(oldCodeStart)) {
1252
1347
  fileContent = fileContent.replace(oldCodeStart, newCode);
1253
1348
  updated = true;
1254
- } else if (fileContent.includes(newCode)) {
1255
- console.log('ℹ️ Method already updated. No changes needed in "BridgeWebViewClient.java".');
1256
1349
  } else {
1257
1350
  console.error('❌ Error: Neither old nor new code found. Unexpected content.');
1258
1351
  process.exit(1);
@@ -1280,7 +1373,7 @@ if (!fileContent.includes(importToast)) {
1280
1373
 
1281
1374
  // Step 3: Save if updated
1282
1375
  if (updated) {
1283
- fs.writeFileSync(bridgeWebViewClientFilePath, fileContent, 'utf8');
1376
+ fs.writeFileSync(bridgeWebViewClientFilePath, fileContent.replace(/\n/g, bridgeWebViewLineEnding), 'utf8');
1284
1377
  console.log('✅ File updated successfully.');
1285
1378
  } else {
1286
1379
  console.log('ℹ️ No changes needed.');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeplay-common",
3
- "version": "4.9.3",
3
+ "version": "4.9.4",
4
4
  "description": "Common build scripts and files",
5
5
  "scripts": {
6
6
  "postinstall": "node scripts/sync-files.js",