Instance and account form and validation improvements

This commit is contained in:
Arkadiusz Fal 2022-12-17 15:57:59 +01:00
parent 9f3a94137c
commit cf0572a94b
4 changed files with 109 additions and 53 deletions

View File

@ -82,14 +82,24 @@ final class AccountValidator: Service {
} }
guard !response.json.isEmpty else { guard !response.json.isEmpty else {
guard let app = self.appsToValidateInstance.popLast() else { if app == .piped {
if response.text.contains("property=\"og:title\" content=\"Piped\"") {
self.isValid.wrappedValue = false
self.isValidated.wrappedValue = true
self.isValidating.wrappedValue = false
self.error?.wrappedValue = "Trying to use Piped front-end URL, you need to use URL for Piped API instead"
return
}
}
guard let nextApp = self.appsToValidateInstance.popLast() else {
self.isValid.wrappedValue = false self.isValid.wrappedValue = false
self.isValidated.wrappedValue = true self.isValidated.wrappedValue = true
self.isValidating.wrappedValue = false self.isValidating.wrappedValue = false
return return
} }
self.tryValidatingUsing(app) self.tryValidatingUsing(nextApp)
return return
} }
@ -128,15 +138,15 @@ final class AccountValidator: Service {
switch app.wrappedValue { switch app.wrappedValue {
case .invidious: case .invidious:
invidiousValidation() validateInvidiousAccount()
case .piped: case .piped:
pipedValidation() validatePipedAccount()
default: default:
setValidationResult(false) setValidationResult(false)
} }
} }
func invidiousValidation() { func validateInvidiousAccount() {
guard let username = account?.username, guard let username = account?.username,
let password = account?.password let password = account?.password
else { else {
@ -177,7 +187,7 @@ final class AccountValidator: Service {
} }
} }
func pipedValidation() { func validatePipedAccount() {
guard let request = accountRequest else { guard let request = accountRequest else {
setValidationResult(false) setValidationResult(false)

View File

@ -24,6 +24,13 @@ struct AccountForm: View {
Group { Group {
header header
form form
#if os(macOS)
VStack {
validationStatus
}
.frame(minHeight: 60, alignment: .topLeading)
.padding(.horizontal, 15)
#endif
footer footer
} }
.frame(maxWidth: 1000) .frame(maxWidth: 1000)
@ -34,7 +41,8 @@ struct AccountForm: View {
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity) .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.background(Color.background(scheme: colorScheme)) .background(Color.background(scheme: colorScheme))
#else #else
.frame(width: 400, height: 145) .frame(width: 400, height: 180)
.padding(.vertical)
#endif #endif
} }
@ -72,32 +80,36 @@ struct AccountForm: View {
.onChange(of: password) { _ in validate() } .onChange(of: password) { _ in validate() }
} }
var formFields: some View { @ViewBuilder var formFields: some View {
Group { TextField("Username", text: $username)
TextField("Username", text: $username) SecureField("Password", text: $password)
SecureField("Password", text: $password)
} #if os(tvOS)
VStack {
validationStatus
}
.frame(minHeight: 100)
#elseif os(iOS)
validationStatus
#endif
} }
var usernamePrompt: String { @ViewBuilder var validationStatus: some View {
switch instance.app { if !username.isEmpty && !password.isEmpty {
case .invidious: Section {
return "SID Cookie" AccountValidationStatus(
default: app: .constant(instance.app),
return "Username" isValid: $isValid,
isValidated: $isValidated,
isValidating: $isValidating,
error: $validationError
)
}
} }
} }
var footer: some View { var footer: some View {
HStack { HStack {
AccountValidationStatus(
app: .constant(instance.app),
isValid: $isValid,
isValidated: $isValidated,
isValidating: $isValidating,
error: $validationError
)
Spacer() Spacer()
Button("Save", action: submitForm) Button("Save", action: submitForm)

View File

@ -9,28 +9,41 @@ struct AccountValidationStatus: View {
@Binding var error: String? @Binding var error: String?
var body: some View { var body: some View {
HStack(spacing: 4) { VStack(alignment: .leading) {
Image(systemName: validationStatusSystemImage) HStack {
.foregroundColor(validationStatusColor) Image(systemName: validationStatusSystemImage)
.foregroundColor(validationStatusColor)
.imageScale(.medium)
.opacity(isValidating ? 1 : (isValidated ? 1 : 0))
.frame(minWidth: 35, minHeight: 35)
.opacity(isValidating ? 1 : (isValidated ? 1 : 0))
VStack(alignment: .leading) {
Text(isValid ? "Connected successfully (\(app?.name ?? "Unknown"))" : "Connection failed") Text(isValid ? "Connected successfully (\(app?.name ?? "Unknown"))" : "Connection failed")
if let error, !isValid { .opacity(isValidated && !isValidating ? 1 : 0)
Text(error) }
.font(.caption2) if errorVisible {
.foregroundColor(.secondary) Text(error ?? "")
.truncationMode(.tail) .frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(1) .lineLimit(nil)
} .multilineTextAlignment(.leading)
.font(.footnote)
.foregroundColor(.secondary)
.padding(.top, 5)
.opacity(errorTextVisible ? 1 : 0)
} }
.frame(minHeight: 35)
.opacity(isValidating ? 0 : (isValidated ? 1 : 0))
} }
} }
var errorVisible: Bool {
#if !os(iOS)
true
#else
errorTextVisible
#endif
}
var errorTextVisible: Bool {
error != nil && isValidated && !isValid && !isValidating
}
var validationStatusSystemImage: String { var validationStatusSystemImage: String {
if isValidating { if isValidating {
return "bolt.horizontal.fill" return "bolt.horizontal.fill"

View File

@ -22,9 +22,14 @@ struct InstanceForm: View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
Group { Group {
header header
form form
#if os(macOS)
VStack {
validationStatus
}
.frame(minHeight: 60, alignment: .topLeading)
.padding(.horizontal, 15)
#endif
footer footer
} }
.frame(maxWidth: 1000) .frame(maxWidth: 1000)
@ -36,7 +41,8 @@ struct InstanceForm: View {
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity) .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.background(Color.background(scheme: colorScheme)) .background(Color.background(scheme: colorScheme))
#else #else
.frame(width: 400, height: 150) .frame(width: 400, height: 180)
.padding(.vertical)
#endif #endif
} }
@ -80,19 +86,34 @@ struct InstanceForm: View {
.autocapitalization(.none) .autocapitalization(.none)
.keyboardType(.URL) .keyboardType(.URL)
#endif #endif
#if os(tvOS)
VStack {
validationStatus
}
.frame(minHeight: 100)
#elseif os(iOS)
validationStatus
#endif
}
}
@ViewBuilder var validationStatus: some View {
if !url.isEmpty {
Section {
AccountValidationStatus(
app: $app,
isValid: $isValid,
isValidated: $isValidated,
isValidating: $isValidating,
error: $validationError
)
}
} }
} }
private var footer: some View { private var footer: some View {
HStack { HStack {
AccountValidationStatus(
app: $app,
isValid: $isValid,
isValidated: $isValidated,
isValidating: $isValidating,
error: $validationError
)
Spacer() Spacer()
Button("Save", action: submitForm) Button("Save", action: submitForm)