Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion apps/iOS/Components/PerformerRecordingsSection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,16 @@ struct PerformerRecordingsSection: View {
controlsBar
.padding(.horizontal, ApproachNoteTheme.spacingXL)

LazyVStack(alignment: .leading, spacing: ApproachNoteTheme.spacingSM) {
// Eager VStack, not LazyVStack — same reason as the song-detail
// RecordingsSection. A lazy outer stack whose children each hold a
// horizontal ScrollView + LazyHStack makes SwiftUI's lazy-layout
// pass fail to settle on long lists: on iPad, Louis Armstrong
// (3231 recordings) pinned the main thread at 100% indefinitely
// inside LazyVStackLayout.finalPlacement ->
// LazyHStackLayout.initialPlacement. This stack holds one row per
// group (decade or song title), not one per recording, so building
// it eagerly is cheap.
VStack(alignment: .leading, spacing: ApproachNoteTheme.spacingSM) {
if !filteredRecordings.isEmpty {
ForEach(groupedRecordings, id: \.groupKey) { group in
groupAccordion(group: group)
Expand Down
12 changes: 11 additions & 1 deletion apps/iOS/Components/RecordingsSection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,17 @@ struct RecordingsSection: View {
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, ApproachNoteTheme.spacingXL)

LazyVStack(alignment: .leading, spacing: ApproachNoteTheme.spacingSM) {
// Deliberately an eager VStack, not a LazyVStack. Each child is a
// collapsed accordion header (a Button with two Texts) and, when
// open, a horizontal ScrollView + LazyHStack of cards. Nesting that
// inside a lazy stack makes SwiftUI's lazy-layout pass fail to reach
// a fixed point on long lists: on iPad, "All of Me" (701 shell rows)
// spun the main thread at 100% forever inside
// LazyVStackLayout.finalPlacement -> LazyHStackLayout.initialPlacement,
// so no touch was delivered and cover art never loaded. Making the
// outer stack eager settles it, and costs little — this stack holds
// one row per group, not one per recording.
VStack(alignment: .leading, spacing: ApproachNoteTheme.spacingSM) {
if !filteredRecordings.isEmpty {
ForEach(groupedRecordings, id: \.groupKey) { group in
groupAccordion(group: group)
Expand Down
Loading