{"action":"created","comment":{"url":"https://api.github.com/repos/Iterable/swift-sdk/pulls/comments/245157171","pull_request_review_id":189212742,"id":245157171,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI0NTE1NzE3MQ==","diff_hunk":"@@ -84,75 +168,119 @@ class InAppManager : IterableInAppManagerProtocol {\n         }\n     }\n     \n-    private var synchronizer: InAppSynchronizerProtocol\n-    private var displayer: InAppDisplayerProtocol\n-    private var inAppDelegate: IterableInAppDelegate\n-    private var urlDelegate: IterableURLDelegate?\n-    private var customActionDelegate: IterableCustomActionDelegate?\n-    private var urlOpener: UrlOpenerProtocol\n+    private var synchronizer: InAppSynchronizerProtocol // this is mutable because we need to set internalApi\n+    private let displayer: InAppDisplayerProtocol\n+    private let inAppDelegate: IterableInAppDelegate\n+    private let urlDelegate: IterableURLDelegate?\n+    private let customActionDelegate: IterableCustomActionDelegate?\n+    private let urlOpener: UrlOpenerProtocol\n+    private let applicationStateProvider: ApplicationStateProviderProtocol\n+    private let notificationCenter: NotificationCenterProtocol\n     \n-    private var messagesMap: [String: IterableInAppMessage] = [:]\n+    private var messagesMap = OrderedDictionary<String, IterableInAppMessage>() // This is mutable\n+    private let queue = DispatchQueue(label: \"InAppQueue\")\n+    private let dateProvider: DateProviderProtocol\n+    private let retryInterval: Double // in seconds, if a message is already showing how long to wait?\n+    private var lastDismissedTime: Date? = nil\n }\n \n extension InAppManager : InAppSynchronizerDelegate {\n     func onInAppMessagesAvailable(messages: [IterableInAppMessage]) {\n         ITBDebug()\n \n         // Remove messages that are no present in server\n-        removeDeletedMessages(messages: messages)\n-        \n-        let newMessages = mergeAndGetNewMessages(messages: messages)\n+        removeDeletedMessages(messagesFromServer: messages)\n \n-        ITBDebug(\"\\(newMessages.count) new messages arrived.\")\n-        if newMessages.count == 1 {\n-            let message = newMessages[0]\n-            if inAppDelegate.onNew(message: message) == .show {\n-                self.show(message: message, consume: true)\n-            } else {\n-                ITBInfo(\"skipping inApp\")\n-                markAsSkipped(message: message)\n+        // add new ones\n+        addNewMessages(messagesFromServer: messages)\n+\n+        // now process\n+        processMessages()\n+    }\n+    \n+    private func processMessages() {\n+        let waitTimeInterval = getWaitTimeInterval()\n+        guard waitTimeInterval <= 0 else {\n+            ITBInfo(\"Need to wait for: \\(waitTimeInterval)\")\n+            queue.asyncAfter(deadline: .now() + waitTimeInterval) {\n+                self.processMessages()\n             }\n-        } else if newMessages.count > 1 {\n-            if let message = inAppDelegate.onNew(batch: newMessages) {\n-                // found content to show\n-                self.show(message: message, consume: true)\n-                \n-                newMessages.filter { $0.messageId != message.messageId }.forEach { markAsSkipped(message: $0) }\n+            return\n+        }\n+        \n+        // We can only check applicationState from main queue so need to do the following\n+        DispatchQueue.main.async {\n+            if self.applicationStateProvider.applicationState == .active {\n+                self.queue.async {\n+                    self.processOneMessage()\n+                }\n             } else {\n-                ITBInfo(\"skipping inApp batch\")\n-                newMessages.forEach {markAsSkipped(message: $0)}\n+                ITBInfo(\"Application is not active\")\n             }\n         }\n     }\n     \n-    private func markAsSkipped(message: IterableInAppMessage) {\n-        if let message = messagesMap[message.messageId] {\n-            message.skipped = true\n-            messagesMap.updateValue(message, forKey: message.messageId)\n+    // How long do we have to wait before showing the message\n+    // > 0 means wait, otherwise we are good to show\n+    private func getWaitTimeInterval() -> Double {\n+        if let lastDismissedTime = lastDismissedTime {\n+            let nextShowingTime = Date(timeInterval: retryInterval, since: lastDismissedTime)\n+            if dateProvider.currentDate >= nextShowingTime {\n+                return 0.0\n+            } else {\n+                return nextShowingTime.timeIntervalSinceReferenceDate - self.dateProvider.currentDate.timeIntervalSinceReferenceDate\n+            }\n         } else {\n-            // Should never happen\n-            ITBError(\"Did not find message\")\n+            // we have not shown any messages\n+            return 0.0\n         }\n     }\n+    \n+    // go through one loop of client side messages, and show the first that is not processed\n+    private func processOneMessage() {\n+        ITBDebug()\n \n-    // Adds new messages to map and returns the new messages\n-    private func mergeAndGetNewMessages(messages: [IterableInAppMessage]) -> [IterableInAppMessage] {\n-        return messages.reduce(into: [IterableInAppMessage]()) { (result, message) in\n-            if !messagesMap.contains(where: { $0.key == message.messageId}) {\n-                messagesMap[message.messageId] = message\n-                result.append(message)\n+        for message in messagesMap.values.filter({ $0.processed == false }) {\n+            ITBDebug(\"campaignId: \\(message.campaignId)\")\n+            message.processed = true\n+            if inAppDelegate.onNew(message: message) == .show {","path":"swift-sdk/Internal/InAppManager.swift","position":268,"original_position":268,"commit_id":"8942c662cc65460e69db3022a6f13f6efb3ad9e2","original_commit_id":"8942c662cc65460e69db3022a6f13f6efb3ad9e2","user":{"login":"tapashmajumder","id":39278182,"node_id":"MDQ6VXNlcjM5Mjc4MTgy","avatar_url":"https://avatars1.githubusercontent.com/u/39278182?v=4","gravatar_id":"","url":"https://api.github.com/users/tapashmajumder","html_url":"https://github.com/tapashmajumder","followers_url":"https://api.github.com/users/tapashmajumder/followers","following_url":"https://api.github.com/users/tapashmajumder/following{/other_user}","gists_url":"https://api.github.com/users/tapashmajumder/gists{/gist_id}","starred_url":"https://api.github.com/users/tapashmajumder/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tapashmajumder/subscriptions","organizations_url":"https://api.github.com/users/tapashmajumder/orgs","repos_url":"https://api.github.com/users/tapashmajumder/repos","events_url":"https://api.github.com/users/tapashmajumder/events{/privacy}","received_events_url":"https://api.github.com/users/tapashmajumder/received_events","type":"User","site_admin":false},"body":"Makes sense. For that we will need to add a method to check for 'canShowMessage()' method on the InAppDisplayer. I will do that.","created_at":"2019-01-03T22:42:04Z","updated_at":"2019-01-03T22:42:04Z","html_url":"https://github.com/Iterable/swift-sdk/pull/35#discussion_r245157171","pull_request_url":"https://api.github.com/repos/Iterable/swift-sdk/pulls/35","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/Iterable/swift-sdk/pulls/comments/245157171"},"html":{"href":"https://github.com/Iterable/swift-sdk/pull/35#discussion_r245157171"},"pull_request":{"href":"https://api.github.com/repos/Iterable/swift-sdk/pulls/35"}},"in_reply_to_id":245149485},"pull_request":{"url":"https://api.github.com/repos/Iterable/swift-sdk/pulls/35","id":240306001,"node_id":"MDExOlB1bGxSZXF1ZXN0MjQwMzA2MDAx","html_url":"https://github.com/Iterable/swift-sdk/pull/35","diff_url":"https://github.com/Iterable/swift-sdk/pull/35.diff","patch_url":"https://github.com/Iterable/swift-sdk/pull/35.patch","issue_url":"https://api.github.com/repos/Iterable/swift-sdk/issues/35","number":35,"state":"open","locked":false,"title":"[MOB-75] - Further improvements to async in-app messages.","user":{"login":"tapashmajumder","id":39278182,"node_id":"MDQ6VXNlcjM5Mjc4MTgy","avatar_url":"https://avatars1.githubusercontent.com/u/39278182?v=4","gravatar_id":"","url":"https://api.github.com/users/tapashmajumder","html_url":"https://github.com/tapashmajumder","followers_url":"https://api.github.com/users/tapashmajumder/followers","following_url":"https://api.github.com/users/tapashmajumder/following{/other_user}","gists_url":"https://api.github.com/users/tapashmajumder/gists{/gist_id}","starred_url":"https://api.github.com/users/tapashmajumder/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tapashmajumder/subscriptions","organizations_url":"https://api.github.com/users/tapashmajumder/orgs","repos_url":"https://api.github.com/users/tapashmajumder/repos","events_url":"https://api.github.com/users/tapashmajumder/events{/privacy}","received_events_url":"https://api.github.com/users/tapashmajumder/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-12-20T21:24:34Z","updated_at":"2019-01-03T22:42:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0a071b90088c26fab9478bac9ae6f4099d91eb7d","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/Iterable/swift-sdk/pulls/35/commits","review_comments_url":"https://api.github.com/repos/Iterable/swift-sdk/pulls/35/comments","review_comment_url":"https://api.github.com/repos/Iterable/swift-sdk/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Iterable/swift-sdk/issues/35/comments","statuses_url":"https://api.github.com/repos/Iterable/swift-sdk/statuses/8942c662cc65460e69db3022a6f13f6efb3ad9e2","head":{"label":"Iterable:feature/mob-75-inapp","ref":"feature/mob-75-inapp","sha":"8942c662cc65460e69db3022a6f13f6efb3ad9e2","user":{"login":"Iterable","id":5148773,"node_id":"MDEyOk9yZ2FuaXphdGlvbjUxNDg3NzM=","avatar_url":"https://avatars0.githubusercontent.com/u/5148773?v=4","gravatar_id":"","url":"https://api.github.com/users/Iterable","html_url":"https://github.com/Iterable","followers_url":"https://api.github.com/users/Iterable/followers","following_url":"https://api.github.com/users/Iterable/following{/other_user}","gists_url":"https://api.github.com/users/Iterable/gists{/gist_id}","starred_url":"https://api.github.com/users/Iterable/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Iterable/subscriptions","organizations_url":"https://api.github.com/users/Iterable/orgs","repos_url":"https://api.github.com/users/Iterable/repos","events_url":"https://api.github.com/users/Iterable/events{/privacy}","received_events_url":"https://api.github.com/users/Iterable/received_events","type":"Organization","site_admin":false},"repo":{"id":136994462,"node_id":"MDEwOlJlcG9zaXRvcnkxMzY5OTQ0NjI=","name":"swift-sdk","full_name":"Iterable/swift-sdk","private":false,"owner":{"login":"Iterable","id":5148773,"node_id":"MDEyOk9yZ2FuaXphdGlvbjUxNDg3NzM=","avatar_url":"https://avatars0.githubusercontent.com/u/5148773?v=4","gravatar_id":"","url":"https://api.github.com/users/Iterable","html_url":"https://github.com/Iterable","followers_url":"https://api.github.com/users/Iterable/followers","following_url":"https://api.github.com/users/Iterable/following{/other_user}","gists_url":"https://api.github.com/users/Iterable/gists{/gist_id}","starred_url":"https://api.github.com/users/Iterable/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Iterable/subscriptions","organizations_url":"https://api.github.com/users/Iterable/orgs","repos_url":"https://api.github.com/users/Iterable/repos","events_url":"https://api.github.com/users/Iterable/events{/privacy}","received_events_url":"https://api.github.com/users/Iterable/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/Iterable/swift-sdk","description":null,"fork":false,"url":"https://api.github.com/repos/Iterable/swift-sdk","forks_url":"https://api.github.com/repos/Iterable/swift-sdk/forks","keys_url":"https://api.github.com/repos/Iterable/swift-sdk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Iterable/swift-sdk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Iterable/swift-sdk/teams","hooks_url":"https://api.github.com/repos/Iterable/swift-sdk/hooks","issue_events_url":"https://api.github.com/repos/Iterable/swift-sdk/issues/events{/number}","events_url":"https://api.github.com/repos/Iterable/swift-sdk/events","assignees_url":"https://api.github.com/repos/Iterable/swift-sdk/assignees{/user}","branches_url":"https://api.github.com/repos/Iterable/swift-sdk/branches{/branch}","tags_url":"https://api.github.com/repos/Iterable/swift-sdk/tags","blobs_url":"https://api.github.com/repos/Iterable/swift-sdk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Iterable/swift-sdk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Iterable/swift-sdk/git/refs{/sha}","trees_url":"https://api.github.com/repos/Iterable/swift-sdk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Iterable/swift-sdk/statuses/{sha}","languages_url":"https://api.github.com/repos/Iterable/swift-sdk/languages","stargazers_url":"https://api.github.com/repos/Iterable/swift-sdk/stargazers","contributors_url":"https://api.github.com/repos/Iterable/swift-sdk/contributors","subscribers_url":"https://api.github.com/repos/Iterable/swift-sdk/subscribers","subscription_url":"https://api.github.com/repos/Iterable/swift-sdk/subscription","commits_url":"https://api.github.com/repos/Iterable/swift-sdk/commits{/sha}","git_commits_url":"https://api.github.com/repos/Iterable/swift-sdk/git/commits{/sha}","comments_url":"https://api.github.com/repos/Iterable/swift-sdk/comments{/number}","issue_comment_url":"https://api.github.com/repos/Iterable/swift-sdk/issues/comments{/number}","contents_url":"https://api.github.com/repos/Iterable/swift-sdk/contents/{+path}","compare_url":"https://api.github.com/repos/Iterable/swift-sdk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Iterable/swift-sdk/merges","archive_url":"https://api.github.com/repos/Iterable/swift-sdk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Iterable/swift-sdk/downloads","issues_url":"https://api.github.com/repos/Iterable/swift-sdk/issues{/number}","pulls_url":"https://api.github.com/repos/Iterable/swift-sdk/pulls{/number}","milestones_url":"https://api.github.com/repos/Iterable/swift-sdk/milestones{/number}","notifications_url":"https://api.github.com/repos/Iterable/swift-sdk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Iterable/swift-sdk/labels{/name}","releases_url":"https://api.github.com/repos/Iterable/swift-sdk/releases{/id}","deployments_url":"https://api.github.com/repos/Iterable/swift-sdk/deployments","created_at":"2018-06-12T00:09:02Z","updated_at":"2018-12-20T21:20:23Z","pushed_at":"2019-01-03T02:09:41Z","git_url":"git://github.com/Iterable/swift-sdk.git","ssh_url":"git@github.com:Iterable/swift-sdk.git","clone_url":"https://github.com/Iterable/swift-sdk.git","svn_url":"https://github.com/Iterable/swift-sdk","homepage":null,"size":1197,"stargazers_count":8,"watchers_count":8,"language":"Swift","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":2,"open_issues":1,"watchers":8,"default_branch":"master"}},"base":{"label":"Iterable:master","ref":"master","sha":"ca244cf37e3b4bc9925899b54f0cd6e557648390","user":{"login":"Iterable","id":5148773,"node_id":"MDEyOk9yZ2FuaXphdGlvbjUxNDg3NzM=","avatar_url":"https://avatars0.githubusercontent.com/u/5148773?v=4","gravatar_id":"","url":"https://api.github.com/users/Iterable","html_url":"https://github.com/Iterable","followers_url":"https://api.github.com/users/Iterable/followers","following_url":"https://api.github.com/users/Iterable/following{/other_user}","gists_url":"https://api.github.com/users/Iterable/gists{/gist_id}","starred_url":"https://api.github.com/users/Iterable/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Iterable/subscriptions","organizations_url":"https://api.github.com/users/Iterable/orgs","repos_url":"https://api.github.com/users/Iterable/repos","events_url":"https://api.github.com/users/Iterable/events{/privacy}","received_events_url":"https://api.github.com/users/Iterable/received_events","type":"Organization","site_admin":false},"repo":{"id":136994462,"node_id":"MDEwOlJlcG9zaXRvcnkxMzY5OTQ0NjI=","name":"swift-sdk","full_name":"Iterable/swift-sdk","private":false,"owner":{"login":"Iterable","id":5148773,"node_id":"MDEyOk9yZ2FuaXphdGlvbjUxNDg3NzM=","avatar_url":"https://avatars0.githubusercontent.com/u/5148773?v=4","gravatar_id":"","url":"https://api.github.com/users/Iterable","html_url":"https://github.com/Iterable","followers_url":"https://api.github.com/users/Iterable/followers","following_url":"https://api.github.com/users/Iterable/following{/other_user}","gists_url":"https://api.github.com/users/Iterable/gists{/gist_id}","starred_url":"https://api.github.com/users/Iterable/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Iterable/subscriptions","organizations_url":"https://api.github.com/users/Iterable/orgs","repos_url":"https://api.github.com/users/Iterable/repos","events_url":"https://api.github.com/users/Iterable/events{/privacy}","received_events_url":"https://api.github.com/users/Iterable/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/Iterable/swift-sdk","description":null,"fork":false,"url":"https://api.github.com/repos/Iterable/swift-sdk","forks_url":"https://api.github.com/repos/Iterable/swift-sdk/forks","keys_url":"https://api.github.com/repos/Iterable/swift-sdk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Iterable/swift-sdk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Iterable/swift-sdk/teams","hooks_url":"https://api.github.com/repos/Iterable/swift-sdk/hooks","issue_events_url":"https://api.github.com/repos/Iterable/swift-sdk/issues/events{/number}","events_url":"https://api.github.com/repos/Iterable/swift-sdk/events","assignees_url":"https://api.github.com/repos/Iterable/swift-sdk/assignees{/user}","branches_url":"https://api.github.com/repos/Iterable/swift-sdk/branches{/branch}","tags_url":"https://api.github.com/repos/Iterable/swift-sdk/tags","blobs_url":"https://api.github.com/repos/Iterable/swift-sdk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Iterable/swift-sdk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Iterable/swift-sdk/git/refs{/sha}","trees_url":"https://api.github.com/repos/Iterable/swift-sdk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Iterable/swift-sdk/statuses/{sha}","languages_url":"https://api.github.com/repos/Iterable/swift-sdk/languages","stargazers_url":"https://api.github.com/repos/Iterable/swift-sdk/stargazers","contributors_url":"https://api.github.com/repos/Iterable/swift-sdk/contributors","subscribers_url":"https://api.github.com/repos/Iterable/swift-sdk/subscribers","subscription_url":"https://api.github.com/repos/Iterable/swift-sdk/subscription","commits_url":"https://api.github.com/repos/Iterable/swift-sdk/commits{/sha}","git_commits_url":"https://api.github.com/repos/Iterable/swift-sdk/git/commits{/sha}","comments_url":"https://api.github.com/repos/Iterable/swift-sdk/comments{/number}","issue_comment_url":"https://api.github.com/repos/Iterable/swift-sdk/issues/comments{/number}","contents_url":"https://api.github.com/repos/Iterable/swift-sdk/contents/{+path}","compare_url":"https://api.github.com/repos/Iterable/swift-sdk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Iterable/swift-sdk/merges","archive_url":"https://api.github.com/repos/Iterable/swift-sdk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Iterable/swift-sdk/downloads","issues_url":"https://api.github.com/repos/Iterable/swift-sdk/issues{/number}","pulls_url":"https://api.github.com/repos/Iterable/swift-sdk/pulls{/number}","milestones_url":"https://api.github.com/repos/Iterable/swift-sdk/milestones{/number}","notifications_url":"https://api.github.com/repos/Iterable/swift-sdk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Iterable/swift-sdk/labels{/name}","releases_url":"https://api.github.com/repos/Iterable/swift-sdk/releases{/id}","deployments_url":"https://api.github.com/repos/Iterable/swift-sdk/deployments","created_at":"2018-06-12T00:09:02Z","updated_at":"2018-12-20T21:20:23Z","pushed_at":"2019-01-03T02:09:41Z","git_url":"git://github.com/Iterable/swift-sdk.git","ssh_url":"git@github.com:Iterable/swift-sdk.git","clone_url":"https://github.com/Iterable/swift-sdk.git","svn_url":"https://github.com/Iterable/swift-sdk","homepage":null,"size":1197,"stargazers_count":8,"watchers_count":8,"language":"Swift","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":2,"open_issues":1,"watchers":8,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Iterable/swift-sdk/pulls/35"},"html":{"href":"https://github.com/Iterable/swift-sdk/pull/35"},"issue":{"href":"https://api.github.com/repos/Iterable/swift-sdk/issues/35"},"comments":{"href":"https://api.github.com/repos/Iterable/swift-sdk/issues/35/comments"},"review_comments":{"href":"https://api.github.com/repos/Iterable/swift-sdk/pulls/35/comments"},"review_comment":{"href":"https://api.github.com/repos/Iterable/swift-sdk/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Iterable/swift-sdk/pulls/35/commits"},"statuses":{"href":"https://api.github.com/repos/Iterable/swift-sdk/statuses/8942c662cc65460e69db3022a6f13f6efb3ad9e2"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"tapashmajumder"}}