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:
@@ -1,8 +1,4 @@
|
|||||||
//
|
// MyPass/ViewModels/EntryEditViewModel.swift
|
||||||
// EntryEditViewModel.swift
|
|
||||||
// MyPass
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
@@ -16,16 +12,17 @@ final class EntryEditViewModel: ObservableObject {
|
|||||||
@Published var url: String
|
@Published var url: String
|
||||||
@Published var notes: String
|
@Published var notes: String
|
||||||
@Published var customFields: [CustomField]
|
@Published var customFields: [CustomField]
|
||||||
|
@Published var groupId: UUID
|
||||||
@Published var errorMessage: String?
|
@Published var errorMessage: String?
|
||||||
@Published var isSaving: Bool = false
|
@Published var isSaving: Bool = false
|
||||||
|
|
||||||
private let session: VaultSession
|
let session: VaultSession
|
||||||
private let groupId: UUID?
|
|
||||||
private let existingEntry: Entry?
|
private let existingEntry: Entry?
|
||||||
|
|
||||||
/// `groupId` is required when adding a new entry, and unused when editing an existing one
|
/// `groupId` is the target group for a new entry, or the entry's current group when
|
||||||
/// (an existing entry's group is looked up internally by `VaultSession.updateEntry`).
|
/// editing (shown read-only in that case -- MyPass doesn't support re-parenting an
|
||||||
init(session: VaultSession, groupId: UUID? = nil, existing: Entry? = nil) {
|
/// existing entry to a different group yet).
|
||||||
|
init(session: VaultSession, groupId: UUID, existing: Entry? = nil) {
|
||||||
self.session = session
|
self.session = session
|
||||||
self.groupId = groupId
|
self.groupId = groupId
|
||||||
self.existingEntry = existing
|
self.existingEntry = existing
|
||||||
@@ -39,6 +36,11 @@ final class EntryEditViewModel: ObservableObject {
|
|||||||
|
|
||||||
var isEditing: Bool { existingEntry != nil }
|
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) {
|
func save(dismiss: @escaping () -> Void) {
|
||||||
Task {
|
Task {
|
||||||
isSaving = true
|
isSaving = true
|
||||||
@@ -53,11 +55,6 @@ final class EntryEditViewModel: ObservableObject {
|
|||||||
entry.customFields = customFields
|
entry.customFields = customFields
|
||||||
try session.updateEntry(entry)
|
try session.updateEntry(entry)
|
||||||
} else {
|
} else {
|
||||||
guard let groupId else {
|
|
||||||
errorMessage = "No group selected for the new entry."
|
|
||||||
isSaving = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let entry = Entry(
|
let entry = Entry(
|
||||||
title: title,
|
title: title,
|
||||||
username: username,
|
username: username,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import MyPassCore
|
|||||||
|
|
||||||
struct EntryDetailView: View {
|
struct EntryDetailView: View {
|
||||||
let entry: Entry
|
let entry: Entry
|
||||||
|
let groupId: UUID
|
||||||
let session: VaultSession
|
let session: VaultSession
|
||||||
|
|
||||||
@State private var showPassword = false
|
@State private var showPassword = false
|
||||||
@@ -30,7 +31,7 @@ struct EntryDetailView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.sheet(isPresented: $showEditSheet) {
|
.sheet(isPresented: $showEditSheet) {
|
||||||
EntryEditView(vm: EntryEditViewModel(session: session, existing: entry))
|
EntryEditView(vm: EntryEditViewModel(session: session, groupId: groupId, existing: entry))
|
||||||
}
|
}
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
.keyboardShortcut("e", modifiers: .command)
|
.keyboardShortcut("e", modifiers: .command)
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
//
|
// MyPass/Views/EntryEditView.swift
|
||||||
// EntryEditView.swift
|
|
||||||
// MyPass
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import MyPassCore
|
import MyPassCore
|
||||||
|
|
||||||
@@ -13,6 +9,16 @@ struct EntryEditView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
Form {
|
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") {
|
Section("Credentials") {
|
||||||
TextField("Title", text: $vm.title)
|
TextField("Title", text: $vm.title)
|
||||||
TextField("Username", text: $vm.username)
|
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: " > ")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user