mirror of
https://github.com/yattee/yattee.git
synced 2026-08-06 07:11:28 +00:00
Apply thumbnail fallback everywhere a single URL was rendered
The previous fix rebuilt the quality chain when converting persisted models back to videos, but many consumers discarded it again by rendering bestThumbnail (usually a maxresdefault.jpg that 404s for older videos) as a single URL with no fallback. Extract the retry logic from VideoThumbnailView into FallbackLazyImage and use it at every in-app site that can iterate: player thumbnails (mini bar, expanded sheet loaders, autoplay previews, tvOS audio-mode artwork - previously a silent black screen), video info card and tvOS header, and the tvOS playlist cover. Sites that fetch or send exactly one URL are rewritten to the always-available hqdefault variant via Thumbnail.reliableURL (exposed as Video.reliableThumbnailURL): Now Playing artwork, Top Shelf snapshots, remote control state, the frozen transition thumbnail, blurred info background, navigation covers, and playlist covers derived from a video's first thumbnail in Invidious/Yattee Server responses. Also invert RecentPlaylist's upgrade helper, which rewrote covers *to* maxresdefault, walk the quality chain when caching download thumbnails for offline artwork instead of giving up after one 404, and expand the remaining single-thumbnail Piped conversions into full chains.
This commit is contained in:
@@ -57,23 +57,16 @@ final class RecentPlaylist {
|
||||
title: playlist.title,
|
||||
authorName: playlist.authorName,
|
||||
videoCount: playlist.videoCount,
|
||||
thumbnailURLString: upgradedThumbnailURLString(playlist.thumbnailURL)
|
||||
thumbnailURLString: reliableThumbnailURLString(playlist.thumbnailURL)
|
||||
)
|
||||
}
|
||||
|
||||
/// Rewrites YouTube `/vi/ID/{default|mq|hq|sd}default.jpg` thumbnails to `maxresdefault.jpg`
|
||||
/// so recent playlist cards show a higher-quality image.
|
||||
static func upgradedThumbnailURLString(_ url: URL?) -> String? {
|
||||
/// Rewrites YouTube `/vi/ID/...` thumbnails to the always-available `hqdefault.jpg`
|
||||
/// variant: recent playlist cards render a single URL without fallback, and
|
||||
/// higher-quality variants (`maxresdefault`/`sddefault`) 404 for many older videos.
|
||||
static func reliableThumbnailURLString(_ url: URL?) -> String? {
|
||||
guard let url else { return nil }
|
||||
let path = url.path
|
||||
let upgradable = ["default.jpg", "mqdefault.jpg", "hqdefault.jpg", "sddefault.jpg"]
|
||||
guard path.range(of: #"/vi/[^/]+/"#, options: .regularExpression) != nil,
|
||||
let match = upgradable.first(where: { path.hasSuffix($0) }),
|
||||
var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
|
||||
return url.absoluteString
|
||||
}
|
||||
components.path = String(path.dropLast(match.count)) + "maxresdefault.jpg"
|
||||
return components.url?.absoluteString ?? url.absoluteString
|
||||
return (Thumbnail.reliableURL(for: url) ?? url).absoluteString
|
||||
}
|
||||
|
||||
private static func extractSourceInfo(from source: ContentSource) -> (String, String?) {
|
||||
|
||||
Reference in New Issue
Block a user