diff --git a/Yattee/Data/DataManager+Recents.swift b/Yattee/Data/DataManager+Recents.swift index 10b49e9a..254c04b4 100644 --- a/Yattee/Data/DataManager+Recents.swift +++ b/Yattee/Data/DataManager+Recents.swift @@ -338,7 +338,7 @@ extension DataManager { existing.title = playlist.title existing.authorName = playlist.authorName existing.videoCount = playlist.videoCount - existing.thumbnailURLString = playlist.thumbnailURL?.absoluteString + existing.thumbnailURLString = RecentPlaylist.upgradedThumbnailURLString(playlist.thumbnailURL) savedEntry = existing } else { // Create new entry diff --git a/Yattee/Data/RecentPlaylist.swift b/Yattee/Data/RecentPlaylist.swift index 856ca4aa..5e3635aa 100644 --- a/Yattee/Data/RecentPlaylist.swift +++ b/Yattee/Data/RecentPlaylist.swift @@ -57,10 +57,25 @@ final class RecentPlaylist { title: playlist.title, authorName: playlist.authorName, videoCount: playlist.videoCount, - thumbnailURLString: playlist.thumbnailURL?.absoluteString + thumbnailURLString: upgradedThumbnailURLString(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? { + 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 + } + private static func extractSourceInfo(from source: ContentSource) -> (String, String?) { switch source { case .global: