Skip to content

Commit 98a583c

Browse files
authored
Merge pull request #327 from Iterable/jay/MOB-4299-version-1.2.3
[MOB-4299] version 1.2.3
2 parents 77f4891 + 0742086 commit 98a583c

File tree

8 files changed

+465
-237
lines changed

8 files changed

+465
-237
lines changed

Iterable-React-Native-SDK.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ Pod::Spec.new do |s|
2424

2525
s.swift_version = '5.3'
2626

27-
s.dependency 'Iterable-iOS-SDK', '~> 6.4.1'
27+
s.dependency 'Iterable-iOS-SDK', '~> 6.4.2'
2828
s.dependency 'React-Core'
2929
end

android/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ def getModuleVersion() {
2222

2323
dependencies {
2424
implementation 'com.facebook.react:react-native:+'
25-
api 'com.iterable:iterableapi:3.4.4'
25+
api 'com.iterable:iterableapi:3.4.5'
2626
// api project(':iterableapi') // links to local android SDK repo rather than by release
2727
}

integration-testing/ios/example.xcodeproj/project.pbxproj

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
4220A76D9E01418EA8F8E9BD /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B032AA4480FF30BB594C1A6C /* libPods-example.a */; };
11+
552A0AAD280E2E0A00A80963 /* Pending.swift in Sources */ = {isa = PBXBuildFile; fileRef = 552A0AAC280E2E0A00A80963 /* Pending.swift */; };
1112
AC1272892499FCC10006A3C5 /* RNE2E.m in Sources */ = {isa = PBXBuildFile; fileRef = AC1272882499FCC10006A3C5 /* RNE2E.m */; };
1213
AC12728B2499FCEC0006A3C5 /* ReactE2E.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC12728A2499FCEC0006A3C5 /* ReactE2E.swift */; };
1314
AC12728D249A567D0006A3C5 /* IterableAPISupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC12728C249A567D0006A3C5 /* IterableAPISupport.swift */; };
@@ -33,6 +34,7 @@
3334

3435
/* Begin PBXFileReference section */
3536
3C757389F2C6D30D9AAFFFFB /* Pods-example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.debug.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.debug.xcconfig"; sourceTree = "<group>"; };
37+
552A0AAC280E2E0A00A80963 /* Pending.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Pending.swift; sourceTree = "<group>"; };
3638
AC1272882499FCC10006A3C5 /* RNE2E.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNE2E.m; sourceTree = "<group>"; };
3739
AC12728A2499FCEC0006A3C5 /* ReactE2E.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactE2E.swift; sourceTree = "<group>"; };
3840
AC12728C249A567D0006A3C5 /* IterableAPISupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IterableAPISupport.swift; sourceTree = "<group>"; };
@@ -124,6 +126,7 @@
124126
AC1272882499FCC10006A3C5 /* RNE2E.m */,
125127
AC12728A2499FCEC0006A3C5 /* ReactE2E.swift */,
126128
AC12728C249A567D0006A3C5 /* IterableAPISupport.swift */,
129+
552A0AAC280E2E0A00A80963 /* Pending.swift */,
127130
ACF93CD724A33A6F004B0745 /* main.jsBundle */,
128131
);
129132
path = example;
@@ -307,6 +310,7 @@
307310
AC12728B2499FCEC0006A3C5 /* ReactE2E.swift in Sources */,
308311
AC1272892499FCC10006A3C5 /* RNE2E.m in Sources */,
309312
AC12728D249A567D0006A3C5 /* IterableAPISupport.swift in Sources */,
313+
552A0AAD280E2E0A00A80963 /* Pending.swift in Sources */,
310314
AC27B4692495224E0079F714 /* ViewController.swift in Sources */,
311315
AC27B4652495224E0079F714 /* AppDelegate.swift in Sources */,
312316
);

integration-testing/ios/example/IterableAPISupport.swift

+9-9
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct IterableAPISupport {
4040
}
4141

4242

43-
static func sendInApp(apiKey: String, to email: String, withCampaignId campaignId: Int) -> Future<SendRequestValue, SendRequestError> {
43+
static func sendInApp(apiKey: String, to email: String, withCampaignId campaignId: Int) -> Pending<SendRequestValue, SendRequestError> {
4444
let body: [String: Any] = [
4545
Const.Key.recipientEmail: email,
4646
Const.Key.campaignId: campaignId
@@ -63,7 +63,7 @@ struct IterableAPISupport {
6363
private static let maxMessages = 100
6464

6565
private static func getInAppMessages(apiKey: String,
66-
email: String) -> Future<[IterableInAppMessage], SendRequestError> {
66+
email: String) -> Pending<[IterableInAppMessage], SendRequestError> {
6767
var args: [String: String] = [
6868
JsonKey.email: email,
6969
JsonKey.InApp.count: maxMessages.description,
@@ -108,10 +108,10 @@ struct IterableAPISupport {
108108
}
109109
}
110110

111-
private static func checkMessagesDone(apiKey: String, email: String, messages: [IterableInAppMessage], attemptsRemaining: Int) -> Future<[IterableInAppMessage], SendRequestError> {
111+
private static func checkMessagesDone(apiKey: String, email: String, messages: [IterableInAppMessage], attemptsRemaining: Int) -> Pending<[IterableInAppMessage], SendRequestError> {
112112
ITBInfo("attemptsRemaining: \(attemptsRemaining), waiting or 1 s...")
113113
guard messages.count > 0 else {
114-
return Promise<[IterableInAppMessage], SendRequestError>(value: [])
114+
return Fulfill<[IterableInAppMessage], SendRequestError>(value: [])
115115
}
116116
guard attemptsRemaining > 0 else {
117117
return SendRequestError.createErroredFuture(reason: "Number of attempts exceeded")
@@ -124,21 +124,21 @@ struct IterableAPISupport {
124124
}
125125

126126
// Call consume one after the other
127-
private static func chainCallConsume(apiKey: String, email: String, messages: [IterableInAppMessage]) -> Future<SendRequestValue, SendRequestError> {
127+
private static func chainCallConsume(apiKey: String, email: String, messages: [IterableInAppMessage]) -> Pending<SendRequestValue, SendRequestError> {
128128
guard messages.count > 0 else {
129-
return Promise<SendRequestValue, SendRequestError>(value: [:])
129+
return Fulfill<SendRequestValue, SendRequestError>(value: [:])
130130
}
131131

132-
let result = Promise<SendRequestValue, SendRequestError>(value: [:])
132+
let result = Fulfill<SendRequestValue, SendRequestError>(value: [:])
133133

134-
return messages.reduce(result) { (partialResult, message) -> Future<SendRequestValue, SendRequestError> in
134+
return messages.reduce(result) { (partialResult, message) -> Pending<SendRequestValue, SendRequestError> in
135135
partialResult.flatMap { _ in
136136
consumeInAppMessage(apiKey: apiKey, email: email, messageId: message.messageId)
137137
}
138138
}
139139
}
140140

141-
private static func consumeInAppMessage(apiKey: String, email: String, messageId: String) -> Future<SendRequestValue, SendRequestError> {
141+
private static func consumeInAppMessage(apiKey: String, email: String, messageId: String) -> Pending<SendRequestValue, SendRequestError> {
142142
var body = [AnyHashable: Any]()
143143

144144
body.setValue(for: JsonKey.messageId, value: messageId)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
//
2+
// Copyright © 2018 Iterable. All rights reserved.
3+
//
4+
5+
import Foundation
6+
7+
enum IterableError: Error {
8+
case general(description: String)
9+
}
10+
11+
extension IterableError: LocalizedError {
12+
var errorDescription: String? {
13+
switch self {
14+
case let .general(description):
15+
return NSLocalizedString(description, comment: "error description")
16+
}
17+
}
18+
}
19+
20+
// This has only two public methods
21+
// either there is a success with result
22+
// or there is a failure with error
23+
// There is no way to set value a result in this class.
24+
class Pending<Value, Failure> where Failure: Error {
25+
fileprivate var successCallbacks = [(Value) -> Void]()
26+
fileprivate var errorCallbacks = [(Failure) -> Void]()
27+
28+
public func onCompletion(receiveValue: @escaping ((Value) -> Void), receiveError: ( (Failure) -> Void)? = nil) {
29+
successCallbacks.append(receiveValue)
30+
31+
// if a successful result already exists (from constructor), report it
32+
if case let Result.success(value)? = result {
33+
successCallbacks.forEach { $0(value) }
34+
}
35+
36+
if let receiveError = receiveError {
37+
errorCallbacks.append(receiveError)
38+
39+
// if a failed result already exists (from constructor), report it
40+
if case let Result.failure(error)? = result {
41+
errorCallbacks.forEach { $0(error) }
42+
}
43+
}
44+
}
45+
46+
@discardableResult public func onSuccess(block: @escaping ((Value) -> Void)) -> Pending<Value, Failure> {
47+
successCallbacks.append(block)
48+
49+
// if a successful result already exists (from constructor), report it
50+
if case let Result.success(value)? = result {
51+
successCallbacks.forEach { $0(value) }
52+
}
53+
54+
return self
55+
}
56+
57+
@discardableResult public func onError(block: @escaping ((Failure) -> Void)) -> Pending<Value, Failure> {
58+
errorCallbacks.append(block)
59+
60+
// if a failed result already exists (from constructor), report it
61+
if case let Result.failure(error)? = result {
62+
errorCallbacks.forEach { $0(error) }
63+
}
64+
65+
return self
66+
}
67+
68+
public func isResolved() -> Bool {
69+
result != nil
70+
}
71+
72+
public func wait() {
73+
// ITBDebug()
74+
guard !isResolved() else {
75+
// ITBDebug("isResolved")
76+
return
77+
}
78+
79+
// ITBDebug("waiting....")
80+
Thread.sleep(forTimeInterval: 0.1)
81+
wait()
82+
}
83+
84+
fileprivate var result: Result<Value, Failure>? {
85+
// Observe whenever a result is assigned, and report it
86+
didSet { result.map(report) }
87+
}
88+
89+
// Report success or error based on result
90+
private func report(result: Result<Value, Failure>) {
91+
switch result {
92+
case let .success(value):
93+
successCallbacks.forEach { $0(value) }
94+
case let .failure(error):
95+
errorCallbacks.forEach { $0(error) }
96+
}
97+
}
98+
}
99+
100+
extension Pending {
101+
func flatMap<NewValue>(_ closure: @escaping (Value) -> Pending<NewValue, Failure>) -> Pending<NewValue, Failure> {
102+
let fulfill = Fulfill<NewValue, Failure>()
103+
104+
onSuccess { value in
105+
let pending = closure(value)
106+
107+
pending.onSuccess { futureValue in
108+
fulfill.resolve(with: futureValue)
109+
}
110+
111+
pending.onError { futureError in
112+
fulfill.reject(with: futureError)
113+
}
114+
}
115+
116+
onError { error in
117+
fulfill.reject(with: error)
118+
}
119+
120+
return fulfill
121+
}
122+
123+
func map<NewValue>(_ closure: @escaping (Value) -> NewValue) -> Pending<NewValue, Failure> {
124+
let fulfill = Fulfill<NewValue, Failure>()
125+
126+
onSuccess { value in
127+
let nextValue = closure(value)
128+
fulfill.resolve(with: nextValue)
129+
}
130+
131+
onError { error in
132+
fulfill.reject(with: error)
133+
}
134+
135+
return fulfill
136+
}
137+
138+
func mapFailure<NewFailure>(_ closure: @escaping (Failure) -> NewFailure) -> Pending<Value, NewFailure> {
139+
let fulfill = Fulfill<Value, NewFailure>()
140+
141+
onSuccess { value in
142+
fulfill.resolve(with: value)
143+
}
144+
145+
onError { error in
146+
let nextError = closure(error)
147+
fulfill.reject(with: nextError)
148+
}
149+
150+
return fulfill
151+
}
152+
153+
func replaceError(with defaultForError: Value) -> Pending<Value, Failure> {
154+
let fulfill = Fulfill<Value, Failure>()
155+
156+
onSuccess { value in
157+
fulfill.resolve(with: value)
158+
}
159+
160+
onError { _ in
161+
fulfill.resolve(with: defaultForError)
162+
}
163+
164+
return fulfill
165+
}
166+
}
167+
168+
// This class takes the responsibility of setting value for Pending
169+
class Fulfill<Value, Failure>: Pending<Value, Failure> where Failure: Error {
170+
public init(value: Value? = nil) {
171+
// ITBDebug()
172+
super.init()
173+
if let value = value {
174+
result = Result.success(value)
175+
} else {
176+
result = nil
177+
}
178+
}
179+
180+
public init(error: Failure) {
181+
// ITBDebug()
182+
super.init()
183+
result = Result.failure(error)
184+
}
185+
186+
deinit {
187+
// ITBDebug()
188+
}
189+
190+
public func resolve(with value: Value) {
191+
result = .success(value)
192+
}
193+
194+
public func reject(with error: Failure) {
195+
result = .failure(error)
196+
}
197+
}

integration-testing/yarn.lock

+4-4
Original file line numberDiff line numberDiff line change
@@ -699,10 +699,10 @@
699699
dependencies:
700700
"@hapi/hoek" "^8.3.0"
701701

702-
"@iterable/react-native-sdk@^1.2.1":
703-
version "1.2.1"
704-
resolved "https://registry.yarnpkg.com/@iterable/react-native-sdk/-/react-native-sdk-1.2.1.tgz#1ed7b61a651d75b4b33b5f5d040b353138750367"
705-
integrity sha512-2GPB8NVM9m7Ly4c3KsXVCfM9fHytjgMRVIH7ywkJXEnJCCkHVIytHRzRyxKgnd3QzpQd4/MD8KCDOvyuafSZLg==
702+
"@iterable/react-native-sdk@^1.2.2":
703+
version "1.2.2"
704+
resolved "https://registry.yarnpkg.com/@iterable/react-native-sdk/-/react-native-sdk-1.2.2.tgz#d22f7a57b38f8928214a8688b01052ee2a98988d"
705+
integrity sha512-g8nr7D9Fhji0OOZOW1F74uuJ3SX7a6lCdOLnHqfsNo1w6IrJRTJsFk/lcvnLM+4BdTu3oWcjHOjaiL8wEnBeTg==
706706

707707
"@jest/console@^24.9.0":
708708
version "24.9.0"

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@iterable/react-native-sdk",
3-
"version": "1.2.2",
3+
"version": "1.2.3",
44
"description": "Iterable SDK for React Native.",
55
"main": "./js/index.js",
66
"types": "./js/index.d.ts",

0 commit comments

Comments
 (0)