Improve compose posting error messages
This commit is contained in:
parent
e19a6528ad
commit
7c4bbfd730
|
@ -50,22 +50,22 @@ public class Client {
|
|||
|
||||
let task = session.dataTask(with: request) { data, response, error in
|
||||
if let error = error {
|
||||
completion(.failure(error))
|
||||
completion(.failure(.networkError(error)))
|
||||
return
|
||||
}
|
||||
guard let data = data,
|
||||
let response = response as? HTTPURLResponse else {
|
||||
completion(.failure(Error.invalidResponse))
|
||||
completion(.failure(.invalidResponse))
|
||||
return
|
||||
}
|
||||
guard response.statusCode == 200 else {
|
||||
let mastodonError = try? self.decoder.decode(MastodonError.self, from: data)
|
||||
let error = mastodonError.flatMap { Error.mastodonError($0.description) } ?? Error.unknownError
|
||||
let error: Error = mastodonError.flatMap { .mastodonError($0.description) } ?? .unexpectedStatus(response.statusCode)
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
guard let result = try? self.decoder.decode(Result.self, from: data) else {
|
||||
completion(.failure(Error.invalidModel))
|
||||
completion(.failure(.invalidModel))
|
||||
return
|
||||
}
|
||||
let pagination = response.allHeaderFields["Link"].flatMap { $0 as? String }.flatMap(Pagination.init)
|
||||
|
@ -315,7 +315,8 @@ public class Client {
|
|||
|
||||
extension Client {
|
||||
public enum Error: LocalizedError {
|
||||
case unknownError
|
||||
case networkError(Swift.Error)
|
||||
case unexpectedStatus(Int)
|
||||
case invalidRequest
|
||||
case invalidResponse
|
||||
case invalidModel
|
||||
|
@ -323,8 +324,13 @@ extension Client {
|
|||
|
||||
public var localizedDescription: String {
|
||||
switch self {
|
||||
case .unknownError:
|
||||
return "Unknown Error"
|
||||
case .networkError(let error):
|
||||
return "Network Error: \(error.localizedDescription)"
|
||||
// todo: support more status codes
|
||||
case .unexpectedStatus(413):
|
||||
return "HTTP 413: Payload Too Large"
|
||||
case .unexpectedStatus(let code):
|
||||
return "HTTP Code \(code)"
|
||||
case .invalidRequest:
|
||||
return "Invalid Request"
|
||||
case .invalidResponse:
|
||||
|
|
|
@ -10,5 +10,5 @@ import Foundation
|
|||
|
||||
public enum Response<Result: Decodable> {
|
||||
case success(Result, Pagination?)
|
||||
case failure(Error)
|
||||
case failure(Client.Error)
|
||||
}
|
||||
|
|
|
@ -22,16 +22,16 @@ public class InstanceSelector {
|
|||
let request = URLRequest(url: url)
|
||||
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
||||
if let error = error {
|
||||
completion(.failure(error))
|
||||
completion(.failure(.networkError(error)))
|
||||
return
|
||||
}
|
||||
guard let data = data,
|
||||
let response = response as? HTTPURLResponse else {
|
||||
completion(.failure(Client.Error.invalidResponse))
|
||||
completion(.failure(.invalidResponse))
|
||||
return
|
||||
}
|
||||
guard response.statusCode == 200 else {
|
||||
completion(.failure(Client.Error.unknownError))
|
||||
completion(.failure(.unexpectedStatus(response.statusCode)))
|
||||
return
|
||||
}
|
||||
guard let result = try? decoder.decode([Instance].self, from: data) else {
|
||||
|
|
|
@ -12,14 +12,14 @@ import Combine
|
|||
|
||||
struct ComposeView: View {
|
||||
@ObservedObject var draft: Draft
|
||||
|
||||
@EnvironmentObject var mastodonController: MastodonController
|
||||
@EnvironmentObject var uiState: ComposeUIState
|
||||
@State var isPosting = false
|
||||
@State var postProgress: Double = 0
|
||||
@State var postTotalProgress: Double = 0
|
||||
@State var isShowingPostErrorAlert = false
|
||||
@State var postError: Error?
|
||||
|
||||
@State private var isPosting = false
|
||||
@State private var postProgress: Double = 0
|
||||
@State private var postTotalProgress: Double = 0
|
||||
@State private var isShowingPostErrorAlert = false
|
||||
@State private var postError: PostError?
|
||||
|
||||
private let stackPadding: CGFloat = 8
|
||||
|
||||
|
@ -191,6 +191,9 @@ struct ComposeView: View {
|
|||
case let .failure(error):
|
||||
self.isShowingPostErrorAlert = true
|
||||
self.postError = error
|
||||
self.postProgress = 0
|
||||
self.postTotalProgress = 0
|
||||
self.isPosting = false
|
||||
|
||||
case let .success(uploadedAttachments):
|
||||
let request = Client.createStatus(text: draft.text,
|
||||
|
@ -222,7 +225,7 @@ struct ComposeView: View {
|
|||
}
|
||||
}
|
||||
|
||||
private func uploadAttachments(_ completion: @escaping (Result<[Attachment], Error>) -> Void) {
|
||||
private func uploadAttachments(_ completion: @escaping (Result<[Attachment], AttachmentUploadError>) -> Void) {
|
||||
let group = DispatchGroup()
|
||||
|
||||
var anyFailed = false
|
||||
|
@ -239,13 +242,13 @@ struct ComposeView: View {
|
|||
let formAttachment = FormAttachment(mimeType: mimeType, data: data, fileName: "file")
|
||||
let request = Client.upload(attachment: formAttachment, description: compAttachment.attachmentDescription)
|
||||
self.mastodonController.run(request) { (response) in
|
||||
postProgress += 1
|
||||
|
||||
switch response {
|
||||
case let .failure(error):
|
||||
uploadedAttachments[index] = .failure(error)
|
||||
anyFailed = true
|
||||
|
||||
case let .success(attachment, _):
|
||||
postProgress += 1
|
||||
uploadedAttachments[index] = .success(attachment)
|
||||
}
|
||||
|
||||
|
@ -274,14 +277,37 @@ struct ComposeView: View {
|
|||
}
|
||||
}
|
||||
|
||||
fileprivate struct AttachmentUploadError: LocalizedError {
|
||||
fileprivate protocol PostError: LocalizedError {}
|
||||
|
||||
extension PostError {
|
||||
var localizedDescription: String {
|
||||
if let self = self as? Client.Error {
|
||||
return self.localizedDescription
|
||||
} else if let self = self as? AttachmentUploadError {
|
||||
return self.localizedDescription
|
||||
} else {
|
||||
return "Unknown Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Client.Error: PostError {}
|
||||
|
||||
fileprivate struct AttachmentUploadError: PostError {
|
||||
let errors: [Error?]
|
||||
|
||||
var localizedDescription: String {
|
||||
return errors.enumerated().compactMap { (index, error) -> String? in
|
||||
guard let error = error else { return nil }
|
||||
return "Attachment \(index + 1): \(error.localizedDescription)"
|
||||
}.joined(separator: ", ")
|
||||
let description: String
|
||||
// need to downcast to use more specific localizedDescription impl from Pachyderm
|
||||
if let error = error as? Client.Error {
|
||||
description = error.localizedDescription
|
||||
} else {
|
||||
description = error.localizedDescription
|
||||
}
|
||||
return "Attachment \(index + 1): \(description)"
|
||||
}.joined(separator: ",\n")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ struct WrappedProgressView: UIViewRepresentable {
|
|||
func updateUIView(_ uiView: UIProgressView, context: Context) {
|
||||
if total > 0 {
|
||||
uiView.setProgress(Float(value / total), animated: true)
|
||||
} else {
|
||||
uiView.setProgress(0, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue