Fix thumbnail aspect ratio in video grid cells

Thumbnails were being stretched vertically due to incorrect aspect ratio handling. Fixed by:
- Using .scaledToFill() on thumbnails to fill the container width
- Constraining container to 16:9 aspect ratio with .fit mode
- Adding matching aspect ratio to placeholder to prevent layout shift during loading

This ensures thumbnails maintain proper proportions while filling the full cell width.
This commit is contained in:
Arkadiusz Fal
2025-11-19 22:37:05 +01:00
parent a55adb2e65
commit 42d53c30db
2 changed files with 13 additions and 11 deletions

View File

@@ -44,13 +44,13 @@ struct ThumbnailView: View {
var webImage: some View { var webImage: some View {
WebImage(url: url) WebImage(url: url)
.resizable()
.onFailure { _ in .onFailure { _ in
if let url { if let url {
thumbnails.insertUnloadable(url) thumbnails.insertUnloadable(url)
} }
} }
.placeholder { placeholder } .placeholder { placeholder }
.resizable()
} }
@ViewBuilder var asyncImageIfAvailable: some View { @ViewBuilder var asyncImageIfAvailable: some View {
@@ -76,6 +76,8 @@ struct ThumbnailView: View {
} }
var placeholder: some View { var placeholder: some View {
Rectangle().fill(Color("PlaceholderColor")) Rectangle()
.fill(Color("PlaceholderColor"))
.aspectRatio(Constants.aspectRatio16x9, contentMode: .fit)
} }
} }

View File

@@ -429,16 +429,14 @@ struct VideoCell: View {
} }
.lineLimit(1) .lineLimit(1)
} }
.aspectRatio(Constants.aspectRatio16x9, contentMode: .fit)
} }
private var thumbnailImage: some View { private var thumbnailImage: some View {
Group {
VideoCellThumbnail(video: video) VideoCellThumbnail(video: video)
#if os(tvOS) #if os(tvOS)
.frame(minHeight: 320) .frame(minHeight: 320)
#endif #endif
}
.mask(RoundedRectangle(cornerRadius: thumbnailRoundingCornerRadius)) .mask(RoundedRectangle(cornerRadius: thumbnailRoundingCornerRadius))
} }
@@ -477,11 +475,13 @@ struct VideoCellThumbnail: View {
private var thumbnails: ThumbnailsModel { .shared } private var thumbnails: ThumbnailsModel { .shared }
var body: some View { var body: some View {
let (url, quality) = thumbnails.best(video) let (url, _) = thumbnails.best(video)
let aspectRatio = (quality == .default || quality == .high) ? Constants.aspectRatio4x3 : Constants.aspectRatio16x9
ThumbnailView(url: url) ThumbnailView(url: url)
.aspectRatio(aspectRatio, contentMode: .fill) .scaledToFill()
.frame(maxWidth: .infinity)
.aspectRatio(Constants.aspectRatio16x9, contentMode: .fit)
.clipped()
} }
} }