iOS: fix chapters list to open at current chapter without auto-scroll animation

Replace ScrollViewReader with scrollPosition to instantly show the current chapter without visible scrolling. This scales better for books with 1000+ chapters.
This commit is contained in:
Admin
2026-03-08 13:34:33 +05:00
parent 825fb04c0d
commit 0df45de2b6

View File

@@ -721,70 +721,66 @@ struct ChaptersListSheet: View {
let onChapterSelect: (Int) -> Void let onChapterSelect: (Int) -> Void
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@State private var scrollPosition: Int?
var body: some View { var body: some View {
NavigationStack { NavigationStack {
ScrollViewReader { proxy in List {
List { ForEach(chapters, id: \.number) { chapter in
ForEach(chapters, id: \.number) { chapter in Button {
Button { onChapterSelect(chapter.number)
onChapterSelect(chapter.number) } label: {
} label: { HStack(spacing: 12) {
HStack(spacing: 12) { // Chapter number badge
// Chapter number badge Text("\(chapter.number)")
Text("\(chapter.number)") .font(.caption.bold())
.font(.caption.bold()) .foregroundStyle(chapter.number == currentChapter ? .white : .secondary)
.foregroundStyle(chapter.number == currentChapter ? .white : .secondary) .frame(width: 44, height: 44)
.frame(width: 44, height: 44) .background(
.background( Circle()
Circle() .fill(chapter.number == currentChapter ? Color.amber : Color.gray.opacity(0.2))
.fill(chapter.number == currentChapter ? Color.amber : Color.gray.opacity(0.2)) )
)
// Chapter title // Chapter title
VStack(alignment: .leading, spacing: 4) { VStack(alignment: .leading, spacing: 4) {
Text(chapter.title.strippingTrailingDate()) Text(chapter.title.strippingTrailingDate())
.font(.subheadline.weight(chapter.number == currentChapter ? .semibold : .regular)) .font(.subheadline.weight(chapter.number == currentChapter ? .semibold : .regular))
.foregroundStyle(chapter.number == currentChapter ? .primary : .primary) .foregroundStyle(chapter.number == currentChapter ? .primary : .primary)
.lineLimit(2) .lineLimit(2)
if chapter.number == currentChapter {
Text("Now Playing")
.font(.caption2)
.foregroundStyle(.amber)
}
}
Spacer()
// Checkmark for current chapter
if chapter.number == currentChapter { if chapter.number == currentChapter {
Image(systemName: "checkmark") Text("Now Playing")
.font(.caption.bold()) .font(.caption2)
.foregroundStyle(.amber) .foregroundStyle(.amber)
} }
} }
.padding(.vertical, 8)
} Spacer()
.buttonStyle(.plain)
.listRowBackground( // Checkmark for current chapter
chapter.number == currentChapter if chapter.number == currentChapter {
? Color.amber.opacity(0.1) Image(systemName: "checkmark")
: Color.clear .font(.caption.bold())
) .foregroundStyle(.amber)
.id(chapter.number) }
}
}
.listStyle(.plain)
.onAppear {
// Scroll to current chapter on appear
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
withAnimation {
proxy.scrollTo(currentChapter, anchor: .center)
} }
.padding(.vertical, 8)
} }
.buttonStyle(.plain)
.listRowBackground(
chapter.number == currentChapter
? Color.amber.opacity(0.1)
: Color.clear
)
.id(chapter.number)
} }
} }
.listStyle(.plain)
.scrollPosition(id: $scrollPosition, anchor: .center)
.onAppear {
// Set initial scroll position without animation
scrollPosition = currentChapter
}
.navigationTitle("Chapters") .navigationTitle("Chapters")
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.toolbar { .toolbar {