From 270e5ffdd3a439c71367e59aa444810ffd1f6b1d Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Sun, 18 Oct 2026 09:04:48 +0200 Subject: [PATCH] Offer a delayed Cancel while a tvOS channel loads, and fill the blank state Without a cached header the channel showed only a spinner, and when the channel request failed while the videos request succeeded (no cache to build the channel from) it rendered nothing at all; both left the tvOS remote with nothing to focus. Cancel stops at the error view and its Retry, since a sidebar channel is a tab root that cannot be popped; the blank state now shows the load error with Retry on every platform. --- Yattee/Localizable.xcstrings | 11 +++++++++++ Yattee/Views/Channel/ChannelView.swift | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/Yattee/Localizable.xcstrings b/Yattee/Localizable.xcstrings index 10b48f8e..bfc856c1 100644 --- a/Yattee/Localizable.xcstrings +++ b/Yattee/Localizable.xcstrings @@ -1745,6 +1745,17 @@ } } }, + "common.loadingStopped" : { + "comment" : "Shown in place of content after the user cancels a slow load on tvOS", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Loading was stopped." + } + } + } + }, "common.loadMore" : { "localizations" : { "en" : { diff --git a/Yattee/Views/Channel/ChannelView.swift b/Yattee/Views/Channel/ChannelView.swift index a76f3d44..eba8b6a7 100644 --- a/Yattee/Views/Channel/ChannelView.swift +++ b/Yattee/Views/Channel/ChannelView.swift @@ -189,9 +189,21 @@ struct ChannelView: View { loadingContent(cachedHeader) } else if isLoading { ProgressView() + #if os(tvOS) + // As a sidebar channel this is a tab root that cannot + // be popped, so Cancel lands on the error and its Retry. + .tvStalledLoadCancel { + isLoading = false + errorMessage = String(localized: "common.loadingStopped") + } + #endif .frame(maxWidth: .infinity, maxHeight: .infinity) } else if let error = errorMessage { errorView(error) + } else { + // The channel request failed while the videos one did not, + // with no cached header to build the channel from. + errorView(String(localized: "channelView.loadError")) } } }