fix: correct add-entry default group and clear search on hide

- GroupFilterViewModel now tracks lastToggledGroupId (the single group
  most recently toggled to a non-empty selection), since toggling a
  group with subgroups expands selectedGroupIds to include the whole
  subtree, breaking the previous count==1 check used to infer the
  active filter group.
- VaultViewModel exposes lastToggledGroupId, forwarded from
  GroupFilterViewModel by VaultRootView (ContentView.swift), and
  EntryListView.defaultGroupId now reads it instead of the broken
  selectedGroupIds.count == 1 check, so the add-entry sheet defaults
  new entries into the group actually being filtered by, not silently
  back to root.
- EntryListView's search toggle button now clears vm.searchQuery when
  hiding the search bar, so a hidden bar can no longer keep filtering
  the list invisibly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WYqycDFsynHH9VnnK7LNSf
This commit is contained in:
2026-09-19 17:25:06 +02:00
co-authored by Claude Sonnet 5
parent 05bd34208b
commit f454b4594a
4 changed files with 17 additions and 6 deletions
+3
View File
@@ -74,5 +74,8 @@ private struct VaultRootView: View {
.onChange(of: filterVM.selectedGroupIds) { _, newValue in .onChange(of: filterVM.selectedGroupIds) { _, newValue in
vaultVM.selectedGroupIds = newValue vaultVM.selectedGroupIds = newValue
} }
.onChange(of: filterVM.lastToggledGroupId) { _, newValue in
vaultVM.lastToggledGroupId = newValue
}
} }
} }
@@ -5,6 +5,10 @@ import MyPassCore
@MainActor @MainActor
final class GroupFilterViewModel: ObservableObject { final class GroupFilterViewModel: ObservableObject {
@Published var selectedGroupIds: Set<UUID> = [] @Published var selectedGroupIds: Set<UUID> = []
/// The group id passed to the most recent `toggle(_:)` call that resulted in a non-empty
/// selection, used as a "best effort" default group for new entries. Cleared to `nil`
/// whenever a toggle empties the selection, or by `clear()`.
@Published private(set) var lastToggledGroupId: UUID?
private let session: VaultSession private let session: VaultSession
@@ -19,9 +23,11 @@ final class GroupFilterViewModel: ObservableObject {
func toggle(_ group: MyPassCore.Group) { func toggle(_ group: MyPassCore.Group) {
guard let root = session.database?.root else { return } guard let root = session.database?.root else { return }
selectedGroupIds = GroupSelection.toggling(group.id, in: root, current: selectedGroupIds) selectedGroupIds = GroupSelection.toggling(group.id, in: root, current: selectedGroupIds)
lastToggledGroupId = selectedGroupIds.isEmpty ? nil : group.id
} }
func clear() { func clear() {
selectedGroupIds = [] selectedGroupIds = []
lastToggledGroupId = nil
} }
} }
+1
View File
@@ -7,6 +7,7 @@ import MyPassCore
final class VaultViewModel: ObservableObject { final class VaultViewModel: ObservableObject {
@Published var searchQuery: String = "" @Published var searchQuery: String = ""
@Published var selectedGroupIds: Set<UUID> = [] @Published var selectedGroupIds: Set<UUID> = []
@Published var lastToggledGroupId: UUID?
@Published var errorMessage: String? @Published var errorMessage: String?
let session: VaultSession let session: VaultSession
+7 -6
View File
@@ -28,7 +28,10 @@ struct EntryListView: View {
.searchable(text: $vm.searchQuery, isPresented: $isSearching, prompt: "Search entries…") .searchable(text: $vm.searchQuery, isPresented: $isSearching, prompt: "Search entries…")
.toolbar { .toolbar {
ToolbarItem(placement: .primaryAction) { ToolbarItem(placement: .primaryAction) {
Button { isSearching.toggle() } label: { Button {
if isSearching { vm.searchQuery = "" }
isSearching.toggle()
} label: {
Image(systemName: "magnifyingglass") Image(systemName: "magnifyingglass")
} }
} }
@@ -51,12 +54,10 @@ struct EntryListView: View {
} }
} }
/// The sole selected filter group if exactly one is active, otherwise the vault root. /// The most recently toggled-on filter group, if any filter is still active via it,
/// otherwise the vault root.
private var defaultGroupId: UUID { private var defaultGroupId: UUID {
if vm.selectedGroupIds.count == 1, let only = vm.selectedGroupIds.first { vm.lastToggledGroupId ?? vm.session.database?.root.id ?? UUID()
return only
}
return vm.session.database?.root.id ?? UUID()
} }
} }