TF-2384 Handle hasMoreChange when get email changes in push notification
(cherry picked from commit 5477675671fa62a1d680e655e6a4e9f3ea09df51)
This commit is contained in:
@@ -9,6 +9,11 @@ class JmapClient {
|
||||
private var authentication: Authentication?
|
||||
private var tokenRefreshManager: TokenRefreshManager?
|
||||
private var authenticationInterceptor: AuthenticationInterceptor?
|
||||
|
||||
private var hasMoreChanges: Bool = true
|
||||
private var currentSinceState: String?
|
||||
private var totalListEmails = [Email]()
|
||||
private var listErrors = [Error]()
|
||||
|
||||
func getNewEmails(
|
||||
apiUrl: String,
|
||||
@@ -19,8 +24,7 @@ class JmapClient {
|
||||
basicAuth: String?,
|
||||
tokenEndpointUrl: String?,
|
||||
oidcScopes: [String]?,
|
||||
onSuccess: @escaping ([Email]) -> Void,
|
||||
onFailure: @escaping (Error) -> Void
|
||||
onComplete: @escaping ([Email], [Error]) -> Void
|
||||
) {
|
||||
if (authenticationType == AuthenticationType.basic) {
|
||||
authentication = AuthenticationCredential(
|
||||
@@ -47,7 +51,26 @@ class JmapClient {
|
||||
accountId: accountId,
|
||||
tokenRefreshManager: tokenRefreshManager
|
||||
)
|
||||
|
||||
|
||||
hasMoreChanges = true
|
||||
currentSinceState = sinceState
|
||||
totalListEmails = [Email]()
|
||||
listErrors = [Error]()
|
||||
|
||||
self.handleGetEmailChanges(
|
||||
apiUrl: apiUrl,
|
||||
accountId: accountId,
|
||||
onComplete: onComplete
|
||||
)
|
||||
}
|
||||
|
||||
private func handleGetEmailChanges(apiUrl: String,
|
||||
accountId: String,
|
||||
onComplete: @escaping ([Email], [Error]) -> Void) {
|
||||
guard hasMoreChanges, let sinceState = currentSinceState else {
|
||||
return onComplete(self.totalListEmails, self.listErrors)
|
||||
}
|
||||
|
||||
let jmapRequestObject = JmapRequestGenerator.shared.createEmailChangesRequest(
|
||||
accountId: accountId,
|
||||
sinceState: sinceState
|
||||
@@ -59,13 +82,29 @@ class JmapClient {
|
||||
headers: HTTPHeaders([jmapHeader]),
|
||||
interceptor: authenticationInterceptor,
|
||||
onSuccess: { (data: JmapResponseObject<Email>) in
|
||||
if let listEmail = data.parsing(methodName: JmapConstants.EMAIL_GET_METHOD_NAME, methodCallId: "c1"), !listEmail.isEmpty {
|
||||
onSuccess(listEmail)
|
||||
if let response = data.parsing(methodName: JmapConstants.EMAIL_GET_METHOD_NAME, methodCallId: "c1") {
|
||||
if let listEmail = response.list, !listEmail.isEmpty {
|
||||
self.totalListEmails.append(contentsOf: listEmail)
|
||||
}
|
||||
self.hasMoreChanges = response.hasMoreChanges ?? false
|
||||
self.currentSinceState = response.newState
|
||||
|
||||
self.handleGetEmailChanges(apiUrl: apiUrl, accountId: accountId, onComplete: onComplete)
|
||||
} else {
|
||||
onFailure(JmapExceptions.notFoundNewEmails)
|
||||
self.listErrors.append(JmapExceptions.notFoundNewEmails)
|
||||
self.hasMoreChanges = false
|
||||
self.currentSinceState = nil
|
||||
|
||||
onComplete(self.totalListEmails, self.listErrors)
|
||||
}
|
||||
},
|
||||
onFailure: onFailure
|
||||
onFailure: { error in
|
||||
self.listErrors.append(error)
|
||||
self.hasMoreChanges = false
|
||||
self.currentSinceState = nil
|
||||
|
||||
onComplete(self.totalListEmails, self.listErrors)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,13 @@ enum ResponseInvocation<T: Codable>: Codable {
|
||||
case .string(_): return nil
|
||||
}
|
||||
}
|
||||
|
||||
var response: MethodResponse<T>? {
|
||||
switch self {
|
||||
case .methodResponse(let method): return method
|
||||
case .string(_): return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct MethodResponse<T: Codable>: Codable {
|
||||
@@ -54,7 +61,7 @@ struct MethodResponse<T: Codable>: Codable {
|
||||
}
|
||||
|
||||
extension JmapResponseObject {
|
||||
func parsing(methodName: String, methodCallId: String) -> [T]? {
|
||||
func parsing(methodName: String, methodCallId: String) -> MethodResponse<T>? {
|
||||
let invocations = methodResponses.first { (responseInvocations: [ResponseInvocation<T>]) in
|
||||
return responseInvocations.contains { (responseInvocation: ResponseInvocation<T>) in
|
||||
return validateResponseInvocation(response: responseInvocation, methodName: methodName, methodCallId: methodCallId)
|
||||
@@ -68,7 +75,7 @@ extension JmapResponseObject {
|
||||
return validateMethodResponse(response: response)
|
||||
}
|
||||
|
||||
return invocation?.listObject
|
||||
return invocation?.response
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,13 +19,15 @@ class AlamofireService {
|
||||
|
||||
request.httpBody = payloadData
|
||||
|
||||
AF.request(request, interceptor: interceptor).validate().responseDecodable(of: T.self) { response in
|
||||
switch(response.result) {
|
||||
case .success(let data):
|
||||
onSuccess(data)
|
||||
case .failure(let error):
|
||||
onFailure(NetworkExceptions(value: "\(error.localizedDescription)"))
|
||||
AF.request(request, interceptor: interceptor)
|
||||
.validate()
|
||||
.responseDecodable(of: T.self, queue: .global(qos: .default)) { response in
|
||||
switch(response.result) {
|
||||
case .success(let data):
|
||||
onSuccess(data)
|
||||
case .failure(let error):
|
||||
onFailure(NetworkExceptions(value: "\(error.localizedDescription)"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,17 +53,18 @@ class TokenRefreshManager {
|
||||
|
||||
request.httpBody = data
|
||||
|
||||
AF.request(request).responseDecodable(of: TokenResponse.self) { response in
|
||||
if (response.response?.statusCode != 200) {
|
||||
onFailure(NetworkExceptions(value: "Failed to get token: \(response.error?.localizedDescription ?? "Unknown Error")"))
|
||||
} else {
|
||||
switch(response.result) {
|
||||
case .success(let data):
|
||||
onSuccess(data)
|
||||
case .failure(let error):
|
||||
onFailure(NetworkExceptions(value: "Failed to get token \(error.localizedDescription)"))
|
||||
AF.request(request)
|
||||
.responseDecodable(of: TokenResponse.self, queue: .global(qos: .default)) { response in
|
||||
if (response.response?.statusCode != 200) {
|
||||
onFailure(NetworkExceptions(value: "Failed to get token: \(response.error?.localizedDescription ?? "Unknown Error")"))
|
||||
} else {
|
||||
switch(response.result) {
|
||||
case .success(let data):
|
||||
onSuccess(data)
|
||||
case .failure(let error):
|
||||
onFailure(NetworkExceptions(value: "Failed to get token \(error.localizedDescription)"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,38 +63,41 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
basicAuth: keychainSharingSession.basicAuth,
|
||||
tokenEndpointUrl: keychainSharingSession.tokenEndpoint,
|
||||
oidcScopes: keychainSharingSession.oidcScopes,
|
||||
onSuccess: { emails in
|
||||
self.keychainController.updateEmailStateToKeychain(accountId: keychainSharingSession.accountId, newState: newEmailState)
|
||||
|
||||
if (emails.count > 1) {
|
||||
for email in emails {
|
||||
if (email.id == emails.last?.id) {
|
||||
break
|
||||
onComplete: { (emails, errors) in
|
||||
if emails.isEmpty {
|
||||
self.modifiedContent?.body = self.newEmailDefaultMessage
|
||||
self.modifiedContent?.badge = NSNumber(value: 1)
|
||||
return self.notify()
|
||||
} else {
|
||||
self.keychainController.updateEmailStateToKeychain(accountId: keychainSharingSession.accountId, newState: newEmailState)
|
||||
|
||||
if (emails.count > 1) {
|
||||
for email in emails {
|
||||
if (email.id == emails.last?.id) {
|
||||
break
|
||||
}
|
||||
self.scheduleLocalNotification(email: email)
|
||||
}
|
||||
self.scheduleLocalNotification(email: email)
|
||||
}
|
||||
|
||||
let delayTimeIntervalNotification: TimeInterval = TimeInterval(self.timeIntervalNotificationTriggerInSecond * (emails.count - 1))
|
||||
let delayTimeIntervalNotification: TimeInterval = TimeInterval(self.timeIntervalNotificationTriggerInSecond * (emails.count - 1))
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + delayTimeIntervalNotification) {
|
||||
self.modifiedContent?.subtitle = emails.last?.subject ?? ""
|
||||
self.modifiedContent?.body = emails.last?.preview ?? ""
|
||||
self.modifiedContent?.badge = NSNumber(value: emails.count)
|
||||
self.modifiedContent?.userInfo[JmapConstants.EMAIL_ID] = emails.last?.id ?? ""
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + delayTimeIntervalNotification) {
|
||||
self.modifiedContent?.subtitle = emails.last?.subject ?? ""
|
||||
self.modifiedContent?.body = emails.last?.preview ?? ""
|
||||
self.modifiedContent?.badge = NSNumber(value: emails.count)
|
||||
self.modifiedContent?.userInfo[JmapConstants.EMAIL_ID] = emails.last?.id ?? ""
|
||||
return self.notify()
|
||||
}
|
||||
} else {
|
||||
self.modifiedContent?.subtitle = emails.first?.subject ?? ""
|
||||
self.modifiedContent?.body = emails.first?.preview ?? ""
|
||||
self.modifiedContent?.badge = NSNumber(value: 1)
|
||||
self.modifiedContent?.userInfo[JmapConstants.EMAIL_ID] = emails.first?.id ?? ""
|
||||
return self.notify()
|
||||
}
|
||||
} else {
|
||||
self.modifiedContent?.subtitle = emails.first?.subject ?? ""
|
||||
self.modifiedContent?.body = emails.first?.preview ?? ""
|
||||
self.modifiedContent?.badge = NSNumber(value: 1)
|
||||
self.modifiedContent?.userInfo[JmapConstants.EMAIL_ID] = emails.first?.id ?? ""
|
||||
return self.notify()
|
||||
}
|
||||
},
|
||||
onFailure: { error in
|
||||
self.modifiedContent?.body = self.newEmailDefaultMessage
|
||||
self.modifiedContent?.badge = NSNumber(value: 1)
|
||||
return self.notify()
|
||||
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user