quick fix

This commit is contained in:
Dallas Groot 2026-04-11 08:36:32 -07:00
parent d32d63a749
commit 92a5a54b8d
3 changed files with 58 additions and 0 deletions

View file

@ -538,6 +538,8 @@ class CompanionPushClient: ObservableObject {
// Notify ConflictManager to refresh use NotificationCenter to avoid
// a cross-module dependency between Foundation and SwiftUI layers.
NotificationCenter.default.post(name: .companionConflictsUpdated, object: nil, userInfo: msg.data)
case "tags_cleaned":
NotificationCenter.default.post(name: .companionTagsCleaned, object: nil, userInfo: msg.data)
case "profile":
if let path = msg.data?["path"] as? String,
let jsonData = try? JSONSerialization.data(withJSONObject: msg.data ?? [:]),
@ -595,6 +597,7 @@ extension Notification.Name {
static let companionArtistPhotoUpdated = Notification.Name("companionArtistPhotoUpdated")
static let companionLibraryChanged = Notification.Name("companionLibraryChanged")
static let companionConflictsUpdated = Notification.Name("companionConflictsUpdated")
static let companionTagsCleaned = Notification.Name("companionTagsCleaned")
}
// MARK: - Conflict Models

View file

@ -10,6 +10,8 @@ struct CompanionSettingsView: View {
@State private var analyzeMessage: String?
@State private var fixLibraryStatus: AnalyzeStatus = .idle
@State private var fixLibraryMessage: String?
@State private var cleanTagsStatus: AnalyzeStatus = .idle
@State private var cleanTagsMessage: String?
private let accentPink = Color(red: 1.0, green: 0.176, blue: 0.333)
@ -122,6 +124,26 @@ struct CompanionSettingsView: View {
}
}
Button(action: triggerCleanTags) {
HStack {
Image(systemName: "tag.slash")
.foregroundColor(cleanTagsStatus == .done ? .green : cleanTagsStatus == .failed ? .red : .orange)
.symbolEffect(.pulse, isActive: cleanTagsStatus == .analyzing)
VStack(alignment: .leading, spacing: 2) {
Text("Clean Picard Tags").foregroundColor(.white)
Text("Remove MusicBrainz IDs, AcoustID, and other Picard-only tags from every file.")
.font(.caption).foregroundColor(.gray)
}
}
}
.disabled(cleanTagsStatus == .analyzing)
if let msg = cleanTagsMessage {
Text(msg)
.font(.caption)
.foregroundColor(cleanTagsStatus == .done ? .green : cleanTagsStatus == .failed ? .red : .gray)
}
Button(action: triggerFixLibrary) {
HStack {
Image(systemName: "folder.badge.gearshape")
@ -142,6 +164,10 @@ struct CompanionSettingsView: View {
.foregroundColor(fixLibraryStatus == .done ? .green : fixLibraryStatus == .failed ? .red : .gray)
}
} header: { Text("Server Actions") }
.onReceive(NotificationCenter.default.publisher(for: .companionTagsCleaned)) { _ in
cleanTagsStatus = .done
cleanTagsMessage = "✓ Tag cleaning complete"
}
Section {
Button(action: { triggerPreAnalyze(force: false) }) {
@ -183,6 +209,33 @@ struct CompanionSettingsView: View {
.navigationBarTitleDisplayMode(.inline)
}
// MARK: - Clean Picard Tags
private func triggerCleanTags() {
cleanTagsStatus = .analyzing
cleanTagsMessage = "Cleaning tags on server… this may take a minute."
Task {
do {
guard let base = CompanionSettings.shared.baseURL else { return }
var req = URLRequest(url: base.appendingPathComponent("library/clean-tags"))
req.httpMethod = "POST"
req.timeoutInterval = 15
let (data, _) = try await URLSession.shared.data(for: req)
let msg = (try? JSONDecoder().decode([String: String].self, from: data))?["message"] ?? "Started"
await MainActor.run {
cleanTagsStatus = .analyzing
cleanTagsMessage = "\(msg)"
}
DebugLogger.shared.log("Clean Picard tags triggered", category: "Companion")
} catch {
await MainActor.run {
cleanTagsStatus = .failed
cleanTagsMessage = "\(error.localizedDescription)"
}
}
}
}
// MARK: - Trigger Server Scan
private func triggerScan() {

View file

@ -1019,6 +1019,7 @@ extension LibraryConflict {
case "orphaned_tracks": return "link.badge.plus"
case "duplicate_track": return "music.note.list"
case "stale_companion_paths": return "externaldrive.badge.xmark"
case "album_reassigned": return "arrow.triangle.2.circlepath.circle.fill"
default: return "exclamationmark.circle"
}
}
@ -1266,6 +1267,7 @@ struct LibraryConflictsView: View {
case "fix_picard_tags": return "Fix Tags"
case "fix_stale_paths": return "Rescan Library"
case "fix_orphaned_tracks": return "Trigger Rescan"
case "fix_album_reassigned": return "Reapply Tags"
default: return "Fix"
}
}