PromtGarageMac / Sources /PromptGarageApp /Views /PromptEditorSheet.swift
smlflg's picture
Initial public upload from Projekte/PromtGarageMac
4977db2 verified
Raw History Blame Contribute Delete
4.02 kB
import PromptGarageCore
import SwiftUI
struct PromptEditorSheet: View {
@Bindable var model: AppModel
let presentation: PromptEditorPresentation
@State private var draft: PromptDraft
init(model: AppModel, presentation: PromptEditorPresentation) {
self.model = model
self.presentation = presentation
_draft = State(initialValue: presentation.initialDraft)
}
var body: some View {
VStack(spacing: 0) {
HStack {
VStack(alignment: .leading, spacing: 3) {
Text(presentation.title)
.font(.title2.weight(.semibold))
Text("Wird ausschließlich in deiner lokalen PromptGarage gespeichert.")
.font(.caption)
.foregroundStyle(.secondary)
}
Spacer()
}
.padding(22)
.background(.bar)
Divider()
Form {
Section("Prompt") {
TextField("Titel", text: $draft.title)
TextEditor(text: $draft.content)
.font(.body)
.frame(minHeight: 230)
.scrollContentBackground(.hidden)
.padding(8)
.background(
Color(nsColor: .textBackgroundColor),
in: RoundedRectangle(cornerRadius: AppUI.compactCornerRadius)
)
.overlay {
RoundedRectangle(cornerRadius: AppUI.compactCornerRadius)
.stroke(Color(nsColor: .separatorColor).opacity(0.7))
}
}
Section("Metadaten") {
TextField("Tags, durch Kommas getrennt", text: optionalTextBinding(\PromptDraft.tags))
TextField("Quelle", text: $draft.source)
TextField("Modell (optional)", text: optionalTextBinding(\PromptDraft.model))
Toggle("Favorit", isOn: $draft.isStarred)
LabeledContent("Bewertung") {
RatingControl(rating: draft.rating) { draft.rating = $0 }
}
}
if let validationMessage = draft.validationMessage {
Section {
Label(validationMessage, systemImage: "exclamationmark.circle")
.foregroundStyle(.red)
}
}
}
.formStyle(.grouped)
Divider()
HStack {
Button("Abbrechen") {
model.editor = nil
}
.keyboardShortcut(.cancelAction)
.disabled(model.isSavingEditor)
Spacer()
Button {
Task { _ = await model.saveEditor(draft, presentation: presentation) }
} label: {
if model.isSavingEditor {
HStack(spacing: 8) {
ProgressView().controlSize(.small)
Text("Speichern …")
}
} else {
Text("Speichern")
}
}
.buttonStyle(.borderedProminent)
.keyboardShortcut(.defaultAction)
.disabled(draft.validationMessage != nil || model.isSavingEditor)
}
.padding(16)
.background(.bar)
}
.frame(width: 680, height: 680)
.interactiveDismissDisabled(model.isSavingEditor)
}
private func optionalTextBinding(_ keyPath: WritableKeyPath<PromptDraft, String?>) -> Binding<String> {
Binding(
get: { draft[keyPath: keyPath] ?? "" },
set: { draft[keyPath: keyPath] = $0.isEmpty ? nil : $0 }
)
}
}