native-update 1.1.1 → 1.1.2

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.
@@ -252,18 +252,18 @@ class AppUpdatePlugin(
252
252
  }
253
253
 
254
254
  // Async method for background update checks
255
- suspend fun getAppUpdateInfoAsync(): AppUpdateInfo? {
255
+ suspend fun getAppUpdateInfoAsync(): AppUpdateStatus? {
256
256
  return try {
257
257
  val appUpdateInfo = appUpdateManager.appUpdateInfo.await()
258
258
 
259
259
  if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {
260
- AppUpdateInfo(
260
+ AppUpdateStatus(
261
261
  updateAvailable = true,
262
262
  currentVersion = getCurrentAppVersion(),
263
263
  availableVersion = appUpdateInfo.availableVersionCode().toString()
264
264
  )
265
265
  } else {
266
- AppUpdateInfo(
266
+ AppUpdateStatus(
267
267
  updateAvailable = false,
268
268
  currentVersion = getCurrentAppVersion(),
269
269
  availableVersion = null
@@ -106,7 +106,7 @@ class BackgroundNotificationManager(
106
106
  }
107
107
 
108
108
  fun sendUpdateNotification(
109
- appUpdate: AppUpdateInfo?,
109
+ appUpdate: AppUpdateStatus?,
110
110
  liveUpdate: LatestVersion?
111
111
  ): Boolean {
112
112
  val permissionStatus = getPermissionStatus()
@@ -127,7 +127,7 @@ class BackgroundNotificationManager(
127
127
  eventData.put("version", appUpdate?.availableVersion ?: liveUpdate?.version ?: "unknown")
128
128
  eventData.put("action", "shown")
129
129
 
130
- plugin.notifyListeners("backgroundUpdateNotification", eventData)
130
+ plugin.notifyBackgroundUpdateListeners("backgroundUpdateNotification", eventData)
131
131
 
132
132
  return true
133
133
  } catch (e: Exception) {
@@ -146,7 +146,7 @@ class BackgroundNotificationManager(
146
146
  }
147
147
 
148
148
  private fun createNotificationBuilder(
149
- appUpdate: AppUpdateInfo?,
149
+ appUpdate: AppUpdateStatus?,
150
150
  liveUpdate: LatestVersion?
151
151
  ): NotificationCompat.Builder {
152
152
  val title = determineTitle(appUpdate, liveUpdate)
@@ -183,7 +183,7 @@ class BackgroundNotificationManager(
183
183
  return builder
184
184
  }
185
185
 
186
- private fun determineTitle(appUpdate: AppUpdateInfo?, liveUpdate: LatestVersion?): String {
186
+ private fun determineTitle(appUpdate: AppUpdateStatus?, liveUpdate: LatestVersion?): String {
187
187
  return when {
188
188
  appUpdate?.updateAvailable == true && liveUpdate?.available == true -> "App Updates Available"
189
189
  appUpdate?.updateAvailable == true -> "App Update Available"
@@ -192,7 +192,7 @@ class BackgroundNotificationManager(
192
192
  }
193
193
  }
194
194
 
195
- private fun determineContent(appUpdate: AppUpdateInfo?, liveUpdate: LatestVersion?): String {
195
+ private fun determineContent(appUpdate: AppUpdateStatus?, liveUpdate: LatestVersion?): String {
196
196
  return when {
197
197
  appUpdate?.updateAvailable == true && liveUpdate?.available == true ->
198
198
  "App version ${appUpdate.availableVersion} and content updates are available"
@@ -237,7 +237,7 @@ class BackgroundNotificationManager(
237
237
  }
238
238
  }
239
239
 
240
- private fun createContentIntent(appUpdate: AppUpdateInfo?, liveUpdate: LatestVersion?): PendingIntent {
240
+ private fun createContentIntent(appUpdate: AppUpdateStatus?, liveUpdate: LatestVersion?): PendingIntent {
241
241
  val intent = context.packageManager.getLaunchIntentForPackage(context.packageName)
242
242
  ?: Intent()
243
243
 
@@ -254,7 +254,7 @@ class BackgroundNotificationManager(
254
254
 
255
255
  private fun addActionButtons(
256
256
  builder: NotificationCompat.Builder,
257
- appUpdate: AppUpdateInfo?,
257
+ appUpdate: AppUpdateStatus?,
258
258
  liveUpdate: LatestVersion?
259
259
  ) {
260
260
  val actionLabels = preferences.actionLabels ?: ActionLabels.default()
@@ -337,13 +337,13 @@ data class NotificationPreferences(
337
337
  title = obj.getString("title"),
338
338
  description = obj.getString("description"),
339
339
  iconName = obj.getString("iconName"),
340
- soundEnabled = obj.getBoolean("soundEnabled", true),
341
- vibrationEnabled = obj.getBoolean("vibrationEnabled", true),
342
- showActions = obj.getBoolean("showActions", true),
340
+ soundEnabled = obj.getBoolean("soundEnabled", true) ?: true,
341
+ vibrationEnabled = obj.getBoolean("vibrationEnabled", true) ?: true,
342
+ showActions = obj.getBoolean("showActions", true) ?: true,
343
343
  actionLabels = actionLabelsObj?.let { ActionLabels.fromJSObject(it) } ?: ActionLabels.default(),
344
344
  channelId = obj.getString("channelId"),
345
345
  channelName = obj.getString("channelName"),
346
- priority = NotificationPriority.fromString(priorityString)
346
+ priority = NotificationPriority.fromString(priorityString ?: "default")
347
347
  )
348
348
  }
349
349
  }
@@ -33,6 +33,10 @@ class BackgroundUpdatePlugin : Plugin() {
33
33
  BackgroundUpdateManager.registerBackgroundUpdatePlugin(this)
34
34
  }
35
35
 
36
+ fun notifyBackgroundUpdateListeners(event: String, data: JSObject) {
37
+ notifyListeners(event, data)
38
+ }
39
+
36
40
  @PluginMethod
37
41
  fun enableBackgroundUpdates(call: PluginCall) {
38
42
  try {
@@ -67,7 +71,7 @@ class BackgroundUpdatePlugin : Plugin() {
67
71
 
68
72
  @PluginMethod
69
73
  fun scheduleBackgroundCheck(call: PluginCall) {
70
- val interval = call.getLong("interval", 24 * 60 * 60 * 1000L) // Default 24 hours
74
+ val interval = call.getLong("interval") ?: (24 * 60 * 60 * 1000L) // Default 24 hours
71
75
  scheduleBackgroundWork(interval)
72
76
  call.resolve()
73
77
  }
@@ -185,8 +189,8 @@ data class BackgroundUpdateConfig(
185
189
  ) {
186
190
  companion object {
187
191
  fun fromJSObject(obj: JSObject): BackgroundUpdateConfig {
188
- val enabled = obj.getBoolean("enabled", false)
189
- val checkInterval = obj.getInt("checkInterval", 24 * 60 * 60 * 1000)
192
+ val enabled = obj.getBoolean("enabled") ?: false
193
+ val checkInterval = obj.getInt("checkInterval") ?: (24 * 60 * 60 * 1000)
190
194
  val updateTypesArray = obj.getJSONArray("updateTypes")
191
195
  val updateTypes = mutableListOf<BackgroundUpdateType>()
192
196
 
@@ -201,14 +205,14 @@ data class BackgroundUpdateConfig(
201
205
  enabled = enabled,
202
206
  checkInterval = checkInterval,
203
207
  updateTypes = updateTypes,
204
- autoInstall = obj.getBoolean("autoInstall", false),
208
+ autoInstall = obj.getBoolean("autoInstall") ?: false,
205
209
  notificationPreferences = notificationPrefs?.let { NotificationPreferences.fromJSObject(it) },
206
- respectBatteryOptimization = obj.getBoolean("respectBatteryOptimization", true),
207
- allowMeteredConnection = obj.getBoolean("allowMeteredConnection", false),
208
- minimumBatteryLevel = obj.getInt("minimumBatteryLevel", 20),
209
- requireWifi = obj.getBoolean("requireWifi", false),
210
- maxRetries = obj.getInt("maxRetries", 3),
211
- retryDelay = obj.getInt("retryDelay", 5000),
210
+ respectBatteryOptimization = obj.getBoolean("respectBatteryOptimization") ?: true,
211
+ allowMeteredConnection = obj.getBoolean("allowMeteredConnection") ?: false,
212
+ minimumBatteryLevel = obj.getInt("minimumBatteryLevel") ?: 20,
213
+ requireWifi = obj.getBoolean("requireWifi") ?: false,
214
+ maxRetries = obj.getInt("maxRetries") ?: 3,
215
+ retryDelay = obj.getInt("retryDelay") ?: 5000,
212
216
  taskIdentifier = obj.getString("taskIdentifier")
213
217
  )
214
218
  }
@@ -274,7 +278,7 @@ data class BackgroundUpdateStatus(
274
278
  data class BackgroundCheckResult(
275
279
  val success: Boolean,
276
280
  val updatesFound: Boolean,
277
- val appUpdate: AppUpdateInfo? = null,
281
+ val appUpdate: AppUpdateStatus? = null,
278
282
  val liveUpdate: LatestVersion? = null,
279
283
  val notificationSent: Boolean = false,
280
284
  val error: UpdateError? = null
@@ -306,7 +310,7 @@ data class UpdateError(
306
310
  }
307
311
 
308
312
  // Placeholder data classes - would be defined in other plugins
309
- data class AppUpdateInfo(
313
+ data class AppUpdateStatus(
310
314
  val updateAvailable: Boolean,
311
315
  val currentVersion: String,
312
316
  val availableVersion: String? = null
@@ -65,7 +65,7 @@ class BackgroundUpdateWorker(
65
65
 
66
66
  private suspend fun performBackgroundCheck(config: BackgroundUpdateConfig): BackgroundCheckResult {
67
67
  try {
68
- var appUpdate: AppUpdateInfo? = null
68
+ var appUpdate: AppUpdateStatus? = null
69
69
  var liveUpdate: LatestVersion? = null
70
70
 
71
71
  // Check for app updates
@@ -99,7 +99,7 @@ class BackgroundUpdateWorker(
99
99
  }
100
100
  }
101
101
 
102
- private suspend fun checkForAppUpdate(): AppUpdateInfo? {
102
+ private suspend fun checkForAppUpdate(): AppUpdateStatus? {
103
103
  return withContext(Dispatchers.IO) {
104
104
  try {
105
105
  val appUpdatePlugin = BackgroundUpdateManager.getAppUpdatePlugin()
@@ -111,7 +111,7 @@ class BackgroundUpdateWorker(
111
111
  val currentVersion = getCurrentAppVersion()
112
112
  val availableVersion = getAvailableAppVersion()
113
113
 
114
- AppUpdateInfo(
114
+ AppUpdateStatus(
115
115
  updateAvailable = availableVersion != currentVersion,
116
116
  currentVersion = currentVersion,
117
117
  availableVersion = if (availableVersion != currentVersion) availableVersion else null
@@ -224,7 +224,7 @@ class BackgroundUpdateWorker(
224
224
  progressData.put("status", if (result.success) "completed" else "failed")
225
225
  progressData.put("percent", 100)
226
226
 
227
- plugin?.notifyListeners("backgroundUpdateProgress", progressData)
227
+ plugin?.notifyBackgroundUpdateListeners("backgroundUpdateProgress", progressData)
228
228
 
229
229
  // Notify about notification if sent
230
230
  if (result.notificationSent) {
@@ -233,7 +233,7 @@ class BackgroundUpdateWorker(
233
233
  notificationData.put("updateAvailable", result.updatesFound)
234
234
  notificationData.put("action", "shown")
235
235
 
236
- plugin?.notifyListeners("backgroundUpdateNotification", notificationData)
236
+ plugin?.notifyBackgroundUpdateListeners("backgroundUpdateNotification", notificationData)
237
237
  }
238
238
  } catch (e: Exception) {
239
239
  android.util.Log.e(TAG, "Failed to notify listeners", e)
@@ -77,9 +77,7 @@ class NativeUpdatePlugin : Plugin() {
77
77
  appReviewPlugin.configure(it)
78
78
  }
79
79
 
80
- config.getJSObject("backgroundUpdate")?.let {
81
- backgroundUpdatePlugin.configure(it)
82
- }
80
+ // Background update configuration is handled separately via enableBackgroundUpdates
83
81
 
84
82
  call.resolve()
85
83
  } catch (e: Exception) {
@@ -259,7 +257,7 @@ class NativeUpdatePlugin : Plugin() {
259
257
  }
260
258
  }
261
259
 
262
- private fun hasRequiredPermissions(): Boolean {
260
+ override fun hasRequiredPermissions(): Boolean {
263
261
  return hasPermission("storage")
264
262
  }
265
263
  }
package/cli/index.js CHANGED
File without changes
@@ -214,12 +214,12 @@ class AppUpdatePlugin {
214
214
 
215
215
  // MARK: - Data Models
216
216
 
217
- struct AppUpdateInfo {
218
- let updateAvailable: Bool
219
- let currentVersion: String
220
- let availableVersion: String?
217
+ public struct AppUpdateInfo {
218
+ public let updateAvailable: Bool
219
+ public let currentVersion: String
220
+ public let availableVersion: String?
221
221
 
222
- func toDictionary() -> [String: Any] {
222
+ public func toDictionary() -> [String: Any] {
223
223
  var obj: [String: Any] = [
224
224
  "updateAvailable": updateAvailable,
225
225
  "currentVersion": currentVersion
@@ -8,20 +8,17 @@ public class BackgroundUpdatePlugin: CAPPlugin {
8
8
 
9
9
  private let backgroundTaskIdentifier = "com.aoneahsan.nativeupdate.background"
10
10
  private var backgroundUpdateConfig: BackgroundUpdateConfig?
11
- private var backgroundUpdateStatus: BackgroundUpdateStatus
11
+ private var backgroundUpdateStatus = BackgroundUpdateStatus(
12
+ enabled: false,
13
+ isRunning: false,
14
+ checkCount: 0,
15
+ failureCount: 0
16
+ )
12
17
  private var notificationManager: BackgroundNotificationManager?
13
18
 
14
19
  public override func load() {
15
20
  super.load()
16
21
 
17
- // Initialize background update status
18
- backgroundUpdateStatus = BackgroundUpdateStatus(
19
- enabled: false,
20
- isRunning: false,
21
- checkCount: 0,
22
- failureCount: 0
23
- )
24
-
25
22
  // Initialize notification manager
26
23
  notificationManager = BackgroundNotificationManager(plugin: self)
27
24
 
@@ -33,6 +30,11 @@ public class BackgroundUpdatePlugin: CAPPlugin {
33
30
  }
34
31
  }
35
32
 
33
+ func configure(_ config: [String: Any]) throws {
34
+ // Configuration is handled in enableBackgroundUpdates
35
+ // This method exists for consistency with other plugins
36
+ }
37
+
36
38
  @objc func enableBackgroundUpdates(_ call: CAPPluginCall) {
37
39
  guard let configData = call.options else {
38
40
  call.reject("Missing configuration")
@@ -40,7 +42,13 @@ public class BackgroundUpdatePlugin: CAPPlugin {
40
42
  }
41
43
 
42
44
  do {
43
- let config = try BackgroundUpdateConfig.from(configData)
45
+ // Convert [AnyHashable: Any] to [String: Any]
46
+ let stringKeyedConfig = configData.reduce(into: [String: Any]()) { result, pair in
47
+ if let key = pair.key as? String {
48
+ result[key] = pair.value
49
+ }
50
+ }
51
+ let config = try BackgroundUpdateConfig.from(stringKeyedConfig)
44
52
  backgroundUpdateConfig = config
45
53
  backgroundUpdateStatus.enabled = config.enabled
46
54
 
@@ -88,7 +96,14 @@ public class BackgroundUpdatePlugin: CAPPlugin {
88
96
  return
89
97
  }
90
98
 
91
- notificationManager?.setPreferences(preferences)
99
+ // Convert [AnyHashable: Any] to [String: Any]
100
+ let stringKeyedPreferences = preferences.reduce(into: [String: Any]()) { result, pair in
101
+ if let key = pair.key as? String {
102
+ result[key] = pair.value
103
+ }
104
+ }
105
+
106
+ notificationManager?.setPreferences(stringKeyedPreferences)
92
107
  call.resolve()
93
108
  }
94
109
 
@@ -172,6 +187,8 @@ public class BackgroundUpdatePlugin: CAPPlugin {
172
187
  return BackgroundCheckResult(
173
188
  success: false,
174
189
  updatesFound: false,
190
+ appUpdate: nil,
191
+ liveUpdate: nil,
175
192
  notificationSent: false,
176
193
  error: UpdateError(code: "INVALID_CONFIG", message: "Background updates not enabled")
177
194
  )
@@ -214,7 +231,8 @@ public class BackgroundUpdatePlugin: CAPPlugin {
214
231
  updatesFound: updatesFound,
215
232
  appUpdate: appUpdate,
216
233
  liveUpdate: liveUpdate,
217
- notificationSent: notificationSent
234
+ notificationSent: notificationSent,
235
+ error: nil
218
236
  )
219
237
 
220
238
  } catch {
@@ -230,6 +248,8 @@ public class BackgroundUpdatePlugin: CAPPlugin {
230
248
  return BackgroundCheckResult(
231
249
  success: false,
232
250
  updatesFound: false,
251
+ appUpdate: nil,
252
+ liveUpdate: nil,
233
253
  notificationSent: false,
234
254
  error: updateError
235
255
  )
@@ -7,7 +7,7 @@ class LiveUpdatePlugin {
7
7
  private var config: [String: Any]?
8
8
  private var progressListener: (([String: Any]) -> Void)?
9
9
  private var stateChangeListener: (([String: Any]) -> Void)?
10
- private var session: URLSession
10
+ private var session: URLSession!
11
11
  private var downloadTask: URLSessionDownloadTask?
12
12
  private let securityManager = SecurityManager()
13
13
 
@@ -444,10 +444,15 @@ class LiveUpdatePlugin {
444
444
  }
445
445
 
446
446
  private func getCurrentVersion() -> String {
447
- if let bundle = getCurrentBundleInfo(),
448
- let version = bundle["version"] as? String {
447
+ // First check if we have an active bundle with version
448
+ let defaults = UserDefaults.standard
449
+ if let activeBundleId = defaults.string(forKey: "native_update_active_bundle"),
450
+ let bundles = defaults.dictionary(forKey: "native_update_bundles"),
451
+ let bundleInfo = bundles[activeBundleId] as? [String: Any],
452
+ let version = bundleInfo["version"] as? String {
449
453
  return version
450
454
  }
455
+ // Fall back to app version
451
456
  return Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0.0"
452
457
  }
453
458
 
@@ -484,7 +489,7 @@ class LiveUpdatePlugin {
484
489
  // Return default bundle
485
490
  return [
486
491
  "bundleId": "default",
487
- "version": getCurrentVersion(),
492
+ "version": Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0.0",
488
493
  "path": "/",
489
494
  "downloadTime": Date().timeIntervalSince1970 * 1000,
490
495
  "size": 0,
@@ -555,19 +560,14 @@ class LiveUpdatePlugin {
555
560
  // Create destination directory
556
561
  try FileManager.default.createDirectory(at: destinationUrl, withIntermediateDirectories: true)
557
562
 
558
- // Use system unzip command
559
- let process = Process()
560
- process.executableURL = URL(fileURLWithPath: "/usr/bin/unzip")
561
- process.arguments = ["-o", zipUrl.path, "-d", destinationUrl.path]
563
+ // Use FileManager to extract (requires iOS unzip library or manual implementation)
564
+ // For now, we'll use a simple file copy as placeholder
565
+ // In production, you would use a library like ZIPFoundation or SSZipArchive
562
566
 
563
- try process.run()
564
- process.waitUntilExit()
565
-
566
- if process.terminationStatus != 0 {
567
- throw NSError(domain: "LiveUpdatePlugin", code: 5, userInfo: [
568
- NSLocalizedDescriptionKey: "Failed to extract bundle"
569
- ])
570
- }
567
+ // This is a placeholder - in real implementation, use a proper unzip library
568
+ throw NSError(domain: "LiveUpdatePlugin", code: 5, userInfo: [
569
+ NSLocalizedDescriptionKey: "Unzip functionality not implemented. Please integrate a zip library like ZIPFoundation."
570
+ ])
571
571
  }
572
572
 
573
573
  private func configureWebViewPath(_ path: String) {
@@ -581,11 +581,11 @@ class LiveUpdatePlugin {
581
581
 
582
582
  // MARK: - Data Models
583
583
 
584
- struct LatestVersion {
585
- let available: Bool
586
- let version: String?
584
+ public struct LatestVersion {
585
+ public let available: Bool
586
+ public let version: String?
587
587
 
588
- func toDictionary() -> [String: Any] {
588
+ public func toDictionary() -> [String: Any] {
589
589
  var obj: [String: Any] = [
590
590
  "available": available
591
591
  ]
@@ -646,8 +646,8 @@ class CertificatePinningDelegate: NSObject, URLSessionDelegate {
646
646
 
647
647
  private func getCertificatePins(for host: String) -> [String] {
648
648
  // Get pins from security manager configuration
649
- guard let securityInfo = securityManager.getSecurityInfo(),
650
- let certificatePinning = securityInfo["certificatePinning"] as? [String: Any],
649
+ let securityInfo = securityManager.getSecurityInfo()
650
+ guard let certificatePinning = securityInfo["certificatePinning"] as? [String: Any],
651
651
  certificatePinning["enabled"] as? Bool == true,
652
652
  let hostPins = certificatePinning["pins"] as? [String: [String]] else {
653
653
  return []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "native-update",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Foundation package for building a comprehensive update system for Capacitor apps. Provides architecture and interfaces but requires backend implementation.",
5
5
  "type": "module",
6
6
  "main": "dist/plugin.cjs.js",