Offer a delayed Cancel while a tvOS remote playlist loads

A remote playlist this account does not own showed only a spinner while
loading, with or without a cached header, so the tvOS remote had nothing
to focus. Cancel stops at the error view and its Retry, since a sidebar
playlist is a tab root that cannot be popped.
This commit is contained in:
Arkadiusz Fal
2026-10-18 19:51:09 +02:00
parent 270e5ffdd3
commit 88551a1366

View File

@@ -247,7 +247,7 @@ struct UnifiedPlaylistDetailView: View {
// Show header with cached data + spinner for video list
loadingContent(cachedHeader)
} else if case .remote = source, isLoading {
ProgressView()
loadingSpinner
.frame(maxWidth: .infinity, maxHeight: .infinity)
} else if let error = errorMessage {
errorView(error)
@@ -404,7 +404,7 @@ struct UnifiedPlaylistDetailView: View {
private var playlistBody: some View {
if videos.isEmpty {
if isLoading {
ProgressView()
loadingSpinner
.frame(maxWidth: .infinity)
.padding(.top, 40)
} else if let errorMessage {
@@ -420,6 +420,19 @@ struct UnifiedPlaylistDetailView: View {
}
}
/// On tvOS a remote playlist this account does not own has no other
/// focusable element while it loads, and as a sidebar playlist it is a tab
/// root that cannot be popped — so Cancel lands on the error and its Retry.
private var loadingSpinner: some View {
ProgressView()
#if os(tvOS)
.tvStalledLoadCancel {
isLoading = false
errorMessage = String(localized: "common.loadingStopped")
}
#endif
}
/// Shows cached header with a spinner below while loading full playlist data.
private func loadingContent(_ cached: CachedPlaylistHeader) -> some View {
ScrollView {
@@ -433,7 +446,7 @@ struct UnifiedPlaylistDetailView: View {
.padding(.horizontal)
// Centered spinner for content area
ProgressView()
loadingSpinner
.frame(maxWidth: .infinity)
.padding(.top, 40)
}