Fall back to lower-quality thumbnails when higher-res variants 404

YouTube's CDN advertises maxres/sddefault thumbnails for every video but
only generates them for sufficiently high-res uploads, so older/low-res
videos return 404 for those qualities. The view picked the best quality
and showed a blank placeholder on failure with no fallback.

VideoThumbnailView now accepts an ordered fallback chain and advances to
the next candidate via NukeUI's onCompletion when a load fails, so a valid
thumbnail is always shown. DeArrowVideoThumbnail feeds it DeArrow branding
first, then the video's own thumbnails best-quality-first.
This commit is contained in:
Arkadiusz Fal
2026-05-11 18:56:06 +02:00
parent a734bb47f7
commit f74659e903
3 changed files with 51 additions and 4 deletions

View File

@@ -34,8 +34,15 @@ struct DeArrowVideoThumbnail: View {
appEnvironment?.deArrowBrandingProvider
}
private var displayThumbnailURL: URL? {
deArrowProvider?.thumbnailURL(for: video) ?? video.bestThumbnail?.url
/// Ordered thumbnail candidates: DeArrow branding (if any) first, then the
/// video's own thumbnails best-quality-first. The view falls back through
/// these so a thumbnail always shows even when higher-res variants 404.
private var thumbnailCandidates: (primary: URL?, fallbacks: [URL]) {
let videoURLs = video.thumbnailURLsByQuality
if let deArrowURL = deArrowProvider?.thumbnailURL(for: video) {
return (deArrowURL, videoURLs)
}
return (videoURLs.first, Array(videoURLs.dropFirst()))
}
#if !os(tvOS)
@@ -91,7 +98,8 @@ struct DeArrowVideoThumbnail: View {
var body: some View {
VideoThumbnailView(
url: displayThumbnailURL,
url: thumbnailCandidates.primary,
fallbackURLs: thumbnailCandidates.fallbacks,
cornerRadius: cornerRadius,
watchProgress: watchProgress,
duration: duration,