vibes-react-native 5.0.0 → 5.0.1-rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/ios/Vibes.swift +2 -3
  2. package/ios/VibesClient.swift +3 -4
  3. package/ios/VibesPluginLogger.swift +2 -5
  4. package/package.json +3 -2
  5. package/vendor/VibesPush/LICENSE +13 -0
  6. package/vendor/VibesPush/Sources/APIDefinition.swift +502 -0
  7. package/vendor/VibesPush/Sources/Actions.swift +24 -0
  8. package/vendor/VibesPush/Sources/AppObserver.swift +137 -0
  9. package/vendor/VibesPush/Sources/AuthTokenBehavior.swift +17 -0
  10. package/vendor/VibesPush/Sources/CombinedLogger.swift +53 -0
  11. package/vendor/VibesPush/Sources/ConsoleLogger.swift +97 -0
  12. package/vendor/VibesPush/Sources/Credential.swift +41 -0
  13. package/vendor/VibesPush/Sources/CredentialManager.swift +24 -0
  14. package/vendor/VibesPush/Sources/Date+iso8601.swift +34 -0
  15. package/vendor/VibesPush/Sources/Date+logPrefix.swift +20 -0
  16. package/vendor/VibesPush/Sources/DeviceToken.swift +15 -0
  17. package/vendor/VibesPush/Sources/DeviceType.swift +143 -0
  18. package/vendor/VibesPush/Sources/Dictionary+merged.swift +11 -0
  19. package/vendor/VibesPush/Sources/Event.swift +83 -0
  20. package/vendor/VibesPush/Sources/EventCollection.swift +36 -0
  21. package/vendor/VibesPush/Sources/EventTracker.swift +39 -0
  22. package/vendor/VibesPush/Sources/FoundationExtensions.swift +16 -0
  23. package/vendor/VibesPush/Sources/GitTag.swift +27 -0
  24. package/vendor/VibesPush/Sources/HTTP/HTTPBehavior.swift +19 -0
  25. package/vendor/VibesPush/Sources/HTTP/HTTPMethod.swift +20 -0
  26. package/vendor/VibesPush/Sources/HTTP/HTTPResource.swift +69 -0
  27. package/vendor/VibesPush/Sources/HTTP/HTTPResourceClient.swift +190 -0
  28. package/vendor/VibesPush/Sources/HTTP/JSONParser.swift +91 -0
  29. package/vendor/VibesPush/Sources/HTTP/Operations/AssociatePersonOperation.swift +56 -0
  30. package/vendor/VibesPush/Sources/HTTP/Operations/BaseOperation.swift +153 -0
  31. package/vendor/VibesPush/Sources/HTTP/Operations/EventOperation.swift +73 -0
  32. package/vendor/VibesPush/Sources/HTTP/Operations/GetGitTagsOperation.swift +61 -0
  33. package/vendor/VibesPush/Sources/HTTP/Operations/GetInboxMessageOperation.swift +59 -0
  34. package/vendor/VibesPush/Sources/HTTP/Operations/GetInboxMessagesOperation.swift +57 -0
  35. package/vendor/VibesPush/Sources/HTTP/Operations/GetPersonOperation.swift +53 -0
  36. package/vendor/VibesPush/Sources/HTTP/Operations/GetVibesAppInfoOperation.swift +45 -0
  37. package/vendor/VibesPush/Sources/HTTP/Operations/MigrationCallbackOperation.swift +45 -0
  38. package/vendor/VibesPush/Sources/HTTP/Operations/RegisterDeviceOperation.swift +66 -0
  39. package/vendor/VibesPush/Sources/HTTP/Operations/RegisterPushOperation.swift +73 -0
  40. package/vendor/VibesPush/Sources/HTTP/Operations/TrackProductActionOperation.swift +75 -0
  41. package/vendor/VibesPush/Sources/HTTP/Operations/TrackPurchaseActionOperation.swift +81 -0
  42. package/vendor/VibesPush/Sources/HTTP/Operations/UnregisterDeviceOperation.swift +64 -0
  43. package/vendor/VibesPush/Sources/HTTP/Operations/UnregisterPushOperation.swift +72 -0
  44. package/vendor/VibesPush/Sources/HTTP/Operations/UpdateDeviceOperationPatch.swift +57 -0
  45. package/vendor/VibesPush/Sources/HTTP/Operations/UpdateDeviceOperationPut.swift +59 -0
  46. package/vendor/VibesPush/Sources/HTTP/Operations/UpdateMessageOperation.swift +50 -0
  47. package/vendor/VibesPush/Sources/HTTP/Operations/VibesQueueOperation.swift +76 -0
  48. package/vendor/VibesPush/Sources/HTTP/ResourceResult.swift +38 -0
  49. package/vendor/VibesPush/Sources/HTTPURLResponse+cURL.swift +16 -0
  50. package/vendor/VibesPush/Sources/InboxMessage.swift +219 -0
  51. package/vendor/VibesPush/Sources/Info.plist +26 -0
  52. package/vendor/VibesPush/Sources/InputStream+readToString.swift +19 -0
  53. package/vendor/VibesPush/Sources/KeychainStorage.swift +64 -0
  54. package/vendor/VibesPush/Sources/LocalObject.swift +25 -0
  55. package/vendor/VibesPush/Sources/LocalStorageKeys.swift +19 -0
  56. package/vendor/VibesPush/Sources/LocalStorageType.swift +47 -0
  57. package/vendor/VibesPush/Sources/LocalValue.swift +67 -0
  58. package/vendor/VibesPush/Sources/PersistentEventStorage.swift +81 -0
  59. package/vendor/VibesPush/Sources/Person.swift +98 -0
  60. package/vendor/VibesPush/Sources/Product.swift +103 -0
  61. package/vendor/VibesPush/Sources/Purchase.swift +108 -0
  62. package/vendor/VibesPush/Sources/TrackedEventType.swift +48 -0
  63. package/vendor/VibesPush/Sources/URLRequest+cURL.swift +36 -0
  64. package/vendor/VibesPush/Sources/UserDefaultsStorage.swift +32 -0
  65. package/vendor/VibesPush/Sources/Vibes.swift +1069 -0
  66. package/vendor/VibesPush/Sources/VibesAPI.swift +81 -0
  67. package/vendor/VibesPush/Sources/VibesAPIDelegate.swift +41 -0
  68. package/vendor/VibesPush/Sources/VibesAppInfo.swift +77 -0
  69. package/vendor/VibesPush/Sources/VibesConfiguration.swift +108 -0
  70. package/vendor/VibesPush/Sources/VibesLogger.swift +65 -0
  71. package/vendor/VibesPush/Sources/VibesResult.swift +78 -0
  72. package/vibes-react-native.podspec +6 -2
@@ -0,0 +1,219 @@
1
+ //
2
+ // InboxMessage.swift
3
+ // VibesPush
4
+ //
5
+ // Created by Moin' Victor on 12/07/2019.
6
+ // Copyright © 2019 Vibes. All rights reserved.
7
+ //
8
+
9
+ import Foundation
10
+
11
+ /// Inbox Message Model
12
+ @objcMembers
13
+ public class InboxMessage: NSObject, JSONDecodable, LocalObjectType, JSONEncodable {
14
+
15
+ static let kActivityTypeKey = "activityType"
16
+ static let kActivityUidKey = "activityUid"
17
+
18
+ static let eActivityTypeKey = "activity_type"
19
+ static let eActivityUidKey = "activity_uid"
20
+ static let eMessageUidKey = "message_uid"
21
+
22
+ /// Local Atrributes
23
+ public var attributes: [String: Any] {
24
+ return [
25
+ "message_uid": messageUID ?? "",
26
+ "subject": subject ?? "",
27
+ "content": content ?? "",
28
+ "detail": detail ?? "",
29
+ "expires_at": expiresAt ?? Date(),
30
+ "created_at": createdAt,
31
+ "collapse_key": collapseKey ?? "",
32
+ "images": images,
33
+ "read": read,
34
+ "inbox_custom_data": inboxCustomData,
35
+ "client_app_data": clientAppData,
36
+ "apprefdata": apprefData,
37
+ ]
38
+ }
39
+
40
+ public func encodeJSON() -> VibesJSONDictionary {
41
+ return [
42
+ "message_uid": messageUID as AnyObject,
43
+ "subject": subject as AnyObject,
44
+ "content": content as AnyObject,
45
+ "detail": detail as AnyObject,
46
+ "expires_at": expiresAt?.iso8601 as AnyObject,
47
+ "created_at": createdAt.iso8601 as AnyObject,
48
+ "collapse_key": collapseKey as AnyObject,
49
+ "images": images as AnyObject,
50
+ "read": read as AnyObject,
51
+ "inbox_custom_data": inboxCustomData as AnyObject,
52
+ "client_app_data": clientAppData as AnyObject,
53
+ "apprefdata": apprefData as AnyObject,
54
+ ] as VibesJSONDictionary
55
+ }
56
+
57
+ public var jsonString: String? {
58
+ let jsonData = try? JSONSerialization.data(withJSONObject: encodeJSON(), options: .prettyPrinted)
59
+ return String(data: jsonData!, encoding: .utf8)
60
+ }
61
+
62
+ /// Main Image for this inbox message
63
+ public var mainImage: String? {
64
+ return images["main"]
65
+ }
66
+
67
+ /// Icon image for this push message
68
+ public var iconImage: String? {
69
+ return images["icon"]
70
+ }
71
+
72
+ /// Inbox message uid
73
+ public var inboxMessageUID: String? {
74
+ return clientAppData["inbox_message_uid"] as? String
75
+ }
76
+
77
+ /// An uniqie identifier assosiated with the message
78
+ public internal(set) var messageUID: String!
79
+ /// The collapse key
80
+ public internal(set) var collapseKey: String?
81
+ /// The subject of the message
82
+ public var subject: String?
83
+ /// A message content
84
+ public var content: String!
85
+ /// Some details for this message, Currently this is the media URL
86
+ public internal(set) var detail: String?
87
+ /// If the message is read
88
+ public var read: Bool = false
89
+ /// images details for this message
90
+ public internal(set) var images = [String: String]()
91
+ /// inbox custom data details for this message
92
+ public internal(set) var inboxCustomData = VibesJSONDictionary()
93
+ /// client app data details for this message
94
+ public internal(set) var clientAppData = VibesJSONDictionary()
95
+ /// Appref data details for this message
96
+ public internal(set) var apprefData = VibesJSONDictionary()
97
+ /// When the message expires
98
+ public var expiresAt: Date?
99
+ /// When the message was created
100
+ public internal(set) var createdAt: Date = Date()
101
+
102
+ override init() {
103
+ }
104
+
105
+ /// Initialize new InboxMessage using properties
106
+ ///
107
+ /// - Parameters:
108
+ /// - messageUID: The message id
109
+ /// - subject: The subject of the message
110
+ /// - content: The content of the message
111
+ /// - detail: The message details
112
+ /// - readStatus: The read status of the message in bool
113
+ /// - expiresAt: Date when the message expires
114
+ init(messageUID: String, subject: String?, content: String, detail: String?, read: Bool, expiresAt: Date? = nil) {
115
+ self.messageUID = messageUID
116
+ self.subject = subject
117
+ self.content = content
118
+ self.detail = detail
119
+ self.read = read
120
+ self.expiresAt = expiresAt
121
+ }
122
+
123
+ /// Initialize new InboxMessage from JSONObject
124
+ ///
125
+ /// - Parameter json: The JSON object
126
+ required convenience init?(json: VibesJSONDictionary) {
127
+ self.init()
128
+ guard let messageUID = json["message_uid"] as? String,
129
+ let content = json["content"] as? String else { return nil }
130
+
131
+ self.subject = json["subject"] as? String
132
+ detail = json["detail"] as? String
133
+ collapseKey = json["collapse_key"] as? String
134
+ if let readStatusValue = json["read"] as? Bool {
135
+ read = readStatusValue
136
+ }
137
+ if let expireDateString = json["expires_at"] as? String,
138
+ let expireDateTime = expireDateString.iso8601 {
139
+ expiresAt = expireDateTime
140
+ }
141
+ if let createdDateString = json["created_at"] as? String,
142
+ let createdDateTime = createdDateString.iso8601 {
143
+ createdAt = createdDateTime
144
+ }
145
+ if let images = json["images"] as? [String: String] {
146
+ self.images = images
147
+ }
148
+ if let inboxCustomData = json["inbox_custom_data"] as? VibesJSONDictionary {
149
+ self.inboxCustomData = inboxCustomData
150
+ }
151
+ if let clientAppData = json["client_app_data"] as? VibesJSONDictionary {
152
+ self.clientAppData = clientAppData
153
+ }
154
+ if let apprefData = json["apprefdata"] as? VibesJSONDictionary {
155
+ self.apprefData = apprefData
156
+ }
157
+ self.messageUID = messageUID
158
+ self.content = content
159
+ }
160
+
161
+ /// Initialize this object using Attributes
162
+ ///
163
+ /// - Parameter attributes: - The dictionary with attributes
164
+ public required convenience init?(attributes: [String: Any]) {
165
+ self.init()
166
+
167
+ guard let messageUID = attributes["message_uid"] as? String, !messageUID.isEmpty,
168
+ let content = attributes["content"] as? String else { return nil }
169
+
170
+ self.subject = attributes["subject"] as? String
171
+ detail = attributes["detail"] as? String
172
+ collapseKey = attributes["collapse_key"] as? String
173
+ if let readStatusValue = attributes["read"] as? Bool {
174
+ read = readStatusValue
175
+ }
176
+ if let expireDate = attributes["expires_at"] as? Date {
177
+ expiresAt = expireDate
178
+ }
179
+ if let createdDateTime = attributes["created_at"] as? Date {
180
+ createdAt = createdDateTime
181
+ }
182
+ if let images = attributes["images"] as? [String: String] {
183
+ self.images = images
184
+ }
185
+ if let inboxCustomData = attributes["inbox_custom_data"] as? VibesJSONDictionary {
186
+ self.inboxCustomData = inboxCustomData
187
+ }
188
+ if let clientAppData = attributes["client_app_data"] as? VibesJSONDictionary {
189
+ self.clientAppData = clientAppData
190
+ }
191
+ if let apprefData = attributes["apprefdata"] as? VibesJSONDictionary {
192
+ self.apprefData = apprefData
193
+ }
194
+ self.messageUID = messageUID
195
+ self.content = content
196
+ }
197
+ }
198
+
199
+ /// Equals Comparison operator for InboxMessage
200
+ ///
201
+ /// - Parameters:
202
+ /// - lhs: The left hand side InboxMessage
203
+ /// - rhs: The right hand side InboxMessage
204
+ /// - Returns: `True` if `lhs` is equal to `rhs`, else returns `False`
205
+ public func == (lhs: InboxMessage, rhs: InboxMessage) -> Bool {
206
+ return lhs.messageUID == rhs.messageUID
207
+ }
208
+
209
+ extension InboxMessage {
210
+
211
+ /// The vent map for this inbox message
212
+ internal func eventMap() -> [String: String] {
213
+ var evMap = [String: String]()
214
+ evMap[InboxMessage.eMessageUidKey] = messageUID
215
+ evMap[InboxMessage.eActivityTypeKey] = apprefData[InboxMessage.kActivityTypeKey] as? String
216
+ evMap[InboxMessage.eActivityUidKey] = apprefData[InboxMessage.kActivityUidKey] as? String
217
+ return evMap
218
+ }
219
+ }
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>en</string>
7
+ <key>CFBundleExecutable</key>
8
+ <string>$(EXECUTABLE_NAME)</string>
9
+ <key>CFBundleIdentifier</key>
10
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11
+ <key>CFBundleInfoDictionaryVersion</key>
12
+ <string>6.0</string>
13
+ <key>CFBundleName</key>
14
+ <string>$(PRODUCT_NAME)</string>
15
+ <key>CFBundlePackageType</key>
16
+ <string>FMWK</string>
17
+ <key>CFBundleShortVersionString</key>
18
+ <string>5.0.0</string>
19
+ <key>CFBundleVersion</key>
20
+ <string>$(CURRENT_PROJECT_VERSION)</string>
21
+ <key>LSApplicationCategoryType</key>
22
+ <string></string>
23
+ <key>NSPrincipalClass</key>
24
+ <string></string>
25
+ </dict>
26
+ </plist>
@@ -0,0 +1,19 @@
1
+ import Foundation
2
+
3
+ extension InputStream {
4
+ /// Read input stream to a String
5
+ func readToString() -> String? {
6
+ var data = Data()
7
+ self.open()
8
+
9
+ let bufferSize = 1024
10
+ let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
11
+ while self.hasBytesAvailable {
12
+ let read = self.read(buffer, maxLength: bufferSize)
13
+ data.append(buffer, count: read)
14
+ }
15
+ buffer.deallocate()
16
+ self.close()
17
+ return String(data: data, encoding: String.Encoding.utf8)
18
+ }
19
+ }
@@ -0,0 +1,64 @@
1
+ import Foundation
2
+ /// A storage adapter that uses the Keychain as a local storage mechanism.
3
+ struct KeychainStorage {
4
+ /// The "service" name to use
5
+ fileprivate let service: String
6
+
7
+ /// Initialize this object.
8
+ ///
9
+ /// - parameters:
10
+ /// - service: the "service" name to use
11
+ init(service: String) {
12
+ self.service = service
13
+ }
14
+ }
15
+
16
+ extension KeychainStorage: LocalStorageType {
17
+ /// Retrieves the value in the keychain for the provided item.
18
+ ///
19
+ /// - parameters:
20
+ /// - item: the local storage item to retreive
21
+ /// - returns: the previously-stored value, or nil
22
+ func get<T>(_ item: LocalValue<T>) -> T? {
23
+ let attributes = [
24
+ String(kSecClass): kSecClassGenericPassword,
25
+ String(kSecAttrService): service,
26
+ String(kSecMatchLimit): kSecMatchLimitOne,
27
+ String(kSecAttrAccount): item.key,
28
+ String(kSecReturnData): true,
29
+ ] as [String: Any]
30
+
31
+ var result: AnyObject?
32
+ let status = SecItemCopyMatching(attributes as CFDictionary, &result)
33
+
34
+ guard status == noErr else { return nil }
35
+ guard let data = result as? Data else { return nil }
36
+
37
+ return T.unarchive(data: data)
38
+ }
39
+
40
+ /// Stores a value in the keychain with the key provided.
41
+ ///
42
+ /// - parameters:
43
+ /// - value: the value to store
44
+ /// - item: the local storage item to use for storage
45
+ /// - returns: a boolean indicating whether storing the value was successful
46
+ func set<T>(_ value: T?, for item: LocalValue<T>) -> Bool {
47
+ var attributes = [
48
+ String(kSecClass): kSecClassGenericPassword,
49
+ String(kSecAttrService): service,
50
+ String(kSecAttrAccount): item.key,
51
+ ] as [String: Any]
52
+
53
+ if let value = value {
54
+ attributes[String(kSecValueData)] = T.archive(value: value)
55
+ SecItemDelete(attributes as CFDictionary)
56
+
57
+ let status = SecItemAdd(attributes as CFDictionary, nil)
58
+ return status == noErr
59
+ } else {
60
+ let status = SecItemDelete(attributes as CFDictionary)
61
+ return status == noErr
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,25 @@
1
+ /// A protocol for anything that can be stored as an object.
2
+ public protocol LocalObjectType {
3
+ /// Attributes that should be used to store this object in local storage.
4
+ var attributes: [String: Any] { get }
5
+
6
+ /// Creates an object from a set of previously-stored attributes.
7
+ ///
8
+ /// - parameters:
9
+ /// - attributes: a dictionary of attributes to use to create this object
10
+ init?(attributes: [String: Any])
11
+ }
12
+
13
+ /// A simple struct for identifying an object that is held in local storage.
14
+ public struct LocalObject<T: LocalObjectType> {
15
+ /// The identifier to use to store this object.
16
+ let key: String
17
+
18
+ /// Initialize this object
19
+ ///
20
+ /// - paremeters:
21
+ /// - key: the identifier to use to store this object
22
+ init(_ key: String) {
23
+ self.key = key
24
+ }
25
+ }
@@ -0,0 +1,19 @@
1
+ /// Type-safe local storage used by Vibes; these static instances encapsulate
2
+ /// the key used to store some data in local storage, along with encoding the
3
+ /// expected type information that should be returned.
4
+ enum LocalStorageKeys {
5
+ /// The current device's push token
6
+ static let pushToken = LocalValue<String>("VIBES_PUSH_TOKEN")
7
+
8
+ /// The current Credential
9
+ static let currentCredential = LocalObject<VibesCredential>("VIBES_CURRENT_CREDENTIAL")
10
+
11
+ /// The set of all known Credentials
12
+ static let allCredentials = LocalValue<[String: String]>("VIBES_ALL_CREDENTIALS")
13
+
14
+ /// All events that have been stored locally
15
+ static let events = LocalObject<EventCollection>("VIBES_EVENTS")
16
+
17
+ /// The current Vibes Person
18
+ static let currentPerson = LocalObject<Person>("VIBES_CURRENT_PERSON")
19
+ }
@@ -0,0 +1,47 @@
1
+ /// A protocol that defines an adapter for allowing the storage of values in
2
+ /// some sort of local storage mechanism (e.g. UserDefaults, Keychain, etc.).
3
+ ///
4
+ /// Adopters of this protocol get the ability to get and set custom objects as
5
+ /// well.
6
+ public protocol LocalStorageType {
7
+ /// Retrieves the value for the given item.
8
+ ///
9
+ /// - parameters:
10
+ /// - item: a local value that identifies this item
11
+ /// - returns: an instance of T, if it was found; nil otherwise
12
+ func get<T>(_ item: LocalValue<T>) -> T?
13
+
14
+ /// Stores a value for the item provided.
15
+ ///
16
+ /// - parameters:
17
+ /// - value: the value to store at the given key
18
+ /// - item: a local value to identify this item
19
+ /// - returns: true if storing was successful; nil otherwise
20
+ @discardableResult
21
+ func set<T>(_ value: T?, for item: LocalValue<T>) -> Bool
22
+ }
23
+
24
+ extension LocalStorageType {
25
+ /// Retrieves the object stored for the given item.
26
+ ///
27
+ /// - parameters:
28
+ /// - item: the local storage item to retreive
29
+ /// - returns: the previously-stored object, or nil
30
+ func get<T>(_ item: LocalObject<T>) -> T? {
31
+ let localValue = LocalValue<[String: Any]>(item.key)
32
+ guard let attributes = get(localValue) else { return nil }
33
+ return T.init(attributes: attributes)
34
+ }
35
+
36
+ /// Stores an object for the item provided.
37
+ ///
38
+ /// - parameters:
39
+ /// - value: the object to store
40
+ /// - item: the local storage item to use for storage
41
+ /// - returns: a boolean indicating whether storing the object was successful
42
+ @discardableResult
43
+ func set<T>(_ value: T?, for item: LocalObject<T>) -> Bool {
44
+ let localValue = LocalValue<[String: Any]>(item.key)
45
+ return set(value?.attributes, for: localValue)
46
+ }
47
+ }
@@ -0,0 +1,67 @@
1
+ /// A protocol for anything that can be stored as a value. This protocol
2
+ /// inherits default implementations, so new values can be added just be
3
+ /// adopting the bare protocol, e.g. `extension Date: LocalValueType {}`
4
+ import Foundation
5
+
6
+ public protocol VibesLocalValueType {
7
+ /// Archives this value to Data that can be stored.
8
+ ///
9
+ /// - paremeters:
10
+ /// - value: an instance of self, e.g. String
11
+ /// - returns: the encoded value, as data
12
+ static func archive(value: Self) -> Data
13
+
14
+ /// Unarchives this value from Data
15
+ ///
16
+ /// - paremeters:
17
+ /// - data: the data to convert into a value
18
+ /// - returns: the value that was decoded
19
+ static func unarchive(data: Data) -> Self?
20
+ }
21
+
22
+ extension VibesLocalValueType {
23
+ public static func archive(value: Self) -> Data {
24
+ return NSKeyedArchiver.archivedData(withRootObject: value)
25
+ }
26
+
27
+ public static func unarchive(data: Data) -> Self? {
28
+ let object = NSKeyedUnarchiver.unarchiveObject(with: data)
29
+ return object as? Self
30
+ }
31
+ }
32
+
33
+ extension String: VibesLocalValueType {
34
+ public static func archive(value: String) -> Data {
35
+ return NSKeyedArchiver.archivedData(withRootObject: value)
36
+ }
37
+
38
+ public static func unarchive(data: Data) -> String? {
39
+ let object = NSKeyedUnarchiver.unarchiveObject(with: data)
40
+ return object as? String
41
+ }
42
+ }
43
+
44
+ extension Dictionary: VibesLocalValueType {
45
+ public static func archive(value: Dictionary) -> Data {
46
+ return NSKeyedArchiver.archivedData(withRootObject: value)
47
+ }
48
+
49
+ public static func unarchive(data: Data) -> Dictionary? {
50
+ let object = NSKeyedUnarchiver.unarchiveObject(with: data)
51
+ return object as? Dictionary
52
+ }
53
+ }
54
+
55
+ /// A simple struct for identifying a value that is held in local storage.
56
+ public struct LocalValue<T: VibesLocalValueType> {
57
+ /// The identifier to use to store this value.
58
+ let key: String
59
+
60
+ /// Initialize this object.
61
+ ///
62
+ /// - paremeters:
63
+ /// - key: the identifier to use to store this value.
64
+ init(_ key: String) {
65
+ self.key = key
66
+ }
67
+ }
@@ -0,0 +1,81 @@
1
+ import Foundation
2
+ /// An object to take care of persisting incoming events when they are received
3
+ /// and removing them once they have been successfully sent to Vibes.
4
+ class PersistentEventStorage {
5
+ /// A serial dispatch queue for changing local storage
6
+ private let internalQueue: DispatchQueue
7
+
8
+ /// The local storage mechanism we are using for storing events
9
+ private let storage: LocalStorageType
10
+
11
+ /// A property for the events currently stored locally.
12
+ var storedEvents: [Event] {
13
+ get {
14
+ return storage.get(LocalStorageKeys.events)?.events ?? []
15
+ }
16
+ set(newEvents) {
17
+ storage.set(EventCollection(events: newEvents), for: LocalStorageKeys.events)
18
+ }
19
+ }
20
+
21
+ /// Initialize this object.
22
+ ///
23
+ /// - parameters:
24
+ /// - storage: a local storage mechanism for storing events
25
+ init(storage: LocalStorageType) {
26
+ self.storage = storage
27
+ self.internalQueue = DispatchQueue(label: "Vibes")
28
+ }
29
+
30
+ /// A convenience typelias for the completion of sending events to be tracked
31
+ /// over the API.
32
+ typealias TrackCompletion = (VibesResult<Void>) -> Void
33
+
34
+ /// A wrapper around sending events to Vibes; this is what handles
35
+ /// persisting/removing events from local storage.
36
+ ///
37
+ /// - parameters:
38
+ /// - events: an Array of events to track.
39
+ /// - callback: a callback for when events have been tracked via the API.
40
+ /// It receives the events to store (which may be a superset of the
41
+ /// events passed in) and a completion to call with the result of sending
42
+ /// the events over the API.
43
+ func tracking(events incomingEvents: [Event], callback: ([Event], @escaping TrackCompletion) -> Void) {
44
+ guard let event = incomingEvents.first else {
45
+ return
46
+ }
47
+
48
+ let uniqueEvents = incomingEvents.firstUniqueElements
49
+ persistEvents(uniqueEvents)
50
+
51
+ let outgoingEvents = storedEvents.filter { $0.type == event.type }
52
+ callback(outgoingEvents, { result in
53
+ switch result {
54
+ case .success:
55
+ self.removeEvents(outgoingEvents)
56
+ default:
57
+ break
58
+ }
59
+ })
60
+ }
61
+
62
+ /// Persist events in local storage.
63
+ ///
64
+ /// - parameters:
65
+ /// - events: an Array of events to persist.
66
+ private func persistEvents(_ events: [Event]) {
67
+ internalQueue.sync {
68
+ storedEvents.append(contentsOf: events)
69
+ }
70
+ }
71
+
72
+ /// Removes events from local storage.
73
+ ///
74
+ /// - parameters:
75
+ /// - events: an Array of events to remove.
76
+ private func removeEvents(_ events: [Event]) {
77
+ internalQueue.sync {
78
+ storedEvents = storedEvents.filter { !events.contains($0) }
79
+ }
80
+ }
81
+ }
@@ -0,0 +1,98 @@
1
+ //
2
+ // Person.swift
3
+ // VibesPush
4
+ //
5
+ // Created by clemwek on 12/07/2019.
6
+ // Copyright © 2019 Vibes. All rights reserved.
7
+ //
8
+ import Foundation
9
+
10
+ @objcMembers
11
+ public class Person: NSObject, JSONDecodable, LocalObjectType {
12
+ public var attributes: [String: Any] {
13
+ return [
14
+ "person_key": personKey ?? "",
15
+ "external_person_id": externalPersonId ?? "",
16
+ "mobile_phone": mobilePhone,
17
+ ]
18
+ }
19
+
20
+ /// An external identifier assosiated with the device or person if available
21
+ public var externalPersonId: String?
22
+ /// The phone number of the assosiated person if available
23
+ public var mdn: String?
24
+ /// A unique identifier for the person, provided by Vibes when assosiated.
25
+ public var personKey: String?
26
+
27
+ private var mobilePhone: [String: String] = [:]
28
+
29
+ override init() {
30
+ }
31
+
32
+ /// Initialize for testing
33
+ ///
34
+ /// - Parameters:
35
+ /// - externalPersonId: external person id
36
+ /// - mdn: phone number
37
+ /// - personKey: person key
38
+ init(externalPersonId: String, mdn: String, personKey: String) {
39
+ self.externalPersonId = externalPersonId
40
+ self.mdn = mdn
41
+ self.personKey = personKey
42
+ }
43
+
44
+ /// Initialize this object using JSONObject
45
+ ///
46
+ /// - Parameter json: The JSONObject
47
+ required convenience init?(json: VibesJSONDictionary) {
48
+ self.init()
49
+
50
+ let mdn: String?
51
+
52
+ guard let personKey = json["person_key"] as? String else { return nil }
53
+
54
+ if let mobilePhone = json["mobile_phone"] as? [String: String] {
55
+ mdn = mobilePhone["mdn"]
56
+ } else {
57
+ mdn = nil
58
+ }
59
+
60
+ self.personKey = personKey
61
+ externalPersonId = json["external_person_id"] as? String
62
+ self.mdn = mdn
63
+ }
64
+
65
+ /// Initialize this object using Attributes
66
+ ///
67
+ /// - Parameter attributes: - The dictionary with attributes
68
+ public required convenience init?(attributes: [String: Any]) {
69
+ self.init()
70
+
71
+ let mdn: String?
72
+
73
+ guard let personKey = attributes["person_key"] as? String,
74
+ !personKey.isEmpty else { return nil }
75
+
76
+ if let mobilePhone = attributes["mobile_phone"] as? [String: String] {
77
+ mdn = mobilePhone["mdn"]
78
+ } else {
79
+ mdn = nil
80
+ }
81
+
82
+ externalPersonId = attributes["external_person_id"] as? String
83
+ self.mdn = mdn
84
+ self.personKey = personKey
85
+ }
86
+ }
87
+
88
+ /// Equals Comparison operator for Person
89
+ ///
90
+ /// - Parameters:
91
+ /// - lhs: The left hand side Person
92
+ /// - rhs: The right hand side Person
93
+ /// - Returns: `True` if `lhs` is equal to `rhs`, else returns `False`
94
+ public func == (lhs: Person, rhs: Person) -> Bool {
95
+ return lhs.personKey == rhs.personKey &&
96
+ lhs.externalPersonId == rhs.externalPersonId &&
97
+ lhs.mdn == rhs.mdn
98
+ }