109 lines
3.6 KiB
Swift
109 lines
3.6 KiB
Swift
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"
|
|
}
|
|
}
|
|
}
|