Skip to content

Commit 766a117

Browse files
Merge pull request #30 from Iterable/feature/mob-1-future
[MOB-1] - Use Future Internally
2 parents a82fcc7 + 4d391ab commit 766a117

File tree

5 files changed

+131
-91
lines changed

5 files changed

+131
-91
lines changed

Tests/swift-sdk-swift-tests/PromiseTests.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class PromiseTests: XCTestCase {
2828
f2.onSuccess { (value) in
2929
XCTAssertEqual(value, "zeeString".count)
3030
expectation1.fulfill()
31-
} .onFailure { _ in
31+
} .onError { _ in
3232
expectation2.fulfill()
3333
}
3434

@@ -46,7 +46,7 @@ class PromiseTests: XCTestCase {
4646

4747
f2.onSuccess { (value) in
4848
expectation1.fulfill()
49-
}.onFailure { error in
49+
}.onError { error in
5050
if let myError = error as? MyError {
5151
XCTAssertEqual(myError.message, "zeeErrorMessage")
5252
expectation2.fulfill()
@@ -72,7 +72,7 @@ class PromiseTests: XCTestCase {
7272
f2.onSuccess { (secondValue) in
7373
XCTAssertEqual(secondValue, "zeeStringzeeString")
7474
expectation1.fulfill()
75-
} .onFailure { _ in
75+
} .onError { _ in
7676
expectation2.fulfill()
7777
}
7878

@@ -94,7 +94,7 @@ class PromiseTests: XCTestCase {
9494

9595
f2.onSuccess { (secondValue) in
9696
expectation1.fulfill()
97-
} .onFailure {(error) in
97+
} .onError {(error) in
9898
if let myError = error as? MyError {
9999
XCTAssertEqual(myError.message, "zeeErrorMessage")
100100
expectation2.fulfill()
@@ -119,7 +119,7 @@ class PromiseTests: XCTestCase {
119119

120120
f2.onSuccess { (secondValue) in
121121
expectation1.fulfill()
122-
}.onFailure {(error) in
122+
}.onError {(error) in
123123
if let myError = error as? MyError {
124124
XCTAssertEqual(myError.message, "zeeErrorMessage")
125125
expectation2.fulfill()
@@ -140,7 +140,7 @@ class PromiseTests: XCTestCase {
140140
f1.onSuccess { (value) in
141141
XCTAssertEqual(value, "zeeValue")
142142
expectation1.fulfill()
143-
}.onFailure { _ in
143+
}.onError { _ in
144144
expectation2.fulfill()
145145
}
146146

@@ -157,7 +157,7 @@ class PromiseTests: XCTestCase {
157157

158158
f1.onSuccess { (value) in
159159
expectation1.fulfill()
160-
}.onFailure { error in
160+
}.onError { error in
161161
if let myError = error as? MyError {
162162
XCTAssertEqual(myError.message, "zeeErrorMessage")
163163
expectation2.fulfill()

swift-sdk/Internal/IterableAPIInternal.swift

Lines changed: 33 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ final class IterableAPIInternal : NSObject, PushTrackerProtocol {
116116
return self.register(token: token, appName: appName, pushServicePlatform: self.config.pushPlatform)
117117
}).onSuccess { (json) in
118118
onSuccess?(json)
119-
}.onFailure { (error) in
119+
}.onError { (error) in
120120
if let sendError = error as? SendRequestError {
121-
onFailure?(sendError.errorMessage, sendError.data)
121+
onFailure?(sendError.reason, sendError.data)
122122
} else {
123123
onFailure?("failed to create user", nil)
124124
}
@@ -132,7 +132,7 @@ final class IterableAPIInternal : NSObject, PushTrackerProtocol {
132132
guard email != nil || userId != nil else {
133133
ITBError("Both email and userId are nil")
134134
onFailure?("Both email and userId are nil", nil)
135-
return SendRequestError.createFailedFuture(reason: "Both email and userId are nil")
135+
return SendRequestError.createErroredFuture(reason: "Both email and userId are nil")
136136
}
137137

138138
hexToken = (token as NSData).iteHexadecimalString()
@@ -178,7 +178,7 @@ final class IterableAPIInternal : NSObject, PushTrackerProtocol {
178178
ITBInfo("sending registerToken request with args \(args)")
179179
return
180180
createPostRequest(forPath: .ITBL_PATH_REGISTER_DEVICE_TOKEN, withBody: args)
181-
.map {sendRequest($0, onSuccess: onSuccess, onFailure: onFailure)} ?? SendRequestError.createFailedFuture(reason: "Couldn't create register request")
181+
.map {sendRequest($0, onSuccess: onSuccess, onFailure: onFailure)} ?? SendRequestError.createErroredFuture(reason: "Couldn't create register request")
182182
}
183183

184184
func disableDeviceForCurrentUser() {
@@ -242,7 +242,7 @@ final class IterableAPIInternal : NSObject, PushTrackerProtocol {
242242

243243
return createPostRequest(forPath: .ITBL_PATH_CREATE_USER, withBody: args).map {
244244
sendRequest($0)
245-
} ?? SendRequestError.createFailedFuture(reason: "Could not create createUser Reqeust")
245+
} ?? SendRequestError.createErroredFuture(reason: "Could not create createUser Reqeust")
246246
}
247247

248248
func trackPurchase(_ total: NSNumber, items: [CommerceItem]) {
@@ -399,56 +399,34 @@ final class IterableAPIInternal : NSObject, PushTrackerProtocol {
399399
}
400400
}
401401

402-
func spawn(inAppNotification callbackBlock:ITEActionBlock?) {
403-
let onSuccess: OnSuccessHandler = { payload in
404-
guard let payload = payload else {
405-
return
406-
}
407-
guard let dialogOptions = IterableInAppManager.getNextMessageFromPayload(payload) else {
408-
ITBError("No notifications found for inApp payload \(payload)")
409-
return
410-
}
411-
guard let message = dialogOptions[.ITBL_IN_APP_CONTENT] as? [AnyHashable : Any] else {
412-
return
413-
}
414-
guard let messageId = dialogOptions[.ITBL_KEY_MESSAGE_ID] as? String else {
415-
return
416-
}
417-
guard let html = message[.ITBL_IN_APP_HTML] as? String else {
418-
return
419-
}
420-
guard html.range(of: AnyHashable.ITBL_IN_APP_HREF, options: [.caseInsensitive]) != nil else {
421-
ITBError("No href tag found in in-app html payload \(html)")
422-
self.inAppConsume(messageId)
423-
return
424-
}
425-
426-
let inAppDisplaySettings = message[.ITBL_IN_APP_DISPLAY_SETTINGS] as? [AnyHashable : Any]
427-
let backgroundAlpha = IterableInAppManager.getBackgroundAlpha(fromInAppSettings: inAppDisplaySettings)
428-
let edgeInsets = IterableInAppManager.getPaddingFromPayload(inAppDisplaySettings)
429-
430-
let notificationMetadata = IterableNotificationMetadata.metadata(fromInAppOptions: messageId)
431-
432-
DispatchQueue.main.async {
433-
let opened = IterableInAppManager.showIterableNotificationHTML(html, trackParams: notificationMetadata, backgroundAlpha: backgroundAlpha, padding: edgeInsets, callbackBlock: callbackBlock)
434-
if opened {
435-
self.inAppConsume(messageId)
402+
@discardableResult func spawn(inAppNotification callbackBlock:ITEActionBlock?) -> Future<IterableInAppManager.ShowInAppResult> {
403+
return getInAppMessages(1)
404+
.map { IterableInAppManager.parseInApp(fromPayload: $0)}
405+
.flatMap { IterableInAppManager.showInApp(parseResult: $0, callbackBlock: callbackBlock)}
406+
.onSuccess {
407+
switch $0 {
408+
case .success(opened: let opened, messageId: let messageId):
409+
if opened {
410+
self.inAppConsume(messageId)
411+
}
412+
case .failure(reason: let reason, messageId: let messageId):
413+
if let messageId = messageId {
414+
self.inAppConsume(messageId)
415+
}
416+
ITBError(reason)
436417
}
437418
}
438-
}
439-
440-
getInAppMessages(1, onSuccess: onSuccess, onFailure: IterableAPIInternal.defaultOnFailure(identifier: "getInAppMessages"))
441419
}
442420

443-
func getInAppMessages(_ count: NSNumber) {
444-
getInAppMessages(count, onSuccess: IterableAPIInternal.defaultOnSucess(identifier: "getMessages"), onFailure: IterableAPIInternal.defaultOnFailure(identifier: "getMessages"))
421+
@discardableResult func getInAppMessages(_ count: NSNumber) -> Future<SendRequestValue> {
422+
return getInAppMessages(count, onSuccess: IterableAPIInternal.defaultOnSucess(identifier: "getMessages"), onFailure: IterableAPIInternal.defaultOnFailure(identifier: "getMessages"))
445423
}
446424

447-
func getInAppMessages(_ count: NSNumber, onSuccess: OnSuccessHandler?, onFailure: OnFailureHandler?) {
425+
@discardableResult func getInAppMessages(_ count: NSNumber, onSuccess: OnSuccessHandler?, onFailure: OnFailureHandler?) -> Future<SendRequestValue> {
448426
guard email != nil || userId != nil else {
449427
ITBError("Both email and userId are nil")
450428
onFailure?("Both email and userId are nil", nil)
451-
return
429+
return SendRequestError.createErroredFuture(reason: "Both email and userId are nil")
452430
}
453431

454432
var args : [AnyHashable : Any] = [
@@ -459,9 +437,9 @@ final class IterableAPIInternal : NSObject, PushTrackerProtocol {
459437

460438
addEmailOrUserId(args: &args)
461439

462-
if let request = createGetRequest(forPath: .ITBL_PATH_GET_INAPP_MESSAGES, withArgs: args as! [String : String]) {
463-
sendRequest(request, onSuccess: onSuccess, onFailure: onFailure)
464-
}
440+
return createGetRequest(forPath: .ITBL_PATH_GET_INAPP_MESSAGES, withArgs: args as! [String : String]).map {
441+
sendRequest($0, onSuccess: onSuccess, onFailure: onFailure)
442+
} ?? SendRequestError.createErroredFuture(reason: "Could not create get request for getInApp")
465443
}
466444

467445
func trackInAppOpen(_ messageId: String) {
@@ -533,9 +511,9 @@ final class IterableAPIInternal : NSObject, PushTrackerProtocol {
533511
@discardableResult func sendRequest(_ request: URLRequest, onSuccess: OnSuccessHandler? = nil, onFailure: OnFailureHandler? = nil) -> Future<SendRequestValue> {
534512
return NetworkHelper.sendRequest(request, usingSession: networkSession).onSuccess { (json) in
535513
onSuccess?(json)
536-
}.onFailure { (failureInfo) in
537-
if let sendError = failureInfo as? SendRequestError {
538-
onFailure?(sendError.errorMessage, sendError.data)
514+
}.onError { (error) in
515+
if let sendError = error as? SendRequestError {
516+
onFailure?(sendError.reason, sendError.data)
539517
} else {
540518
onFailure?("send request failed", nil)
541519
}
@@ -796,9 +774,9 @@ final class IterableAPIInternal : NSObject, PushTrackerProtocol {
796774

797775
NetworkHelper.sendRequest(request, usingSession: networkSession).onSuccess { (json) in
798776
self.handleDDL(json: json)
799-
}.onFailure { (failureInfo) in
800-
if let sendError = failureInfo as? SendRequestError, let errorMessage = sendError.errorMessage {
801-
ITBError(errorMessage)
777+
}.onError { (error) in
778+
if let sendError = error as? SendRequestError, let reason = sendError.reason {
779+
ITBError(reason)
802780
} else {
803781
ITBError("failed to send handleDDl request")
804782
}

swift-sdk/Internal/IterableInAppManager.swift

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,8 @@ class IterableInAppManager: NSObject {
133133
return padding
134134
}
135135

136-
/*!
137-
@method
138-
139-
@abstract Gets the int value of the padding from the payload
136+
/**
137+
Gets the int value of the padding from the payload
140138

141139
@param value the value
142140

@@ -172,6 +170,32 @@ class IterableInAppManager: NSObject {
172170
}
173171
}
174172

173+
enum ShowInAppResult {
174+
case success(opened: Bool, messageId: String)
175+
case failure(reason: String, messageId: String?)
176+
}
177+
178+
static func showInApp(parseResult: InAppParseResult, callbackBlock:ITEActionBlock?) -> Future<ShowInAppResult> {
179+
switch parseResult {
180+
case .success(let inAppDetails):
181+
let result = Promise<ShowInAppResult>()
182+
let notificationMetadata = IterableNotificationMetadata.metadata(fromInAppOptions: inAppDetails.messageId)
183+
184+
DispatchQueue.main.async {
185+
let opened = IterableInAppManager.showIterableNotificationHTML(inAppDetails.html,
186+
trackParams: notificationMetadata,
187+
backgroundAlpha: inAppDetails.backgroundAlpha,
188+
padding: inAppDetails.edgeInsets,
189+
callbackBlock: callbackBlock)
190+
result.resolve(with: .success(opened: opened, messageId: inAppDetails.messageId))
191+
}
192+
return result
193+
case .failure(let reason, let messageId):
194+
return Promise<ShowInAppResult>(value: .failure(reason: reason, messageId: messageId))
195+
}
196+
}
197+
198+
175199
private static func getTopViewController() -> UIViewController? {
176200
guard let rootViewController = IterableUtil.rootViewController else {
177201
return nil
@@ -183,6 +207,44 @@ class IterableInAppManager: NSObject {
183207
return topViewController
184208
}
185209

210+
enum InAppParseResult {
211+
case success(InAppDetails)
212+
case failure(reason: String, messageId: String?)
213+
}
214+
215+
struct InAppDetails {
216+
let edgeInsets: UIEdgeInsets
217+
let backgroundAlpha: Double
218+
let messageId: String
219+
let html: String
220+
}
221+
222+
// Payload is what comes from Api
223+
// If successful you get InAppDetails
224+
static func parseInApp(fromPayload payload: [AnyHashable : Any]) -> InAppParseResult {
225+
guard let dialogOptions = IterableInAppManager.getNextMessageFromPayload(payload) else {
226+
return .failure(reason: "No notifications found for inApp payload \(payload)", messageId: nil)
227+
}
228+
guard let message = dialogOptions[.ITBL_IN_APP_CONTENT] as? [AnyHashable : Any] else {
229+
return .failure(reason: "no message", messageId: nil)
230+
}
231+
guard let messageId = dialogOptions[.ITBL_KEY_MESSAGE_ID] as? String else {
232+
return .failure(reason: "no message id", messageId: nil)
233+
}
234+
guard let html = message[.ITBL_IN_APP_HTML] as? String else {
235+
return .failure(reason: "no html", messageId: nil)
236+
}
237+
guard html.range(of: AnyHashable.ITBL_IN_APP_HREF, options: [.caseInsensitive]) != nil else {
238+
return .failure(reason: "No href tag found in in-app html payload \(html)", messageId: messageId)
239+
}
240+
241+
let inAppDisplaySettings = message[.ITBL_IN_APP_DISPLAY_SETTINGS] as? [AnyHashable : Any]
242+
let backgroundAlpha = IterableInAppManager.getBackgroundAlpha(fromInAppSettings: inAppDisplaySettings)
243+
let edgeInsets = IterableInAppManager.getPaddingFromPayload(inAppDisplaySettings)
244+
245+
return .success(InAppDetails(edgeInsets: edgeInsets, backgroundAlpha: backgroundAlpha, messageId: messageId, html: html))
246+
}
247+
186248
/**
187249
Creates and adds an alert action button to an alertController
188250

swift-sdk/Internal/NetworkHelper.swift

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@ import Foundation
99
typealias SendRequestValue = [AnyHashable : Any]
1010

1111
struct SendRequestError : Error {
12-
let errorMessage: String?
12+
let reason: String?
1313
let data: Data?
1414

15-
init(errorMessage: String? = nil, data: Data? = nil) {
16-
self.errorMessage = errorMessage
15+
init(reason: String? = nil, data: Data? = nil) {
16+
self.reason = reason
1717
self.data = data
1818
}
1919

20-
static func createFailedFuture(reason: String? = nil) -> Future<SendRequestValue> {
21-
return Promise<SendRequestValue>(error: SendRequestError(errorMessage: reason))
20+
static func createErroredFuture(reason: String? = nil) -> Future<SendRequestValue> {
21+
return Promise<SendRequestValue>(error: SendRequestError(reason: reason))
2222
}
2323
}
2424

2525
extension SendRequestError : LocalizedError {
2626
var localizedDescription: String {
27-
return errorMessage ?? ""
27+
return reason ?? ""
2828
}
2929
}
3030

@@ -61,10 +61,10 @@ struct NetworkHelper {
6161

6262
static func createResultFromNetworkResponse(data: Data?, response: URLResponse?, error: Error?) -> Result<SendRequestValue> {
6363
if let error = error {
64-
return .error(SendRequestError(errorMessage: "\(error.localizedDescription)", data: data))
64+
return .error(SendRequestError(reason: "\(error.localizedDescription)", data: data))
6565
}
6666
guard let response = response as? HTTPURLResponse else {
67-
return .error(SendRequestError(errorMessage: "No response", data: nil))
67+
return .error(SendRequestError(reason: "No response", data: nil))
6868
}
6969

7070
let responseCode = response.statusCode
@@ -84,33 +84,33 @@ struct NetworkHelper {
8484
}
8585

8686
if responseCode == 401 {
87-
return .error(SendRequestError(errorMessage: "Invalid API Key", data: data))
87+
return .error(SendRequestError(reason: "Invalid API Key", data: data))
8888
} else if responseCode >= 400 {
89-
var errorMessage = "Invalid Request"
89+
var reason = "Invalid Request"
9090
if let jsonDict = json as? [AnyHashable : Any], let msgFromDict = jsonDict["msg"] as? String {
91-
errorMessage = msgFromDict
91+
reason = msgFromDict
9292
} else if responseCode >= 500 {
93-
errorMessage = "Internal Server Error"
93+
reason = "Internal Server Error"
9494
}
95-
return .error(SendRequestError(errorMessage: errorMessage, data: data))
95+
return .error(SendRequestError(reason: reason, data: data))
9696
} else if responseCode == 200 {
9797
if let data = data, data.count > 0 {
9898
if let jsonError = jsonError {
9999
var reason = "Could not parse json, error: \(jsonError.localizedDescription)"
100100
if let stringValue = String(data: data, encoding: .utf8) {
101101
reason = "Could not parse json: \(stringValue), error: \(jsonError.localizedDescription)"
102102
}
103-
return .error(SendRequestError(errorMessage: reason, data: data))
103+
return .error(SendRequestError(reason: reason, data: data))
104104
} else if let json = json as? [AnyHashable : Any] {
105105
return .value(json)
106106
} else {
107-
return .error(SendRequestError(errorMessage: "Response is not a dictionary", data: data))
107+
return .error(SendRequestError(reason: "Response is not a dictionary", data: data))
108108
}
109109
} else {
110-
return .error(SendRequestError(errorMessage: "No data received", data: data))
110+
return .error(SendRequestError(reason: "No data received", data: data))
111111
}
112112
} else {
113-
return .error(SendRequestError(errorMessage: "Received non-200 response: \(responseCode)", data: data))
113+
return .error(SendRequestError(reason: "Received non-200 response: \(responseCode)", data: data))
114114
}
115115
}
116116
}

0 commit comments

Comments
 (0)