Redesign predefinedprompttemplates view
This commit is contained in:
parent
ed9a13c16b
commit
6d3fac76ef
@ -43,7 +43,7 @@ enum PromptTemplates {
|
||||
- Don't add any information not available in the <TRANSCRIPT> text ever.
|
||||
""",
|
||||
icon: "checkmark.seal.fill",
|
||||
description: "Default system prompt for improving clarity and accuracy of transcriptions"
|
||||
description: "Default system prompt"
|
||||
),
|
||||
TemplatePrompt(
|
||||
id: UUID(),
|
||||
@ -77,7 +77,7 @@ enum PromptTemplates {
|
||||
- Don't add any information not available in the <TRANSCRIPT> text ever.
|
||||
""",
|
||||
icon: "envelope.fill",
|
||||
description: "Template for converting casual messages into professional email format"
|
||||
description: "Professional email formatting"
|
||||
),
|
||||
TemplatePrompt(
|
||||
id: UUID(),
|
||||
@ -96,7 +96,7 @@ enum PromptTemplates {
|
||||
- Don't add any information not available in the <TRANSCRIPT> text ever.
|
||||
""",
|
||||
icon: "pencil.circle.fill",
|
||||
description: "Rewrites transcriptions with enhanced clarity, improved sentence structure, and rhythmic flow while preserving original meaning."
|
||||
description: "Rewrites with better clarity."
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
90
VoiceInk/Views/PredefinedPromptsView.swift
Normal file
90
VoiceInk/Views/PredefinedPromptsView.swift
Normal file
@ -0,0 +1,90 @@
|
||||
import SwiftUI
|
||||
|
||||
struct PredefinedPromptsView: View {
|
||||
let onSelect: (TemplatePrompt) -> Void
|
||||
|
||||
private let columns: [GridItem] = Array(repeating: GridItem(.flexible(), spacing: 18), count: 2)
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
LazyVGrid(columns: columns, spacing: 16) {
|
||||
ForEach(PromptTemplates.all) { template in
|
||||
PredefinedTemplateButton(prompt: template) {
|
||||
onSelect(template)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 24)
|
||||
.padding(.vertical, 20)
|
||||
}
|
||||
.frame(minWidth: 410, idealWidth: 520, maxWidth: 570, maxHeight: 440)
|
||||
}
|
||||
}
|
||||
|
||||
struct PredefinedTemplateButton: View {
|
||||
let prompt: TemplatePrompt
|
||||
let action: () -> Void
|
||||
|
||||
var body: some View {
|
||||
Button(action: action) {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
HStack(alignment: .center, spacing: 12) {
|
||||
RoundedRectangle(cornerRadius: 10, style: .continuous)
|
||||
.fill(Color(NSColor.unemphasizedSelectedTextBackgroundColor))
|
||||
.frame(width: 42, height: 42)
|
||||
.overlay(
|
||||
Image(systemName: prompt.icon)
|
||||
.font(.system(size: 19, weight: .medium))
|
||||
.foregroundColor(Color(NSColor.labelColor))
|
||||
)
|
||||
|
||||
Text(prompt.title)
|
||||
.font(.system(size: 15, weight: .semibold))
|
||||
.foregroundColor(.primary)
|
||||
.lineLimit(1)
|
||||
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
|
||||
Text(prompt.description)
|
||||
.font(.system(size: 12))
|
||||
.foregroundColor(Color(NSColor.secondaryLabelColor))
|
||||
.lineLimit(1)
|
||||
.truncationMode(.tail)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .topLeading)
|
||||
.padding(.horizontal, 18)
|
||||
.padding(.vertical, 12)
|
||||
.background(cardBackground)
|
||||
.overlay(cardStroke)
|
||||
.contentShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
|
||||
.shadow(color: cardShadowColor, radius: 6, x: 0, y: 4)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
|
||||
private var cardBackground: some View {
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.fill(Color(NSColor.controlBackgroundColor))
|
||||
}
|
||||
|
||||
private var cardStroke: some View {
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.stroke(
|
||||
LinearGradient(
|
||||
colors: [
|
||||
Color(NSColor.separatorColor).opacity(0.35),
|
||||
Color(NSColor.separatorColor).opacity(0.15)
|
||||
],
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
),
|
||||
lineWidth: 1
|
||||
)
|
||||
}
|
||||
|
||||
private var cardShadowColor: Color {
|
||||
Color(NSColor.shadowColor).opacity(0.25)
|
||||
}
|
||||
}
|
||||
@ -215,36 +215,32 @@ struct PromptEditorView: View {
|
||||
.padding(.horizontal)
|
||||
|
||||
if case .add = mode {
|
||||
// Templates Section with modern styling
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
Text("Start with a Predefined Template")
|
||||
.font(.title2)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
|
||||
let columns = [
|
||||
GridItem(.flexible(), spacing: 16),
|
||||
GridItem(.flexible(), spacing: 16)
|
||||
]
|
||||
|
||||
LazyVGrid(columns: columns, spacing: 16) {
|
||||
ForEach(PromptTemplates.all) { template in
|
||||
CleanTemplateButton(prompt: template) {
|
||||
title = template.title
|
||||
promptText = template.promptText
|
||||
selectedIcon = template.icon
|
||||
description = template.description
|
||||
}
|
||||
}
|
||||
// Popover keeps templates accessible without taking space in the layout
|
||||
Button("Start with a Predefined Template") {
|
||||
showingPredefinedPrompts.toggle()
|
||||
}
|
||||
.font(.headline)
|
||||
.padding(.horizontal, 24)
|
||||
.padding(.vertical, 12)
|
||||
.background(
|
||||
Capsule()
|
||||
.fill(Color(.windowBackgroundColor).opacity(0.9))
|
||||
)
|
||||
.overlay(
|
||||
Capsule()
|
||||
.stroke(Color.secondary.opacity(0.2), lineWidth: 1)
|
||||
)
|
||||
.buttonStyle(.plain)
|
||||
.padding(.horizontal)
|
||||
.popover(isPresented: $showingPredefinedPrompts, arrowEdge: .bottom) {
|
||||
PredefinedPromptsView { template in
|
||||
title = template.title
|
||||
promptText = template.promptText
|
||||
selectedIcon = template.icon
|
||||
description = template.description
|
||||
showingPredefinedPrompts = false
|
||||
}
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.padding(.vertical, 16)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 16)
|
||||
.fill(Color(.windowBackgroundColor).opacity(0.6))
|
||||
)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -282,90 +278,6 @@ struct PromptEditorView: View {
|
||||
}
|
||||
}
|
||||
|
||||
// Clean template button with minimal styling
|
||||
struct CleanTemplateButton: View {
|
||||
let prompt: TemplatePrompt
|
||||
let action: () -> Void
|
||||
|
||||
var body: some View {
|
||||
Button(action: action) {
|
||||
HStack(alignment: .top, spacing: 12) {
|
||||
// Clean icon design
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.fill(Color.accentColor.opacity(0.15))
|
||||
.frame(width: 44, height: 44)
|
||||
|
||||
Image(systemName: prompt.icon)
|
||||
.font(.system(size: 20, weight: .semibold))
|
||||
.foregroundColor(.accentColor)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text(prompt.title)
|
||||
.font(.system(size: 16, weight: .semibold))
|
||||
.foregroundColor(.primary)
|
||||
.lineLimit(1)
|
||||
|
||||
Text(prompt.description)
|
||||
.font(.system(size: 13))
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(2)
|
||||
.multilineTextAlignment(.leading)
|
||||
}
|
||||
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.padding(16)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.fill(Color(.controlBackgroundColor))
|
||||
)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.stroke(Color.secondary.opacity(0.2), lineWidth: 1)
|
||||
)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
|
||||
// Keep the old TemplateButton for backward compatibility if needed elsewhere
|
||||
struct TemplateButton: View {
|
||||
let prompt: TemplatePrompt
|
||||
let action: () -> Void
|
||||
|
||||
var body: some View {
|
||||
Button(action: action) {
|
||||
HStack(alignment: .center, spacing: 12) {
|
||||
Image(systemName: prompt.icon)
|
||||
.font(.system(size: 20, weight: .medium))
|
||||
.foregroundColor(.accentColor)
|
||||
.frame(width: 28, height: 28)
|
||||
.background(Color.accentColor.opacity(0.12))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 6))
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text(prompt.title)
|
||||
.font(.system(size: 15, weight: .semibold))
|
||||
.foregroundColor(.primary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.padding(12)
|
||||
.frame(height: 60)
|
||||
.background(Color(NSColor.controlBackgroundColor))
|
||||
.cornerRadius(10)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 10)
|
||||
.stroke(Color.secondary.opacity(0.18), lineWidth: 1)
|
||||
)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
|
||||
// Reusable Trigger Words Editor Component
|
||||
struct TriggerWordsEditor: View {
|
||||
@Binding var triggerWords: [String]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user