@capgo/capacitor-updater 7.15.2 → 7.16.0
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/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +11 -1
- package/android/src/main/java/ee/forgr/capacitor_updater/CapgoUpdater.java +64 -2
- package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +8 -1
- package/ios/Sources/CapacitorUpdaterPlugin/CapgoUpdater.swift +36 -0
- package/package.json +1 -1
|
@@ -33,9 +33,11 @@ import java.net.URL;
|
|
|
33
33
|
import java.util.ArrayList;
|
|
34
34
|
import java.util.Arrays;
|
|
35
35
|
import java.util.Date;
|
|
36
|
+
import java.util.HashSet;
|
|
36
37
|
import java.util.List;
|
|
37
38
|
import java.util.Map;
|
|
38
39
|
import java.util.Objects;
|
|
40
|
+
import java.util.Set;
|
|
39
41
|
import java.util.Timer;
|
|
40
42
|
import java.util.TimerTask;
|
|
41
43
|
import java.util.UUID;
|
|
@@ -58,7 +60,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
58
60
|
private static final String statsUrlDefault = "https://plugin.capgo.app/stats";
|
|
59
61
|
private static final String channelUrlDefault = "https://plugin.capgo.app/channel_self";
|
|
60
62
|
|
|
61
|
-
private final String PLUGIN_VERSION = "7.
|
|
63
|
+
private final String PLUGIN_VERSION = "7.16.0";
|
|
62
64
|
private static final String DELAY_CONDITION_PREFERENCES = "";
|
|
63
65
|
|
|
64
66
|
private SharedPreferences.Editor editor;
|
|
@@ -443,6 +445,14 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
443
445
|
logger.error("Failed to delete: " + bundle.getId() + " " + e.getMessage());
|
|
444
446
|
}
|
|
445
447
|
}
|
|
448
|
+
final List<BundleInfo> storedBundles = this.implementation.list(true);
|
|
449
|
+
final Set<String> allowedIds = new HashSet<>();
|
|
450
|
+
for (final BundleInfo info : storedBundles) {
|
|
451
|
+
if (info != null && info.getId() != null && !info.getId().isEmpty()) {
|
|
452
|
+
allowedIds.add(info.getId());
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
this.implementation.cleanupDownloadDirectories(allowedIds);
|
|
446
456
|
}
|
|
447
457
|
this.editor.putString("LatestNativeBuildVersion", this.currentBuildVersion);
|
|
448
458
|
this.editor.apply();
|
|
@@ -32,6 +32,7 @@ import java.util.Iterator;
|
|
|
32
32
|
import java.util.List;
|
|
33
33
|
import java.util.Map;
|
|
34
34
|
import java.util.Objects;
|
|
35
|
+
import java.util.Set;
|
|
35
36
|
import java.util.concurrent.CompletableFuture;
|
|
36
37
|
import java.util.concurrent.ConcurrentHashMap;
|
|
37
38
|
import java.util.concurrent.TimeUnit;
|
|
@@ -354,6 +355,7 @@ public class CapgoUpdater {
|
|
|
354
355
|
Boolean isManifest
|
|
355
356
|
) {
|
|
356
357
|
File downloaded = null;
|
|
358
|
+
File extractedDir = null;
|
|
357
359
|
String checksum = "";
|
|
358
360
|
|
|
359
361
|
try {
|
|
@@ -385,6 +387,9 @@ public class CapgoUpdater {
|
|
|
385
387
|
}
|
|
386
388
|
// Remove the decryption for manifest downloads
|
|
387
389
|
} catch (Exception e) {
|
|
390
|
+
if (!isManifest) {
|
|
391
|
+
safeDelete(downloaded);
|
|
392
|
+
}
|
|
388
393
|
final Boolean res = this.delete(id);
|
|
389
394
|
if (!res) {
|
|
390
395
|
logger.info("Double error, cannot cleanup: " + version);
|
|
@@ -400,10 +405,10 @@ public class CapgoUpdater {
|
|
|
400
405
|
|
|
401
406
|
try {
|
|
402
407
|
if (!isManifest) {
|
|
403
|
-
|
|
408
|
+
extractedDir = this.unzip(id, downloaded, this.randomString());
|
|
404
409
|
this.notifyDownload(id, 91);
|
|
405
410
|
final String idName = bundleDirectory + "/" + id;
|
|
406
|
-
this.flattenAssets(
|
|
411
|
+
this.flattenAssets(extractedDir, idName);
|
|
407
412
|
} else {
|
|
408
413
|
this.notifyDownload(id, 91);
|
|
409
414
|
final String idName = bundleDirectory + "/" + id;
|
|
@@ -431,6 +436,10 @@ public class CapgoUpdater {
|
|
|
431
436
|
}
|
|
432
437
|
}
|
|
433
438
|
} catch (IOException e) {
|
|
439
|
+
if (!isManifest) {
|
|
440
|
+
safeDelete(extractedDir);
|
|
441
|
+
safeDelete(downloaded);
|
|
442
|
+
}
|
|
434
443
|
e.printStackTrace();
|
|
435
444
|
final Map<String, Object> ret = new HashMap<>();
|
|
436
445
|
ret.put("version", version);
|
|
@@ -438,6 +447,9 @@ public class CapgoUpdater {
|
|
|
438
447
|
CapgoUpdater.this.sendStats("download_fail");
|
|
439
448
|
return false;
|
|
440
449
|
}
|
|
450
|
+
if (!isManifest) {
|
|
451
|
+
safeDelete(downloaded);
|
|
452
|
+
}
|
|
441
453
|
return true;
|
|
442
454
|
}
|
|
443
455
|
|
|
@@ -455,6 +467,56 @@ public class CapgoUpdater {
|
|
|
455
467
|
}
|
|
456
468
|
}
|
|
457
469
|
|
|
470
|
+
public void cleanupDownloadDirectories(final Set<String> allowedIds) {
|
|
471
|
+
if (this.documentsDir == null) {
|
|
472
|
+
logger.warn("Documents directory is null, skipping download cleanup");
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
final File bundleRoot = new File(this.documentsDir, bundleDirectory);
|
|
477
|
+
if (!bundleRoot.exists() || !bundleRoot.isDirectory()) {
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
final File[] entries = bundleRoot.listFiles();
|
|
482
|
+
if (entries != null) {
|
|
483
|
+
for (final File entry : entries) {
|
|
484
|
+
if (!entry.isDirectory()) {
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
final String id = entry.getName();
|
|
489
|
+
|
|
490
|
+
if (allowedIds != null && allowedIds.contains(id)) {
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
try {
|
|
495
|
+
this.deleteDirectory(entry);
|
|
496
|
+
this.removeBundleInfo(id);
|
|
497
|
+
logger.info("Deleted orphan bundle directory: " + id);
|
|
498
|
+
} catch (IOException e) {
|
|
499
|
+
logger.error("Failed to delete orphan bundle directory: " + id + " " + e.getMessage());
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
private void safeDelete(final File target) {
|
|
506
|
+
if (target == null || !target.exists()) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
try {
|
|
510
|
+
if (target.isDirectory()) {
|
|
511
|
+
this.deleteDirectory(target);
|
|
512
|
+
} else if (!target.delete()) {
|
|
513
|
+
logger.warn("Failed to delete file: " + target.getAbsolutePath());
|
|
514
|
+
}
|
|
515
|
+
} catch (IOException cleanupError) {
|
|
516
|
+
logger.warn("Cleanup failed for " + target.getAbsolutePath() + ": " + cleanupError.getMessage());
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
458
520
|
private void setCurrentBundle(final File bundle) {
|
|
459
521
|
this.editor.putString(this.CAP_SERVER_PATH, bundle.getPath());
|
|
460
522
|
logger.info("Current bundle set to: " + bundle);
|
|
@@ -50,7 +50,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
50
50
|
CAPPluginMethod(name: "isShakeMenuEnabled", returnType: CAPPluginReturnPromise)
|
|
51
51
|
]
|
|
52
52
|
public var implementation = CapgoUpdater()
|
|
53
|
-
private let PLUGIN_VERSION: String = "7.
|
|
53
|
+
private let PLUGIN_VERSION: String = "7.16.0"
|
|
54
54
|
static let updateUrlDefault = "https://plugin.capgo.app/updates"
|
|
55
55
|
static let statsUrlDefault = "https://plugin.capgo.app/stats"
|
|
56
56
|
static let channelUrlDefault = "https://plugin.capgo.app/channel_self"
|
|
@@ -248,6 +248,13 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
248
248
|
logger.error("Delete failed, id \(version.getId()) doesn't exist")
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
|
+
|
|
252
|
+
let storedBundles = implementation.list(raw: true)
|
|
253
|
+
let allowedIds = Set(storedBundles.compactMap { info -> String? in
|
|
254
|
+
let id = info.getId()
|
|
255
|
+
return id.isEmpty ? nil : id
|
|
256
|
+
})
|
|
257
|
+
implementation.cleanupDownloadDirectories(allowedIds: allowedIds)
|
|
251
258
|
}
|
|
252
259
|
UserDefaults.standard.set(self.currentBuildVersion, forKey: "LatestNativeBuildVersion")
|
|
253
260
|
UserDefaults.standard.synchronize()
|
|
@@ -886,6 +886,42 @@ import UIKit
|
|
|
886
886
|
return self.delete(id: id, removeInfo: true)
|
|
887
887
|
}
|
|
888
888
|
|
|
889
|
+
public func cleanupDownloadDirectories(allowedIds: Set<String>) {
|
|
890
|
+
let bundleRoot = libraryDir.appendingPathComponent(bundleDirectory)
|
|
891
|
+
let fileManager = FileManager.default
|
|
892
|
+
|
|
893
|
+
guard fileManager.fileExists(atPath: bundleRoot.path) else {
|
|
894
|
+
return
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
do {
|
|
898
|
+
let contents = try fileManager.contentsOfDirectory(at: bundleRoot, includingPropertiesForKeys: [.isDirectoryKey], options: [.skipsHiddenFiles])
|
|
899
|
+
|
|
900
|
+
for url in contents {
|
|
901
|
+
let resourceValues = try url.resourceValues(forKeys: [.isDirectoryKey])
|
|
902
|
+
if resourceValues.isDirectory != true {
|
|
903
|
+
continue
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
let id = url.lastPathComponent
|
|
907
|
+
|
|
908
|
+
if allowedIds.contains(id) {
|
|
909
|
+
continue
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
do {
|
|
913
|
+
try fileManager.removeItem(at: url)
|
|
914
|
+
self.removeBundleInfo(id: id)
|
|
915
|
+
logger.info("Deleted orphan bundle directory: \(id)")
|
|
916
|
+
} catch {
|
|
917
|
+
logger.error("Failed to delete orphan bundle directory: \(id) \(error.localizedDescription)")
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
} catch {
|
|
921
|
+
logger.error("Failed to enumerate bundle directory for cleanup: \(error.localizedDescription)")
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
|
|
889
925
|
public func getBundleDirectory(id: String) -> URL {
|
|
890
926
|
return libraryDir.appendingPathComponent(self.bundleDirectory).appendingPathComponent(id)
|
|
891
927
|
}
|