mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-03-21 16:13:27 -04:00
Add actionsheet when selecting autofill credential to choose username or email (#771)
This commit is contained in:
@@ -33,11 +33,11 @@ class CredentialProviderViewController: ASCredentialProviderViewController {
|
||||
await self.registerCredentialIdentities(credentials: credentials)
|
||||
return credentials
|
||||
},
|
||||
selectionHandler: { [weak self] credential in
|
||||
selectionHandler: { [weak self] identifier, password in
|
||||
guard let self = self else { return }
|
||||
let passwordCredential = ASPasswordCredential(
|
||||
user: credential.username ?? "",
|
||||
password: credential.password?.value ?? ""
|
||||
user: identifier,
|
||||
password: password
|
||||
)
|
||||
self.extensionContext.completeRequest(withSelectedCredential: passwordCredential, completionHandler: nil)
|
||||
},
|
||||
@@ -49,13 +49,13 @@ class CredentialProviderViewController: ASCredentialProviderViewController {
|
||||
))
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
self.viewModel = viewModel
|
||||
|
||||
|
||||
let hostingController = UIHostingController(
|
||||
rootView: CredentialProviderView(viewModel: viewModel)
|
||||
)
|
||||
|
||||
|
||||
addChild(hostingController)
|
||||
view.addSubview(hostingController.view)
|
||||
|
||||
@@ -87,12 +87,14 @@ class CredentialProviderViewController: ASCredentialProviderViewController {
|
||||
override func provideCredentialWithoutUserInteraction(for credentialIdentity: ASPasswordCredentialIdentity) {
|
||||
do {
|
||||
let credentials = try VaultStore.shared.getAllCredentials()
|
||||
|
||||
|
||||
if let matchingCredential = credentials.first(where: { credential in
|
||||
return credential.id.uuidString == credentialIdentity.recordIdentifier
|
||||
}) {
|
||||
// Use the identifier that matches the credential identity
|
||||
let identifier = credentialIdentity.user
|
||||
let passwordCredential = ASPasswordCredential(
|
||||
user: matchingCredential.username ?? "",
|
||||
user: identifier,
|
||||
password: matchingCredential.password?.value ?? ""
|
||||
)
|
||||
self.extensionContext.completeRequest(withSelectedCredential: passwordCredential, completionHandler: nil)
|
||||
@@ -114,7 +116,7 @@ class CredentialProviderViewController: ASCredentialProviderViewController {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This registers all known AliasVault credentials into iOS native credential storage, which iOS can then use to suggest autofill credentials when a user
|
||||
* focuses an input field on a login form. These suggestions will then be shown above the iOS keyboard, which saves the user one step.
|
||||
|
||||
@@ -106,6 +106,33 @@ public struct CredentialProviderView: View {
|
||||
.sheet(isPresented: $viewModel.showAddCredential) {
|
||||
AddCredentialView(viewModel: viewModel)
|
||||
}
|
||||
.actionSheet(isPresented: $viewModel.showSelectionOptions) {
|
||||
guard let credential = viewModel.selectedCredential else {
|
||||
return ActionSheet(title: Text("Select Login Method"), message: Text("No credential selected."), buttons: [.cancel()])
|
||||
}
|
||||
|
||||
var buttons: [ActionSheet.Button] = []
|
||||
|
||||
if let username = credential.username, !username.isEmpty {
|
||||
buttons.append(.default(Text("Username: \(username)")) {
|
||||
viewModel.selectUsernamePassword()
|
||||
})
|
||||
}
|
||||
|
||||
if let email = credential.alias?.email, !email.isEmpty {
|
||||
buttons.append(.default(Text("Email: \(email)")) {
|
||||
viewModel.selectEmailPassword()
|
||||
})
|
||||
}
|
||||
|
||||
buttons.append(.cancel())
|
||||
|
||||
return ActionSheet(
|
||||
title: Text("Select Login Method"),
|
||||
message: Text("Choose how you want to log in"),
|
||||
buttons: buttons
|
||||
)
|
||||
}
|
||||
.alert("Error", isPresented: $viewModel.showError) {
|
||||
Button("OK") {
|
||||
viewModel.dismissError()
|
||||
@@ -134,18 +161,20 @@ public class CredentialProviderViewModel: ObservableObject {
|
||||
@Published var showError = false
|
||||
@Published var errorMessage = ""
|
||||
@Published var showAddCredential = false
|
||||
@Published var showSelectionOptions = false
|
||||
@Published var selectedCredential: Credential?
|
||||
|
||||
@Published var newUsername = ""
|
||||
@Published var newPassword = ""
|
||||
@Published var newService = ""
|
||||
|
||||
private let loader: () async throws -> [Credential]
|
||||
private let selectionHandler: (Credential) -> Void
|
||||
private let selectionHandler: (String, String) -> Void
|
||||
private let cancelHandler: () -> Void
|
||||
|
||||
public init(
|
||||
loader: @escaping () async throws -> [Credential],
|
||||
selectionHandler: @escaping (Credential) -> Void,
|
||||
selectionHandler: @escaping (String, String) -> Void,
|
||||
cancelHandler: @escaping () -> Void
|
||||
) {
|
||||
self.loader = loader
|
||||
@@ -245,7 +274,32 @@ public class CredentialProviderViewModel: ObservableObject {
|
||||
}
|
||||
|
||||
func selectCredential(_ credential: Credential) {
|
||||
selectionHandler(credential)
|
||||
selectedCredential = credential
|
||||
|
||||
// If we only have one option, use it directly
|
||||
let username = credential.username?.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let email = credential.alias?.email?.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
|
||||
if (username?.isEmpty ?? true) || (email?.isEmpty ?? true) {
|
||||
let identifier = username?.isEmpty == false ? username! : (email ?? "")
|
||||
selectionHandler(identifier, credential.password?.value ?? "")
|
||||
return
|
||||
}
|
||||
|
||||
// If we have both options, show selection sheet
|
||||
showSelectionOptions = true
|
||||
}
|
||||
|
||||
func selectUsernamePassword() {
|
||||
guard let credential = selectedCredential else { return }
|
||||
selectionHandler(credential.username ?? "", credential.password?.value ?? "")
|
||||
showSelectionOptions = false
|
||||
}
|
||||
|
||||
func selectEmailPassword() {
|
||||
guard let credential = selectedCredential else { return }
|
||||
selectionHandler(credential.alias?.email ?? "", credential.password?.value ?? "")
|
||||
showSelectionOptions = false
|
||||
}
|
||||
|
||||
func cancel() {
|
||||
@@ -464,8 +518,8 @@ class PreviewCredentialProviderViewModel: CredentialProviderViewModel {
|
||||
try? await Task.sleep(nanoseconds: 1_000_000_000) // Simulate network delay
|
||||
return previewCredentials
|
||||
},
|
||||
selectionHandler: { credential in
|
||||
print("Selected credential: \(credential)")
|
||||
selectionHandler: { identifier, password in
|
||||
print("Selected credential: \(identifier) with password: \(password)")
|
||||
},
|
||||
cancelHandler: {
|
||||
print("Canceled")
|
||||
|
||||
Reference in New Issue
Block a user