@capacitor/background-runner 2.1.0 → 2.3.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/CapacitorBackgroundRunner.podspec +1 -1
- package/Package.swift +45 -0
- package/README.md +65 -3
- package/android/src/main/java/io/ionic/backgroundrunner/plugin/BackgroundRunnerPlugin.kt +45 -1
- package/android/src/main/java/io/ionic/backgroundrunner/plugin/api/Notification.kt +4 -2
- package/android/src/main/java/io/ionic/backgroundrunner/plugin/api/Notifications.kt +21 -0
- package/android/src/main/libs/android-js-engine-release.aar +0 -0
- package/dist/docs.json +83 -0
- package/dist/esm/definitions.d.ts +17 -1
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +4 -1
- package/dist/esm/web.js +6 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +8 -4
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +8 -4
- package/dist/plugin.js.map +1 -1
- package/ios/{Plugin → Sources/CapacitorBackgroundRunner}/BackgroundRunner.swift +26 -11
- package/ios/{Plugin → Sources/CapacitorBackgroundRunner}/CapacitorAPI/Geolocation.swift +21 -9
- package/ios/{Plugin → Sources/CapacitorBackgroundRunner}/CapacitorAPI/Notifications.swift +4 -3
- package/ios/{Plugin → Sources/CapacitorBackgroundRunner}/CapacitorAPI/Reachability.swift +1 -1
- package/ios/{Plugin/BackgroundRunnerPlugin.swift → Sources/CapacitorBackgroundRunner/CapacitorBackgroundRunner.swift} +104 -1
- package/ios/{Plugin → Sources/CapacitorBackgroundRunner}/Context+CapacitorAPI.swift +8 -2
- package/ios/{Plugin → Sources}/RunnerEngine/Context.swift +1 -1
- package/ios/{Plugin → Sources}/RunnerEngine/JSCrypto.swift +3 -3
- package/ios/{Plugin → Sources}/RunnerEngine/JSError.swift +1 -1
- package/ios/{Plugin → Sources}/RunnerEngine/Runner.swift +1 -1
- package/ios/Tests/CapacitorBackgroundRunnerTests/CapacitorBackgroundRunnerTests.swift +21 -0
- package/ios/Tests/RunnerEngineTests/ContextTests.swift +393 -0
- package/ios/Tests/RunnerEngineTests/RunnerTests.swift +32 -0
- package/package.json +24 -22
- package/scripts/install_libs.js +4 -12
- package/ios/Plugin/BackgroundRunnerPlugin.h +0 -10
- package/ios/Plugin/BackgroundRunnerPlugin.m +0 -11
- package/ios/Plugin/Info.plist +0 -24
- /package/ios/{Plugin/BackgroundRunnerErrors.swift → Sources/CapacitorBackgroundRunner/BackgroundRunnerPluginError.swift} +0 -0
- /package/ios/{Plugin → Sources/CapacitorBackgroundRunner}/CapacitorAPI/App.swift +0 -0
- /package/ios/{Plugin → Sources/CapacitorBackgroundRunner}/CapacitorAPI/Device.swift +0 -0
- /package/ios/{Plugin → Sources/CapacitorBackgroundRunner}/CapacitorAPI/KV.swift +0 -0
- /package/ios/{Plugin → Sources/CapacitorBackgroundRunner}/CapacitorAPI/Watch.swift +0 -0
- /package/ios/{Plugin → Sources/CapacitorBackgroundRunner}/RunnerConfig.swift +0 -0
- /package/ios/{Plugin/WatchConnectivtySessionDelegate.swift → Sources/CapacitorBackgroundRunner/WatchConnectivitySessionDelegate.swift} +0 -0
- /package/ios/{Plugin → Sources}/RunnerEngine/Errors.swift +0 -0
- /package/ios/{Plugin → Sources}/RunnerEngine/JSConsole.swift +0 -0
- /package/ios/{Plugin → Sources}/RunnerEngine/JSFetch.swift +0 -0
- /package/ios/{Plugin → Sources}/RunnerEngine/JSResponse.swift +0 -0
- /package/ios/{Plugin → Sources}/RunnerEngine/JSTextDecoder.swift +0 -0
- /package/ios/{Plugin → Sources}/RunnerEngine/JSTextEncoder.swift +0 -0
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
import Capacitor
|
|
3
1
|
import BackgroundTasks
|
|
2
|
+
import Capacitor
|
|
3
|
+
import Foundation
|
|
4
4
|
import JavaScriptCore
|
|
5
5
|
|
|
6
|
+
#if canImport(RunnerEngine)
|
|
7
|
+
import RunnerEngine
|
|
8
|
+
#endif
|
|
9
|
+
|
|
6
10
|
public class BackgroundRunner {
|
|
7
11
|
public static let shared = BackgroundRunner()
|
|
8
12
|
public var config: RunnerConfig?
|
|
@@ -27,7 +31,8 @@ public class BackgroundRunner {
|
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
guard let interval = config.interval else {
|
|
30
|
-
throw BackgroundRunnerPluginError.invalidRunnerConfig(
|
|
34
|
+
throw BackgroundRunnerPluginError.invalidRunnerConfig(
|
|
35
|
+
reason: "cannot register background task without a configured interval")
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
let request = BGAppRefreshTaskRequest(identifier: config.label)
|
|
@@ -64,7 +69,9 @@ public class BackgroundRunner {
|
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
// swiftlint:disable:next cyclomatic_complexity function_body_length
|
|
67
|
-
public func execute(
|
|
72
|
+
public func execute(
|
|
73
|
+
config: RunnerConfig, inputArgs: [String: Any]? = nil, callbackId: String? = nil
|
|
74
|
+
) throws -> [String: Any]? {
|
|
68
75
|
do {
|
|
69
76
|
let context = try initContext(config: config, callbackId: callbackId)
|
|
70
77
|
|
|
@@ -73,7 +80,7 @@ public class BackgroundRunner {
|
|
|
73
80
|
var result: [String: Any]?
|
|
74
81
|
var rejectionErr: JSError?
|
|
75
82
|
|
|
76
|
-
let resolveFunc: @convention(block)(JavaScriptCore.JSValue) -> Void = { returnObj in
|
|
83
|
+
let resolveFunc: @convention(block) (JavaScriptCore.JSValue) -> Void = { returnObj in
|
|
77
84
|
if !returnObj.isUndefined && !returnObj.isNull {
|
|
78
85
|
var dict: [String: Any] = [:]
|
|
79
86
|
|
|
@@ -88,7 +95,7 @@ public class BackgroundRunner {
|
|
|
88
95
|
return
|
|
89
96
|
}
|
|
90
97
|
|
|
91
|
-
let rejectFunc: @convention(block)(JavaScriptCore.JSValue) -> Void = { rejectObj in
|
|
98
|
+
let rejectFunc: @convention(block) (JavaScriptCore.JSValue) -> Void = { rejectObj in
|
|
92
99
|
var rejectionTitle = "Error"
|
|
93
100
|
var rejectionMessage = ""
|
|
94
101
|
|
|
@@ -136,7 +143,7 @@ public class BackgroundRunner {
|
|
|
136
143
|
waitGroup.wait()
|
|
137
144
|
|
|
138
145
|
if let rejection = rejectionErr {
|
|
139
|
-
throw EngineError.jsException(details: rejection.
|
|
146
|
+
throw EngineError.jsException(details: rejection.toString())
|
|
140
147
|
}
|
|
141
148
|
|
|
142
149
|
return result
|
|
@@ -146,7 +153,8 @@ public class BackgroundRunner {
|
|
|
146
153
|
}
|
|
147
154
|
}
|
|
148
155
|
|
|
149
|
-
public func dispatchEvent(event: String, inputArgs: [String: Any]?, callbackId: String? = nil)
|
|
156
|
+
public func dispatchEvent(event: String, inputArgs: [String: Any]?, callbackId: String? = nil)
|
|
157
|
+
throws {
|
|
150
158
|
if let config = config {
|
|
151
159
|
let waitGroup = DispatchGroup()
|
|
152
160
|
waitGroup.enter()
|
|
@@ -174,13 +182,17 @@ public class BackgroundRunner {
|
|
|
174
182
|
}
|
|
175
183
|
|
|
176
184
|
private func loadRunnerConfig() throws -> RunnerConfig? {
|
|
177
|
-
guard
|
|
185
|
+
guard
|
|
186
|
+
let capacitorConfigFileURL = Bundle.main.url(
|
|
187
|
+
forResource: "capacitor.config.json", withExtension: nil)
|
|
188
|
+
else {
|
|
178
189
|
throw BackgroundRunnerPluginError.runnerError(reason: "capacitor.config.json file not found")
|
|
179
190
|
}
|
|
180
191
|
|
|
181
192
|
let capacitorConfigFileData = try Data(contentsOf: capacitorConfigFileURL)
|
|
182
193
|
|
|
183
|
-
if let capConfig = JSTypes.coerceDictionaryToJSObject(
|
|
194
|
+
if let capConfig = JSTypes.coerceDictionaryToJSObject(
|
|
195
|
+
try JSONSerialization.jsonObject(with: capacitorConfigFileData) as? [String: Any]) {
|
|
184
196
|
if let jsonConfig = capConfig[keyPath: "plugins.BackgroundRunner"] as? JSObject {
|
|
185
197
|
return try RunnerConfig(from: jsonConfig)
|
|
186
198
|
}
|
|
@@ -190,7 +202,10 @@ public class BackgroundRunner {
|
|
|
190
202
|
}
|
|
191
203
|
|
|
192
204
|
private func initContext(config: RunnerConfig, callbackId: String?) throws -> Context {
|
|
193
|
-
guard
|
|
205
|
+
guard
|
|
206
|
+
let srcFileURL = Bundle.main.url(
|
|
207
|
+
forResource: config.src, withExtension: nil, subdirectory: "public")
|
|
208
|
+
else {
|
|
194
209
|
throw BackgroundRunnerPluginError.runnerError(reason: "source file not found")
|
|
195
210
|
}
|
|
196
211
|
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import CoreLocation
|
|
1
2
|
import Foundation
|
|
2
3
|
import JavaScriptCore
|
|
3
|
-
|
|
4
|
+
|
|
5
|
+
#if canImport(RunnerEngine)
|
|
6
|
+
import RunnerEngine
|
|
7
|
+
#endif
|
|
4
8
|
|
|
5
9
|
@objc protocol CapacitorGeolocationExports: JSExport {
|
|
6
10
|
var isWatchingPosition: Bool { get }
|
|
@@ -32,9 +36,12 @@ class CapacitorGeolocation: NSObject, CapacitorGeolocationExports, CLLocationMan
|
|
|
32
36
|
self.context = context
|
|
33
37
|
self.locationManager.delegate = self
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
if CLLocationManager.authorizationStatus() == .authorizedAlways {
|
|
40
|
+
self.locationManager.allowsBackgroundLocationUpdates = true
|
|
41
|
+
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
|
|
42
|
+
self.locationManager.pausesLocationUpdatesAutomatically = false
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
}
|
|
39
46
|
|
|
40
47
|
static func getCurrentKnownLocation() -> CLLocation? {
|
|
@@ -71,7 +78,8 @@ class CapacitorGeolocation: NSObject, CapacitorGeolocationExports, CLLocationMan
|
|
|
71
78
|
return
|
|
72
79
|
}
|
|
73
80
|
|
|
74
|
-
return try await withCheckedThrowingContinuation({
|
|
81
|
+
return try await withCheckedThrowingContinuation({
|
|
82
|
+
(continuation: CheckedContinuation<Void, Error>) in
|
|
75
83
|
permissionContinuation = continuation
|
|
76
84
|
|
|
77
85
|
DispatchQueue.main.async {
|
|
@@ -96,7 +104,8 @@ class CapacitorGeolocation: NSObject, CapacitorGeolocationExports, CLLocationMan
|
|
|
96
104
|
|
|
97
105
|
self.isWatchingLocation = true
|
|
98
106
|
} catch {
|
|
99
|
-
JSContext.current().exception = JSValue(
|
|
107
|
+
JSContext.current().exception = JSValue(
|
|
108
|
+
newErrorFromMessage: "\(error)", in: JSContext.current())
|
|
100
109
|
}
|
|
101
110
|
}
|
|
102
111
|
|
|
@@ -121,7 +130,8 @@ class CapacitorGeolocation: NSObject, CapacitorGeolocationExports, CLLocationMan
|
|
|
121
130
|
|
|
122
131
|
return buildLocationDict(location: lastLocation)
|
|
123
132
|
} catch {
|
|
124
|
-
JSContext.current().exception = JSValue(
|
|
133
|
+
JSContext.current().exception = JSValue(
|
|
134
|
+
newErrorFromMessage: "\(error)", in: JSContext.current())
|
|
125
135
|
|
|
126
136
|
return nil
|
|
127
137
|
}
|
|
@@ -139,7 +149,8 @@ class CapacitorGeolocation: NSObject, CapacitorGeolocationExports, CLLocationMan
|
|
|
139
149
|
try? context.dispatchEvent(event: "currentLocation", details: details)
|
|
140
150
|
}
|
|
141
151
|
|
|
142
|
-
pendingCurrentLocationCalls.forEach {
|
|
152
|
+
pendingCurrentLocationCalls.forEach {
|
|
153
|
+
(callId: Int, callback: (Result<CLLocation?, Error>) -> Void) in
|
|
143
154
|
pendingCurrentLocationCalls.removeValue(forKey: callId)
|
|
144
155
|
callback(.success(locations.last))
|
|
145
156
|
}
|
|
@@ -162,7 +173,8 @@ class CapacitorGeolocation: NSObject, CapacitorGeolocationExports, CLLocationMan
|
|
|
162
173
|
try? context.dispatchEvent(event: "currentLocation", details: details)
|
|
163
174
|
}
|
|
164
175
|
|
|
165
|
-
pendingCurrentLocationCalls.forEach {
|
|
176
|
+
pendingCurrentLocationCalls.forEach {
|
|
177
|
+
(callId: Int, callback: (Result<CLLocation?, Error>) -> Void) in
|
|
166
178
|
pendingCurrentLocationCalls.removeValue(forKey: callId)
|
|
167
179
|
callback(.failure(error))
|
|
168
180
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Foundation
|
|
2
|
+
import UIKit
|
|
2
3
|
import JavaScriptCore
|
|
3
4
|
import UserNotifications
|
|
4
5
|
|
|
@@ -136,7 +137,7 @@ class CapacitorNotifications: NSObject, CapacitorNotificationsExports {
|
|
|
136
137
|
let content = UNMutableNotificationContent()
|
|
137
138
|
content.title = NSString.localizedUserNotificationString(forKey: notificationOption.title, arguments: nil)
|
|
138
139
|
content.body = NSString.localizedUserNotificationString(forKey: notificationOption.body, arguments: nil)
|
|
139
|
-
content.userInfo = [:]
|
|
140
|
+
content.userInfo = ["source": "capacitor-background-runner"]
|
|
140
141
|
|
|
141
142
|
if let extra = notificationOption.extra {
|
|
142
143
|
content.userInfo["cap_extra"] = extra
|
|
@@ -195,7 +196,7 @@ class CapacitorNotifications: NSObject, CapacitorNotificationsExports {
|
|
|
195
196
|
|
|
196
197
|
let badgeOptions = SetBadgeOption(from: jsonDict)
|
|
197
198
|
|
|
198
|
-
DispatchQueue.main.
|
|
199
|
+
DispatchQueue.main.async {
|
|
199
200
|
if #available(iOS 16.0, *) {
|
|
200
201
|
UNUserNotificationCenter.current().setBadgeCount(badgeOptions.count)
|
|
201
202
|
} else {
|
|
@@ -213,7 +214,7 @@ class CapacitorNotifications: NSObject, CapacitorNotificationsExports {
|
|
|
213
214
|
throw CapacitorNotificationsErrors.permissionDenied
|
|
214
215
|
}
|
|
215
216
|
|
|
216
|
-
DispatchQueue.main.
|
|
217
|
+
DispatchQueue.main.async {
|
|
217
218
|
if #available(iOS 16.0, *) {
|
|
218
219
|
UNUserNotificationCenter.current().setBadgeCount(0)
|
|
219
220
|
} else {
|
|
@@ -191,7 +191,7 @@ public extension Reachability {
|
|
|
191
191
|
_ = unmanagedWeakifiedReachability.retain()
|
|
192
192
|
return UnsafeRawPointer(unmanagedWeakifiedReachability.toOpaque())
|
|
193
193
|
},
|
|
194
|
-
release: { (info: UnsafeRawPointer)
|
|
194
|
+
release: { (info: UnsafeRawPointer) in
|
|
195
195
|
let unmanagedWeakifiedReachability = Unmanaged<ReachabilityWeakifier>.fromOpaque(info)
|
|
196
196
|
unmanagedWeakifiedReachability.release()
|
|
197
197
|
},
|
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
import Capacitor
|
|
3
3
|
import WatchConnectivity
|
|
4
|
+
import UserNotifications
|
|
4
5
|
|
|
5
6
|
@objc(BackgroundRunnerPlugin)
|
|
6
|
-
public class BackgroundRunnerPlugin: CAPPlugin {
|
|
7
|
+
public class BackgroundRunnerPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
8
|
+
public let identifier = "CapacitorBackgroundRunnerPlugin"
|
|
9
|
+
public let jsName = "CapacitorBackgroundRunner"
|
|
10
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
11
|
+
CAPPluginMethod(name: "checkPermissions", returnType: CAPPluginReturnPromise),
|
|
12
|
+
CAPPluginMethod(name: "requestPermissions", returnType: CAPPluginReturnPromise),
|
|
13
|
+
CAPPluginMethod(name: "dispatchEvent", returnType: CAPPluginReturnPromise),
|
|
14
|
+
CAPPluginMethod(name: "registerBackgroundTask", returnType: CAPPluginReturnPromise),
|
|
15
|
+
CAPPluginMethod(name: "removeNotificationListeners", returnType: CAPPluginReturnPromise)
|
|
16
|
+
]
|
|
7
17
|
private let impl = BackgroundRunner()
|
|
18
|
+
private weak var originalDelegate: UNUserNotificationCenterDelegate?
|
|
8
19
|
|
|
9
20
|
override public func load() {
|
|
10
21
|
NotificationCenter.default.addObserver(
|
|
@@ -14,6 +25,9 @@ public class BackgroundRunnerPlugin: CAPPlugin {
|
|
|
14
25
|
object: nil
|
|
15
26
|
)
|
|
16
27
|
|
|
28
|
+
// Register as notification delegate
|
|
29
|
+
registerNotificationCategories()
|
|
30
|
+
|
|
17
31
|
initWatchConnectivity()
|
|
18
32
|
}
|
|
19
33
|
|
|
@@ -95,6 +109,11 @@ public class BackgroundRunnerPlugin: CAPPlugin {
|
|
|
95
109
|
call.resolve()
|
|
96
110
|
}
|
|
97
111
|
|
|
112
|
+
@objc func removeNotificationListeners(_ call: CAPPluginCall) {
|
|
113
|
+
notifyListeners("backgroundRunnerNotificationReceived", data: nil)
|
|
114
|
+
call.resolve()
|
|
115
|
+
}
|
|
116
|
+
|
|
98
117
|
@objc private func didEnterBackground() {
|
|
99
118
|
do {
|
|
100
119
|
try impl.scheduleBackgroundTasks()
|
|
@@ -175,4 +194,88 @@ public class BackgroundRunnerPlugin: CAPPlugin {
|
|
|
175
194
|
|
|
176
195
|
print("Watch Connectivity Enabled")
|
|
177
196
|
}
|
|
197
|
+
|
|
198
|
+
@objc func registerNotificationCategories() {
|
|
199
|
+
let notificationCenter = UNUserNotificationCenter.current()
|
|
200
|
+
|
|
201
|
+
// Capture the original delegate if it's not self
|
|
202
|
+
if notificationCenter.delegate !== self {
|
|
203
|
+
originalDelegate = notificationCenter.delegate
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Set the plugin as the notification delegate
|
|
207
|
+
notificationCenter.delegate = self
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// MARK: - UNUserNotificationCenterDelegate
|
|
212
|
+
extension BackgroundRunnerPlugin: UNUserNotificationCenterDelegate {
|
|
213
|
+
// This method will be called when a notification is tapped
|
|
214
|
+
public func userNotificationCenter(_ center: UNUserNotificationCenter,
|
|
215
|
+
didReceive response: UNNotificationResponse,
|
|
216
|
+
withCompletionHandler completionHandler: @escaping () -> Void) {
|
|
217
|
+
let userInfo = response.notification.request.content.userInfo
|
|
218
|
+
|
|
219
|
+
if isBackgroundRunnerNotification(userInfo) {
|
|
220
|
+
handleBackgroundRunnerNotification(response, completionHandler: completionHandler)
|
|
221
|
+
} else {
|
|
222
|
+
forwardToOriginalDelegate(center, didReceive: response, withCompletionHandler: completionHandler)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// This is needed to present notifications when the app is in the foreground
|
|
227
|
+
public func userNotificationCenter(_ center: UNUserNotificationCenter,
|
|
228
|
+
willPresent notification: UNNotification,
|
|
229
|
+
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
|
230
|
+
let userInfo = notification.request.content.userInfo
|
|
231
|
+
|
|
232
|
+
if isBackgroundRunnerNotification(userInfo) {
|
|
233
|
+
handleBackgroundRunnerPresentation(completionHandler: completionHandler)
|
|
234
|
+
} else {
|
|
235
|
+
forwardToOriginalDelegate(center, willPresent: notification, withCompletionHandler: completionHandler)
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// MARK: - Helper Methods
|
|
240
|
+
|
|
241
|
+
private func isBackgroundRunnerNotification(_ userInfo: [AnyHashable: Any]) -> Bool {
|
|
242
|
+
return (userInfo["source"] as? String) == "capacitor-background-runner"
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private func handleBackgroundRunnerNotification(_ response: UNNotificationResponse, completionHandler: @escaping () -> Void) {
|
|
246
|
+
let actionTypeId = response.notification.request.content.categoryIdentifier
|
|
247
|
+
let notificationId = Int(response.notification.request.identifier) ?? -1
|
|
248
|
+
|
|
249
|
+
let eventData: [String: Any] = [
|
|
250
|
+
"actionTypeId": actionTypeId,
|
|
251
|
+
"notificationId": notificationId
|
|
252
|
+
]
|
|
253
|
+
|
|
254
|
+
notifyListeners("backgroundRunnerNotificationReceived", data: eventData, retainUntilConsumed: true)
|
|
255
|
+
completionHandler()
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private func forwardToOriginalDelegate(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
|
259
|
+
if let originalDelegate = originalDelegate, originalDelegate.responds(to: #selector(userNotificationCenter(_:didReceive:withCompletionHandler:))) {
|
|
260
|
+
originalDelegate.userNotificationCenter?(center, didReceive: response, withCompletionHandler: completionHandler)
|
|
261
|
+
} else {
|
|
262
|
+
completionHandler()
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private func handleBackgroundRunnerPresentation(completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
|
267
|
+
if #available(iOS 14.0, *) {
|
|
268
|
+
completionHandler([.banner, .sound, .badge])
|
|
269
|
+
} else {
|
|
270
|
+
completionHandler([.alert, .sound, .badge])
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
private func forwardToOriginalDelegate(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
|
275
|
+
if let originalDelegate = originalDelegate, originalDelegate.responds(to: #selector(userNotificationCenter(_:willPresent:withCompletionHandler:))) {
|
|
276
|
+
originalDelegate.userNotificationCenter?(center, willPresent: notification, withCompletionHandler: completionHandler)
|
|
277
|
+
} else {
|
|
278
|
+
handleBackgroundRunnerPresentation(completionHandler: completionHandler)
|
|
279
|
+
}
|
|
280
|
+
}
|
|
178
281
|
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
|
|
3
|
+
#if canImport(RunnerEngine)
|
|
4
|
+
import RunnerEngine
|
|
5
|
+
#endif
|
|
6
|
+
|
|
3
7
|
extension Context {
|
|
4
8
|
public func setupCapacitorAPI() {
|
|
5
9
|
jsContext.setObject(CapacitorKVStore.self, forKeyedSubscript: "CapacitorKV" as NSString)
|
|
6
|
-
jsContext.setObject(
|
|
10
|
+
jsContext.setObject(
|
|
11
|
+
CapacitorGeolocation(context: self), forKeyedSubscript: "CapacitorGeolocation" as NSString)
|
|
7
12
|
jsContext.setObject(CapacitorWatch(), forKeyedSubscript: "CapacitorWatch" as NSString)
|
|
8
|
-
jsContext.setObject(
|
|
13
|
+
jsContext.setObject(
|
|
14
|
+
CapacitorNotifications.self, forKeyedSubscript: "CapacitorNotifications" as NSString)
|
|
9
15
|
jsContext.setObject(CapacitorDevice(), forKeyedSubscript: "CapacitorDevice" as NSString)
|
|
10
16
|
jsContext.setObject(CapacitorApp.self, forKeyedSubscript: "CapacitorApp" as NSString)
|
|
11
17
|
}
|
|
@@ -13,17 +13,17 @@ class JSCrypto: NSObject, JSCryptoExports {
|
|
|
13
13
|
var rnd = [UInt8](repeating: 0, count: size)
|
|
14
14
|
_ = SecRandomCopyBytes(kSecRandomDefault, size, &rnd)
|
|
15
15
|
|
|
16
|
-
if arr.toArray()
|
|
16
|
+
if arr.toArray() is [UInt8] {
|
|
17
17
|
for i in 0...(size - 1) {
|
|
18
18
|
arr.setObject(rnd[i], atIndexedSubscript: i)
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
if arr.toArray()
|
|
21
|
+
if arr.toArray() is [UInt16] {
|
|
22
22
|
for i in 0...(size - 1) {
|
|
23
23
|
arr.setObject(UInt16(rnd[i]), atIndexedSubscript: i)
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
if arr.toArray()
|
|
26
|
+
if arr.toArray() is [UInt32] {
|
|
27
27
|
for i in 0...(size - 1) {
|
|
28
28
|
arr.setObject(UInt32(rnd[i]), forKeyedSubscript: i)
|
|
29
29
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import Testing
|
|
2
|
+
@testable import CapacitorBackgroundRunner
|
|
3
|
+
@testable import RunnerEngine
|
|
4
|
+
|
|
5
|
+
@Test func testKeyValueAPI() async throws {
|
|
6
|
+
let runner = Runner()
|
|
7
|
+
let context = try runner.createContext(name: "io.backgroundrunner.testkv")
|
|
8
|
+
context.setupCapacitorAPI()
|
|
9
|
+
|
|
10
|
+
_ = try context.execute(code: "CapacitorKV.set('test', 'hello world');")
|
|
11
|
+
|
|
12
|
+
let value = try context.execute(code: "CapacitorKV.get('test');")
|
|
13
|
+
|
|
14
|
+
#expect(value?.toDictionary()?["value"] as? String == "hello world")
|
|
15
|
+
|
|
16
|
+
_ = try context.execute(code: "CapacitorKV.remove('test');")
|
|
17
|
+
|
|
18
|
+
let nullValue = try context.execute(code: "CapacitorKV.get('test');")
|
|
19
|
+
|
|
20
|
+
#expect(nullValue?.isNull ?? false)
|
|
21
|
+
}
|