From e52cf3f39bab57025e62f257828f2ed1918c22cf Mon Sep 17 00:00:00 2001 From: Christophe Vila Date: Sat, 19 Sep 2026 19:15:16 +0200 Subject: [PATCH] feat: add CredentialListView for AutoFill extension Co-Authored-By: Claude Haiku 4.5 Claude-Session: https://claude.ai/code/session_01WYqycDFsynHH9VnnK7LNSf --- AutoFill/Views/CredentialListView.swift | 62 +++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 AutoFill/Views/CredentialListView.swift diff --git a/AutoFill/Views/CredentialListView.swift b/AutoFill/Views/CredentialListView.swift new file mode 100644 index 0000000..afbb24d --- /dev/null +++ b/AutoFill/Views/CredentialListView.swift @@ -0,0 +1,62 @@ +// AutoFill/Views/CredentialListView.swift +import SwiftUI +import MyPassCore + +struct CredentialListView: View { + @ObservedObject var vm: ExtensionViewModel + @State private var searchQuery: String = "" + + private var displayedSuggested: [Entry] { + searchQuery.isEmpty ? vm.suggestedEntries : [] + } + + private var displayedAll: [Entry] { + let entries = searchQuery.isEmpty ? vm.allEntries : vm.session.allEntries() + guard !searchQuery.isEmpty else { return entries } + let q = searchQuery.lowercased() + return entries.filter { + $0.title.lowercased().contains(q) + || $0.username.lowercased().contains(q) + || $0.url.lowercased().contains(q) + } + } + + var body: some View { + List { + if !displayedSuggested.isEmpty { + Section("Suggested") { + ForEach(displayedSuggested) { entry in + CredentialRow(entry: entry) { vm.select(entry) } + } + } + } + Section(displayedSuggested.isEmpty ? "" : "All Entries") { + if displayedAll.isEmpty { + Text("No entries found").foregroundStyle(.secondary) + } else { + ForEach(displayedAll) { entry in + CredentialRow(entry: entry) { vm.select(entry) } + } + } + } + } + .searchable(text: $searchQuery, prompt: "Search…") + } +} + +private struct CredentialRow: View { + let entry: Entry + let onSelect: () -> Void + + var body: some View { + Button(action: onSelect) { + VStack(alignment: .leading, spacing: 2) { + Text(entry.title).font(.body).foregroundStyle(.primary) + Text(entry.username).font(.caption).foregroundStyle(.secondary) + if !entry.url.isEmpty { + Text(entry.url).font(.caption2).foregroundStyle(.tertiary) + } + } + } + } +}