@adobe/react-native-aepmessaging 7.1.1 → 7.2.1
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/README.md +61 -2
- package/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingConstants.java +19 -0
- package/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingModule.java +152 -18
- package/android/src/main/java/com/adobe/marketing/mobile/reactnative/messaging/RCTAEPMessagingUtil.java +1 -1
- package/dist/Messaging.d.ts +17 -0
- package/dist/Messaging.js +34 -7
- package/dist/Messaging.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/models/ContentCard.d.ts +6 -1
- package/dist/models/ContentCard.js +9 -0
- package/dist/models/ContentCard.js.map +1 -1
- package/dist/models/HTMLProposition.d.ts +6 -2
- package/dist/models/HTMLProposition.js +9 -0
- package/dist/models/HTMLProposition.js.map +1 -1
- package/dist/models/JSONProposition.d.ts +12 -0
- package/dist/models/{JSONPropositionItem.js → JSONProposition.js} +10 -1
- package/dist/models/JSONProposition.js.map +1 -0
- package/dist/models/Message.d.ts +14 -0
- package/dist/models/Message.js +51 -1
- package/dist/models/Message.js.map +1 -1
- package/dist/models/MessagingProposition.d.ts +10 -3
- package/dist/models/MessagingProposition.js +45 -0
- package/dist/models/MessagingProposition.js.map +1 -1
- package/dist/models/MessagingPropositionItem.d.ts +3 -2
- package/dist/models/PropositionItem.d.ts +83 -0
- package/dist/models/PropositionItem.js +78 -0
- package/dist/models/PropositionItem.js.map +1 -0
- package/ios/src/RCTAEPMessaging.mm +32 -0
- package/ios/src/RCTAEPMessaging.swift +150 -45
- package/ios/src/RCTAEPMessagingConstants.swift +5 -1
- package/ios/src/RCTAEPMessagingDataBridge.swift +19 -0
- package/package.json +2 -2
- package/src/Messaging.ts +46 -13
- package/src/index.ts +13 -5
- package/src/models/ContentCard.ts +12 -1
- package/src/models/HTMLProposition.ts +15 -6
- package/src/models/{JSONPropositionItem.ts → JSONProposition.ts} +15 -6
- package/src/models/Message.ts +61 -2
- package/src/models/MessagingProposition.ts +45 -3
- package/src/models/MessagingPropositionItem.ts +6 -2
- package/src/models/PropositionItem.ts +135 -0
- package/tutorials/In-App Messaging.md +67 -0
- package/dist/models/JSONPropositionItem.d.ts +0 -8
- package/dist/models/JSONPropositionItem.js.map +0 -1
|
@@ -21,6 +21,7 @@ import WebKit
|
|
|
21
21
|
@objc(RCTAEPMessaging)
|
|
22
22
|
public class RCTAEPMessaging: RCTEventEmitter, MessagingDelegate {
|
|
23
23
|
private var messageCache = [String: Message]()
|
|
24
|
+
private var jsHandlerMessageCache = [String: Message]()
|
|
24
25
|
private var latestMessage: Message? = nil
|
|
25
26
|
private let semaphore = DispatchSemaphore(value: 0)
|
|
26
27
|
private var shouldSaveMessage = false
|
|
@@ -64,7 +65,7 @@ public class RCTAEPMessaging: RCTEventEmitter, MessagingDelegate {
|
|
|
64
65
|
) {
|
|
65
66
|
resolve(self.latestMessage != nil ? RCTAEPMessagingDataBridge.transformToMessage(message: self.latestMessage!) : nil)
|
|
66
67
|
}
|
|
67
|
-
|
|
68
|
+
|
|
68
69
|
@objc
|
|
69
70
|
func getPropositionsForSurfaces(
|
|
70
71
|
_ surfaces: [String],
|
|
@@ -72,16 +73,29 @@ public class RCTAEPMessaging: RCTEventEmitter, MessagingDelegate {
|
|
|
72
73
|
withRejecter reject: @escaping RCTPromiseRejectBlock
|
|
73
74
|
) {
|
|
74
75
|
let surfacePaths = surfaces.map { $0.isEmpty ? Surface() : Surface(path: $0) }
|
|
75
|
-
Messaging.getPropositionsForSurfaces(surfacePaths) { propositions, error in
|
|
76
|
+
Messaging.getPropositionsForSurfaces(surfacePaths) { [weak self] propositions, error in
|
|
77
|
+
guard let self = self else { return }
|
|
76
78
|
guard error == nil else {
|
|
77
79
|
reject("Unable to Retrieve Propositions", nil, nil)
|
|
78
80
|
return
|
|
79
81
|
}
|
|
80
|
-
|
|
81
|
-
resolve([String: Any]())
|
|
82
|
-
return
|
|
82
|
+
guard let propositions = propositions, !propositions.isEmpty else {
|
|
83
|
+
resolve([String: Any]())
|
|
84
|
+
return
|
|
83
85
|
}
|
|
84
|
-
|
|
86
|
+
|
|
87
|
+
// Populate uuid->Proposition map using scopeDetails.activity.id
|
|
88
|
+
for (_, list) in propositions {
|
|
89
|
+
for proposition in list {
|
|
90
|
+
if let pMap = proposition.asDictionary() {
|
|
91
|
+
if let key = RCTAEPMessagingDataBridge.extractActivityId(from: pMap) {
|
|
92
|
+
self.propositionByUuid[key] = proposition
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
resolve(RCTAEPMessagingDataBridge.transformPropositionDict(dict: propositions))
|
|
85
99
|
}
|
|
86
100
|
}
|
|
87
101
|
|
|
@@ -113,92 +127,81 @@ public class RCTAEPMessaging: RCTEventEmitter, MessagingDelegate {
|
|
|
113
127
|
) {
|
|
114
128
|
let mapped = surfaces.map { Surface(path: $0) }
|
|
115
129
|
Messaging.updatePropositionsForSurfaces(mapped)
|
|
130
|
+
propositionByUuid.removeAll()
|
|
116
131
|
resolve(nil)
|
|
117
132
|
}
|
|
118
133
|
|
|
119
134
|
/// Message Class Methods
|
|
120
135
|
@objc
|
|
121
|
-
func
|
|
122
|
-
_ id: String
|
|
123
|
-
withResolver resolve: @escaping RCTPromiseResolveBlock,
|
|
124
|
-
withRejecter reject: @escaping RCTPromiseRejectBlock
|
|
136
|
+
func clear(
|
|
137
|
+
_ id: String
|
|
125
138
|
) {
|
|
126
139
|
let msg = messageCache[id]
|
|
127
140
|
if msg != nil {
|
|
128
141
|
messageCache.removeValue(forKey: msg!.id)
|
|
129
|
-
|
|
142
|
+
print("clear: \(id) removed")
|
|
143
|
+
} else {
|
|
144
|
+
print("clear: \(id) not found")
|
|
130
145
|
}
|
|
131
|
-
reject(Constants.CACHE_MISS, nil, nil)
|
|
132
146
|
}
|
|
133
147
|
|
|
134
148
|
@objc
|
|
135
|
-
func
|
|
149
|
+
func dismiss(
|
|
136
150
|
_ id: String,
|
|
137
|
-
|
|
138
|
-
withResolver resolve: @escaping RCTPromiseResolveBlock,
|
|
139
|
-
withRejecter reject: @escaping RCTPromiseRejectBlock
|
|
151
|
+
suppressAutoTrack: Bool
|
|
140
152
|
) {
|
|
141
153
|
let msg = messageCache[id]
|
|
142
154
|
if msg != nil {
|
|
143
155
|
msg!.dismiss(suppressAutoTrack: suppressAutoTrack)
|
|
144
|
-
|
|
145
|
-
|
|
156
|
+
print("dismiss: \(id) to \(suppressAutoTrack)")
|
|
157
|
+
} else {
|
|
158
|
+
print("dismiss: \(id) not found")
|
|
146
159
|
}
|
|
147
|
-
reject(Constants.CACHE_MISS, nil, nil)
|
|
148
160
|
}
|
|
149
161
|
|
|
150
162
|
@objc
|
|
151
163
|
func setAutoTrack(
|
|
152
164
|
_ id: String,
|
|
153
|
-
|
|
154
|
-
withResolver resolve: @escaping RCTPromiseResolveBlock,
|
|
155
|
-
withRejecter reject: @escaping RCTPromiseRejectBlock
|
|
165
|
+
autoTrack: Bool
|
|
156
166
|
) {
|
|
157
|
-
|
|
158
167
|
let msg = messageCache[id]
|
|
159
|
-
if msg != nil {
|
|
160
|
-
msg!.autoTrack =
|
|
161
|
-
|
|
162
|
-
|
|
168
|
+
if (msg != nil) {
|
|
169
|
+
msg!.autoTrack = autoTrack
|
|
170
|
+
print("setAutoTrack: \(id) to \(autoTrack)")
|
|
171
|
+
} else {
|
|
172
|
+
print("setAutoTrack: \(id) not found")
|
|
163
173
|
}
|
|
164
|
-
reject(Constants.CACHE_MISS, nil, nil)
|
|
165
174
|
}
|
|
166
175
|
|
|
167
176
|
@objc
|
|
168
|
-
private func
|
|
169
|
-
_ id: String
|
|
170
|
-
withResolver resolve: @escaping RCTPromiseResolveBlock,
|
|
171
|
-
withRejecter reject: @escaping RCTPromiseRejectBlock
|
|
177
|
+
private func show(
|
|
178
|
+
_ id: String
|
|
172
179
|
) {
|
|
173
180
|
let msg = messageCache[id]
|
|
174
181
|
if msg != nil {
|
|
175
182
|
msg!.show()
|
|
176
|
-
|
|
177
|
-
|
|
183
|
+
print("show: \(id) shown")
|
|
184
|
+
} else {
|
|
185
|
+
print("show: \(id) not found")
|
|
178
186
|
}
|
|
179
|
-
reject(Constants.CACHE_MISS, nil, nil)
|
|
180
|
-
|
|
181
187
|
}
|
|
182
188
|
|
|
183
189
|
@objc
|
|
184
|
-
func
|
|
190
|
+
func track(
|
|
185
191
|
_ id: String,
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
withResolver resolve: @escaping RCTPromiseResolveBlock,
|
|
189
|
-
withRejecter reject: @escaping RCTPromiseRejectBlock
|
|
192
|
+
interaction: String,
|
|
193
|
+
eventType: Int
|
|
190
194
|
) {
|
|
191
|
-
|
|
192
195
|
let msg = messageCache[id]
|
|
193
196
|
let eventType =
|
|
194
197
|
MessagingEdgeEventType.init(rawValue: eventType)
|
|
195
198
|
?? MessagingEdgeEventType.dismiss
|
|
196
199
|
if msg != nil {
|
|
197
200
|
msg!.track(interaction, withEdgeEventType: eventType)
|
|
198
|
-
|
|
199
|
-
|
|
201
|
+
print("track: \(id) to \(interaction) and \(eventType)")
|
|
202
|
+
} else {
|
|
203
|
+
print("track: \(id) not found")
|
|
200
204
|
}
|
|
201
|
-
reject(Constants.CACHE_MISS, nil, nil)
|
|
202
205
|
}
|
|
203
206
|
|
|
204
207
|
@objc
|
|
@@ -249,11 +252,95 @@ public class RCTAEPMessaging: RCTEventEmitter, MessagingDelegate {
|
|
|
249
252
|
}
|
|
250
253
|
}
|
|
251
254
|
|
|
255
|
+
@objc
|
|
256
|
+
func handleJavascriptMessage(
|
|
257
|
+
_ messageId: String,
|
|
258
|
+
handlerName: String
|
|
259
|
+
) {
|
|
260
|
+
guard let message = jsHandlerMessageCache[messageId] else {
|
|
261
|
+
print("[RCTAEPMessaging] handleJavascriptMessage: No message found in cache for messageId: \(messageId)")
|
|
262
|
+
return
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
message.handleJavascriptMessage(handlerName) { [weak self] content in
|
|
266
|
+
self?.emitNativeEvent(
|
|
267
|
+
name: Constants.ON_JAVASCRIPT_MESSAGE_EVENT,
|
|
268
|
+
body: [
|
|
269
|
+
Constants.MESSAGE_ID_KEY: messageId,
|
|
270
|
+
Constants.HANDLER_NAME_KEY: handlerName,
|
|
271
|
+
Constants.CONTENT_KEY: content ?? ""
|
|
272
|
+
]
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/// MARK: - Unified PropositionItem Tracking Methods
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Tracks interactions with a PropositionItem using the provided interaction and event type.
|
|
281
|
+
* This method is used by the React Native PropositionItem.track() method.
|
|
282
|
+
*
|
|
283
|
+
* - Parameters:
|
|
284
|
+
* - uuid: The UUID mapped to the PropositionItem (derived from activityId)
|
|
285
|
+
* - interaction: A custom string value to be recorded in the interaction (optional)
|
|
286
|
+
* - eventType: The MessagingEdgeEventType numeric value
|
|
287
|
+
* - tokens: Array containing the sub-item tokens for recording interaction (optional)
|
|
288
|
+
*/
|
|
289
|
+
|
|
290
|
+
@objc
|
|
291
|
+
func trackPropositionItem(
|
|
292
|
+
_ uuid: String,
|
|
293
|
+
interaction: String?,
|
|
294
|
+
eventType: Int,
|
|
295
|
+
tokens: [String]?,
|
|
296
|
+
withResolver resolve: @escaping RCTPromiseResolveBlock,
|
|
297
|
+
withRejecter reject: @escaping RCTPromiseRejectBlock
|
|
298
|
+
) {
|
|
299
|
+
NSLog("[MessagingBridge] trackPropositionItem called with eventType=\(eventType), uuid=\(uuid), interaction=\(String(describing: interaction)), tokens=\(String(describing: tokens))")
|
|
300
|
+
|
|
301
|
+
guard !uuid.isEmpty else {
|
|
302
|
+
NSLog("[MessagingBridge] Empty uuid provided; no-op.")
|
|
303
|
+
resolve(nil)
|
|
304
|
+
return
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
guard let proposition = propositionByUuid[uuid] else {
|
|
308
|
+
NSLog("[MessagingBridge] No cached proposition for uuid=\(uuid); no-op.")
|
|
309
|
+
resolve(nil)
|
|
310
|
+
return
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
NSLog("[MessagingBridge] Found proposition for uuid=\(uuid). scope=\(proposition.scope), items=\(proposition.items.count)")
|
|
314
|
+
|
|
315
|
+
// Event type mapping (Android parity)
|
|
316
|
+
let edgeEventType = mapEdgeEventType(eventType) ?? .display
|
|
317
|
+
|
|
318
|
+
// Track on the first item under this proposition
|
|
319
|
+
guard let item = proposition.items.first else {
|
|
320
|
+
NSLog("[MessagingBridge] Proposition for uuid=\(uuid) has no items; no-op.")
|
|
321
|
+
resolve(nil)
|
|
322
|
+
return
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Direct call without normalization (expecting valid inputs)
|
|
326
|
+
NSLog("[MessagingBridge] Tracking (direct) uuid=\(uuid), interaction=\(String(describing: interaction)), tokens=\(String(describing: tokens)), eventType=\(edgeEventType.rawValue)")
|
|
327
|
+
item.track(interaction, withEdgeEventType: edgeEventType, forTokens: tokens)
|
|
328
|
+
|
|
329
|
+
NSLog("[MessagingBridge] Tracking complete for uuid=\(uuid)")
|
|
330
|
+
resolve(nil)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
// Map uuid (scopeDetails.activity.id) -> parent Proposition
|
|
336
|
+
private var propositionByUuid = [String: Proposition]()
|
|
337
|
+
|
|
252
338
|
// Messaging Delegate Methods
|
|
253
339
|
public func onDismiss(message: Showable) {
|
|
254
340
|
if let fullscreenMessage = message as? FullscreenMessage,
|
|
255
341
|
let parentMessage = fullscreenMessage.parent
|
|
256
342
|
{
|
|
343
|
+
jsHandlerMessageCache.removeValue(forKey: parentMessage.id)
|
|
257
344
|
emitNativeEvent(
|
|
258
345
|
name: Constants.ON_DISMISS_EVENT,
|
|
259
346
|
body: RCTAEPMessagingDataBridge.transformToMessage(
|
|
@@ -267,6 +354,7 @@ public class RCTAEPMessaging: RCTEventEmitter, MessagingDelegate {
|
|
|
267
354
|
if let fullscreenMessage = message as? FullscreenMessage,
|
|
268
355
|
let message = fullscreenMessage.parent
|
|
269
356
|
{
|
|
357
|
+
jsHandlerMessageCache[message.id] = message
|
|
270
358
|
emitNativeEvent(
|
|
271
359
|
name: Constants.ON_SHOW_EVENT,
|
|
272
360
|
body: RCTAEPMessagingDataBridge.transformToMessage(message: message)
|
|
@@ -328,3 +416,20 @@ public class RCTAEPMessaging: RCTEventEmitter, MessagingDelegate {
|
|
|
328
416
|
RCTAEPMessaging.emitter.sendEvent(withName: name, body: body)
|
|
329
417
|
}
|
|
330
418
|
}
|
|
419
|
+
|
|
420
|
+
// MARK: - Private helpers
|
|
421
|
+
private extension RCTAEPMessaging {
|
|
422
|
+
/// Maps JS MessagingEdgeEventType integer values to AEPMessaging.MessagingEdgeEventType cases
|
|
423
|
+
/// JS enum values: DISMISS=0, INTERACT=1, TRIGGER=2, DISPLAY=3, PUSH_APPLICATION_OPENED=4, PUSH_CUSTOM_ACTION=5
|
|
424
|
+
func mapEdgeEventType(_ value: Int) -> MessagingEdgeEventType? {
|
|
425
|
+
switch value {
|
|
426
|
+
case 0: return .dismiss
|
|
427
|
+
case 1: return .interact
|
|
428
|
+
case 2: return .trigger
|
|
429
|
+
case 3: return .display
|
|
430
|
+
case 4: return .pushApplicationOpened
|
|
431
|
+
case 5: return .pushCustomAction
|
|
432
|
+
default: return nil
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
@@ -16,7 +16,11 @@ class Constants {
|
|
|
16
16
|
static let ON_SHOW_EVENT = "onShow"
|
|
17
17
|
static let SHOULD_SHOW_MESSAGE_EVENT = "shouldShowMessage"
|
|
18
18
|
static let URL_LOADED_EVENT = "urlLoaded"
|
|
19
|
+
static let ON_JAVASCRIPT_MESSAGE_EVENT = "onJavascriptMessage"
|
|
19
20
|
static let SUPPORTED_EVENTS = [
|
|
20
|
-
ON_DISMISS_EVENT, ON_SHOW_EVENT, SHOULD_SHOW_MESSAGE_EVENT, URL_LOADED_EVENT,
|
|
21
|
+
ON_DISMISS_EVENT, ON_SHOW_EVENT, SHOULD_SHOW_MESSAGE_EVENT, URL_LOADED_EVENT, ON_JAVASCRIPT_MESSAGE_EVENT
|
|
21
22
|
]
|
|
23
|
+
static let MESSAGE_ID_KEY = "messageId"
|
|
24
|
+
static let HANDLER_NAME_KEY = "handlerName"
|
|
25
|
+
static let CONTENT_KEY = "content"
|
|
22
26
|
}
|
|
@@ -27,4 +27,23 @@ public class RCTAEPMessagingDataBridge: NSObject {
|
|
|
27
27
|
.map({ $0.asDictionary() })
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
|
|
31
|
+
/// Extracts the activity identifier from a proposition dictionary at scopeDetails.activity.id
|
|
32
|
+
static func extractActivityId(from propositionDict: [String: Any]) -> String? {
|
|
33
|
+
guard let scopeDetails = propositionDict["scopeDetails"] as? [String: Any] else {
|
|
34
|
+
NSLog("[MessagingBridge] Missing scopeDetails on proposition; cannot extract activity.id")
|
|
35
|
+
return nil
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
guard let activity = scopeDetails["activity"] as? [String: Any] else {
|
|
39
|
+
NSLog("[MessagingBridge] Missing activity under scopeDetails; cannot extract activity.id")
|
|
40
|
+
return nil
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
guard let id = activity["id"] as? String, !id.isEmpty else {
|
|
44
|
+
NSLog("[MessagingBridge] Missing or empty activity.id; skipping uuid cache mapping")
|
|
45
|
+
return nil
|
|
46
|
+
}
|
|
47
|
+
return id
|
|
48
|
+
}
|
|
30
49
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/react-native-aepmessaging",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.2.1",
|
|
4
4
|
"description": "Adobe Experience Platform support for React Native apps.",
|
|
5
5
|
"homepage": "https://developer.adobe.com/client-sdks/documentation/",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"installConfig": {
|
|
40
40
|
"hoistingLimits": "dependencies"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "9e1fa8cd101f66602d9f9250fe8aa1f32b341da9"
|
|
43
43
|
}
|
package/src/Messaging.ts
CHANGED
|
@@ -37,6 +37,7 @@ export interface NativeMessagingModule {
|
|
|
37
37
|
updatePropositionsForSurfaces: (surfaces: string[]) => void;
|
|
38
38
|
trackContentCardDisplay: (proposition: MessagingProposition, contentCard: ContentCard) => void;
|
|
39
39
|
trackContentCardInteraction: (proposition: MessagingProposition, contentCard: ContentCard) => void;
|
|
40
|
+
trackPropositionItem: (itemId: string, interaction: string | null, eventType: number, tokens: string[] | null) => void;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
const RCTAEPMessaging: NativeModule & NativeMessagingModule =
|
|
@@ -90,17 +91,46 @@ class Messaging {
|
|
|
90
91
|
static async getPropositionsForSurfaces(
|
|
91
92
|
surfaces: string[]
|
|
92
93
|
): Promise<Record<string, MessagingProposition[]>> {
|
|
93
|
-
return await RCTAEPMessaging.getPropositionsForSurfaces(surfaces);
|
|
94
|
-
}
|
|
95
94
|
|
|
95
|
+
const propositionsList = await RCTAEPMessaging.getPropositionsForSurfaces(surfaces);
|
|
96
|
+
let messagingPropositionsForSurfaces: Record<string, MessagingProposition[]> = {};
|
|
97
|
+
|
|
98
|
+
for (const [surface, propositions] of Object.entries(propositionsList)) {
|
|
99
|
+
messagingPropositionsForSurfaces[surface] = propositions.map(
|
|
100
|
+
(proposition) => new MessagingProposition(proposition)
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return messagingPropositionsForSurfaces;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @deprecated Use PropositionItem.track(...) instead.
|
|
109
|
+
*/
|
|
96
110
|
static trackContentCardDisplay(proposition: MessagingProposition, contentCard: ContentCard): void {
|
|
97
111
|
RCTAEPMessaging.trackContentCardDisplay(proposition, contentCard);
|
|
98
112
|
}
|
|
99
113
|
|
|
114
|
+
/**
|
|
115
|
+
* @deprecated Use PropositionItem.track(...) instead.
|
|
116
|
+
*/
|
|
100
117
|
static trackContentCardInteraction(proposition: MessagingProposition, contentCard: ContentCard): void {
|
|
101
118
|
RCTAEPMessaging.trackContentCardInteraction(proposition, contentCard);
|
|
102
119
|
}
|
|
103
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Tracks interactions with a PropositionItem using the provided interaction and event type.
|
|
123
|
+
* This method is used internally by the PropositionItem.track() method.
|
|
124
|
+
*
|
|
125
|
+
* @param {string} itemId - The unique identifier of the PropositionItem
|
|
126
|
+
* @param {string | null} interaction - A custom string value to be recorded in the interaction
|
|
127
|
+
* @param {number} eventType - The MessagingEdgeEventType numeric value
|
|
128
|
+
* @param {string[] | null} tokens - Array containing the sub-item tokens for recording interaction
|
|
129
|
+
*/
|
|
130
|
+
static trackPropositionItem(itemId: string, interaction: string | null, eventType: number, tokens: string[] | null): void {
|
|
131
|
+
RCTAEPMessaging.trackPropositionItem(itemId, interaction, eventType, tokens);
|
|
132
|
+
}
|
|
133
|
+
|
|
104
134
|
/**
|
|
105
135
|
* Function to set the UI Message delegate to listen the Message lifecycle events.
|
|
106
136
|
* @returns A function to unsubscribe from all event listeners
|
|
@@ -110,31 +140,34 @@ class Messaging {
|
|
|
110
140
|
|
|
111
141
|
const eventEmitter = new NativeEventEmitter(RCTAEPMessaging);
|
|
112
142
|
|
|
113
|
-
eventEmitter.addListener('onShow', (message) =>
|
|
114
|
-
messagingDelegate?.onShow?.(message)
|
|
143
|
+
eventEmitter.addListener('onShow', (message: Message) =>
|
|
144
|
+
messagingDelegate?.onShow?.(new Message(message))
|
|
115
145
|
);
|
|
116
146
|
|
|
117
|
-
eventEmitter.addListener('onDismiss', (message) => {
|
|
118
|
-
|
|
147
|
+
eventEmitter.addListener('onDismiss', (message: Message) => {
|
|
148
|
+
const messageInstance = new Message(message);
|
|
149
|
+
messageInstance._clearJavascriptMessageHandlers();
|
|
150
|
+
messagingDelegate?.onDismiss?.(messageInstance);
|
|
119
151
|
});
|
|
120
152
|
|
|
121
|
-
eventEmitter.addListener('shouldShowMessage', (message) => {
|
|
153
|
+
eventEmitter.addListener('shouldShowMessage', (message: Message) => {
|
|
154
|
+
const messageInstance = new Message(message);
|
|
122
155
|
const shouldShowMessage =
|
|
123
|
-
messagingDelegate?.shouldShowMessage?.(
|
|
156
|
+
messagingDelegate?.shouldShowMessage?.(messageInstance) ?? true;
|
|
124
157
|
const shouldSaveMessage =
|
|
125
|
-
messagingDelegate?.shouldSaveMessage?.(
|
|
158
|
+
messagingDelegate?.shouldSaveMessage?.(messageInstance) ?? false;
|
|
126
159
|
RCTAEPMessaging.setMessageSettings(shouldShowMessage, shouldSaveMessage);
|
|
127
160
|
});
|
|
128
161
|
|
|
129
162
|
if (Platform.OS === 'ios') {
|
|
130
|
-
eventEmitter.addListener('urlLoaded', (event) =>
|
|
131
|
-
messagingDelegate?.urlLoaded?.(event.url, event.message)
|
|
163
|
+
eventEmitter.addListener('urlLoaded', (event: {url: string, message: Message}) =>
|
|
164
|
+
messagingDelegate?.urlLoaded?.(event.url, new Message(event.message))
|
|
132
165
|
);
|
|
133
166
|
}
|
|
134
167
|
|
|
135
168
|
if (Platform.OS === 'android') {
|
|
136
|
-
eventEmitter.addListener('onContentLoaded', (event) =>
|
|
137
|
-
messagingDelegate?.onContentLoaded?.(event.message)
|
|
169
|
+
eventEmitter.addListener('onContentLoaded', (event: {message: Message}) =>
|
|
170
|
+
messagingDelegate?.onContentLoaded?.(new Message(event.message))
|
|
138
171
|
);
|
|
139
172
|
}
|
|
140
173
|
|
package/src/index.ts
CHANGED
|
@@ -11,25 +11,27 @@ governing permissions and limitations under the License.
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import Messaging from './Messaging';
|
|
14
|
-
import { ContentCard } from './models/ContentCard';
|
|
15
|
-
|
|
14
|
+
import { ContentCard, ContentCardData } from './models/ContentCard';
|
|
15
|
+
|
|
16
16
|
import { InAppMessage } from './models/InAppMessage';
|
|
17
|
-
import {
|
|
17
|
+
import { HTMLProposition, HTMLPropositionData } from './models/HTMLProposition';
|
|
18
|
+
import { JSONPropositionItem, JSONPropositionData } from './models/JSONProposition';
|
|
19
|
+
|
|
18
20
|
import Message from './models/Message';
|
|
19
21
|
import { MessagingDelegate } from './models/MessagingDelegate';
|
|
20
22
|
import MessagingEdgeEventType from './models/MessagingEdgeEventType';
|
|
21
23
|
import { MessagingProposition } from './models/MessagingProposition';
|
|
22
24
|
import { MessagingPropositionItem } from './models/MessagingPropositionItem';
|
|
23
25
|
import { PersonalizationSchema } from './models/PersonalizationSchema';
|
|
26
|
+
import { PropositionItem, PropositionItemData } from './models/PropositionItem';
|
|
24
27
|
import { Activity, Characteristics } from './models/ScopeDetails';
|
|
25
28
|
|
|
26
29
|
export {
|
|
27
30
|
Activity,
|
|
28
31
|
Characteristics,
|
|
29
32
|
ContentCard,
|
|
30
|
-
|
|
33
|
+
ContentCardData,
|
|
31
34
|
InAppMessage,
|
|
32
|
-
JSONPropositionItem,
|
|
33
35
|
Messaging,
|
|
34
36
|
Message,
|
|
35
37
|
MessagingDelegate,
|
|
@@ -37,4 +39,10 @@ export {
|
|
|
37
39
|
MessagingProposition,
|
|
38
40
|
MessagingPropositionItem,
|
|
39
41
|
PersonalizationSchema,
|
|
42
|
+
PropositionItem,
|
|
43
|
+
PropositionItemData,
|
|
44
|
+
HTMLProposition,
|
|
45
|
+
HTMLPropositionData,
|
|
46
|
+
JSONPropositionItem,
|
|
47
|
+
JSONPropositionData,
|
|
40
48
|
};
|
|
@@ -11,11 +11,12 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { PersonalizationSchema } from './PersonalizationSchema';
|
|
14
|
+
import { PropositionItem, PropositionItemData } from './PropositionItem';
|
|
14
15
|
|
|
15
16
|
type ContentCardTemplate = 'SmallImage';
|
|
16
17
|
type DismissButtonStyle = 'circle' | 'none' | 'simple';
|
|
17
18
|
|
|
18
|
-
export interface
|
|
19
|
+
export interface ContentCardData extends PropositionItemData {
|
|
19
20
|
id: string;
|
|
20
21
|
data: {
|
|
21
22
|
contentType: 'application/json';
|
|
@@ -45,3 +46,13 @@ export interface ContentCard {
|
|
|
45
46
|
};
|
|
46
47
|
schema: PersonalizationSchema.CONTENT_CARD;
|
|
47
48
|
}
|
|
49
|
+
|
|
50
|
+
export class ContentCard extends PropositionItem {
|
|
51
|
+
declare data: ContentCardData['data']; // Override data type for better typing
|
|
52
|
+
|
|
53
|
+
constructor(contentCardData: ContentCardData) {
|
|
54
|
+
super(contentCardData);
|
|
55
|
+
this.data = contentCardData.data;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
}
|
|
@@ -11,11 +11,20 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { PersonalizationSchema } from './PersonalizationSchema';
|
|
14
|
+
import { PropositionItem, PropositionItemData } from './PropositionItem';
|
|
14
15
|
|
|
15
|
-
export interface
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
schema: PersonalizationSchema.HTML_CONTENT;
|
|
16
|
+
export interface HTMLPropositionData extends PropositionItemData {
|
|
17
|
+
data: {
|
|
18
|
+
content: string;
|
|
19
|
+
};
|
|
20
|
+
schema: PersonalizationSchema.HTML_CONTENT;
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
export class HTMLProposition extends PropositionItem {
|
|
24
|
+
declare data: HTMLPropositionData['data'];
|
|
25
|
+
|
|
26
|
+
constructor(htmlData: HTMLPropositionData) {
|
|
27
|
+
super(htmlData);
|
|
28
|
+
this.data = htmlData.data;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -11,11 +11,20 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { PersonalizationSchema } from './PersonalizationSchema';
|
|
14
|
+
import { PropositionItem, PropositionItemData } from './PropositionItem';
|
|
14
15
|
|
|
15
|
-
export interface
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
schema: PersonalizationSchema.JSON_CONTENT;
|
|
16
|
+
export interface JSONPropositionData extends PropositionItemData {
|
|
17
|
+
data: {
|
|
18
|
+
content: any;
|
|
19
|
+
};
|
|
20
|
+
schema: PersonalizationSchema.JSON_CONTENT;
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
export class JSONPropositionItem extends PropositionItem {
|
|
24
|
+
declare data: JSONPropositionData['data'];
|
|
25
|
+
|
|
26
|
+
constructor(jsonData: JSONPropositionData) {
|
|
27
|
+
super(jsonData);
|
|
28
|
+
this.data = jsonData.data;
|
|
29
|
+
}
|
|
30
|
+
}
|
package/src/models/Message.ts
CHANGED
|
@@ -10,9 +10,23 @@ OF ANY KIND, either express or implied. See the License for the specific languag
|
|
|
10
10
|
governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { NativeModules } from 'react-native';
|
|
13
|
+
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
|
|
14
|
+
|
|
14
15
|
const RCTAEPMessaging = NativeModules.AEPMessaging;
|
|
15
16
|
|
|
17
|
+
// Registery to store inAppMessage callbacks for each message in Message.handleJavascriptMessage
|
|
18
|
+
// Record - {messageId : {handlerName : callback}}
|
|
19
|
+
const jsMessageHandlers: Record<string, Record<string, (content: string) => void>> = {};
|
|
20
|
+
const handleJSMessageEventEmitter = new NativeEventEmitter(RCTAEPMessaging);
|
|
21
|
+
|
|
22
|
+
// invokes the callback registered in Message.handleJavascriptMessage with the content received from the inAppMessage webview
|
|
23
|
+
handleJSMessageEventEmitter.addListener('onJavascriptMessage', (event) => {
|
|
24
|
+
const {messageId, handlerName, content} = event;
|
|
25
|
+
if (jsMessageHandlers[messageId] && jsMessageHandlers[messageId][handlerName]) {
|
|
26
|
+
jsMessageHandlers[messageId][handlerName](content);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
16
30
|
class Message {
|
|
17
31
|
id: string;
|
|
18
32
|
autoTrack: boolean;
|
|
@@ -47,7 +61,16 @@ class Message {
|
|
|
47
61
|
* of the autoTrack setting.
|
|
48
62
|
*/
|
|
49
63
|
dismiss(suppressAutoTrack?: boolean) {
|
|
50
|
-
|
|
64
|
+
// iOS message.dismiss() accepts a boolean parameter to suppress autoTrack
|
|
65
|
+
// but on android side, message.dismiss() does not accept any parameters
|
|
66
|
+
if (Platform.OS === 'android') {
|
|
67
|
+
RCTAEPMessaging.dismiss(this.id);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (Platform.OS === 'ios') {
|
|
71
|
+
RCTAEPMessaging.dismiss(this.id, suppressAutoTrack ? true : false);
|
|
72
|
+
}
|
|
73
|
+
|
|
51
74
|
}
|
|
52
75
|
|
|
53
76
|
/**
|
|
@@ -67,6 +90,42 @@ class Message {
|
|
|
67
90
|
clear() {
|
|
68
91
|
RCTAEPMessaging.clear(this.id);
|
|
69
92
|
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Adds a handler for named JavaScript messages sent from the message's WebView.
|
|
96
|
+
* The parameter passed to handler will contain the body of the message passed from the WebView's JavaScript.
|
|
97
|
+
* @param {string} handlerName: The name of the message that should be handled by the handler
|
|
98
|
+
* @param {function} handler: The method or closure to be called with the body of the message created in the Message's JavaScript
|
|
99
|
+
*/
|
|
100
|
+
handleJavascriptMessage(handlerName: string, handler: (content: string) => void) {
|
|
101
|
+
// Validate parameters
|
|
102
|
+
if (!handlerName) {
|
|
103
|
+
console.warn('[AEP Messaging] handleJavascriptMessage: handlerName is required');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (typeof handler !== 'function') {
|
|
108
|
+
console.warn('[AEP Messaging] handleJavascriptMessage: handler must be a function');
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// cache the callback
|
|
113
|
+
if (!jsMessageHandlers[this.id]) {
|
|
114
|
+
jsMessageHandlers[this.id] = {};
|
|
115
|
+
}
|
|
116
|
+
jsMessageHandlers[this.id][handlerName] = handler;
|
|
117
|
+
RCTAEPMessaging.handleJavascriptMessage(this.id, handlerName);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @internal - For internal use only.
|
|
122
|
+
* Clears all the javascript message handlers for the message.
|
|
123
|
+
* This function must be called if the callbacks registered in handleJavascriptMessage are no longer needed.
|
|
124
|
+
* Failure to call this function may lead to memory leaks.
|
|
125
|
+
*/
|
|
126
|
+
_clearJavascriptMessageHandlers() {
|
|
127
|
+
delete jsMessageHandlers[this.id];
|
|
128
|
+
}
|
|
70
129
|
}
|
|
71
130
|
|
|
72
131
|
export default Message;
|