From 80aa04f625ba44edb7bdf2fc14cc53d050bb2bdc Mon Sep 17 00:00:00 2001 From: Ultradesu Date: Tue, 9 Jun 2026 11:00:51 +0100 Subject: [PATCH] fix: enrich player track info from API + share button feedback PlayerTrackInfoView auto-fetches full release data when current track is missing audio/lastfm fields (e.g. after device transfer). Share button turns green with checkmark for 1.5s after copying URL. Co-Authored-By: Claude Sonnet 4.6 --- furumi_macos/ContentView.swift | 14 +++++++++++--- furumi_macos/TrackInfoView.swift | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/furumi_macos/ContentView.swift b/furumi_macos/ContentView.swift index fd51033..09d24a3 100644 --- a/furumi_macos/ContentView.swift +++ b/furumi_macos/ContentView.swift @@ -36,6 +36,7 @@ struct ContentView: View { @State private var showingQueue = false @State private var showingDevices = false @State private var remoteSeekOverride: Double? = nil // optimistic seek for client mode + @State private var shareCopied = false // ViewModels bound to session (optional) @State private var globalVM: GlobalArtistsViewModel? @@ -560,9 +561,11 @@ struct ContentView: View { .disabled(player.currentTrack == nil) Button(action: shareCurrentTrack) { - Image(systemName: "square.and.arrow.up").font(.system(size: 14)) + Image(systemName: shareCopied ? "checkmark" : "square.and.arrow.up") + .font(.system(size: 14)) } - .buttonStyle(.plain).foregroundColor(.secondary) + .buttonStyle(.plain) + .foregroundColor(shareCopied ? .green : .secondary) .disabled(player.currentTrack == nil) Button(action: { showingTrackInfo.toggle() }) { @@ -572,7 +575,7 @@ struct ContentView: View { .disabled(player.currentTrack == nil) .popover(isPresented: $showingTrackInfo, arrowEdge: .bottom) { if let track = player.currentTrack { - TrackInfoView(track: track) + PlayerTrackInfoView(track: track, service: authManager.catalogService) } } @@ -706,6 +709,11 @@ struct ContentView: View { let url = "\(baseUrl.trimmingCharacters(in: CharacterSet(charactersIn: "/")))/share/track/\(track.id)" NSPasteboard.general.clearContents() NSPasteboard.general.setString(url, forType: .string) + withAnimation(.easeIn(duration: 0.1)) { shareCopied = true } + Task { + try? await Task.sleep(nanoseconds: 1_500_000_000) + withAnimation(.easeOut(duration: 0.4)) { shareCopied = false } + } } } diff --git a/furumi_macos/TrackInfoView.swift b/furumi_macos/TrackInfoView.swift index 86d0050..22734cd 100644 --- a/furumi_macos/TrackInfoView.swift +++ b/furumi_macos/TrackInfoView.swift @@ -5,6 +5,24 @@ import SwiftUI +/// Wrapper used by the player bar — enriches track data from the API if fields are missing +struct PlayerTrackInfoView: View { + let track: TrackCard + let service: CatalogService? + + @State private var enriched: TrackCard? + + var body: some View { + TrackInfoView(track: enriched ?? track) + .task(id: track.id) { + guard track.audioFormat == nil, track.releaseId > 0, let service else { return } + guard let detail = try? await service.releaseDetail(id: track.releaseId), + let full = detail.tracks.first(where: { $0.id == track.id }) else { return } + enriched = full + } + } +} + struct TrackInfoView: View { let track: TrackCard