feat: auto-start recording and deletion of empty meetings
This commit is contained in:
@@ -26,12 +26,21 @@ class MeetingViewModel: ObservableObject {
|
|||||||
@Published var isGeneratingNotes = false
|
@Published var isGeneratingNotes = false
|
||||||
@Published var errorMessage: String?
|
@Published var errorMessage: String?
|
||||||
@Published var isRecording = false
|
@Published var isRecording = false
|
||||||
@Published var selectedTab: MeetingViewTab = .myNotes
|
@Published var selectedTab: MeetingViewTab = .transcript // Default to transcript tab
|
||||||
@Published var recordingState: RecordingState = .idle
|
@Published var recordingState: RecordingState = .idle
|
||||||
@Published var isDeleted = false
|
@Published var isDeleted = false
|
||||||
|
|
||||||
private let audioManager = AudioManager()
|
private let audioManager = AudioManager()
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
private var isNewMeeting = false
|
||||||
|
|
||||||
|
// Computed property to check if meeting is empty
|
||||||
|
var isEmpty: Bool {
|
||||||
|
return meeting.transcriptChunks.isEmpty &&
|
||||||
|
meeting.userNotes.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty &&
|
||||||
|
meeting.generatedNotes.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty &&
|
||||||
|
meeting.title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
init(meeting: Meeting = Meeting()) {
|
init(meeting: Meeting = Meeting()) {
|
||||||
// Load the latest version of the meeting from storage if it exists
|
// Load the latest version of the meeting from storage if it exists
|
||||||
@@ -43,6 +52,16 @@ class MeetingViewModel: ObservableObject {
|
|||||||
self.meeting = meeting
|
self.meeting = meeting
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detect if this is a new meeting based on content, not storage existence
|
||||||
|
isNewMeeting = isEmpty
|
||||||
|
|
||||||
|
// Set initial tab based on notes existence
|
||||||
|
if !self.meeting.generatedNotes.isEmpty {
|
||||||
|
selectedTab = .enhancedNotes
|
||||||
|
} else {
|
||||||
|
selectedTab = .transcript
|
||||||
|
}
|
||||||
|
|
||||||
// NEW: Seed the audio manager with any existing transcript chunks so the initial
|
// NEW: Seed the audio manager with any existing transcript chunks so the initial
|
||||||
// published value doesn't overwrite the saved transcript with an empty array.
|
// published value doesn't overwrite the saved transcript with an empty array.
|
||||||
audioManager.transcriptChunks = self.meeting.transcriptChunks
|
audioManager.transcriptChunks = self.meeting.transcriptChunks
|
||||||
@@ -70,6 +89,12 @@ class MeetingViewModel: ObservableObject {
|
|||||||
self?.saveMeeting()
|
self?.saveMeeting()
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
// Auto-start recording for empty meetings
|
||||||
|
if isNewMeeting {
|
||||||
|
print("🚀 Auto-starting recording for empty meeting")
|
||||||
|
startRecording()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateRecordingState() {
|
private func updateRecordingState() {
|
||||||
@@ -107,6 +132,16 @@ class MeetingViewModel: ObservableObject {
|
|||||||
func stopRecording() {
|
func stopRecording() {
|
||||||
audioManager.stopRecording()
|
audioManager.stopRecording()
|
||||||
saveMeeting()
|
saveMeeting()
|
||||||
|
|
||||||
|
// Auto-generate notes if there's a transcript and no existing notes
|
||||||
|
if !meeting.formattedTranscript.isEmpty && meeting.generatedNotes.isEmpty {
|
||||||
|
print("🤖 Auto-generating notes after recording stopped")
|
||||||
|
// Switch to enhanced notes tab immediately when starting generation
|
||||||
|
selectedTab = .enhancedNotes
|
||||||
|
Task {
|
||||||
|
await generateNotes()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateNotes() async {
|
func generateNotes() async {
|
||||||
@@ -175,4 +210,13 @@ class MeetingViewModel: ObservableObject {
|
|||||||
NotificationCenter.default.post(name: .meetingDeleted, object: meeting)
|
NotificationCenter.default.post(name: .meetingDeleted, object: meeting)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deleteIfEmpty() {
|
||||||
|
if isEmpty {
|
||||||
|
print("🗑️ Auto-deleting empty meeting")
|
||||||
|
deleteMeeting()
|
||||||
|
} else {
|
||||||
|
saveMeeting()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -147,7 +147,8 @@ struct MeetingDetailView: View {
|
|||||||
Text("Are you sure you want to delete this meeting? This action cannot be undone.")
|
Text("Are you sure you want to delete this meeting? This action cannot be undone.")
|
||||||
}
|
}
|
||||||
.onDisappear {
|
.onDisappear {
|
||||||
viewModel.saveMeeting()
|
// Auto-delete empty meetings when leaving, otherwise save
|
||||||
|
viewModel.deleteIfEmpty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ struct RenderedNotesView: View {
|
|||||||
} else if let level = headingLevel(for: trimmed) {
|
} else if let level = headingLevel(for: trimmed) {
|
||||||
let content = String(trimmed.dropFirst(level + 1)).trimmingCharacters(in: .whitespaces)
|
let content = String(trimmed.dropFirst(level + 1)).trimmingCharacters(in: .whitespaces)
|
||||||
Text(content)
|
Text(content)
|
||||||
.font(.system(size: CGFloat(28 - level * 4), weight: .bold))
|
.font(.system(size: CGFloat(18 - level * 2), weight: .bold))
|
||||||
.foregroundColor(.white)
|
.foregroundColor(.white)
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
} else if let (indentLevel, bullet, content) = listItemInfo(for: line) {
|
} else if let (indentLevel, bullet, content) = listItemInfo(for: line) {
|
||||||
|
|||||||
Reference in New Issue
Block a user