import MusicAssistantCore import SwiftUI struct ArabicLyricsReviewView: View { @Binding var project: SongProject private let processor = ArabicPronunciationProcessor() @State private var processedLyrics = "" @State private var processingNotes: [ArabicPronunciationProcessingNote] = [] var body: some View { VStack(alignment: .leading, spacing: 10) { HStack { Text("Arabic lyrics review") .font(.headline) Spacer() Button(action: refreshProcessedLyrics) { Label("Refresh processed lyrics", systemImage: "arrow.clockwise") .labelStyle(.iconOnly) } .buttonStyle(.borderless) .help("Refresh processed lyrics") } Text("Original lyrics") .font(.subheadline) .foregroundStyle(.secondary) TextEditor(text: .constant(project.lyrics.text)) .font(.body) .frame(minHeight: 96) .disabled(true) Text("Processed lyrics") .font(.subheadline) .foregroundStyle(.secondary) TextEditor(text: $processedLyrics) .font(.body) .frame(minHeight: 96) ForEach(Array(processingNotes.enumerated()), id: \.offset) { entry in Label(entry.element.title, systemImage: entry.element.systemImage) .font(.caption) .foregroundStyle(.secondary) } Button(action: applyProcessedLyrics) { Label("Use processed lyrics", systemImage: "checkmark.circle") } .disabled(!canApplyProcessedLyrics) } .onAppear(perform: refreshProcessedLyrics) } private var canApplyProcessedLyrics: Bool { let trimmedLyrics = processedLyrics.trimmingCharacters(in: .whitespacesAndNewlines) return !trimmedLyrics.isEmpty && processedLyrics != project.lyrics.text } private func refreshProcessedLyrics() { let result = processor.process( lyrics: project.lyrics.text, settings: project.arabicPronunciationSettings ) processedLyrics = result.text processingNotes = result.notes } private func applyProcessedLyrics() { project.applyReviewedArabicLyrics(processedLyrics) } } private extension ArabicPronunciationProcessingNote { var title: String { switch self { case .processingDisabled: return "Arabic processing is disabled" case .diacritizationPolicyUnspecified: return "Select a diacritics policy to continue" case .pronunciationTargetedDiacriticsNeedReview: return "Targeted diacritics need review" case .fullTashkeelNeedsReview: return "Full tashkeel needs review" case .tanweenAdditionNeedsReview: return "Tanween addition needs review" case let .preservedSpellingsProtected(count): return "Protected \(count) preserved spelling\(count == 1 ? "" : "s")" } } var systemImage: String { switch self { case .processingDisabled, .diacritizationPolicyUnspecified: return "info.circle" case .pronunciationTargetedDiacriticsNeedReview, .fullTashkeelNeedsReview, .tanweenAdditionNeedsReview: return "exclamationmark.triangle" case .preservedSpellingsProtected: return "checkmark.shield" } } }