@blueid/access-capacitor 0.79.0 → 0.80.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.
@@ -10,15 +10,18 @@
10
10
  <key>HeadersPath</key>
11
11
  <string>Headers</string>
12
12
  <key>LibraryIdentifier</key>
13
- <string>ios-arm64</string>
13
+ <string>ios-arm64_x86_64-simulator</string>
14
14
  <key>LibraryPath</key>
15
15
  <string>libCBlueIDAccess.a</string>
16
16
  <key>SupportedArchitectures</key>
17
17
  <array>
18
18
  <string>arm64</string>
19
+ <string>x86_64</string>
19
20
  </array>
20
21
  <key>SupportedPlatform</key>
21
22
  <string>ios</string>
23
+ <key>SupportedPlatformVariant</key>
24
+ <string>simulator</string>
22
25
  </dict>
23
26
  <dict>
24
27
  <key>BinaryPath</key>
@@ -26,16 +29,15 @@
26
29
  <key>HeadersPath</key>
27
30
  <string>Headers</string>
28
31
  <key>LibraryIdentifier</key>
29
- <string>macos-arm64_x86_64</string>
32
+ <string>ios-arm64</string>
30
33
  <key>LibraryPath</key>
31
34
  <string>libCBlueIDAccess.a</string>
32
35
  <key>SupportedArchitectures</key>
33
36
  <array>
34
37
  <string>arm64</string>
35
- <string>x86_64</string>
36
38
  </array>
37
39
  <key>SupportedPlatform</key>
38
- <string>macos</string>
40
+ <string>ios</string>
39
41
  </dict>
40
42
  <dict>
41
43
  <key>BinaryPath</key>
@@ -43,7 +45,7 @@
43
45
  <key>HeadersPath</key>
44
46
  <string>Headers</string>
45
47
  <key>LibraryIdentifier</key>
46
- <string>ios-arm64_x86_64-simulator</string>
48
+ <string>macos-arm64_x86_64</string>
47
49
  <key>LibraryPath</key>
48
50
  <string>libCBlueIDAccess.a</string>
49
51
  <key>SupportedArchitectures</key>
@@ -52,9 +54,7 @@
52
54
  <string>x86_64</string>
53
55
  </array>
54
56
  <key>SupportedPlatform</key>
55
- <string>ios</string>
56
- <key>SupportedPlatformVariant</key>
57
- <string>simulator</string>
57
+ <string>macos</string>
58
58
  </dict>
59
59
  </array>
60
60
  <key>CFBundlePackageType</key>
@@ -0,0 +1,145 @@
1
+ import Foundation
2
+
3
+ private class ForegroundScheduler {
4
+ private var timer: Timer?
5
+ private var scheduler: BlueAccessSyncScheduler?
6
+
7
+ func setup(_ scheduler: BlueAccessSyncScheduler) {
8
+ self.scheduler = scheduler
9
+ }
10
+
11
+ func suspend() {
12
+ timer?.invalidate()
13
+ timer = nil
14
+ }
15
+
16
+ func schedule(_ now: Bool? = false) {
17
+ guard #available(macOS 10.15, *) else {
18
+ blueLogWarn("Unsupported platform")
19
+ return
20
+ }
21
+
22
+ suspend()
23
+
24
+ if now == true {
25
+ self.handleTask()
26
+ } else {
27
+ blueRunInMainThread {
28
+ self.timer = Timer.scheduledTimer(
29
+ timeInterval: self.scheduler!.timeInterval,
30
+ target: self,
31
+ selector: #selector(self.handleTask),
32
+ userInfo: nil,
33
+ repeats: false
34
+ )
35
+ }
36
+ }
37
+ }
38
+
39
+ @available(macOS 10.15, *)
40
+ @objc private func handleTask() {
41
+ DispatchQueue.global(qos: .background).async {
42
+ Task {
43
+ do {
44
+ try await self.scheduler!.synchronizeAccessCredentials()
45
+ } catch {
46
+ blueLogError(error.localizedDescription)
47
+ }
48
+
49
+ if (self.scheduler!.autoSchedule) {
50
+ self.schedule()
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+ internal class BlueAccessSyncScheduler: BlueEventListener {
58
+ public static let shared = BlueAccessSyncScheduler()
59
+
60
+ let timeInterval: TimeInterval
61
+ let autoSchedule: Bool
62
+
63
+ private let foregroundScheduler = ForegroundScheduler()
64
+
65
+ private let command: BlueSynchronizeAccessCredentialsCommand
66
+
67
+ private var syncing = false
68
+
69
+ init(
70
+ timeInterval: TimeInterval? = 60 * 60 * 6, // every 6h by default
71
+ autoSchedule: Bool? = true,
72
+ command: BlueSynchronizeAccessCredentialsCommand? = nil
73
+ ) {
74
+ self.command = command ?? blueCommands.synchronizeAccessCredentials
75
+ self.timeInterval = timeInterval ?? 60
76
+ self.autoSchedule = autoSchedule ?? true
77
+
78
+ foregroundScheduler.setup(self)
79
+
80
+ blueAddEventListener(listener: self)
81
+ }
82
+
83
+ deinit {
84
+ blueRemoveEventListener(listener: self)
85
+ }
86
+
87
+ func willResignActive() {
88
+ suspend()
89
+ }
90
+
91
+ func willTerminate() {
92
+ suspend()
93
+ }
94
+
95
+ func didBecomeActive() {
96
+ schedule(true)
97
+ }
98
+
99
+ func didFinishLaunching() {
100
+ schedule(true)
101
+ }
102
+
103
+ func blueEvent(event: BlueEventType, data: Any?) {
104
+ if (event == .accessCredentialAdded) {
105
+ schedule()
106
+ }
107
+ }
108
+
109
+ func schedule(_ now: Bool? = false) {
110
+ do {
111
+ guard try blueAccessCredentialsKeyChain.getNumberOfEntries() > 0 else {
112
+ return
113
+ }
114
+ } catch {
115
+ blueLogError(error.localizedDescription)
116
+ }
117
+
118
+ blueRemoveEventListener(listener: self)
119
+
120
+ foregroundScheduler.schedule(now)
121
+ }
122
+
123
+ func suspend() {
124
+ foregroundScheduler.suspend()
125
+ }
126
+
127
+ func synchronizeAccessCredentials() async throws -> Void {
128
+ if (syncing) {
129
+ blueLogInfo("There is already a synchronization in progress")
130
+ return
131
+ }
132
+
133
+ syncing = true
134
+
135
+ blueFireListeners(fireEvent: BlueEventType.tokenSyncStarted, data: nil)
136
+
137
+ defer {
138
+ syncing = false
139
+
140
+ blueFireListeners(fireEvent: BlueEventType.tokenSyncFinished, data: nil)
141
+ }
142
+
143
+ _ = try await command.runAsync()
144
+ }
145
+ }
@@ -40,18 +40,3 @@ public struct BlueOpenAppSettingsCommand: BlueAsyncCommand {
40
40
  completionHandler(false)
41
41
  }
42
42
  }
43
-
44
- internal func blueAppHasLaunchedBefore() -> Bool {
45
- if let hasLaunchedBefore = hasLaunchedBefore {
46
- return hasLaunchedBefore
47
- }
48
-
49
- let result = blueAppStorage.getBool(id: "hasLaunchedBefore")
50
- if (!result) {
51
- blueAppStorage.storeBool(id: "hasLaunchedBefore", bool: true)
52
- }
53
-
54
- hasLaunchedBefore = true
55
-
56
- return result
57
- }
@@ -18,7 +18,7 @@ public final class BlueAppDelegate: NSObject {
18
18
  }
19
19
  #endif
20
20
 
21
- BlueTokenSyncScheduler.shared.didFinishLaunching()
21
+ BlueAccessSyncScheduler.shared.didFinishLaunching()
22
22
  }
23
23
 
24
24
  #if os(iOS) || os(watchOS)
@@ -38,7 +38,7 @@ public final class BlueAppDelegate: NSObject {
38
38
  #endif
39
39
 
40
40
  @objc public static func willResignActive() {
41
- BlueTokenSyncScheduler.shared.willResignActive()
41
+ BlueAccessSyncScheduler.shared.willResignActive()
42
42
  }
43
43
 
44
44
  @objc public static func didBecomeActive() {
@@ -46,7 +46,7 @@ public final class BlueAppDelegate: NSObject {
46
46
  blueNearbyAppBecameActive()
47
47
  #endif
48
48
 
49
- BlueTokenSyncScheduler.shared.didBecomeActive()
49
+ BlueAccessSyncScheduler.shared.didBecomeActive()
50
50
  }
51
51
 
52
52
  @objc public static func didEnterBackground() {
@@ -62,6 +62,6 @@ public final class BlueAppDelegate: NSObject {
62
62
  fatalError(error.localizedDescription)
63
63
  }
64
64
 
65
- BlueTokenSyncScheduler.shared.willTerminate()
65
+ BlueAccessSyncScheduler.shared.willTerminate()
66
66
  }
67
67
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blueid/access-capacitor",
3
- "version": "0.79.0",
3
+ "version": "0.80.0",
4
4
  "description": "Capacitor JS plugin for the BlueID Access SDK",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -1,265 +0,0 @@
1
- //
2
- // BlueTokenSyncScheduler.swift
3
- //
4
- // Description: Synchronize all tokens from all available credentials at specific intervals.
5
- //
6
- // If you would like to test the background task during development, execute the following code in the console:
7
- // ```
8
- // e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.blue-id.BlueTokenSyncScheduler"]
9
- // ```
10
- //
11
- // Reference: https://developer.apple.com/documentation/backgroundtasks/starting-and-terminating-tasks-during-development#Launch-a-Task
12
- //
13
- // Copyright © 2023 BlueID. All rights reserved.
14
- //
15
-
16
- import Foundation
17
-
18
- private let bgTaskIdentifier = "com.blue-id.BlueTokenSyncScheduler"
19
-
20
- private class ForegroundScheduler {
21
- private var timer: Timer?
22
- private var scheduler: BlueTokenSyncScheduler?
23
-
24
- func setup(_ scheduler: BlueTokenSyncScheduler) {
25
- self.scheduler = scheduler
26
- }
27
-
28
- func suspend() {
29
- timer?.invalidate()
30
- timer = nil
31
- }
32
-
33
- func schedule(_ now: Bool? = false) {
34
- guard #available(macOS 10.15, *) else {
35
- blueLogWarn("Unsupported platform")
36
- return
37
- }
38
-
39
- suspend()
40
-
41
- if now == true {
42
- self.handleTask()
43
- } else {
44
- blueRunInMainThread {
45
- self.timer = Timer.scheduledTimer(
46
- timeInterval: self.scheduler!.timeInterval,
47
- target: self,
48
- selector: #selector(self.handleTask),
49
- userInfo: nil,
50
- repeats: false
51
- )
52
- }
53
- }
54
- }
55
-
56
- @available(macOS 10.15, *)
57
- @objc private func handleTask() {
58
- DispatchQueue.global(qos: .background).async {
59
- Task {
60
- do {
61
- try await self.scheduler!.syncTokens()
62
- } catch {
63
- blueLogError("Tokens could not be synchronized")
64
- }
65
-
66
- if (self.scheduler!.autoSchedule) {
67
- self.schedule()
68
- }
69
- }
70
- }
71
- }
72
- }
73
-
74
-
75
- #if os(iOS) || os(watchOS)
76
- import BackgroundTasks
77
-
78
- private class BackgroundScheduler {
79
- private var scheduler: BlueTokenSyncScheduler?
80
-
81
- func setup(_ scheduler: BlueTokenSyncScheduler) {
82
- self.scheduler = scheduler
83
- }
84
-
85
- func registerIdentifiers() {
86
- let registered = BGTaskScheduler.shared.register(forTaskWithIdentifier: bgTaskIdentifier, using: DispatchQueue.global()) { task in
87
- self.handleTask(task: task as! BGProcessingTask)
88
- }
89
-
90
- if (!registered) {
91
- blueLogWarn("Could not register background task identifier: \(bgTaskIdentifier)")
92
- return
93
- }
94
-
95
- blueLogDebug("Background task identifier has been successfully registered: \(bgTaskIdentifier)")
96
- }
97
-
98
- func suspend() {
99
- BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: bgTaskIdentifier)
100
- }
101
-
102
- func schedule() {
103
- do {
104
- let request = BGProcessingTaskRequest(identifier: bgTaskIdentifier)
105
- request.earliestBeginDate = Date(timeIntervalSinceNow: scheduler!.timeInterval)
106
- request.requiresNetworkConnectivity = true
107
-
108
- try BGTaskScheduler.shared.submit(request)
109
-
110
- blueLogDebug("Background task has been successfully scheduled")
111
- } catch {
112
- blueLogError("Background task could not be scheduled: \(error)")
113
- }
114
- }
115
-
116
- private func handleTask(task: BGProcessingTask) -> Void {
117
- task.expirationHandler = {
118
- task.setTaskCompleted(success: false)
119
- }
120
-
121
- Task {
122
- do {
123
- try await scheduler!.syncTokens()
124
-
125
- task.setTaskCompleted(success: true)
126
- } catch {
127
- task.setTaskCompleted(success: false)
128
- }
129
-
130
- if (scheduler!.autoSchedule) {
131
- schedule()
132
- }
133
- }
134
- }
135
- }
136
- #endif
137
-
138
- internal class BlueTokenSyncScheduler: BlueEventListener {
139
- public static let shared = BlueTokenSyncScheduler()
140
-
141
- let timeInterval: TimeInterval
142
- let autoSchedule: Bool
143
-
144
- #if os(iOS) || os(watchOS)
145
- private let backgroundScheduler = BackgroundScheduler()
146
- #endif
147
-
148
- private let foregroundScheduler = ForegroundScheduler()
149
-
150
- private let command: BlueSynchronizeAccessCredentialCommand
151
-
152
- init(
153
- timeInterval: TimeInterval? = 60,
154
- autoSchedule: Bool? = true,
155
- command: BlueSynchronizeAccessCredentialCommand? = nil
156
- ) {
157
- self.command = command ?? blueCommands.synchronizeAccessCredential
158
- self.timeInterval = timeInterval ?? 60
159
- self.autoSchedule = autoSchedule ?? true
160
-
161
- foregroundScheduler.setup(self)
162
-
163
- #if os(iOS) || os(watchOS)
164
- backgroundScheduler.setup(self)
165
- #endif
166
-
167
- blueAddEventListener(listener: self)
168
- }
169
-
170
- deinit {
171
- blueRemoveEventListener(listener: self)
172
- }
173
-
174
- func willResignActive() {
175
- foregroundScheduler.suspend()
176
-
177
- #if os(iOS) || os(watchOS)
178
- backgroundScheduler.schedule()
179
- #endif
180
- }
181
-
182
- func didBecomeActive() {
183
- #if os(iOS) || os(watchOS)
184
- backgroundScheduler.suspend()
185
- #endif
186
-
187
- foregroundScheduler.schedule()
188
- }
189
-
190
- func didFinishLaunching() {
191
- setup()
192
- }
193
-
194
- func willTerminate() {
195
- suspend()
196
- }
197
-
198
- func blueEvent(event: BlueEventType, data: Any?) {
199
- if (event == .accessCredentialAdded) {
200
- schedule()
201
- }
202
- }
203
-
204
- func setup() {
205
- #if os(iOS)
206
- backgroundScheduler.registerIdentifiers()
207
- #endif
208
-
209
- schedule(true)
210
- }
211
-
212
- func schedule(_ now: Bool? = false) {
213
- do {
214
- guard try blueAccessCredentialsKeyChain.getNumberOfEntries() > 0 else {
215
- return
216
- }
217
- } catch {
218
- blueLogError(error.localizedDescription)
219
- }
220
-
221
- blueRemoveEventListener(listener: self)
222
-
223
- foregroundScheduler.schedule(now)
224
- }
225
-
226
- func suspend() {
227
- foregroundScheduler.suspend()
228
-
229
- #if os(iOS) || os(watchOS)
230
- backgroundScheduler.suspend()
231
- #endif
232
- }
233
-
234
- @available(macOS 10.15, *)
235
- func syncTokens() async throws -> Void {
236
- blueFireListeners(fireEvent: BlueEventType.tokenSyncStarted, data: nil)
237
-
238
- defer {
239
- blueFireListeners(fireEvent: BlueEventType.tokenSyncFinished, data: nil)
240
- }
241
-
242
- let accessCredentialList = try await blueCommands.getAccessCredentials.runAsync()
243
-
244
- await withThrowingTaskGroup(of: Void.self) { group in
245
- // After deleting the app, since we store credentials in KeyChain Access, they reappear upon app reinstallation.
246
- // But, as the device list is not saved there, it is lost.
247
- // So, when searching for nearby devices, nothing is shown due to the absence of the device list.
248
- // Although this issue would be solved in this synchronization, the synchronization may not return the device list as it depends on the refresh rate and can take up to 30 days, which is not ideal.
249
- // Therefore, we force a refresh in case the app has never been launched before.
250
- let forceRefresh = !blueAppHasLaunchedBefore()
251
-
252
- for credential in accessCredentialList.credentials {
253
- group.addTask {
254
- do {
255
- try await self.command.runAsync(credentialID: credential.credentialID.id, forceRefresh: forceRefresh)
256
-
257
- blueLogDebug("Access credential has been successfully synchronized: \(credential.credentialID.id)")
258
- } catch {
259
- blueLogError("Access credential could not be synchronized: \(credential.credentialID.id) - \(error.localizedDescription)")
260
- }
261
- }
262
- }
263
- }
264
- }
265
- }