vOOice/VoiceInk/Views/History/TranscriptionDetailView.swift
Beingpax 531da7b172 Redesign transcription history with three-pane layout and compact audio player
- Implement three-pane Xcode-style layout with toggleable sidebars
- Refactor into modular components for better maintainability
- Replace tabbed interface with iMessage-style message bubbles
- Redesign audio player for 70% height reduction with horizontal layout
- Update to native macOS colors and remove custom backgrounds
- Increase minimum window size to 1000x700 for better usability
2025-12-29 11:44:50 +05:45

101 lines
3.4 KiB
Swift

import SwiftUI
struct TranscriptionDetailView: View {
let transcription: Transcription
private var hasAudioFile: Bool {
if let urlString = transcription.audioFileURL,
let url = URL(string: urlString),
FileManager.default.fileExists(atPath: url.path) {
return true
}
return false
}
var body: some View {
VStack(spacing: 12) {
ScrollView {
VStack(spacing: 16) {
MessageBubble(
label: "Original",
text: transcription.text,
isEnhanced: false
)
if let enhancedText = transcription.enhancedText {
MessageBubble(
label: "Enhanced",
text: enhancedText,
isEnhanced: true
)
}
}
.padding(16)
}
if hasAudioFile, let urlString = transcription.audioFileURL,
let url = URL(string: urlString) {
VStack(spacing: 0) {
Divider()
AudioPlayerView(url: url)
.padding(.horizontal, 10)
.padding(.vertical, 6)
.background(
RoundedRectangle(cornerRadius: 8, style: .continuous)
.fill(Color(NSColor.controlBackgroundColor).opacity(0.5))
)
.padding(.horizontal, 12)
.padding(.top, 6)
}
}
}
.padding(.vertical, 12)
.background(Color(NSColor.controlBackgroundColor))
}
}
private struct MessageBubble: View {
let label: String
let text: String
let isEnhanced: Bool
var body: some View {
HStack(alignment: .bottom) {
if isEnhanced { Spacer(minLength: 60) }
VStack(alignment: isEnhanced ? .leading : .trailing, spacing: 4) {
Text(label)
.font(.system(size: 9, weight: .medium))
.foregroundColor(.secondary.opacity(0.7))
.padding(.horizontal, 12)
ScrollView {
Text(text)
.font(.system(size: 14, weight: .regular))
.lineSpacing(2)
.textSelection(.enabled)
.padding(.horizontal, 12)
.padding(.vertical, 10)
}
.frame(maxHeight: 350)
.background {
if isEnhanced {
RoundedRectangle(cornerRadius: 18, style: .continuous)
.fill(Color.accentColor.opacity(0.2))
} else {
RoundedRectangle(cornerRadius: 18, style: .continuous)
.fill(.thinMaterial)
.overlay(
RoundedRectangle(cornerRadius: 18, style: .continuous)
.strokeBorder(Color.primary.opacity(0.06), lineWidth: 0.5)
)
}
}
}
if !isEnhanced { Spacer(minLength: 60) }
}
}
}