diff --git a/ios/RocketChat Watch App/ActionHandler/ErrorActionHandler.swift b/ios/RocketChat Watch App/ActionHandler/ErrorActionHandler.swift index 5e5ba8955..a9eff8a1b 100644 --- a/ios/RocketChat Watch App/ActionHandler/ErrorActionHandler.swift +++ b/ios/RocketChat Watch App/ActionHandler/ErrorActionHandler.swift @@ -1,3 +1,5 @@ +import Foundation + protocol ErrorActionHandling { func handle(error: RocketChatError) } @@ -12,18 +14,26 @@ final class ErrorActionHandler { init(server: Server) { self.server = server } -} - -extension ErrorActionHandler: ErrorActionHandling { - func handle(error: RocketChatError) { + + private func handleOnMain(error: RocketChatError) { switch error { + case .server(let response): + router.present(error: response) case .unauthorized: router.route(to: .serverList) database.remove() serversDB.remove(server) - default: - break + case .unknown: + print("Unexpected error on Client.") + } + } +} + +extension ErrorActionHandler: ErrorActionHandling { + func handle(error: RocketChatError) { + DispatchQueue.main.async { + self.handleOnMain(error: error) } } } diff --git a/ios/RocketChat Watch App/AppRouter.swift b/ios/RocketChat Watch App/AppRouter.swift index 3a35bc794..438f86439 100644 --- a/ios/RocketChat Watch App/AppRouter.swift +++ b/ios/RocketChat Watch App/AppRouter.swift @@ -2,16 +2,27 @@ import Foundation protocol AppRouting { func route(to route: Route) + func present(error: ErrorResponse) } final class AppRouter: ObservableObject { @Published private(set) var route: Route = .loading + + @Published var error: ErrorResponse? } extension AppRouter: AppRouting { func route(to route: Route) { self.route = route } + + func present(error: ErrorResponse) { + guard self.error == nil else { + return + } + + self.error = error + } } enum Route: Equatable { diff --git a/ios/RocketChat Watch App/AppView.swift b/ios/RocketChat Watch App/AppView.swift index bbb76a361..4aff4df63 100644 --- a/ios/RocketChat Watch App/AppView.swift +++ b/ios/RocketChat Watch App/AppView.swift @@ -26,6 +26,11 @@ struct AppView: View { .onAppear { loadRoute() } + .sheet(item: $router.error) { error in + Text(error.error) + .multilineTextAlignment(.center) + .padding() + } } private func loadRoute() { diff --git a/ios/RocketChat Watch App/Client/RocketChatClient.swift b/ios/RocketChat Watch App/Client/RocketChatClient.swift index 9ea8d3ad2..87e299652 100644 --- a/ios/RocketChat Watch App/Client/RocketChatClient.swift +++ b/ios/RocketChat Watch App/Client/RocketChatClient.swift @@ -12,6 +12,8 @@ protocol RocketChatClientProtocol { } final class RocketChatClient: NSObject { + @Dependency private var errorActionHandler: ErrorActionHandling + private let server: Server init(server: Server) { @@ -42,22 +44,27 @@ final class RocketChatClient: NSObject { urlRequest.httpBody = request.body return session.dataTaskPublisher(for: urlRequest) - .tryMap { (data, response) in - guard let httpResponse = response as? HTTPURLResponse, 200...299 ~= httpResponse.statusCode else { + .tryMap { data, response in + if let response = response as? HTTPURLResponse, response.statusCode == 401 { throw RocketChatError.unauthorized } - return try data.decode(T.Response.self) - } - .mapError { error in - if let error = error as? DecodingError { - return .decoding(error: error) - } - if let error = error as? RocketChatError { - return error + let decoder = JSONDecoder() + + if let response = try? decoder.decode(T.Response.self, from: data) { + return response } - return .unknown(error: error) + let response = try decoder.decode(ErrorResponse.self, from: data) + throw RocketChatError.server(response: response) + } + .mapError { [weak self] error in + guard let error = error as? RocketChatError else { + return .unknown + } + + self?.errorActionHandler.handle(error: error) + return error } .eraseToAnyPublisher() } diff --git a/ios/RocketChat Watch App/Client/RocketChatError.swift b/ios/RocketChat Watch App/Client/RocketChatError.swift index 868167f39..ab47047fe 100644 --- a/ios/RocketChat Watch App/Client/RocketChatError.swift +++ b/ios/RocketChat Watch App/Client/RocketChatError.swift @@ -1,7 +1,15 @@ import Foundation -enum RocketChatError: Error { - case decoding(error: Error) - case unknown(error: Error) - case unauthorized +struct ErrorResponse: Codable, Identifiable { + var id: String { + error + } + + let error: String +} + +enum RocketChatError: Error { + case server(response: ErrorResponse) + case unauthorized + case unknown } diff --git a/ios/RocketChat Watch App/Loaders/MessagesLoader.swift b/ios/RocketChat Watch App/Loaders/MessagesLoader.swift index ec13ede2e..c196ac64e 100644 --- a/ios/RocketChat Watch App/Loaders/MessagesLoader.swift +++ b/ios/RocketChat Watch App/Loaders/MessagesLoader.swift @@ -16,7 +16,6 @@ final class MessagesLoader { @Dependency private var client: RocketChatClientProtocol @Dependency private var database: Database @Dependency private var serversDB: ServersDatabase - @Dependency private var errorActionHandler: ErrorActionHandling private var roomID: String? @@ -34,8 +33,8 @@ final class MessagesLoader { client.syncMessages(rid: rid, updatedSince: date) .receive(on: DispatchQueue.main) .sink { [weak self] completion in - if case .failure(let error) = completion { - self?.errorActionHandler.handle(error: error) + if case .failure = completion { + self?.scheduledSyncMessages(in: room, from: newUpdatedSince) } } receiveValue: { [weak self] messagesResponse in let messages = messagesResponse.result.updated @@ -58,9 +57,9 @@ final class MessagesLoader { client.getHistory(rid: rid, t: room.t ?? "", latest: date) .receive(on: DispatchQueue.main) - .sink { [weak self] completion in + .sink { completion in if case .failure(let error) = completion { - self?.errorActionHandler.handle(error: error) + print(error) } } receiveValue: { [weak self] messagesResponse in let messages = messagesResponse.messages @@ -85,9 +84,9 @@ final class MessagesLoader { client.sendRead(rid: rid) .receive(on: DispatchQueue.main) - .sink { [weak self] completion in + .sink { completion in if case .failure(let error) = completion { - self?.errorActionHandler.handle(error: error) + print(error) } } receiveValue: { _ in diff --git a/ios/RocketChat Watch App/Loaders/RoomsLoader.swift b/ios/RocketChat Watch App/Loaders/RoomsLoader.swift index a91b8db03..0519f0aa8 100644 --- a/ios/RocketChat Watch App/Loaders/RoomsLoader.swift +++ b/ios/RocketChat Watch App/Loaders/RoomsLoader.swift @@ -11,7 +11,6 @@ final class RoomsLoader { @Dependency private var client: RocketChatClientProtocol @Dependency private var database: Database @Dependency private var serversDB: ServersDatabase - @Dependency private var errorActionHandler: ErrorActionHandling private var timer: Timer? private var cancellable = CancelBag() @@ -33,8 +32,8 @@ final class RoomsLoader { ) .receive(on: DispatchQueue.main) .sink { [weak self] completion in - if case .failure(let error) = completion { - self?.errorActionHandler.handle(error: error) + if case .failure = completion { + self?.scheduledLoadRooms(in: server) } } receiveValue: { (roomsResponse, subscriptionsResponse) in let rooms = roomsResponse.update