diff --git a/ios/Sources/GutenbergKit/Sources/EditorHTTPClient.swift b/ios/Sources/GutenbergKit/Sources/EditorHTTPClient.swift index 431a03828..6ad43e659 100644 --- a/ios/Sources/GutenbergKit/Sources/EditorHTTPClient.swift +++ b/ios/Sources/GutenbergKit/Sources/EditorHTTPClient.swift @@ -20,9 +20,9 @@ public enum EditorResponseData { } /// A WordPress REST API error response. -struct WPError: Decodable { - let code: String - let message: String +public struct WPError: Decodable, Sendable { + public let code: String + public let message: String } /// An HTTP client for making authenticated requests to the WordPress REST API. @@ -32,13 +32,13 @@ struct WPError: Decodable { public actor EditorHTTPClient: EditorHTTPClientProtocol { /// Errors that can occur during HTTP requests. - enum ClientError: Error { + public enum ClientError: Error, Sendable { /// The server returned a WordPress-formatted error response. - case wpError(WPError) + case wpError(WPError, requestURL: URL) /// A file download failed with the given HTTP status code. - case downloadFailed(statusCode: Int) + case downloadFailed(statusCode: Int, requestURL: URL) /// An unexpected error occurred with the given response data and status code. - case unknown(response: Data, statusCode: Int) + case unknown(response: Data, statusCode: Int, requestURL: URL) } /// The base user agent string identifying the platform. @@ -79,13 +79,18 @@ public actor EditorHTTPClient: EditorHTTPClientProtocol { let httpResponse = response as! HTTPURLResponse guard 200...299 ~= httpResponse.statusCode else { - Logger.http.error("📡 HTTP error fetching \(configuredRequest.url!.absoluteString): \(httpResponse.statusCode)") + let requestURL = configuredRequest.url! + Logger.http.error("📡 HTTP error fetching \(requestURL.absoluteString): \(httpResponse.statusCode)") if let wpError = try? JSONDecoder().decode(WPError.self, from: data) { - throw ClientError.wpError(wpError) + throw ClientError.wpError(wpError, requestURL: requestURL) } - throw ClientError.unknown(response: data, statusCode: httpResponse.statusCode) + throw ClientError.unknown( + response: data, + statusCode: httpResponse.statusCode, + requestURL: requestURL + ) } return (data, httpResponse) @@ -100,9 +105,13 @@ public actor EditorHTTPClient: EditorHTTPClientProtocol { let httpResponse = response as! HTTPURLResponse guard 200...299 ~= httpResponse.statusCode else { - Logger.http.error("📡 HTTP error fetching \(configuredRequest.url!.absoluteString): \(httpResponse.statusCode)") + let requestURL = configuredRequest.url! + Logger.http.error("📡 HTTP error fetching \(requestURL.absoluteString): \(httpResponse.statusCode)") - throw ClientError.downloadFailed(statusCode: httpResponse.statusCode) + throw ClientError.downloadFailed( + statusCode: httpResponse.statusCode, + requestURL: requestURL + ) } return (url, response as! HTTPURLResponse) diff --git a/ios/Sources/GutenbergKit/Sources/EditorViewController.swift b/ios/Sources/GutenbergKit/Sources/EditorViewController.swift index e3c53e336..808c7034f 100644 --- a/ios/Sources/GutenbergKit/Sources/EditorViewController.swift +++ b/ios/Sources/GutenbergKit/Sources/EditorViewController.swift @@ -241,7 +241,7 @@ public final class EditorViewController: UIViewController, GutenbergEditorContro do { try self.loadEditor(dependencies: dependencies) } catch { - self.error = error + self.failToLoad(error) } } else { // ASYNC FLOW: No dependencies - fetch them asynchronously @@ -286,11 +286,15 @@ public final class EditorViewController: UIViewController, GutenbergEditorContro // Continue to the shared loading path try self.loadEditor(dependencies: dependencies) } catch { - // Display error view - this sets self.error which triggers displayError() - self.error = error + self.failToLoad(error) } } + private func failToLoad(_ error: Error) { + self.error = error + self.delegate?.editor(self, didFailToLoad: error) + } + // MARK: - Shared Loading Path: Load Editor into WebView /// Loads the editor HTML into the WebView with the given dependencies. diff --git a/ios/Sources/GutenbergKit/Sources/EditorViewControllerDelegate.swift b/ios/Sources/GutenbergKit/Sources/EditorViewControllerDelegate.swift index e614f7259..91041f7b4 100644 --- a/ios/Sources/GutenbergKit/Sources/EditorViewControllerDelegate.swift +++ b/ios/Sources/GutenbergKit/Sources/EditorViewControllerDelegate.swift @@ -16,6 +16,9 @@ public protocol EditorViewControllerDelegate: AnyObject { /// - warning: Make sure not to update user content if that happens (it shouldn't) func editor(_ viewContoller: EditorViewController, didEncounterCriticalError error: Error) + /// Called after an error that prevents the editor from loading is displayed. + func editor(_ viewController: EditorViewController, didFailToLoad error: Error) + /// Notifies the client about the new edits. /// /// - note: To get the latest content, call ``EditorViewController/getTitleAndContent()``. @@ -74,6 +77,10 @@ public protocol EditorViewControllerDelegate: AnyObject { func editorDidRequestLatestContent(_ controller: EditorViewController) -> (title: String, content: String)? } +extension EditorViewControllerDelegate { + public func editor(_ viewController: EditorViewController, didFailToLoad error: Error) {} +} + #endif public struct EditorState {