Submit on OpenVPN fields (#805)

Submit on password or OTP depending on the selected method.
This commit is contained in:
Davide 2024-11-03 11:27:12 +01:00 committed by GitHub
parent fff21c3250
commit fbe2d84113
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 46 additions and 20 deletions

View File

@ -29,5 +29,5 @@ public protocol InteractiveViewProviding {
associatedtype InteractiveContent: View
@MainActor
func interactiveView(with editor: ProfileEditor) -> InteractiveContent
func interactiveView(with editor: ProfileEditor, onSubmit: @escaping () -> Void) -> InteractiveContent
}

View File

@ -27,13 +27,14 @@ import PassepartoutKit
import SwiftUI
extension OpenVPNModule.Builder: InteractiveViewProviding {
public func interactiveView(with editor: ProfileEditor) -> some View {
public func interactiveView(with editor: ProfileEditor, onSubmit: @escaping () -> Void) -> some View {
let draft = editor[self]
return OpenVPNCredentialsView(
isInteractive: draft.isInteractive,
credentials: draft.credentials,
isAuthenticating: true
isAuthenticating: true,
onSubmit: onSubmit
)
}
}

View File

@ -46,7 +46,9 @@ public struct OpenVPNCredentialsView: View {
@Binding
private var credentials: OpenVPN.Credentials?
private var isAuthenticating = false
private let isAuthenticating: Bool
private let onSubmit: (() -> Void)?
@State
private var builder = OpenVPN.Credentials.Builder()
@ -60,11 +62,13 @@ public struct OpenVPNCredentialsView: View {
public init(
isInteractive: Binding<Bool>,
credentials: Binding<OpenVPN.Credentials?>,
isAuthenticating: Bool = false
isAuthenticating: Bool = false,
onSubmit: (() -> Void)? = nil
) {
_isInteractive = isInteractive
_credentials = credentials
self.isAuthenticating = isAuthenticating
self.onSubmit = onSubmit
}
public var body: some View {
@ -154,22 +158,11 @@ private extension OpenVPNCredentialsView {
var inputSection: some View {
Group {
if !isAuthenticating || builder.otpMethod == .none {
ThemeTextField(Strings.Global.username, text: $builder.username, placeholder: Strings.Placeholders.username)
.textContentType(.username)
.focused($focusedField, equals: .username)
ThemeSecureField(title: Strings.Global.password, text: $builder.password, placeholder: Strings.Placeholders.secret)
.textContentType(.password)
.focused($focusedField, equals: .password)
usernameField
passwordField
}
if isEligibleForInteractiveLogin, isAuthenticating, builder.otpMethod != .none {
ThemeSecureField(
title: Strings.Unlocalized.otp,
text: $builder.otp ?? "",
placeholder: Strings.Placeholders.secret
)
.textContentType(.oneTimeCode)
.focused($focusedField, equals: .otp)
otpField
}
}
.themeSection(footer: inputFooter)
@ -182,6 +175,38 @@ private extension OpenVPNCredentialsView {
}
return nil
}
var usernameField: some View {
ThemeTextField(Strings.Global.username, text: $builder.username, placeholder: Strings.Placeholders.username)
.textContentType(.username)
.focused($focusedField, equals: .username)
}
var passwordField: some View {
ThemeSecureField(title: Strings.Global.password, text: $builder.password, placeholder: Strings.Placeholders.secret)
.textContentType(.password)
.focused($focusedField, equals: .password)
.onSubmit {
if builder.otpMethod == .none {
onSubmit?()
}
}
}
var otpField: some View {
ThemeSecureField(
title: Strings.Unlocalized.otp,
text: $builder.otp ?? "",
placeholder: Strings.Placeholders.secret
)
.textContentType(.oneTimeCode)
.focused($focusedField, equals: .otp)
.onSubmit {
if builder.otpMethod != .none {
onSubmit?()
}
}
}
}
#Preview {

View File

@ -163,7 +163,7 @@ private extension InteractiveCoordinator {
}
func innerView(with provider: any InteractiveViewProviding) -> some View {
AnyView(provider.interactiveView(with: manager.editor))
AnyView(provider.interactiveView(with: manager.editor, onSubmit: confirm))
}
func confirm() {