From 1397a2fee6808974376b41cbc4b4893a787a2fa1 Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Sat, 22 Nov 2025 23:06:56 +0100 Subject: [PATCH] Fix tvOS captions list always showing as unavailable in MPV The captions context menu on tvOS was always empty because it relied on an .onAppear callback that was never triggered. The captionsPicker view with .onAppear was only rendered on iOS/macOS, not tvOS. Changes: - Access captions directly from player.currentVideo?.captions instead of using a state variable populated via .onAppear - Fix label logic to show "Disabled" when captions are available but not selected, and "Not available" only when video has no captions - Remove unused state variables and helper functions --- Shared/Player/Controls/ControlsOverlay.swift | 37 +++----------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/Shared/Player/Controls/ControlsOverlay.swift b/Shared/Player/Controls/ControlsOverlay.swift index fc8399c5..728b22b0 100644 --- a/Shared/Player/Controls/ControlsOverlay.swift +++ b/Shared/Player/Controls/ControlsOverlay.swift @@ -5,8 +5,6 @@ struct ControlsOverlay: View { @ObservedObject private var player = PlayerModel.shared private var model = PlayerControlsModel.shared - @State private var availableCaptions: [Captions] = [] - @State private var isLoadingCaptions = true @State private var contentSize: CGSize = .zero @Default(.showMPVPlaybackStats) private var showMPVPlaybackStats @@ -378,11 +376,11 @@ struct ControlsOverlay: View { Text("\(language.description.capitalized) (\(language.rawValue))") .foregroundColor(.accentColor) } else { - if captionsBinding.wrappedValue == nil { - Text("Not available") - } else { + if player.currentVideo?.captions.isEmpty == false { Text("Disabled") .foregroundColor(.accentColor) + } else { + Text("Not available") } } } @@ -391,7 +389,7 @@ struct ControlsOverlay: View { .contextMenu { Button("Disabled") { captionsBinding.wrappedValue = nil } - ForEach(availableCaptions) { caption in + ForEach(player.currentVideo?.captions ?? []) { caption in Button(caption.description) { captionsBinding.wrappedValue = caption } } Button("Cancel", role: .cancel) {} @@ -400,7 +398,7 @@ struct ControlsOverlay: View { } @ViewBuilder private var captionsPicker: some View { - let captions = availableCaptions + let captions = player.currentVideo?.captions ?? [] Picker("Captions", selection: captionsBinding) { if captions.isEmpty { Text("Not available").tag(Captions?.none) @@ -412,31 +410,6 @@ struct ControlsOverlay: View { } } .disabled(captions.isEmpty) - .onAppear { - loadCaptions() - } - } - - private func loadCaptions() { - isLoadingCaptions = true - - // Fetch captions asynchronously - Task { - let fetchedCaptions = await fetchCaptions() - await MainActor.run { - // Update state on the main thread - self.availableCaptions = fetchedCaptions - self.isLoadingCaptions = false - } - } - } - - private func fetchCaptions() async -> [Captions] { - // Access currentVideo from the main actor context - await MainActor.run { - // Safely access the main actor-isolated currentVideo property - player.currentVideo?.captions ?? [] - } } private var captionsBinding: Binding {