feat: enhance transcript handling with collapsed chunks
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import SwiftUI
|
||||
|
||||
struct TranscriptChunkView: View {
|
||||
let chunk: TranscriptChunk
|
||||
struct CollapsedTranscriptChunkView: View {
|
||||
let chunk: CollapsedTranscriptChunk
|
||||
|
||||
var body: some View {
|
||||
HStack(alignment: .top, spacing: 8) {
|
||||
@@ -11,58 +11,30 @@ struct TranscriptChunkView: View {
|
||||
.font(.caption)
|
||||
.foregroundColor(chunk.source == .mic ? .blue : .orange)
|
||||
|
||||
Text(chunk.source.rawValue)
|
||||
Text(chunk.source.displayName)
|
||||
.font(.caption)
|
||||
.fontWeight(.medium)
|
||||
.foregroundColor(chunk.source == .mic ? .blue : .orange)
|
||||
}
|
||||
.frame(width: 60, alignment: .leading)
|
||||
.frame(width: 50, alignment: .leading)
|
||||
|
||||
// Transcript text
|
||||
Text(chunk.text)
|
||||
Text(chunk.combinedText)
|
||||
.font(.body)
|
||||
.foregroundColor(chunk.isFinal ? .primary : .secondary)
|
||||
.italic(!chunk.isFinal)
|
||||
.foregroundColor(.primary)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
.padding(.vertical, 2)
|
||||
.opacity(chunk.isFinal ? 1.0 : 0.7)
|
||||
}
|
||||
}
|
||||
|
||||
struct MeetingDetailView: View {
|
||||
@StateObject private var viewModel: MeetingViewModel
|
||||
@State private var selectedTranscriptFilter: TranscriptFilter = .all
|
||||
|
||||
init(meeting: Meeting) {
|
||||
self._viewModel = StateObject(wrappedValue: MeetingViewModel(meeting: meeting))
|
||||
}
|
||||
|
||||
enum TranscriptFilter: String, CaseIterable {
|
||||
case all = "All"
|
||||
case mic = "Microphone"
|
||||
case system = "System Audio"
|
||||
|
||||
var icon: String {
|
||||
switch self {
|
||||
case .all: return "waveform"
|
||||
case .mic: return "mic.fill"
|
||||
case .system: return "speaker.wave.2.fill"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var filteredTranscriptChunks: [TranscriptChunk] {
|
||||
switch selectedTranscriptFilter {
|
||||
case .all:
|
||||
return viewModel.meeting.transcriptChunks
|
||||
case .mic:
|
||||
return viewModel.meeting.transcriptChunks.filter { $0.source == .mic }
|
||||
case .system:
|
||||
return viewModel.meeting.transcriptChunks.filter { $0.source == .system }
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 20) {
|
||||
// Recording Controls
|
||||
@@ -105,50 +77,23 @@ struct MeetingDetailView: View {
|
||||
Text("Live Transcript")
|
||||
.font(.headline)
|
||||
Spacer()
|
||||
|
||||
// Filter controls
|
||||
Picker("Filter", selection: $selectedTranscriptFilter) {
|
||||
ForEach(TranscriptFilter.allCases, id: \.self) { filter in
|
||||
Label(filter.rawValue, systemImage: filter.icon)
|
||||
.tag(filter)
|
||||
}
|
||||
}
|
||||
.pickerStyle(SegmentedPickerStyle())
|
||||
.frame(width: 200)
|
||||
|
||||
Menu {
|
||||
Button {
|
||||
viewModel.copyTranscript()
|
||||
} label: {
|
||||
Label("Copy All", systemImage: "doc.on.doc")
|
||||
}
|
||||
|
||||
Button {
|
||||
viewModel.copyMicTranscript()
|
||||
} label: {
|
||||
Label("Copy Microphone Only", systemImage: "mic.fill")
|
||||
}
|
||||
|
||||
Button {
|
||||
viewModel.copySystemTranscript()
|
||||
} label: {
|
||||
Label("Copy System Audio Only", systemImage: "speaker.wave.2.fill")
|
||||
}
|
||||
Button {
|
||||
viewModel.copyTranscript()
|
||||
} label: {
|
||||
Label("Copy", systemImage: "doc.on.doc")
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
if filteredTranscriptChunks.isEmpty {
|
||||
if viewModel.meeting.collapsedTranscriptChunks.isEmpty {
|
||||
Text("Transcript will appear here...")
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding()
|
||||
.foregroundColor(.secondary)
|
||||
} else {
|
||||
LazyVStack(alignment: .leading, spacing: 4) {
|
||||
ForEach(filteredTranscriptChunks) { chunk in
|
||||
TranscriptChunkView(chunk: chunk)
|
||||
ForEach(viewModel.meeting.collapsedTranscriptChunks) { chunk in
|
||||
CollapsedTranscriptChunkView(chunk: chunk)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
@@ -226,4 +171,5 @@ struct MeetingDetailView: View {
|
||||
NavigationStack {
|
||||
MeetingDetailView(meeting: Meeting())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user