From dd6bbbe6915910e77f93c9306f0e2a5aee2e7e58 Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Sat, 17 Oct 2026 23:49:13 +0200 Subject: [PATCH] Offer a delayed Cancel while the tvOS video page loads The video page showed only a spinner until the video loaded, and rendered nothing at all in the frame before a videoID load started; either left the tvOS remote with nothing to focus. Both now show the spinner with the delayed Cancel, which pops the page. --- Yattee/Views/Video/VideoInfoView.swift | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Yattee/Views/Video/VideoInfoView.swift b/Yattee/Views/Video/VideoInfoView.swift index bff0b11b..5de4153b 100644 --- a/Yattee/Views/Video/VideoInfoView.swift +++ b/Yattee/Views/Video/VideoInfoView.swift @@ -21,6 +21,9 @@ struct VideoInfoView: View { @Environment(\.appEnvironment) private var appEnvironment @Environment(\.presentAppSheet) private var presentAppSheet @Environment(\.videoQueueContext) private var videoQueueContext + #if os(tvOS) + @Environment(\.dismiss) private var dismiss + #endif private let initMode: VideoInfoInitMode @@ -274,14 +277,17 @@ struct VideoInfoView: View { var body: some View { Group { if isLoadingInitialVideo || (displayedVideoIsPlaceholder && isLoadingVideoDetails) { - ProgressView() - .frame(maxWidth: .infinity, maxHeight: .infinity) + loadingView } else if let error = initialVideoLoadError { videoLoadErrorView(error) } else if let error = videoDetailsLoadError, displayedVideoIsPlaceholder { videoLoadErrorView(error) } else if displayedVideo != nil { videoContent + } else { + // The first frame in videoID mode, before the load has started: + // rendering nothing here would leave tvOS nothing to focus. + loadingView } } // Opaque background so the header gradient (which fades to windowBackgroundColor) @@ -858,6 +864,14 @@ struct VideoInfoView: View { } #endif + private var loadingView: some View { + ProgressView() + #if os(tvOS) + .tvStalledLoadCancel { dismiss() } + #endif + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + /// Error view shown when the video fails to load — either the initial /// fetch in videoID mode, or the details fetch for a placeholder video /// that has no metadata of its own to fall back on.