Extract instance/account validation status view

This commit is contained in:
Arkadiusz Fal
2021-09-28 22:33:12 +02:00
parent 7446c945b5
commit 78a0291e5d
8 changed files with 112 additions and 77 deletions

View File

@@ -5,7 +5,7 @@ import SwiftUI
struct AddToPlaylistView: View {
@EnvironmentObject<PlaylistsModel> private var model
@State var video: Video
let video: Video
@Environment(\.dismiss) private var dismiss

View File

@@ -8,8 +8,9 @@ struct AccountFormView: View {
@State private var name = ""
@State private var sid = ""
@State private var valid = false
@State private var validated = false
@State private var isValid = false
@State private var isValidated = false
@State private var isValidating = false
@State private var validationDebounce = Debounce()
@FocusState private var focused: Bool
@@ -82,12 +83,12 @@ struct AccountFormView: View {
var footer: some View {
HStack {
validationStatus
ValidationStatusView(isValid: $isValid, isValidated: $isValidated, isValidating: $isValidating, error: .constant(nil))
Spacer()
Button("Save", action: submitForm)
.disabled(!valid)
.disabled(!isValid)
#if !os(tvOS)
.keyboardShortcut(.defaultAction)
#endif
@@ -99,17 +100,6 @@ struct AccountFormView: View {
.padding(.horizontal)
}
var validationStatus: some View {
HStack(spacing: 4) {
Image(systemName: valid ? "checkmark.circle.fill" : "xmark.circle.fill")
.foregroundColor(valid ? .green : .red)
VStack(alignment: .leading) {
Text(valid ? "Account found" : "Invalid account details")
}
}
.opacity(validated ? 1 : 0)
}
private func initializeForm() {
focused = true
}
@@ -122,13 +112,15 @@ struct AccountFormView: View {
return
}
validationDebounce.debouncing(2) {
isValidating = true
validationDebounce.debouncing(1) {
validator.validateAccount()
}
}
private func submitForm() {
guard valid else {
guard isValid else {
return
}
@@ -143,8 +135,9 @@ struct AccountFormView: View {
url: instance.url,
account: Instance.Account(instanceID: instance.id, url: instance.url, sid: sid),
id: $sid,
valid: $valid,
validated: $validated
isValid: $isValid,
isValidated: $isValidated,
isValidating: $isValidating
)
}
}

View File

@@ -16,7 +16,6 @@ struct InstanceDetailsSettingsView: View {
List {
Section(header: Text("Accounts")) {
ForEach(instances.accounts(instanceID), id: \.self) { account in
#if !os(tvOS)
HStack(spacing: 2) {
Text(account.description)
@@ -27,13 +26,13 @@ struct InstanceDetailsSettingsView: View {
}
.swipeActions(edge: .leading, allowsFullSwipe: true) {
if instances.defaultAccount != account {
Button("Make Default", action: { makeDefault(account) })
Button("Make Default") { makeDefault(account) }
} else {
Button("Reset Default", action: resetDefaultAccount)
}
}
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
Button("Remove", role: .destructive, action: { removeAccount(account) })
Button("Remove", role: .destructive) { removeAccount(account) }
}
#else
@@ -47,8 +46,8 @@ struct InstanceDetailsSettingsView: View {
}
}
.contextMenu {
Button("Toggle Default", action: { toggleDefault(account) })
Button("Remove", role: .destructive, action: { removeAccount(account) })
Button("Toggle Default") { toggleDefault(account) }
Button("Remove", role: .destructive) { removeAccount(account) }
}
#endif
}

View File

@@ -6,8 +6,9 @@ struct InstanceFormView: View {
@State private var name = ""
@State private var url = ""
@State private var valid = false
@State private var validated = false
@State private var isValid = false
@State private var isValidated = false
@State private var isValidating = false
@State private var validationError: String?
@State private var validationDebounce = Debounce()
@@ -73,21 +74,24 @@ struct InstanceFormView: View {
private var formFields: some View {
Group {
TextField("Name", text: $name, prompt: Text("Instance Name (optional)"))
.focused($nameFieldFocused)
TextField("URL", text: $url, prompt: Text("https://invidious.home.net"))
#if !os(macOS)
.autocapitalization(.none)
.keyboardType(.URL)
#endif
}
}
private var footer: some View {
HStack(alignment: .center) {
validationStatus
ValidationStatusView(isValid: $isValid, isValidated: $isValidated, isValidating: $isValidating, error: $validationError)
Spacer()
Button("Save", action: submitForm)
.disabled(!valid)
.disabled(!isValid)
#if !os(tvOS)
.keyboardShortcut(.defaultAction)
#endif
@@ -98,31 +102,13 @@ struct InstanceFormView: View {
.padding(.horizontal)
}
private var validationStatus: some View {
HStack(spacing: 4) {
Image(systemName: valid ? "checkmark.circle.fill" : "xmark.circle.fill")
.foregroundColor(valid ? .green : .red)
VStack(alignment: .leading) {
Text(valid ? "Connected successfully" : "Connection failed")
if !valid {
Text(validationError ?? "Unknown Error")
.font(.caption2)
.foregroundColor(.secondary)
.truncationMode(.tail)
.lineLimit(1)
}
}
.frame(minHeight: 35)
}
.opacity(validated ? 1 : 0)
}
var validator: AccountValidator {
AccountValidator(
url: url,
id: $url,
valid: $valid,
validated: $validated,
isValid: $isValid,
isValidated: $isValidated,
isValidating: $isValidating,
error: $validationError
)
}
@@ -135,6 +121,8 @@ struct InstanceFormView: View {
return
}
isValidating = true
validationDebounce.debouncing(2) {
validator.validateInstance()
}
@@ -145,7 +133,7 @@ struct InstanceFormView: View {
}
func submitForm() {
guard valid else {
guard isValid else {
return
}

View File

@@ -0,0 +1,48 @@
import Foundation
import SwiftUI
struct ValidationStatusView: View {
@Binding var isValid: Bool
@Binding var isValidated: Bool
@Binding var isValidating: Bool
@Binding var error: String?
var body: some View {
HStack(spacing: 4) {
Image(systemName: validationStatusSystemImage)
.foregroundColor(validationStatusColor)
.frame(minWidth: 35, minHeight: 35)
.opacity(isValidating ? 1 : (isValidated ? 1 : 0))
VStack(alignment: .leading) {
Text(isValid ? "Connected successfully" : "Connection failed")
if !isValid && !error.isNil {
Text(error!)
.font(.caption2)
.foregroundColor(.secondary)
.truncationMode(.tail)
.lineLimit(1)
}
}
.frame(minHeight: 35)
.opacity(isValidating ? 0 : (isValidated ? 1 : 0))
}
}
var validationStatusSystemImage: String {
if isValidating {
return "bolt.horizontal.fill"
} else {
return isValid ? "checkmark.circle.fill" : "xmark.circle.fill"
}
}
var validationStatusColor: Color {
if isValidating {
return .accentColor
} else {
return isValid ? .green : .red
}
}
}