@encorekit/web-sdk 2.0.3 → 2.0.6

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.
Files changed (79) hide show
  1. package/README.md +112 -40
  2. package/dist/cjs/index.cjs +1 -1
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/esm/index.js +1 -1
  5. package/dist/esm/index.js.map +1 -1
  6. package/dist/umd/encore.min.js +1 -1
  7. package/dist/umd/encore.min.js.map +1 -1
  8. package/embed/README.md +82 -367
  9. package/examples/ios-webview/EncoreURLBuilder.swift +179 -61
  10. package/examples/ios-webview/README.md +75 -354
  11. package/examples/ios-webview/SimpleEncoreView.swift +49 -36
  12. package/examples/ios-webview/SimpleExample.swift +30 -86
  13. package/package.json +3 -7
  14. package/types/analytics/DiagnosticsOutbox.d.ts +22 -0
  15. package/types/analytics/DiagnosticsOutbox.d.ts.map +1 -0
  16. package/types/analytics/ReliableOutbox.d.ts +40 -0
  17. package/types/analytics/ReliableOutbox.d.ts.map +1 -0
  18. package/types/analytics/events.d.ts +100 -0
  19. package/types/analytics/events.d.ts.map +1 -1
  20. package/types/analytics/placementResolved.d.ts +150 -0
  21. package/types/analytics/placementResolved.d.ts.map +1 -0
  22. package/types/api/APIClient.d.ts +10 -2
  23. package/types/api/APIClient.d.ts.map +1 -1
  24. package/types/api/errorReportLimits.d.ts +50 -0
  25. package/types/api/errorReportLimits.d.ts.map +1 -0
  26. package/types/api/generated/types.d.ts +54 -7
  27. package/types/api/generated/types.d.ts.map +1 -1
  28. package/types/core/Configuration.d.ts +5 -0
  29. package/types/core/Configuration.d.ts.map +1 -1
  30. package/types/core/Encore.d.ts +61 -2
  31. package/types/core/Encore.d.ts.map +1 -1
  32. package/types/core/OfferManager.d.ts +29 -3
  33. package/types/core/OfferManager.d.ts.map +1 -1
  34. package/types/core/PlacementBuilder.d.ts +26 -2
  35. package/types/core/PlacementBuilder.d.ts.map +1 -1
  36. package/types/core/StrictUnlock.d.ts +20 -0
  37. package/types/core/StrictUnlock.d.ts.map +1 -0
  38. package/types/core/StrictUnlockReconciler.d.ts +94 -0
  39. package/types/core/StrictUnlockReconciler.d.ts.map +1 -0
  40. package/types/core/TransactionStore.d.ts +57 -13
  41. package/types/core/TransactionStore.d.ts.map +1 -1
  42. package/types/core/VerificationPoller.d.ts.map +1 -1
  43. package/types/core/claimBehavior.d.ts +28 -0
  44. package/types/core/claimBehavior.d.ts.map +1 -0
  45. package/types/core/errorContext.d.ts +18 -0
  46. package/types/core/errorContext.d.ts.map +1 -0
  47. package/types/core/errorType.d.ts +59 -0
  48. package/types/core/errorType.d.ts.map +1 -0
  49. package/types/core/hostDisplay.d.ts +50 -0
  50. package/types/core/hostDisplay.d.ts.map +1 -0
  51. package/types/core/useCase.d.ts +21 -0
  52. package/types/core/useCase.d.ts.map +1 -1
  53. package/types/core/version.d.ts +1 -1
  54. package/types/experiments/ExposureOutbox.d.ts +4 -28
  55. package/types/experiments/ExposureOutbox.d.ts.map +1 -1
  56. package/types/types.d.ts +188 -3
  57. package/types/types.d.ts.map +1 -1
  58. package/types/ui/OfferCard.d.ts +3 -1
  59. package/types/ui/OfferCard.d.ts.map +1 -1
  60. package/types/ui/OfferCarousel.d.ts +5 -0
  61. package/types/ui/OfferCarousel.d.ts.map +1 -1
  62. package/types/ui/OfferModal.d.ts +20 -0
  63. package/types/ui/OfferModal.d.ts.map +1 -1
  64. package/types/ui/PrimerScreen.d.ts +18 -11
  65. package/types/ui/PrimerScreen.d.ts.map +1 -1
  66. package/types/ui/RedemptionScreen.d.ts +15 -19
  67. package/types/ui/RedemptionScreen.d.ts.map +1 -1
  68. package/types/ui/RewardActions.d.ts +35 -0
  69. package/types/ui/RewardActions.d.ts.map +1 -1
  70. package/types/ui/appearance.d.ts +14 -0
  71. package/types/ui/appearance.d.ts.map +1 -1
  72. package/types/ui/brandComponents.d.ts.map +1 -1
  73. package/types/ui/styles.d.ts.map +1 -1
  74. package/types/utils/logger.d.ts +11 -1
  75. package/types/utils/logger.d.ts.map +1 -1
  76. package/embed/index.html +0 -57
  77. package/embed/styles.css +0 -154
  78. package/examples/ios-webview/EncoreWebViewBridge.swift +0 -419
  79. package/examples/ios-webview/ExampleViewController.swift +0 -233
package/embed/index.html DELETED
@@ -1,57 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
6
- <meta name="apple-mobile-web-app-capable" content="yes">
7
- <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
8
- <title>Encore Embed</title>
9
- <link rel="stylesheet" href="embed/styles.css">
10
- <!-- Mobile-native styles for iOS bottom sheet UI -->
11
- <link rel="stylesheet" href="embed/mobile-styles.css">
12
- <!-- Override Web SDK modal to work as bottom sheet -->
13
- <link rel="stylesheet" href="embed/mobile-overrides.css">
14
- </head>
15
- <body>
16
- <!--
17
- This page is designed to be embedded in iOS WKWebView.
18
- It remains transparent until an offer is presented.
19
- -->
20
-
21
- <!-- Loading indicator (hidden by default) -->
22
- <div id="encore-loading" class="encore-loading" style="display: none;">
23
- <div class="encore-spinner"></div>
24
- </div>
25
-
26
- <!-- Debug panel (only shown in development) -->
27
- <div id="encore-debug" class="encore-debug" style="display: none;">
28
- <div class="debug-header">
29
- <span>Encore Debug</span>
30
- <div class="debug-controls">
31
- <button id="debug-minimize" title="Minimize">−</button>
32
- <button id="debug-close" title="Close">×</button>
33
- </div>
34
- </div>
35
- <div id="debug-log" class="debug-log"></div>
36
- </div>
37
-
38
- <!-- Credit Claimed Confirmation View -->
39
- <div id="encore-claimed" class="encore-claimed-view" style="display: none;">
40
- <div class="claimed-content">
41
- <div class="claimed-checkmark">✓</div>
42
- <h2 class="claimed-title">Credit Claimed!</h2>
43
- <p class="claimed-message">Your reward has been unlocked</p>
44
- <button id="claimed-done" class="encore-button encore-button-primary">Done</button>
45
- </div>
46
- </div>
47
-
48
- <!-- Load Encore Web SDK (local build) -->
49
- <script src="embed/dist/encore.min.js"></script>
50
-
51
- <!-- Load iOS Bridge -->
52
- <script src="embed/dist/bridge.min.js"></script>
53
-
54
- <!-- Load Application Logic -->
55
- <script src="embed/dist/app.min.js"></script>
56
- </body>
57
- </html>
package/embed/styles.css DELETED
@@ -1,154 +0,0 @@
1
- /**
2
- * Encore Embed Styles
3
- * Minimal styles for the embed container
4
- * The Web SDK provides its own modal styles
5
- */
6
-
7
- * {
8
- margin: 0;
9
- padding: 0;
10
- box-sizing: border-box;
11
- }
12
-
13
- html, body {
14
- width: 100%;
15
- height: 100%;
16
- /* White background to fill the sheet */
17
- background: white;
18
- overflow: hidden;
19
- /* No padding - SwiftUI sheet handles safe areas */
20
- padding: 0;
21
- }
22
-
23
- /* Prevent text selection in embed */
24
- body {
25
- -webkit-user-select: none;
26
- user-select: none;
27
- -webkit-touch-callout: none;
28
- }
29
-
30
- /* Loading indicator */
31
- .encore-loading {
32
- position: fixed;
33
- top: 50%;
34
- left: 50%;
35
- transform: translate(-50%, -50%);
36
- z-index: 9997;
37
- }
38
-
39
- .encore-spinner {
40
- width: 40px;
41
- height: 40px;
42
- border: 4px solid rgba(0, 0, 0, 0.1);
43
- border-top-color: #000;
44
- border-radius: 50%;
45
- animation: encore-spin 1s linear infinite;
46
- }
47
-
48
- @keyframes encore-spin {
49
- to { transform: rotate(360deg); }
50
- }
51
-
52
- /* Dark mode support */
53
- @media (prefers-color-scheme: dark) {
54
- .encore-spinner {
55
- border-color: rgba(255, 255, 255, 0.1);
56
- border-top-color: #fff;
57
- }
58
- }
59
-
60
- /* Debug panel */
61
- .encore-debug {
62
- position: fixed;
63
- bottom: 0;
64
- left: 0;
65
- right: 0;
66
- max-height: 40vh;
67
- background: rgba(0, 0, 0, 0.9);
68
- color: #00ff00;
69
- font-family: 'Courier New', monospace;
70
- font-size: 12px;
71
- z-index: 99999;
72
- border-top: 2px solid #00ff00;
73
- display: flex;
74
- flex-direction: column;
75
- transition: max-height 0.3s ease;
76
- }
77
-
78
- .encore-debug.minimized {
79
- max-height: 40px;
80
- }
81
-
82
- .encore-debug.minimized .debug-log {
83
- display: none;
84
- }
85
-
86
- .encore-debug.minimized .debug-header {
87
- border-bottom: none;
88
- }
89
-
90
- .debug-header {
91
- display: flex;
92
- justify-content: space-between;
93
- align-items: center;
94
- padding: 8px 12px;
95
- background: rgba(0, 0, 0, 0.95);
96
- border-bottom: 1px solid #00ff00;
97
- font-weight: bold;
98
- cursor: pointer;
99
- }
100
-
101
- .debug-controls {
102
- display: flex;
103
- gap: 8px;
104
- }
105
-
106
- #debug-minimize,
107
- #debug-close {
108
- background: transparent;
109
- border: 1px solid #00ff00;
110
- color: #00ff00;
111
- width: 24px;
112
- height: 24px;
113
- border-radius: 50%;
114
- cursor: pointer;
115
- font-size: 16px;
116
- line-height: 1;
117
- padding: 0;
118
- }
119
-
120
- #debug-minimize:active,
121
- #debug-close:active {
122
- background: rgba(0, 255, 0, 0.2);
123
- }
124
-
125
- .debug-log {
126
- flex: 1;
127
- overflow-y: auto;
128
- padding: 8px 12px;
129
- -webkit-overflow-scrolling: touch;
130
- }
131
-
132
- .debug-entry {
133
- margin-bottom: 4px;
134
- word-break: break-word;
135
- }
136
-
137
- .debug-entry.error {
138
- color: #ff0000;
139
- }
140
-
141
- .debug-entry.warning {
142
- color: #ffaa00;
143
- }
144
-
145
- .debug-entry.info {
146
- color: #00aaff;
147
- }
148
-
149
- /* Ensure Web SDK modal appears above everything */
150
- :root {
151
- --encore-modal-z-index: 9998;
152
- --encore-backdrop-z-index: 9997;
153
- }
154
-
@@ -1,419 +0,0 @@
1
- //
2
- // EncoreWebViewBridge.swift
3
- // Encore iOS WebView Bridge
4
- //
5
- // A Swift bridge for integrating Encore via WKWebView
6
- // instead of the native iOS SDK.
7
- //
8
-
9
- import Foundation
10
- import WebKit
11
-
12
- /// Entitlement types that can be granted to users
13
- public enum EncoreEntitlementType: String, Codable {
14
- case freeTrial = "free_trial"
15
- case discount = "discount"
16
- case credit = "credit"
17
- }
18
-
19
- /// Entitlement granted to a user
20
- public struct EncoreEntitlement: Codable {
21
- public let type: String
22
- public let value: Int?
23
- public let unit: String?
24
-
25
- public init(type: String, value: Int? = nil, unit: String? = nil) {
26
- self.type = type
27
- self.value = value
28
- self.unit = unit
29
- }
30
- }
31
-
32
- /// Reason why an entitlement was not granted
33
- public enum EncoreDeclineReason: String {
34
- case userClosedModal
35
- case userClickedOutside
36
- case userDeclinedLastOffer
37
- case noOffersAvailable
38
- case error
39
- case unknown
40
- }
41
-
42
- /// Error from Encore SDK
43
- public struct EncoreError: Error, Codable {
44
- public let code: String
45
- public let message: String
46
- public let context: String?
47
-
48
- public init(code: String, message: String, context: String? = nil) {
49
- self.code = code
50
- self.message = message
51
- self.context = context
52
- }
53
- }
54
-
55
- /// Delegate protocol for Encore events
56
- public protocol EncoreWebViewBridgeDelegate: AnyObject {
57
- /// Called when the embed page is ready
58
- func encoreBridgeDidBecomeReady(_ bridge: EncoreWebViewBridge)
59
-
60
- /// Called when SDK is initialized successfully
61
- func encoreBridge(_ bridge: EncoreWebViewBridge, didInitializeWithUserId userId: String)
62
-
63
- /// Called when an entitlement is granted
64
- func encoreBridge(_ bridge: EncoreWebViewBridge, didGrantEntitlement entitlement: EncoreEntitlement)
65
-
66
- /// Called when user declines an offer
67
- func encoreBridge(_ bridge: EncoreWebViewBridge, userDeclinedWithReason reason: EncoreDeclineReason)
68
-
69
- /// Called when an error occurs
70
- func encoreBridge(_ bridge: EncoreWebViewBridge, didEncounterError error: EncoreError)
71
- }
72
-
73
- /// Configuration for Encore SDK
74
- public struct EncoreConfiguration {
75
- public let apiKey: String
76
- public let environment: String
77
- public let userId: String?
78
- public let attributes: [String: String]?
79
- public let logLevel: String?
80
-
81
- public init(
82
- apiKey: String,
83
- environment: String = "production",
84
- userId: String? = nil,
85
- attributes: [String: String]? = nil,
86
- logLevel: String? = nil
87
- ) {
88
- self.apiKey = apiKey
89
- self.environment = environment
90
- self.userId = userId
91
- self.attributes = attributes
92
- self.logLevel = logLevel
93
- }
94
- }
95
-
96
- /// Bridge class for communicating with Encore Web SDK in WKWebView
97
- public class EncoreWebViewBridge: NSObject {
98
-
99
- // MARK: - Properties
100
-
101
- public weak var delegate: EncoreWebViewBridgeDelegate?
102
- public private(set) var webView: WKWebView?
103
-
104
- /// Indicates if the JavaScript embed is ready to receive messages
105
- /// Reset to false when navigation starts (page reload/navigation)
106
- public private(set) var isReady = false
107
-
108
- /// Indicates if the Encore SDK has been initialized in JavaScript
109
- /// Reset to false when navigation starts to handle page reloads properly
110
- public private(set) var isInitialized = false
111
-
112
- public private(set) var currentUserId: String?
113
-
114
- private let embedURL: URL
115
- private let configuration: EncoreConfiguration?
116
-
117
- /// Message queue for storing messages sent before the embed is ready
118
- /// Cleared on each navigation to prevent stale messages from being sent
119
- private var messageQueue: [[String: Any]] = []
120
-
121
- // MARK: - Initialization
122
-
123
- /// Initialize with a custom embed URL
124
- /// - Parameters:
125
- /// - embedURL: The URL of the Encore embed page
126
- /// - configuration: Optional configuration to auto-initialize SDK
127
- public init(embedURL: URL, configuration: EncoreConfiguration? = nil) {
128
- self.embedURL = embedURL
129
- self.configuration = configuration
130
- super.init()
131
- }
132
-
133
- /// Initialize with default Encore embed URL
134
- /// - Parameter configuration: Optional configuration to auto-initialize SDK
135
- public convenience init(configuration: EncoreConfiguration? = nil) {
136
- // Default to production embed URL
137
- let url = URL(string: "https://encorekit.com/embed/")!
138
- self.init(embedURL: url, configuration: configuration)
139
- }
140
-
141
- // MARK: - Setup
142
-
143
- /// Setup and configure the WKWebView
144
- /// Call this method and add the returned webView to your view hierarchy
145
- /// - Returns: Configured WKWebView instance
146
- public func setupWebView() -> WKWebView {
147
- let config = WKWebViewConfiguration()
148
-
149
- // Enable JavaScript
150
- config.preferences.javaScriptEnabled = true
151
-
152
- // Add message handler for Encore messages
153
- let contentController = WKUserContentController()
154
- contentController.add(self, name: "encore")
155
- config.userContentController = contentController
156
-
157
- // Create webView with transparent background
158
- let webView = WKWebView(frame: .zero, configuration: config)
159
- webView.backgroundColor = .clear
160
- webView.isOpaque = false
161
- webView.scrollView.isScrollEnabled = false
162
- webView.navigationDelegate = self
163
-
164
- self.webView = webView
165
-
166
- return webView
167
- }
168
-
169
- /// Load the Encore embed page
170
- public func loadEmbed() {
171
- guard let webView = webView else {
172
- print("[Encore] Error: WebView not setup. Call setupWebView() first.")
173
- return
174
- }
175
-
176
- var urlComponents = URLComponents(url: embedURL, resolvingAgainstBaseURL: true)
177
-
178
- // If configuration provided, add as URL parameters for quick initialization
179
- if let config = configuration {
180
- var queryItems: [URLQueryItem] = [
181
- URLQueryItem(name: "apiKey", value: config.apiKey),
182
- URLQueryItem(name: "environment", value: config.environment)
183
- ]
184
-
185
- if let userId = config.userId {
186
- queryItems.append(URLQueryItem(name: "userId", value: userId))
187
- }
188
-
189
- urlComponents?.queryItems = queryItems
190
- }
191
-
192
- guard let finalURL = urlComponents?.url else {
193
- print("[Encore] Error: Invalid embed URL")
194
- return
195
- }
196
-
197
- let request = URLRequest(url: finalURL)
198
- webView.load(request)
199
- }
200
-
201
- // MARK: - Public Methods
202
-
203
- /// Configure the Encore SDK
204
- /// - Parameter configuration: Configuration object
205
- public func configure(_ configuration: EncoreConfiguration) {
206
- var payload: [String: Any] = [
207
- "apiKey": configuration.apiKey,
208
- "environment": configuration.environment
209
- ]
210
-
211
- if let userId = configuration.userId {
212
- payload["userId"] = userId
213
- }
214
-
215
- if let attributes = configuration.attributes {
216
- payload["attributes"] = attributes
217
- }
218
-
219
- if let logLevel = configuration.logLevel {
220
- payload["logLevel"] = logLevel
221
- }
222
-
223
- sendMessage(type: "configure", payload: payload)
224
- }
225
-
226
- /// Present an offer to the user
227
- public func presentOffer() {
228
- sendMessage(type: "presentOffer", payload: [:])
229
- }
230
-
231
- /// Identify a user
232
- /// - Parameters:
233
- /// - userId: User identifier
234
- /// - attributes: Optional user attributes
235
- public func identify(userId: String, attributes: [String: String]? = nil) {
236
- var payload: [String: Any] = ["userId": userId]
237
- if let attributes = attributes {
238
- payload["attributes"] = attributes
239
- }
240
- sendMessage(type: "identify", payload: payload)
241
- }
242
-
243
- /// Set user attributes
244
- /// - Parameter attributes: User attributes dictionary
245
- public func setUserAttributes(_ attributes: [String: String]) {
246
- sendMessage(type: "setUserAttributes", payload: ["attributes": attributes])
247
- }
248
-
249
- /// Reset the SDK state
250
- /// This sends a reset message to the JS SDK and clears the local state.
251
- /// Note: Page reloads automatically reset state in didStartProvisionalNavigation
252
- public func reset() {
253
- sendMessage(type: "reset", payload: [:])
254
- isInitialized = false
255
- currentUserId = nil
256
- }
257
-
258
- /// Get current SDK state
259
- public func getState() {
260
- sendMessage(type: "getState", payload: [:])
261
- }
262
-
263
- // MARK: - Private Methods
264
-
265
- private func sendMessage(type: String, payload: [String: Any]) {
266
- let message: [String: Any] = [
267
- "type": type,
268
- "payload": payload
269
- ]
270
-
271
- if isReady {
272
- postMessageToWebView(message)
273
- } else {
274
- // Queue messages until webview is ready
275
- messageQueue.append(message)
276
- }
277
- }
278
-
279
- private func postMessageToWebView(_ message: [String: Any]) {
280
- guard let webView = webView else { return }
281
-
282
- do {
283
- let jsonData = try JSONSerialization.data(withJSONObject: message)
284
- let jsonString = String(data: jsonData, encoding: .utf8) ?? "{}"
285
-
286
- let script = """
287
- window.postMessage(\(jsonString), '*');
288
- """
289
-
290
- webView.evaluateJavaScript(script) { _, error in
291
- if let error = error {
292
- print("[Encore] Error posting message: \(error)")
293
- }
294
- }
295
- } catch {
296
- print("[Encore] Error serializing message: \(error)")
297
- }
298
- }
299
-
300
- private func flushMessageQueue() {
301
- while !messageQueue.isEmpty {
302
- let message = messageQueue.removeFirst()
303
- postMessageToWebView(message)
304
- }
305
- }
306
-
307
- private func handleMessage(_ body: Any) {
308
- guard let dict = body as? [String: Any],
309
- let type = dict["type"] as? String else {
310
- return
311
- }
312
-
313
- let payload = dict["payload"] as? [String: Any] ?? [:]
314
-
315
- print("[Encore] Received message: \(type)")
316
-
317
- switch type {
318
- case "encore:ready":
319
- isReady = true
320
- flushMessageQueue()
321
- delegate?.encoreBridgeDidBecomeReady(self)
322
-
323
- case "encore:initialized":
324
- isInitialized = true
325
- if let userId = payload["userId"] as? String {
326
- currentUserId = userId
327
- delegate?.encoreBridge(self, didInitializeWithUserId: userId)
328
- }
329
-
330
- case "encore:entitlementGranted":
331
- if let entitlementData = payload["entitlement"] as? [String: Any],
332
- let jsonData = try? JSONSerialization.data(withJSONObject: entitlementData),
333
- let entitlement = try? JSONDecoder().decode(EncoreEntitlement.self, from: jsonData) {
334
- delegate?.encoreBridge(self, didGrantEntitlement: entitlement)
335
- }
336
-
337
- case "encore:userDeclined":
338
- if let reasonString = payload["reason"] as? String,
339
- let reason = EncoreDeclineReason(rawValue: reasonString) {
340
- delegate?.encoreBridge(self, userDeclinedWithReason: reason)
341
- } else {
342
- delegate?.encoreBridge(self, userDeclinedWithReason: .unknown)
343
- }
344
-
345
- case "encore:error":
346
- if let jsonData = try? JSONSerialization.data(withJSONObject: payload),
347
- let error = try? JSONDecoder().decode(EncoreError.self, from: jsonData) {
348
- delegate?.encoreBridge(self, didEncounterError: error)
349
- }
350
-
351
- case "encore:state":
352
- // Handle state response if needed
353
- print("[Encore] Current state: \(payload)")
354
-
355
- default:
356
- print("[Encore] Unknown message type: \(type)")
357
- }
358
- }
359
- }
360
-
361
- // MARK: - WKScriptMessageHandler
362
-
363
- extension EncoreWebViewBridge: WKScriptMessageHandler {
364
- public func userContentController(
365
- _ userContentController: WKUserContentController,
366
- didReceive message: WKScriptMessage
367
- ) {
368
- guard message.name == "encore" else { return }
369
- handleMessage(message.body)
370
- }
371
- }
372
-
373
- // MARK: - WKNavigationDelegate
374
-
375
- extension EncoreWebViewBridge: WKNavigationDelegate {
376
- public func webView(
377
- _ webView: WKWebView,
378
- didStartProvisionalNavigation navigation: WKNavigation!
379
- ) {
380
- print("[Encore] WebView started loading")
381
-
382
- // Reset state when navigation starts - the JS environment will be reloaded
383
- // This ensures we re-initialize even if the user refreshes or navigates
384
- isReady = false
385
- isInitialized = false
386
- messageQueue.removeAll()
387
-
388
- print("[Encore] State reset for new navigation")
389
- }
390
-
391
- public func webView(
392
- _ webView: WKWebView,
393
- didFinish navigation: WKNavigation!
394
- ) {
395
- print("[Encore] WebView finished loading")
396
-
397
- // If we have initial configuration and haven't initialized yet, do it now
398
- // Note: isInitialized will be false after didStartProvisionalNavigation reset,
399
- // so this will properly re-initialize on page reloads
400
- if !isInitialized, let config = configuration {
401
- print("[Encore] Auto-configuring SDK with stored configuration")
402
- configure(config)
403
- }
404
- }
405
-
406
- public func webView(
407
- _ webView: WKWebView,
408
- didFail navigation: WKNavigation!,
409
- withError error: Error
410
- ) {
411
- print("[Encore] WebView navigation failed: \(error.localizedDescription)")
412
-
413
- // Reset state on navigation failure as well
414
- isReady = false
415
- isInitialized = false
416
- messageQueue.removeAll()
417
- }
418
- }
419
-