Allow researching for local servers and cancelling requests

This commit is contained in:
Ethan Pippin 2021-10-15 11:31:36 -06:00
parent dfc8aedf78
commit f3a6cee8ca
4 changed files with 82 additions and 39 deletions

View File

@ -21,46 +21,73 @@ struct ConnectToServerView: View {
.disableAutocorrection(true) .disableAutocorrection(true)
.autocapitalization(.none) .autocapitalization(.none)
.keyboardType(.URL) .keyboardType(.URL)
Button {
viewModel.connectToServer(uri: uri) if viewModel.isLoading {
} label: { Button(role: .destructive) {
HStack { viewModel.cancelConnection()
Text("Connect") } label: {
Spacer() Text("Cancel")
if viewModel.isLoading {
ProgressView()
}
} }
} else {
Button {
viewModel.connectToServer(uri: uri)
} label: {
Text("Connect")
}
.disabled(uri.isEmpty)
} }
.disabled(viewModel.isLoading || uri.isEmpty)
} header: { } header: {
Text("Connect to a Jellyfin server") Text("Connect to a Jellyfin server")
} }
Section(header: Text("Local Servers")) { Section {
if viewModel.searching { if viewModel.searching {
ProgressView() HStack(alignment: .center, spacing: 5) {
} Spacer()
ForEach(viewModel.discoveredServers.sorted(by: { $0.name < $1.name }), id: \.id) { discoveredServer in ProgressView()
Button(action: { Text("Searching")
viewModel.connectToServer(uri: discoveredServer.url.absoluteString) .foregroundColor(.secondary)
}, label: { Spacer()
HStack { }
Text(discoveredServer.name) } else {
.font(.headline) if viewModel.discoveredServers.isEmpty {
Text("\(discoveredServer.host)") HStack(alignment: .center) {
.font(.subheadline) Spacer()
Text("No local servers found")
.font(.callout)
.foregroundColor(.secondary) .foregroundColor(.secondary)
Spacer() Spacer()
if viewModel.isLoading {
ProgressView()
}
} }
} else {
ForEach(viewModel.discoveredServers.sorted(by: { $0.name < $1.name }), id: \.id) { discoveredServer in
Button {
viewModel.connectToServer(uri: discoveredServer.url.absoluteString)
} label: {
VStack(alignment: .leading, spacing: 5) {
Text(discoveredServer.name)
.font(.title3)
Text(discoveredServer.host)
.font(.subheadline)
.foregroundColor(.secondary)
}
}
.disabled(viewModel.isLoading)
}
}
}
} header: {
HStack {
Text("Local Servers")
Spacer()
}) Button {
viewModel.discoverServers()
} label: {
Image(systemName: "arrow.clockwise.circle.fill")
}
.disabled(viewModel.searching || viewModel.isLoading)
} }
} }
.onAppear(perform: self.viewModel.discoverServers)
.headerProminence(.increased) .headerProminence(.increased)
} }
.alert(item: $viewModel.errorMessage) { _ in .alert(item: $viewModel.errorMessage) { _ in
@ -70,7 +97,9 @@ struct ConnectToServerView: View {
} }
.navigationTitle("Connect") .navigationTitle("Connect")
.onAppear { .onAppear {
viewModel.discoverServers()
AppURLHandler.shared.appURLState = .allowedInLogin AppURLHandler.shared.appURLState = .allowedInLogin
} }
.navigationBarBackButtonHidden(viewModel.isLoading)
} }
} }

View File

@ -28,19 +28,20 @@ struct UserSignInView: View {
.disableAutocorrection(true) .disableAutocorrection(true)
.autocapitalization(.none) .autocapitalization(.none)
Button { if viewModel.isLoading {
viewModel.login(username: username, password: password) Button(role: .destructive) {
} label: { viewModel.cancelSignIn()
HStack { } label: {
Text("Connect") Text("Cancel")
Spacer()
if viewModel.isLoading {
ProgressView()
}
} }
} else {
Button {
viewModel.login(username: username, password: password)
} label: {
Text("Connect")
}
.disabled(username.isEmpty)
} }
.disabled(viewModel.isLoading || username.isEmpty)
} header: { } header: {
Text("Sign In to \(viewModel.server.name)") Text("Sign In to \(viewModel.server.name)")
} }
@ -51,5 +52,6 @@ struct UserSignInView: View {
dismissButton: .cancel()) dismissButton: .cancel())
} }
.navigationTitle("Sign In") .navigationTitle("Sign In")
.navigationBarBackButtonHidden(viewModel.isLoading)
} }
} }

View File

@ -64,4 +64,10 @@ final class ConnectToServerViewModel: ViewModel {
searching = false searching = false
} }
} }
func cancelConnection() {
for cancellable in cancellables {
cancellable.cancel()
}
}
} }

View File

@ -43,4 +43,10 @@ final class UserSignInViewModel: ViewModel {
} }
.store(in: &cancellables) .store(in: &cancellables)
} }
func cancelSignIn() {
for cancellable in cancellables {
cancellable.cancel()
}
}
} }