Make redirects work
This commit is contained in:
parent
bd48fc8dbb
commit
2d05e318ff
|
@ -13,8 +13,7 @@ import GeminiProtocol
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
let navigator: NavigationManager
|
let navigator: NavigationManager
|
||||||
@State var task: GeminiDataTask?
|
@State var task: GeminiDataTask?
|
||||||
@State var document: Document?
|
@State var state: ViewState = .loading
|
||||||
@State var errorMessage: String?
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
mainView
|
mainView
|
||||||
|
@ -24,17 +23,18 @@ struct ContentView: View {
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var mainView: some View {
|
private var mainView: some View {
|
||||||
if let document = document {
|
switch state {
|
||||||
DocumentView(document: document, changeURL: navigator.changeURL)
|
case .loading:
|
||||||
} else if let errorMessage = errorMessage {
|
loadingView
|
||||||
|
.onAppear(perform: self.loadDocument)
|
||||||
|
case let .error(message):
|
||||||
VStack {
|
VStack {
|
||||||
Text("An error occurred")
|
Text("An error occurred")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
Text(errorMessage)
|
Text(message)
|
||||||
}
|
}
|
||||||
} else {
|
case let .document(doc):
|
||||||
loadingView
|
DocumentView(document: doc, changeURL: navigator.changeURL)
|
||||||
.onAppear(perform: self.loadDocument)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,25 +50,39 @@ struct ContentView: View {
|
||||||
private func loadDocument() {
|
private func loadDocument() {
|
||||||
let url = navigator.currentURL
|
let url = navigator.currentURL
|
||||||
task = try! GeminiDataTask(url: url, completion: { (response) in
|
task = try! GeminiDataTask(url: url, completion: { (response) in
|
||||||
|
self.task = nil
|
||||||
switch response {
|
switch response {
|
||||||
case let .failure(error):
|
case let .failure(error):
|
||||||
self.errorMessage = error.localizedDescription
|
state = .error(error.localizedDescription)
|
||||||
case let .success(response):
|
case let .success(response):
|
||||||
guard let text = response.bodyText else {
|
if response.status.isRedirect {
|
||||||
self.errorMessage = "Response had no body text"
|
if let redirect = URL(string: response.meta) {
|
||||||
return
|
navigator.changeURL(redirect)
|
||||||
|
loadDocument()
|
||||||
|
} else {
|
||||||
|
state = .error("Invalid redirect URL: '\(response.meta)'")
|
||||||
|
}
|
||||||
|
} else if response.status.isSuccess,
|
||||||
|
let text = response.bodyText {
|
||||||
|
state = .document(GeminiParser.parse(text: text, baseURL: url))
|
||||||
|
} else {
|
||||||
|
state = .error("Unknown error: \(response.header)")
|
||||||
}
|
}
|
||||||
self.document = GeminiParser.parse(text: text, baseURL: url)
|
|
||||||
}
|
}
|
||||||
self.task = nil
|
|
||||||
})
|
})
|
||||||
task!.resume()
|
task!.resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func urlChanged(_ newValue: URL) {
|
private func urlChanged(_ newValue: URL) {
|
||||||
self.task = nil
|
state = .loading
|
||||||
self.document = nil
|
}
|
||||||
self.errorMessage = nil
|
}
|
||||||
|
|
||||||
|
extension ContentView {
|
||||||
|
enum ViewState {
|
||||||
|
case loading
|
||||||
|
case document(Document)
|
||||||
|
case error(String)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,15 +35,15 @@ public extension GeminiResponseHeader {
|
||||||
case certificateNotValid = 62
|
case certificateNotValid = 62
|
||||||
|
|
||||||
// Status type helpers
|
// Status type helpers
|
||||||
var isInput: Bool { rawValue / 10 == 1 }
|
public var isInput: Bool { rawValue / 10 == 1 }
|
||||||
var isSuccess: Bool { rawValue / 10 == 2 }
|
public var isSuccess: Bool { rawValue / 10 == 2 }
|
||||||
var isRedirect: Bool { rawValue / 10 == 3 }
|
public var isRedirect: Bool { rawValue / 10 == 3 }
|
||||||
var isTemporaryFailure: Bool { rawValue / 10 == 4 }
|
public var isTemporaryFailure: Bool { rawValue / 10 == 4 }
|
||||||
var isPermanentFailure: Bool { rawValue / 10 == 5 }
|
public var isPermanentFailure: Bool { rawValue / 10 == 5 }
|
||||||
var isClientCertificateRequired: Bool { rawValue / 10 == 6 }
|
public var isClientCertificateRequired: Bool { rawValue / 10 == 6 }
|
||||||
|
|
||||||
// Other helpers
|
// Other helpers
|
||||||
var isFailure: Bool { isTemporaryFailure || isPermanentFailure }
|
public var isFailure: Bool { isTemporaryFailure || isPermanentFailure }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue