feat: require groupId in EntryEditViewModel, add group picker to EntryEditView

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:02:03 +02:00
co-authored by Claude Sonnet 5
parent fe8b569753
commit 1ec0d02e44
3 changed files with 29 additions and 21 deletions
+12 -15
View File
@@ -1,8 +1,4 @@
//
// EntryEditViewModel.swift
// MyPass
//
// MyPass/ViewModels/EntryEditViewModel.swift
import Foundation
import Combine
import SwiftUI
@@ -16,16 +12,17 @@ final class EntryEditViewModel: ObservableObject {
@Published var url: String
@Published var notes: String
@Published var customFields: [CustomField]
@Published var groupId: UUID
@Published var errorMessage: String?
@Published var isSaving: Bool = false
private let session: VaultSession
private let groupId: UUID?
let session: VaultSession
private let existingEntry: Entry?
/// `groupId` is required when adding a new entry, and unused when editing an existing one
/// (an existing entry's group is looked up internally by `VaultSession.updateEntry`).
init(session: VaultSession, groupId: UUID? = nil, existing: Entry? = nil) {
/// `groupId` is the target group for a new entry, or the entry's current group when
/// editing (shown read-only in that case -- MyPass doesn't support re-parenting an
/// existing entry to a different group yet).
init(session: VaultSession, groupId: UUID, existing: Entry? = nil) {
self.session = session
self.groupId = groupId
self.existingEntry = existing
@@ -39,6 +36,11 @@ final class EntryEditViewModel: ObservableObject {
var isEditing: Bool { existingEntry != nil }
var flatGroups: [FlatGroup] {
guard let root = session.database?.root else { return [] }
return flattenGroups(in: root)
}
func save(dismiss: @escaping () -> Void) {
Task {
isSaving = true
@@ -53,11 +55,6 @@ final class EntryEditViewModel: ObservableObject {
entry.customFields = customFields
try session.updateEntry(entry)
} else {
guard let groupId else {
errorMessage = "No group selected for the new entry."
isSaving = false
return
}
let entry = Entry(
title: title,
username: username,
+2 -1
View File
@@ -9,6 +9,7 @@ import MyPassCore
struct EntryDetailView: View {
let entry: Entry
let groupId: UUID
let session: VaultSession
@State private var showPassword = false
@@ -30,7 +31,7 @@ struct EntryDetailView: View {
}
}
.sheet(isPresented: $showEditSheet) {
EntryEditView(vm: EntryEditViewModel(session: session, existing: entry))
EntryEditView(vm: EntryEditViewModel(session: session, groupId: groupId, existing: entry))
}
#if os(macOS)
.keyboardShortcut("e", modifiers: .command)
+15 -5
View File
@@ -1,8 +1,4 @@
//
// EntryEditView.swift
// MyPass
//
// MyPass/Views/EntryEditView.swift
import SwiftUI
import MyPassCore
@@ -13,6 +9,16 @@ struct EntryEditView: View {
var body: some View {
NavigationStack {
Form {
if !vm.isEditing {
Section("Group") {
Picker("Group", selection: $vm.groupId) {
ForEach(vm.flatGroups) { flatGroup in
Text(groupLabel(for: flatGroup)).tag(flatGroup.group.id)
}
}
}
}
Section("Credentials") {
TextField("Title", text: $vm.title)
TextField("Username", text: $vm.username)
@@ -69,4 +75,8 @@ struct EntryEditView: View {
}
}
}
private func groupLabel(for flatGroup: FlatGroup) -> String {
(flatGroup.breadcrumb.map(\.name) + [flatGroup.group.name]).joined(separator: " > ")
}
}