Force uniform 1:1 square crop on all gallery cells

Replace ZStack-based cell with Color.clear.aspectRatio(1,.fit) + .overlay.
The overlay constrains all children (image, video badge, sync dot) to the
exact square frame, so scaledToFill cannot inflate the cell height in
LazyVGrid. Previously, the ZStack let the filled image push beyond the
aspectRatio constraint, causing inconsistent row heights.

Co-Authored-By: Kutesir <kutesir@provoc.ug>
Co-Authored-By: Sentry <sentry@provoc.ug>
This commit is contained in:
Robin Kutesa
2026-05-19 09:53:42 +03:00
parent 47867f2ef3
commit 0bcb8f849c

View File

@@ -260,21 +260,11 @@ struct GalleryCell: View {
@State private var taskID = UUID() @State private var taskID = UUID()
var body: some View { var body: some View {
ZStack { // Color.clear anchors the 1:1 square; .overlay constrains all children to that
cellBackground // exact frame so scaledToFill never inflates the cell height in LazyVGrid.
if item.mediaType == .video, image != nil { Color.clear
videoOverlay.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomLeading)
}
syncDot.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)
}
.aspectRatio(1, contentMode: .fit) .aspectRatio(1, contentMode: .fit)
.clipped() .overlay {
.id(taskID)
.task(id: taskID) { await loadThumbnail() }
}
@ViewBuilder
private var cellBackground: some View {
if let img = image { if let img = image {
Image(uiImage: img) Image(uiImage: img)
.resizable() .resizable()
@@ -286,6 +276,14 @@ struct GalleryCell: View {
.shimmer() .shimmer()
} }
} }
.overlay(alignment: .bottomLeading) {
if item.mediaType == .video, image != nil { videoOverlay }
}
.overlay(alignment: .bottomTrailing) { syncDot }
.clipped()
.id(taskID)
.task(id: taskID) { await loadThumbnail() }
}
private var videoOverlay: some View { private var videoOverlay: some View {
HStack(spacing: 3) { HStack(spacing: 3) {