Skip to content

Commit 6d9b979

Browse files
authored
Merge pull request #603 from amanjayshahomnicg/issue-342
[MOB-4431] Clear lastpushpayload if app is not launched via a notification click
2 parents fd55d0a + 1dd0db4 commit 6d9b979

9 files changed

+19
-270
lines changed

swift-sdk/Constants.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ enum Const {
4242
}
4343

4444
public enum UserDefault {
45-
static let payloadKey = "itbl_payload_key"
4645
static let attributionInfoKey = "itbl_attribution_info_key"
4746
static let emailKey = "itbl_email"
4847
static let userIdKey = "itbl_userid"
@@ -52,7 +51,6 @@ enum Const {
5251
static let sdkVersion = "itbl_sdk_version"
5352
static let offlineMode = "itbl_offline_mode"
5453

55-
static let payloadExpiration = 24
5654
static let attributionInfoExpiration = 24
5755
}
5856

@@ -63,7 +61,6 @@ enum Const {
6361
static let email = "itbl_email"
6462
static let userId = "itbl_userid"
6563
static let authToken = "itbl_auth_token"
66-
static let lastPushPayloadAndExpiration = "itbl_last_push_payload_and_expiration"
6764
}
6865
}
6966

swift-sdk/Internal/InternalIterableAPI.swift

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@ import UIKit
77

88
final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {
99
var apiKey: String
10-
10+
var lastPushPayload: [AnyHashable: Any]? {
11+
get {
12+
_payloadData
13+
} set {
14+
setPayloadData(newValue)
15+
}
16+
}
17+
1118
var email: String? {
1219
get {
1320
_email
@@ -46,10 +53,6 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {
4653
appPackageName: Bundle.main.appPackageName ?? "")
4754
}
4855

49-
var lastPushPayload: [AnyHashable: Any]? {
50-
localStorage.getLastPushPayload(dateProvider.currentDate)
51-
}
52-
5356
var attributionInfo: IterableAttributionInfo? {
5457
get {
5558
localStorage.getAttributionInfo(currentDate: dateProvider.currentDate)
@@ -85,6 +88,7 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {
8588
urlDelegate: config.urlDelegate,
8689
urlOpener: urlOpener,
8790
allowedProtocols: config.allowedProtocols)
91+
8892
pending.onSuccess { attributionInfo in
8993
if let attributionInfo = attributionInfo {
9094
self.attributionInfo = attributionInfo
@@ -100,6 +104,11 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {
100104
func removeDeviceAttribute(name: String) {
101105
deviceAttributes.removeValue(forKey: name)
102106
}
107+
108+
func setPayloadData(_ data: [AnyHashable: Any]?) {
109+
ITBInfo()
110+
_payloadData = data
111+
}
103112

104113
func setEmail(_ email: String?, authToken: String? = nil) {
105114
ITBInfo()
@@ -416,6 +425,7 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {
416425
private var deepLinkManager: DeepLinkManager
417426

418427
private var _email: String?
428+
private var _payloadData: [AnyHashable: Any]?
419429
private var _userId: String?
420430

421431
/// the hex representation of this device token
@@ -537,15 +547,15 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {
537547
}
538548

539549
private func save(pushPayload payload: [AnyHashable: Any]) {
540-
let expiration = Calendar.current.date(byAdding: .hour,
541-
value: Const.UserDefault.payloadExpiration,
542-
to: dateProvider.currentDate)
543-
localStorage.saveLastPushPayload(payload, withExpiration: expiration)
544550

545551
if let metadata = IterablePushNotificationMetadata.metadata(fromLaunchOptions: payload) {
546552
if let templateId = metadata.templateId {
547553
attributionInfo = IterableAttributionInfo(campaignId: metadata.campaignId, templateId: templateId, messageId: metadata.messageId)
548554
}
555+
556+
if !metadata.isGhostPush {
557+
lastPushPayload = payload
558+
}
549559
}
550560
}
551561

swift-sdk/Internal/IterableKeychain.swift

Lines changed: 0 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -63,74 +63,10 @@ class IterableKeychain {
6363
}
6464
}
6565

66-
func getLastPushPayload(currentDate: Date) -> [AnyHashable: Any]? {
67-
guard let payloadExpirationPair = getPayloadExpirationPairFromKeychain() else {
68-
return nil
69-
}
70-
71-
if isLastPushPayloadExpired(expiration: payloadExpirationPair.expiration, currentDate: currentDate) {
72-
removePayloadExpirationPairFromKeychain()
73-
return nil
74-
}
75-
76-
return decodeJsonPayload(payloadExpirationPair.payload)
77-
}
78-
79-
func setLastPushPayload(_ payload: [AnyHashable: Any]?, withExpiration expiration: Date?) {
80-
guard let payload = payload, JSONSerialization.isValidJSONObject(payload) else {
81-
removePayloadExpirationPairFromKeychain()
82-
return
83-
}
84-
85-
savePayloadExpirationPairToKeychain(payload: payload, expiration: expiration)
86-
}
87-
8866
// MARK: - PRIVATE/INTERNAL
8967

9068
private let wrapper: KeychainWrapper
9169

92-
private func getPayloadExpirationPairFromKeychain() -> (payload: Data, expiration: Date?)? {
93-
// get the value from the keychain
94-
guard let keychainValue = wrapper.data(forKey: Const.Keychain.Key.lastPushPayloadAndExpiration) else {
95-
return nil
96-
}
97-
98-
// decode the payload/expiration pair
99-
guard let payloadExpirationPair = try? JSONDecoder().decode(LastPushPayloadValue.self, from: keychainValue) else {
100-
return nil
101-
}
102-
103-
// cast the payload as a JSON object
104-
guard let lastPushPayloadJSON = try? JSONSerialization.jsonObject(with: payloadExpirationPair.payload, options: []) as? [AnyHashable: Any] else {
105-
return nil
106-
}
107-
108-
guard let lastPushPayloadData = try? JSONSerialization.data(withJSONObject: lastPushPayloadJSON) else {
109-
return nil
110-
}
111-
112-
return (payload: lastPushPayloadData, expiration: payloadExpirationPair.expiration)
113-
}
114-
115-
private func savePayloadExpirationPairToKeychain(payload: [AnyHashable: Any]?, expiration: Date?) {
116-
guard let payload = payload else {
117-
removePayloadExpirationPairFromKeychain()
118-
return
119-
}
120-
121-
guard let payloadAsData = encodeJsonPayload(payload) else {
122-
return
123-
}
124-
125-
let payloadExpirationPair = LastPushPayloadValue(payload: payloadAsData, expiration: expiration)
126-
127-
guard let encodedPair = try? JSONEncoder().encode(payloadExpirationPair) else {
128-
return
129-
}
130-
131-
wrapper.set(encodedPair, forKey: Const.Keychain.Key.lastPushPayloadAndExpiration)
132-
}
133-
13470
private func encodeJsonPayload(_ json: [AnyHashable: Any]?) -> Data? {
13571
guard let json = json, JSONSerialization.isValidJSONObject(json) else {
13672
return nil
@@ -147,20 +83,4 @@ class IterableKeychain {
14783
return try? JSONSerialization.jsonObject(with: data) as? [AnyHashable: Any]
14884
}
14985

150-
private func removePayloadExpirationPairFromKeychain() {
151-
wrapper.removeValue(forKey: Const.Keychain.Key.lastPushPayloadAndExpiration)
152-
}
153-
154-
private func isLastPushPayloadExpired(expiration: Date?, currentDate: Date) -> Bool {
155-
guard let expiration = expiration else {
156-
return false
157-
}
158-
159-
return !(expiration.timeIntervalSinceReferenceDate > currentDate.timeIntervalSinceReferenceDate)
160-
}
161-
162-
private struct LastPushPayloadValue: Codable {
163-
let payload: Data
164-
let expiration: Date?
165-
}
16686
}

swift-sdk/Internal/IterableUserDefaults.swift

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -78,33 +78,9 @@ class IterableUserDefaults {
7878
try? save(codable: attributionInfo, withKey: .attributionInfo, andExpiration: expiration)
7979
}
8080

81-
// migrated to IterableKeychain
82-
func getPayload(currentDate: Date) -> [AnyHashable: Any]? {
83-
(try? dict(withKey: .payload, currentDate: currentDate)) ?? nil
84-
}
85-
86-
// migrated to IterableKeychain
87-
func save(payload: [AnyHashable: Any]?, withExpiration expiration: Date?) {
88-
try? save(dict: payload, withKey: .payload, andExpiration: expiration)
89-
}
9081

9182
// MARK: data migration functions
9283

93-
func getLastPushPayloadExpirationPairForMigration() -> (payload: [AnyHashable: Any]?, expiration: Date?)? {
94-
guard let encodedEnvelope = userDefaults.value(forKey: UserDefaultsKey.payload.value) as? Data else {
95-
return nil
96-
}
97-
98-
do {
99-
let envelope = try JSONDecoder().decode(Envelope.self, from: encodedEnvelope)
100-
let decoded = try JSONSerialization.jsonObject(with: envelope.payload, options: []) as? [AnyHashable: Any]
101-
102-
return (payload: decoded, envelope.expiration)
103-
} catch {
104-
return nil
105-
}
106-
}
107-
10884
func getAuthDataForMigration() -> (email: String?, userId: String?, authToken: String?) {
10985
return (email: email, userId: userId, authToken: authToken)
11086
}
@@ -212,8 +188,6 @@ class IterableUserDefaults {
212188
private init(value: String) {
213189
self.value = value
214190
}
215-
216-
static let payload = UserDefaultsKey(value: Const.UserDefault.payloadKey)
217191
static let attributionInfo = UserDefaultsKey(value: Const.UserDefault.attributionInfoKey)
218192
static let email = UserDefaultsKey(value: Const.UserDefault.emailKey)
219193
static let userId = UserDefaultsKey(value: Const.UserDefault.userIdKey)

swift-sdk/Internal/LocalStorage.swift

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -75,22 +75,11 @@ struct LocalStorage: LocalStorageProtocol {
7575
iterableUserDefaults.save(attributionInfo: attributionInfo, withExpiration: expiration)
7676
}
7777

78-
func getLastPushPayload(_ currentDate: Date) -> [AnyHashable: Any]? {
79-
return keychain.getLastPushPayload(currentDate: currentDate)
80-
}
81-
82-
func saveLastPushPayload(_ payload: [AnyHashable: Any]?, withExpiration expiration: Date?) {
83-
keychain.setLastPushPayload(payload, withExpiration: expiration)
84-
}
85-
8678
func upgrade() {
8779
ITBInfo()
8880

8981
/// moves `email`, `userId`, and `authToken` from `UserDefaults` to `IterableKeychain`
9082
moveAuthDataFromUserDefaultsToKeychain()
91-
92-
/// moves `lastPushPayload` from `UserDefaults` to `IterableKeychain`
93-
moveLastPushPayloadFromUserDefaultsToKeychain()
9483
}
9584

9685
// MARK: Private
@@ -131,13 +120,4 @@ struct LocalStorage: LocalStorageProtocol {
131120
ITBInfo("UPDATED: migrated authToken from UserDefaults to IterableKeychain")
132121
}
133122
}
134-
135-
private func moveLastPushPayloadFromUserDefaultsToKeychain() {
136-
if let (userDefaultLastPushPayload, expiration) = iterableUserDefaults.getLastPushPayloadExpirationPairForMigration() {
137-
keychain.setLastPushPayload(userDefaultLastPushPayload, withExpiration: expiration)
138-
iterableUserDefaults.save(payload: nil, withExpiration: nil)
139-
140-
ITBInfo("UPDATED: migrated lastPushPayload from UserDefaults to IterableKeychain")
141-
}
142-
}
143123
}

swift-sdk/Internal/LocalStorageProtocol.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ protocol LocalStorageProtocol {
2323

2424
func save(attributionInfo: IterableAttributionInfo?, withExpiration expiration: Date?)
2525

26-
func getLastPushPayload(_ currentDate: Date) -> [AnyHashable: Any]?
27-
28-
func saveLastPushPayload(_ payload: [AnyHashable: Any]?, withExpiration expiration: Date?)
29-
3026
func upgrade()
3127
}
3228

tests/common/MockLocalStorage.swift

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,6 @@ class MockLocalStorage: LocalStorageProtocol {
3333
attributionInfoExpiration = expiration
3434
}
3535

36-
func getLastPushPayload(_ currentDate: Date) -> [AnyHashable : Any]? {
37-
guard !MockLocalStorage.isExpired(expiration: payloadExpiration, currentDate: currentDate) else {
38-
return nil
39-
}
40-
41-
return payload
42-
}
43-
44-
func saveLastPushPayload(_ payload: [AnyHashable : Any]?, withExpiration expiration: Date?) {
45-
self.payload = payload
46-
payloadExpiration = expiration
47-
}
48-
49-
private var payload: [AnyHashable: Any]? = nil
50-
private var payloadExpiration: Date? = nil
51-
5236
private var attributionInfo: IterableAttributionInfo? = nil
5337
private var attributionInfoExpiration: Date? = nil
5438

tests/unit-tests/LocalStorageTests.swift

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ class LocalStorageTests: XCTestCase {
3434
testKeychain.email = nil
3535
testKeychain.userId = nil
3636
testKeychain.authToken = nil
37-
testKeychain.setLastPushPayload(nil, withExpiration: nil)
3837
}
3938

4039
func testUserIdAndEmail() throws {
@@ -109,81 +108,6 @@ class LocalStorageTests: XCTestCase {
109108
"\(JsonKey.campaignId): \(attributionInfo.campaignId), \(JsonKey.templateId): \(attributionInfo.templateId), \(JsonKey.messageId): \(attributionInfo.messageId)")
110109
}
111110

112-
func testPayload() throws {
113-
let mockDateProvider = MockDateProvider()
114-
let localStorage = MockLocalStorage()
115-
116-
let payload: [AnyHashable: Any] = [
117-
"email": "ilya@iterable.com",
118-
"device": [
119-
"token": "foo",
120-
"platform": "bar",
121-
"applicationName": "baz",
122-
"dataFields": [
123-
"name": "green",
124-
"localizedModel": "eggs",
125-
"userInterfaceIdiom": "and",
126-
"identifierForVendor": "ham",
127-
"systemName": "iterable",
128-
"systemVersion": "is",
129-
"model": "awesome",
130-
],
131-
],
132-
]
133-
134-
let currentDate = Date()
135-
let expiration = Calendar.current.date(byAdding: Calendar.Component.hour, value: 24, to: currentDate)!
136-
137-
localStorage.saveLastPushPayload(payload, withExpiration: expiration)
138-
139-
// 23 hours, not expired, still present
140-
mockDateProvider.currentDate = Calendar.current.date(byAdding: Calendar.Component.hour, value: 23, to: currentDate)!
141-
let fromLocalStorage: [AnyHashable: Any] = localStorage.getLastPushPayload(mockDateProvider.currentDate)!
142-
143-
XCTAssertTrue(NSDictionary(dictionary: payload).isEqual(to: fromLocalStorage))
144-
145-
mockDateProvider.currentDate = Calendar.current.date(byAdding: Calendar.Component.hour, value: 25, to: currentDate)!
146-
let fromLocalStorage2: [AnyHashable: Any]? = localStorage.getLastPushPayload(mockDateProvider.currentDate)
147-
148-
XCTAssertNil(fromLocalStorage2)
149-
}
150-
151-
func testSaveBadPayload() throws {
152-
class A {}
153-
154-
let mockDateProvider = MockDateProvider()
155-
let localStorage = LocalStorage(userDefaults: LocalStorageTests.getTestUserDefaults())
156-
let payload: [AnyHashable: Any] = [
157-
"email": "ilya@iterable.com",
158-
"device": [
159-
"token": "foo",
160-
"platform": "bar",
161-
"applicationName": "baz",
162-
"dataFields": [
163-
"name": "green",
164-
"localizedModel": "eggs",
165-
"userInterfaceIdiom": "and",
166-
"identifierForVendor": "ham",
167-
"systemName": "iterable",
168-
"systemVersion": "is",
169-
"model": "awesome",
170-
],
171-
],
172-
"someClass": A(),
173-
]
174-
175-
let currentDate = Date()
176-
let expiration = Calendar.current.date(byAdding: Calendar.Component.hour, value: 24, to: currentDate)!
177-
178-
localStorage.saveLastPushPayload(payload, withExpiration: expiration)
179-
180-
// 23 hours, not expired, still present
181-
mockDateProvider.currentDate = Calendar.current.date(byAdding: Calendar.Component.hour, value: 23, to: currentDate)!
182-
let fromLocalStorage = localStorage.getLastPushPayload(mockDateProvider.currentDate)
183-
184-
XCTAssertNil(fromLocalStorage)
185-
}
186-
187111
func testDeviceId() {
188112
var localStorage = LocalStorage(userDefaults: LocalStorageTests.getTestUserDefaults())
189113
let deviceId = UUID().uuidString

0 commit comments

Comments
 (0)