Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge all other AUT branch code #732

Merged
merged 3 commits into from May 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions swift-sdk/Constants.swift
Expand Up @@ -51,6 +51,8 @@ enum Const {
static let userByUserId = "users/byUserId";
static let userByEmail = "users/getByEmail";
static let mergeUser = "users/merge";
static let getCriteria = "anonymoususer/list";
static let trackAnonSession = "anonymoususer/events/session";
}

public enum UserDefault {
Expand Down Expand Up @@ -178,6 +180,7 @@ enum JsonKey {
static let actionIdentifier = "actionIdentifier"
static let userText = "userText"
static let appAlreadyRunning = "appAlreadyRunning"
static let anonSessionContext = "anonSessionContext"

static let html = "html"

Expand Down
8 changes: 4 additions & 4 deletions swift-sdk/Internal/AnonymousUserManager+Functions.swift
Expand Up @@ -60,15 +60,15 @@ struct CriteriaCompletionChecker {
self.anonymousCriteria = anonymousCriteria
}

func getMatchedCriteria() -> Int? {
var criteriaId: Int? = nil
func getMatchedCriteria() -> String? {
var criteriaId: String? = nil
if let json = try? JSONSerialization.jsonObject(with: anonymousCriteria, options: []) as? [String: Any] {
// Access the criteriaList
if let criteriaList = json["criteriaList"] as? [[String: Any]] {
if let criteriaList = json["criterias"] as? [[String: Any]] {
// Iterate over the criteria
for criteria in criteriaList {
// Perform operations on each criteria
if let searchQuery = criteria["searchQuery"] as? [String: Any], let currentCriteriaId = criteria["criteriaId"] as? Int {
if let searchQuery = criteria["searchQuery"] as? [String: Any], let currentCriteriaId = criteria["criteriaId"] as? String {
// we will split purhase/updatecart event items as seperate events because we need to compare it against the single item in criteria json
var eventsToProcess = getEventsWithCartItems()
eventsToProcess.append(contentsOf: getNonCartEvents())
Expand Down
40 changes: 18 additions & 22 deletions swift-sdk/Internal/AnonymousUserManager.swift
Expand Up @@ -75,27 +75,33 @@ public class AnonymousUserManager: AnonymousUserManagerProtocol {
// Stores an anonymous sessions locally. Updates the last session time each time when new session is created
public func updateAnonSession() {
if var sessions = localStorage.anonymousSessions {
sessions.itbl_anon_sessions.number_of_sessions += 1
sessions.itbl_anon_sessions.last_session = getUTCDateTime()
sessions.itbl_anon_sessions.totalAnonSessionCount += 1
sessions.itbl_anon_sessions.lastAnonSession = (Int(self.dateProvider.currentDate.timeIntervalSince1970) * 1000)
localStorage.anonymousSessions = sessions
} else {
// create session object for the first time
let initialAnonSessions = IterableAnonSessions(number_of_sessions: 1, last_session: getUTCDateTime(), first_session: getUTCDateTime())
let initialAnonSessions = IterableAnonSessions(totalAnonSessionCount: 1, lastAnonSession: (Int(self.dateProvider.currentDate.timeIntervalSince1970) * 1000), firstAnonSession: (Int(self.dateProvider.currentDate.timeIntervalSince1970) * 1000))
let anonSessionWrapper = IterableAnonSessionsWrapper(itbl_anon_sessions: initialAnonSessions)
localStorage.anonymousSessions = anonSessionWrapper
}
}

// Creates a user after criterias met and login the user and then sync the data through track APIs
private func createKnownUserIfCriteriaMatched(criteriaId: Int?) {
private func createKnownUserIfCriteriaMatched(criteriaId: String?) {
if (criteriaId != nil) {
var anonSessions = convertToDictionary(data: localStorage.anonymousSessions?.itbl_anon_sessions)
let userId = IterableUtil.generateUUID()
IterableAPI.setUserId(userId)
var anonSessions = convertToDictionary(data: localStorage.anonymousSessions?.itbl_anon_sessions)
anonSessions["anon_criteria_id"] = criteriaId
anonSessions["matchedCriteriaId"] = criteriaId
var appName = ""
notificationStateProvider.isNotificationsEnabled { isEnabled in
anonSessions["pushOptIn"] = isEnabled
IterableAPI.track(event: "itbl_anon_sessions", dataFields: anonSessions)
if (isEnabled) {
appName = Bundle.main.appPackageName ?? ""
}
if (!appName.isEmpty) {
anonSessions["mobilePushOptIn"] = appName
}
IterableAPI.implementation?.apiClient.trackAnonSession(createdAt: (Int(self.dateProvider.currentDate.timeIntervalSince1970) * 1000), requestJson: anonSessions)
self.syncEvents()
}
}
Expand Down Expand Up @@ -174,7 +180,7 @@ public class AnonymousUserManager: AnonymousUserManagerProtocol {
}

// Checks if criterias are being met and returns criteriaId if it matches the criteria.
private func evaluateCriteriaAndReturnID() -> Int? {
private func evaluateCriteriaAndReturnID() -> String? {
guard let events = localStorage.anonymousUserEvents, let criteriaData = localStorage.criteriaData else {
return nil
}
Expand All @@ -183,19 +189,9 @@ public class AnonymousUserManager: AnonymousUserManagerProtocol {
}
// Gets the anonymous criteria
public func getAnonCriteria() {
// call API when it is available and save data in userdefaults, until then just save the data in userdefaults using static data from anoncriteria_response.json
if let path = Bundle.module.path(forResource: "anoncriteria_response", ofType: "json") {
let fileURL = URL(fileURLWithPath: path)
do {
let data = try Data(contentsOf: fileURL)
// Process your data here
localStorage.criteriaData = data
} catch {
print("Error reading file: \(error)")
}
} else {
print("File not found in the package")
}
IterableAPI.implementation?.getCriteriaData { returnedData in
self.localStorage.criteriaData = returnedData
};
}

// Stores event data locally
Expand Down
10 changes: 10 additions & 0 deletions swift-sdk/Internal/ApiClient.swift
Expand Up @@ -293,4 +293,14 @@ extension ApiClient: ApiClientProtocol {
let result = createRequestCreator().flatMap { $0.createMergeUserRequest(sourceEmail, sourceUserId, destinationEmail, destinationUserId: destinationUserId) }
return send(iterableRequestResult: result)
}

func getCriteria() -> Pending<SendRequestValue, SendRequestError> {
let result = createRequestCreator().flatMap { $0.createGetCriteriaRequest() }
return send(iterableRequestResult: result)
}

func trackAnonSession(createdAt: Int, requestJson: [AnyHashable: Any]) -> Pending<SendRequestValue, SendRequestError> {
let result = createRequestCreator().flatMap { $0.createTrackAnonSessionRequest(createdAt: createdAt, requestJson: requestJson) }
return send(iterableRequestResult: result)
}
}
4 changes: 4 additions & 0 deletions swift-sdk/Internal/ApiClientProtocol.swift
Expand Up @@ -57,4 +57,8 @@ protocol ApiClientProtocol: AnyObject {
func getUserByEmail(email: String) -> Pending<SendRequestValue, SendRequestError>

func mergeUser(sourceEmail: String, sourceUserId: String, destinationEmail: String, destinationUserId: String) -> Pending<SendRequestValue, SendRequestError>

func getCriteria() -> Pending<SendRequestValue, SendRequestError>

func trackAnonSession(createdAt: Int, requestJson: [AnyHashable: Any]) -> Pending<SendRequestValue, SendRequestError>
}
19 changes: 18 additions & 1 deletion swift-sdk/Internal/InternalIterableAPI.swift
Expand Up @@ -180,7 +180,13 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {
logoutPreviousUser()

_email = nil
_userId = userId
if _userId == nil {
_userId = userId
localStorage.userId = userId
anonymousUserManager.syncNonSyncedEvents()
} else {
_userId = userId
}
_successCallback = successHandler
_failureCallback = failureHandler

Expand Down Expand Up @@ -781,6 +787,17 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {
}
}

func getCriteriaData(completion: @escaping (Data) -> Void) {
apiClient.getCriteria().onSuccess { data in
do {
let jsonData = try JSONSerialization.data(withJSONObject: data, options: [])
completion(jsonData)
} catch {
print("Error converting dictionary to data: \(error)")
}
}
}

deinit {
ITBInfo()
requestHandler.stop()
Expand Down
6 changes: 3 additions & 3 deletions swift-sdk/Internal/Models.swift
Expand Up @@ -23,9 +23,9 @@ struct CriteriaItem: Codable {
}

struct IterableAnonSessions: Codable {
var number_of_sessions: Int
var last_session: String
var first_session: String
var totalAnonSessionCount: Int
var lastAnonSession: Int
var firstAnonSession: Int
}

struct IterableAnonSessionsWrapper: Codable {
Expand Down
20 changes: 20 additions & 0 deletions swift-sdk/Internal/RequestCreator.swift
Expand Up @@ -529,6 +529,26 @@ struct RequestCreator {
return .success(.post(createPostRequest(path: Const.Path.mergeUser, body: body)))
}

func createGetCriteriaRequest() -> Result<IterableRequest, IterableError> {
let body: [AnyHashable: Any] = [:]
return .success(.get(createGetRequest(forPath: Const.Path.getCriteria, withArgs: body as! [String: String])))
}

func createTrackAnonSessionRequest(createdAt: Int, requestJson: [AnyHashable: Any]) -> Result<IterableRequest, IterableError> {
if case .none = auth.emailOrUserId {
ITBError(Self.authMissingMessage)
return .failure(IterableError.general(description: Self.authMissingMessage))
}

var body = [AnyHashable: Any]()

setCurrentUser(inDict: &body)
body.setValue(for: JsonKey.Body.createdAt, value: createdAt)
body.setValue(for: JsonKey.deviceInfo, value: deviceMetadata.asDictionary())
body.setValue(for: JsonKey.anonSessionContext, value: requestJson)
return .success(.post(createPostRequest(path: Const.Path.trackAnonSession, body: body)))
}

// MARK: - PRIVATE

private static let authMissingMessage = "Both email and userId are nil"
Expand Down