diff --git a/Sources/MusicAssistantApp/Presentation/ArabicPronunciationSettingsView.swift b/Sources/MusicAssistantApp/Presentation/ArabicPronunciationSettingsView.swift new file mode 100644 index 0000000..c15a452 --- /dev/null +++ b/Sources/MusicAssistantApp/Presentation/ArabicPronunciationSettingsView.swift @@ -0,0 +1,91 @@ +import MusicAssistantCore +import SwiftUI + +struct ArabicPronunciationSettingsView: View { + @Binding var settings: ArabicPronunciationSettings + + @State private var newPreservedSpelling = "" + + var body: some View { + Toggle("Enable Arabic pronunciation processing", isOn: $settings.isEnabled) + + Picker("Diacritics", selection: $settings.diacritizationPolicy) { + Text("Unspecified").tag(ArabicDiacritizationPolicy.unspecified) + Text("Pronunciation targeted").tag(ArabicDiacritizationPolicy.pronunciationTargeted) + Text("Full tashkeel").tag(ArabicDiacritizationPolicy.fullTashkeel) + } + .disabled(!settings.isEnabled) + + Picker("Tanween", selection: $settings.tanweenPolicy) { + Text("Unspecified").tag(ArabicTanweenPolicy.unspecified) + Text("Preserve user input").tag(ArabicTanweenPolicy.preserveUserInput) + Text("Add when pronunciation needs it").tag(ArabicTanweenPolicy.addWhenPronunciationRequires) + Text("Remove when unwanted").tag(ArabicTanweenPolicy.removeWhenUnwanted) + } + .disabled(!settings.isEnabled) + + TextField("Pronunciation notes", text: userNotesBinding, axis: .vertical) + .lineLimit(2...4) + .disabled(!settings.isEnabled) + + if settings.preservedSpellings.isEmpty { + Text("No preserved spellings") + .foregroundStyle(.secondary) + } else { + ForEach(settings.preservedSpellings.indices, id: \.self) { index in + HStack { + Text(settings.preservedSpellings[index]) + .lineLimit(1) + + Spacer() + + Button { + settings.preservedSpellings.remove(at: index) + } label: { + Label("Remove preserved spelling", systemImage: "minus.circle") + .labelStyle(.iconOnly) + } + .buttonStyle(.borderless) + .help("Remove preserved spelling") + } + } + } + + HStack { + TextField("Preserve spelling", text: $newPreservedSpelling) + .onSubmit(addPreservedSpelling) + + Button(action: addPreservedSpelling) { + Label("Add preserved spelling", systemImage: "plus.circle.fill") + .labelStyle(.iconOnly) + } + .buttonStyle(.borderless) + .disabled(trimmedNewPreservedSpelling.isEmpty) + .help("Add preserved spelling") + } + .disabled(!settings.isEnabled) + } + + private var userNotesBinding: Binding { + Binding { + settings.userNotes ?? "" + } set: { newValue in + let trimmedValue = newValue.trimmingCharacters(in: .whitespacesAndNewlines) + settings.userNotes = trimmedValue.isEmpty ? nil : trimmedValue + } + } + + private var trimmedNewPreservedSpelling: String { + newPreservedSpelling.trimmingCharacters(in: .whitespacesAndNewlines) + } + + private func addPreservedSpelling() { + let spelling = trimmedNewPreservedSpelling + guard !spelling.isEmpty, !settings.preservedSpellings.contains(spelling) else { + return + } + + settings.preservedSpellings.append(spelling) + newPreservedSpelling = "" + } +} diff --git a/Sources/MusicAssistantApp/Presentation/ProjectInspectorView.swift b/Sources/MusicAssistantApp/Presentation/ProjectInspectorView.swift index df83c5a..cc025c9 100644 --- a/Sources/MusicAssistantApp/Presentation/ProjectInspectorView.swift +++ b/Sources/MusicAssistantApp/Presentation/ProjectInspectorView.swift @@ -103,6 +103,12 @@ struct ProjectInspectorView: View { ) } + Section("Arabic Pronunciation") { + ArabicPronunciationSettingsView( + settings: $project.arabicPronunciationSettings + ) + } + Section("Song Structure") { SongStructureEditorView(project: $project) } diff --git a/docs/TASKS.md b/docs/TASKS.md index 958d776..3e0b568 100644 --- a/docs/TASKS.md +++ b/docs/TASKS.md @@ -67,7 +67,7 @@ requirement is missing and blocks implementation, record it in ## Phase 5 --- Arabic Lyrics Processing -- [ ] Add Arabic-specific settings UI. +- [x] Add Arabic-specific settings UI. - [ ] Support diacritics/harakat/tanween processing. - [ ] Preserve intentional spelling/dialect choices where possible. - [ ] Allow user to compare/edit processed Arabic before Suno handoff.