Commit 2da95eba44

2da95eba44fa770ba7df90ba427a75bcd66872a4

parent: 368c59e3f8

Unsigned

cmc <hello@cleberg.net> · 2026-07-16 03:08 UTC

fix: render patchsets on a plain list

Collapsing patches shrank the layout loop from 3674pt/1647pt to 718pt/600pt but
did not end it. The oscillating item is section 1 item 0 — the cover letter, not
a patch — so size alone was not the cause.

The log shows the cell laid out at width 390.0 while the content reports its
preferred size at 390.333. That is inset grouped's 20pt insets landing on a
fractional width: the Text reflows to a different height than the cell was sized
for, each size triggers the other, and it never settles.

ThreadDetailView renders the same bodies through the same DiffView with the same
modifiers and does not loop. The difference is .listStyle(.plain), which this
view never set and so inherited inset grouped.

Layout: unified · split

Hutch/Views/Patchsets/PatchsetDetailView.swift +6
@@ -49,6 +49,12 @@ struct PatchsetDetailView: View {
4949 patchesSection(patchset)
5050 }
5151 .themedList()
52 // Inset grouped lays cells out at a rounded width while the content
53 // measures itself at the unrounded one, so a long Text reflows to a
54 // different height than the cell was sized for and the two chase each
55 // other into a layout loop. ThreadDetailView renders the same bodies
56 // through the same DiffView on a plain list without that fight.
57 .listStyle(.plain)
5258 .refreshable { await viewModel.loadPatchset() }
5359 .overlay {
5460 if viewModel.isUpdatingStatus {