@@ -21,9 +21,12 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
2121 private var embeddedSessionManager = EmbeddedSessionManager ()
2222
2323 private var activityMonitor: IterableActivityMonitor ? = null
24+
2425 // endregion
2526
2627 // region constructor
28+
29+ // Constructor of this class with actionHandler and updateHandler
2730 public constructor (
2831 iterableApi: IterableApi
2932 ) {
@@ -34,19 +37,23 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
3437 activityMonitor?.addCallback(this )
3538 }
3639 }
40+
3741 // endregion
3842
39- // region public methods
43+ // region getters and setters
4044
45+ // Add updateHandler to the list
4146 public fun addUpdateListener (updateHandler : IterableEmbeddedUpdateHandler ) {
4247 updateHandleListeners.add(updateHandler)
4348 }
4449
50+ // Remove updateHandler from the list
4551 public fun removeUpdateListener (updateHandler : IterableEmbeddedUpdateHandler ) {
4652 updateHandleListeners.remove(updateHandler)
4753 embeddedSessionManager.endSession()
4854 }
4955
56+ // Get the list of updateHandlers
5057 public fun getUpdateHandlers (): List <IterableEmbeddedUpdateHandler > {
5158 return updateHandleListeners
5259 }
@@ -55,6 +62,11 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
5562 return embeddedSessionManager
5663 }
5764
65+ // endregion
66+
67+ // region public methods
68+
69+ // Gets the list of embedded messages in memory without syncing
5870 fun getMessages (placementId : Long ): List <IterableEmbeddedMessage >? {
5971 return localPlacementMessagesMap[placementId]
6072 }
@@ -67,41 +79,96 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
6779 return localPlacementIds
6880 }
6981
70-
7182 @JvmOverloads
7283 fun syncMessages (placementIds : Array <Long > = emptyArray()) {
7384 if (iterableApi.config.enableEmbeddedMessaging) {
7485 IterableLogger .v(TAG , " Syncing messages..." )
7586
76- IterableApi .sharedInstance.getEmbeddedMessages(
77- placementIds,
78- { data ->
79- try {
80- processEmbeddedMessagesResponse(data)
81- notifySyncSucceeded()
82- } catch (e: JSONException ) {
83- IterableLogger .e(TAG , e.toString())
84- notifySyncFailed(e.message)
87+ IterableApi .sharedInstance.getEmbeddedMessages(placementIds, { data ->
88+ IterableLogger .v(TAG , " Got response from network call to get embedded messages" )
89+ try {
90+ val previousPlacementIds = getPlacementIds()
91+ val currentPlacementIds: MutableList <Long > = mutableListOf ()
92+
93+ val placementsArray =
94+ data.optJSONArray(IterableConstants .ITERABLE_EMBEDDED_MESSAGE_PLACEMENTS )
95+ if (placementsArray != null ) {
96+ // if there are no placements in the payload
97+ // reset the local message storage and trigger a UI update
98+ if (placementsArray.length() == 0 ) {
99+ reset()
100+ if (previousPlacementIds.isNotEmpty()) {
101+ updateHandleListeners.forEach {
102+ IterableLogger .d(TAG , " Calling updateHandler" )
103+ it.onMessagesUpdated()
104+ }
105+ }
106+ } else {
107+ for (i in 0 until placementsArray.length()) {
108+ val placementJson = placementsArray.optJSONObject(i)
109+ val placement =
110+ IterableEmbeddedPlacement .fromJSONObject(placementJson)
111+ val placementId = placement.placementId
112+ val messages = placement.messages
113+
114+ currentPlacementIds.add(placementId)
115+ updateLocalMessageMap(placementId, messages)
116+ }
117+ }
118+ }
119+
120+ // compare previous placements to the current placement payload
121+ val removedPlacementIds =
122+ previousPlacementIds.subtract(currentPlacementIds.toSet())
123+
124+ // if there are placements removed, update the local storage and trigger UI update
125+ if (removedPlacementIds.isNotEmpty()) {
126+ removedPlacementIds.forEach {
127+ localPlacementMessagesMap.remove(it)
128+ }
129+
130+ updateHandleListeners.forEach {
131+ IterableLogger .d(TAG , " Calling updateHandler" )
132+ it.onMessagesUpdated()
133+ }
85134 }
86- },
87- { reason, data ->
88- handleSyncFailure(reason, data)
89- notifySyncFailed(reason)
135+
136+ // store placements from payload for next comparison
137+ localPlacementIds = currentPlacementIds
138+
139+ notifySyncSucceeded()
140+ } catch (e: JSONException ) {
141+ IterableLogger .e(TAG , e.toString())
142+ notifySyncFailed(e.message)
143+ }
144+ }, { reason, _ ->
145+ if (reason.equals(
146+ " SUBSCRIPTION_INACTIVE" ,
147+ ignoreCase = true
148+ ) || reason.equals(" Invalid API Key" , ignoreCase = true )
149+ ) {
150+ IterableLogger .e(TAG , " Subscription is inactive. Stopping sync" )
151+ broadcastSubscriptionInactive()
152+ return @getEmbeddedMessages
90153 }
91- )
154+ IterableLogger .e(TAG , " Error while fetching embedded messages: $reason " )
155+ notifySyncFailed(reason)
156+ })
92157 }
93158 }
94159
95160 fun handleEmbeddedClick (message : IterableEmbeddedMessage , buttonIdentifier : String? , clickedUrl : String? ) {
96161 if ((clickedUrl != null ) && clickedUrl.toString().isNotEmpty()) {
97162 if (clickedUrl.startsWith(IterableConstants .URL_SCHEME_ACTION )) {
163+ // This is an action:// URL, pass that to the custom action handler
98164 val actionName: String = clickedUrl.replace(IterableConstants .URL_SCHEME_ACTION , " " )
99165 IterableActionRunner .executeAction(
100166 context,
101167 IterableAction .actionCustomAction(actionName),
102168 IterableActionSource .EMBEDDED
103169 )
104170 } else if (clickedUrl.startsWith(IterableConstants .URL_SCHEME_ITBL )) {
171+ // Handle itbl:// URLs, pass that to the custom action handler for compatibility
105172 val actionName: String = clickedUrl.replace(IterableConstants .URL_SCHEME_ITBL , " " )
106173 IterableActionRunner .executeAction(
107174 context,
@@ -118,70 +185,6 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
118185 }
119186 }
120187
121- // endregion
122-
123- // region private methods
124-
125- private fun processEmbeddedMessagesResponse (data : JSONObject ) {
126- IterableLogger .v(TAG , " Got response from network call to get embedded messages" )
127- val previousPlacementIds = getPlacementIds()
128- val currentPlacementIds: MutableList <Long > = mutableListOf ()
129-
130- val placementsArray =
131- data.optJSONArray(IterableConstants .ITERABLE_EMBEDDED_MESSAGE_PLACEMENTS )
132- if (placementsArray != null ) {
133- if (placementsArray.length() == 0 ) {
134- reset()
135- if (previousPlacementIds.isNotEmpty()) {
136- updateHandleListeners.forEach {
137- IterableLogger .d(TAG , " Calling updateHandler" )
138- it.onMessagesUpdated()
139- }
140- }
141- } else {
142- for (i in 0 until placementsArray.length()) {
143- val placementJson = placementsArray.optJSONObject(i)
144- val placement =
145- IterableEmbeddedPlacement .fromJSONObject(placementJson)
146- val placementId = placement.placementId
147- val messages = placement.messages
148-
149- currentPlacementIds.add(placementId)
150- updateLocalMessageMap(placementId, messages)
151- }
152- }
153- }
154-
155- val removedPlacementIds =
156- previousPlacementIds.subtract(currentPlacementIds.toSet())
157-
158- if (removedPlacementIds.isNotEmpty()) {
159- removedPlacementIds.forEach {
160- localPlacementMessagesMap.remove(it)
161- }
162-
163- updateHandleListeners.forEach {
164- IterableLogger .d(TAG , " Calling updateHandler" )
165- it.onMessagesUpdated()
166- }
167- }
168-
169- localPlacementIds = currentPlacementIds
170- }
171-
172- private fun handleSyncFailure (reason : String , data : JSONObject ? ) {
173- if (reason.equals(
174- " SUBSCRIPTION_INACTIVE" ,
175- ignoreCase = true
176- ) || reason.equals(" Invalid API Key" , ignoreCase = true )
177- ) {
178- IterableLogger .e(TAG , " Subscription is inactive. Stopping sync" )
179- broadcastSubscriptionInactive()
180- } else {
181- IterableLogger .e(TAG , " Error while fetching embedded messages: $reason " )
182- }
183- }
184-
185188 private fun notifySyncSucceeded () {
186189 updateHandleListeners.forEach {
187190 it.onEmbeddedMessagingSyncSucceeded()
@@ -208,18 +211,23 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
208211 IterableLogger .printInfo()
209212 var localMessagesChanged = false
210213
214+ // Get local messages in a mutable list
211215 val localMessageMap = mutableMapOf<String , IterableEmbeddedMessage >()
212216 getMessages(placementId)?.toMutableList()?.forEach {
213217 localMessageMap[it.metadata.messageId] = it
214218 }
215219
220+ // Compare the remote list to local list
221+ // if there are new messages, trigger a message update in UI and send out received events
216222 remoteMessageList.forEach {
217223 if (! localMessageMap.containsKey(it.metadata.messageId)) {
218224 localMessagesChanged = true
219225 IterableApi .getInstance().trackEmbeddedMessageReceived(it)
220226 }
221227 }
222228
229+ // Compare the local list to remote list
230+ // if there are messages to remove, trigger a message update in UI
223231 val remoteMessageMap = mutableMapOf<String , IterableEmbeddedMessage >()
224232 remoteMessageList.forEach {
225233 remoteMessageMap[it.metadata.messageId] = it
@@ -231,20 +239,19 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
231239 }
232240 }
233241
242+ // update local message map for placement with remote message list
234243 localPlacementMessagesMap[placementId] = remoteMessageList
235244
245+ // if local messages changed, trigger a message update in UI
236246 if (localMessagesChanged) {
237247 updateHandleListeners.forEach {
238248 IterableLogger .d(TAG , " Calling updateHandler" )
239249 it.onMessagesUpdated()
240250 }
241251 }
242252 }
243-
244253 // endregion
245254
246- // region AppStateCallback overrides
247-
248255 override fun onSwitchToForeground () {
249256 IterableLogger .printInfo()
250257 embeddedSessionManager.startSession()
@@ -255,8 +262,6 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
255262 override fun onSwitchToBackground () {
256263 embeddedSessionManager.endSession()
257264 }
258-
259- // endregion
260265}
261266
262267// region interfaces
0 commit comments