feat: use a default template for automatic notes
This commit is contained in:
@@ -270,6 +270,19 @@ class LocalStorageManager {
|
||||
return templates.sorted { $0.title < $1.title }
|
||||
}
|
||||
|
||||
func preferredTemplateID(in templates: [NoteTemplate]? = nil) -> UUID? {
|
||||
let availableTemplates = templates ?? loadTemplates()
|
||||
if let selectedTemplateID = UserDefaultsManager.shared.selectedTemplateId,
|
||||
availableTemplates.contains(where: { $0.id == selectedTemplateID }) {
|
||||
return selectedTemplateID
|
||||
}
|
||||
|
||||
let fallbackTemplateID = availableTemplates.first(where: { $0.title == "Standard Meeting" })?.id
|
||||
?? availableTemplates.first?.id
|
||||
UserDefaultsManager.shared.selectedTemplateId = fallbackTemplateID
|
||||
return fallbackTemplateID
|
||||
}
|
||||
|
||||
/// Deletes a template from local storage
|
||||
/// - Parameter template: The template to delete
|
||||
/// - Returns: True if successful, false otherwise
|
||||
|
||||
@@ -244,7 +244,7 @@ private final class LocalRecordingController {
|
||||
return statusPayload()
|
||||
}
|
||||
|
||||
let meeting = Meeting()
|
||||
let meeting = Meeting(templateId: LocalStorageManager.shared.preferredTemplateID())
|
||||
guard LocalStorageManager.shared.saveMeeting(meeting) else {
|
||||
throw LocalRecordingError.saveFailed
|
||||
}
|
||||
@@ -288,9 +288,7 @@ private final class LocalRecordingController {
|
||||
meeting.transcriptChunks = chunks
|
||||
let templates = LocalStorageManager.shared.loadTemplates()
|
||||
if meeting.templateId == nil {
|
||||
meeting.templateId = UserDefaultsManager.shared.selectedTemplateId
|
||||
?? templates.first(where: { $0.title == "Standard Meeting" })?.id
|
||||
?? templates.first?.id
|
||||
meeting.templateId = LocalStorageManager.shared.preferredTemplateID(in: templates)
|
||||
}
|
||||
_ = LocalStorageManager.shared.saveMeeting(meeting)
|
||||
NotificationCenter.default.post(name: .meetingSaved, object: meeting)
|
||||
|
||||
@@ -68,7 +68,7 @@ class MeetingListViewModel: ObservableObject {
|
||||
}
|
||||
|
||||
func createNewMeeting() -> Meeting {
|
||||
let newMeeting = Meeting()
|
||||
let newMeeting = Meeting(templateId: LocalStorageManager.shared.preferredTemplateID())
|
||||
meetings.insert(newMeeting, at: 0)
|
||||
_ = LocalStorageManager.shared.saveMeeting(newMeeting)
|
||||
// Track meeting creation event
|
||||
|
||||
@@ -228,11 +228,13 @@ class MeetingViewModel: ObservableObject {
|
||||
func loadTemplates() {
|
||||
templates = LocalStorageManager.shared.loadTemplates()
|
||||
|
||||
// Load per-meeting template or default to Standard Meeting
|
||||
if let meetingTemplateId = meeting.templateId {
|
||||
// Keep an existing meeting's template, otherwise use the configured default.
|
||||
if let meetingTemplateId = meeting.templateId,
|
||||
templates.contains(where: { $0.id == meetingTemplateId }) {
|
||||
selectedTemplateId = meetingTemplateId
|
||||
} else if let defaultTemplate = templates.first(where: { $0.title == "Standard Meeting" }) {
|
||||
selectedTemplateId = defaultTemplate.id
|
||||
} else {
|
||||
selectedTemplateId = LocalStorageManager.shared.preferredTemplateID(in: templates)
|
||||
meeting.templateId = selectedTemplateId
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,24 +52,7 @@ class SettingsViewModel: ObservableObject {
|
||||
|
||||
func loadTemplates() {
|
||||
templates = LocalStorageManager.shared.loadTemplates()
|
||||
|
||||
// Validate that the selected template still exists
|
||||
if let selectedId = settings.selectedTemplateId {
|
||||
if !templates.contains(where: { $0.id == selectedId }) {
|
||||
// Selected template was deleted, clear the selection
|
||||
settings.selectedTemplateId = nil
|
||||
}
|
||||
}
|
||||
|
||||
// If no template is selected, select the first default template
|
||||
if settings.selectedTemplateId == nil {
|
||||
if let defaultTemplate = templates.first(where: { $0.title == "Standard Meeting" }) {
|
||||
settings.selectedTemplateId = defaultTemplate.id
|
||||
} else if let firstTemplate = templates.first {
|
||||
// Fallback to first available template
|
||||
settings.selectedTemplateId = firstTemplate.id
|
||||
}
|
||||
}
|
||||
settings.selectedTemplateId = LocalStorageManager.shared.preferredTemplateID(in: templates)
|
||||
}
|
||||
|
||||
func saveSettings(showMessage: Bool = true) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import SwiftUI
|
||||
@MainActor
|
||||
class TemplatesViewModel: ObservableObject {
|
||||
@Published var templates: [NoteTemplate] = []
|
||||
@Published private(set) var defaultTemplateID: UUID? = nil
|
||||
@Published var isLoading = false
|
||||
@Published var errorMessage: String?
|
||||
|
||||
@@ -14,9 +15,15 @@ class TemplatesViewModel: ObservableObject {
|
||||
func loadTemplates() {
|
||||
isLoading = true
|
||||
templates = LocalStorageManager.shared.loadTemplates()
|
||||
defaultTemplateID = LocalStorageManager.shared.preferredTemplateID(in: templates)
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
func setDefaultTemplate(_ template: NoteTemplate) {
|
||||
UserDefaultsManager.shared.selectedTemplateId = template.id
|
||||
defaultTemplateID = template.id
|
||||
}
|
||||
|
||||
func saveTemplate(_ template: NoteTemplate) {
|
||||
if LocalStorageManager.shared.saveTemplate(template) {
|
||||
loadTemplates()
|
||||
|
||||
@@ -145,6 +145,12 @@ struct SettingsView: View {
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
|
||||
Picker("Default template", selection: $viewModel.settings.selectedTemplateId) {
|
||||
ForEach(viewModel.templates) { template in
|
||||
Text(template.title).tag(Optional(template.id))
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
navigationPath.append("templates")
|
||||
} label: {
|
||||
|
||||
@@ -16,7 +16,7 @@ struct TemplateListView: View {
|
||||
Text(template.title)
|
||||
.font(.headline)
|
||||
if template.isDefault {
|
||||
Text("Default")
|
||||
Text("Built-in")
|
||||
.font(.caption)
|
||||
.padding(.horizontal, 6)
|
||||
.padding(.vertical, 2)
|
||||
@@ -39,6 +39,15 @@ struct TemplateListView: View {
|
||||
|
||||
Spacer()
|
||||
|
||||
Button {
|
||||
viewModel.setDefaultTemplate(template)
|
||||
} label: {
|
||||
Image(systemName: viewModel.defaultTemplateID == template.id ? "star.fill" : "star")
|
||||
.foregroundColor(viewModel.defaultTemplateID == template.id ? .accentColor : .secondary)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.help(viewModel.defaultTemplateID == template.id ? "Default template" : "Use as default template")
|
||||
|
||||
if !template.isDefault {
|
||||
Button(role: .destructive) {
|
||||
viewModel.deleteTemplate(template)
|
||||
@@ -50,6 +59,14 @@ struct TemplateListView: View {
|
||||
}
|
||||
}
|
||||
.contextMenu {
|
||||
if viewModel.defaultTemplateID != template.id {
|
||||
Button {
|
||||
viewModel.setDefaultTemplate(template)
|
||||
} label: {
|
||||
Label("Use as Default", systemImage: "star")
|
||||
}
|
||||
}
|
||||
|
||||
if !template.isDefault {
|
||||
Button(role: .destructive) {
|
||||
viewModel.deleteTemplate(template)
|
||||
|
||||
Reference in New Issue
Block a user