diff --git a/JellyfinPlayer/Views/ConnectToServerView.swift b/JellyfinPlayer/Views/ConnectToServerView.swift index af47c549..1e262c44 100644 --- a/JellyfinPlayer/Views/ConnectToServerView.swift +++ b/JellyfinPlayer/Views/ConnectToServerView.swift @@ -21,46 +21,73 @@ struct ConnectToServerView: View { .disableAutocorrection(true) .autocapitalization(.none) .keyboardType(.URL) - Button { - viewModel.connectToServer(uri: uri) - } label: { - HStack { - Text("Connect") - Spacer() - if viewModel.isLoading { - ProgressView() - } + + if viewModel.isLoading { + Button(role: .destructive) { + viewModel.cancelConnection() + } label: { + Text("Cancel") } + } else { + Button { + viewModel.connectToServer(uri: uri) + } label: { + Text("Connect") + } + .disabled(uri.isEmpty) } - .disabled(viewModel.isLoading || uri.isEmpty) } header: { Text("Connect to a Jellyfin server") } - Section(header: Text("Local Servers")) { + Section { if viewModel.searching { - ProgressView() - } - ForEach(viewModel.discoveredServers.sorted(by: { $0.name < $1.name }), id: \.id) { discoveredServer in - Button(action: { - viewModel.connectToServer(uri: discoveredServer.url.absoluteString) - }, label: { - HStack { - Text(discoveredServer.name) - .font(.headline) - Text("• \(discoveredServer.host)") - .font(.subheadline) + HStack(alignment: .center, spacing: 5) { + Spacer() + ProgressView() + Text("Searching") + .foregroundColor(.secondary) + Spacer() + } + } else { + if viewModel.discoveredServers.isEmpty { + HStack(alignment: .center) { + Spacer() + Text("No local servers found") + .font(.callout) .foregroundColor(.secondary) 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) } .alert(item: $viewModel.errorMessage) { _ in @@ -70,7 +97,9 @@ struct ConnectToServerView: View { } .navigationTitle("Connect") .onAppear { + viewModel.discoverServers() AppURLHandler.shared.appURLState = .allowedInLogin } + .navigationBarBackButtonHidden(viewModel.isLoading) } } diff --git a/JellyfinPlayer/Views/UserSignInView.swift b/JellyfinPlayer/Views/UserSignInView.swift index 81110c28..f4f91fd9 100644 --- a/JellyfinPlayer/Views/UserSignInView.swift +++ b/JellyfinPlayer/Views/UserSignInView.swift @@ -28,19 +28,20 @@ struct UserSignInView: View { .disableAutocorrection(true) .autocapitalization(.none) - Button { - viewModel.login(username: username, password: password) - } label: { - HStack { - Text("Connect") - Spacer() - if viewModel.isLoading { - ProgressView() - } + if viewModel.isLoading { + Button(role: .destructive) { + viewModel.cancelSignIn() + } label: { + Text("Cancel") } + } else { + Button { + viewModel.login(username: username, password: password) + } label: { + Text("Connect") + } + .disabled(username.isEmpty) } - .disabled(viewModel.isLoading || username.isEmpty) - } header: { Text("Sign In to \(viewModel.server.name)") } @@ -51,5 +52,6 @@ struct UserSignInView: View { dismissButton: .cancel()) } .navigationTitle("Sign In") + .navigationBarBackButtonHidden(viewModel.isLoading) } } diff --git a/Shared/ViewModels/ConnectToServerViewModel.swift b/Shared/ViewModels/ConnectToServerViewModel.swift index e2c08c8b..2ea3b086 100644 --- a/Shared/ViewModels/ConnectToServerViewModel.swift +++ b/Shared/ViewModels/ConnectToServerViewModel.swift @@ -64,4 +64,10 @@ final class ConnectToServerViewModel: ViewModel { searching = false } } + + func cancelConnection() { + for cancellable in cancellables { + cancellable.cancel() + } + } } diff --git a/Shared/ViewModels/UserSignInViewModel.swift b/Shared/ViewModels/UserSignInViewModel.swift index 470f4ecc..01fc1428 100644 --- a/Shared/ViewModels/UserSignInViewModel.swift +++ b/Shared/ViewModels/UserSignInViewModel.swift @@ -43,4 +43,10 @@ final class UserSignInViewModel: ViewModel { } .store(in: &cancellables) } + + func cancelSignIn() { + for cancellable in cancellables { + cancellable.cancel() + } + } }