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:
@@ -721,70 +721,66 @@ struct ChaptersListSheet: View {
|
||||
let onChapterSelect: (Int) -> Void
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@State private var scrollPosition: Int?
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
ScrollViewReader { proxy in
|
||||
List {
|
||||
ForEach(chapters, id: \.number) { chapter in
|
||||
Button {
|
||||
onChapterSelect(chapter.number)
|
||||
} label: {
|
||||
HStack(spacing: 12) {
|
||||
// Chapter number badge
|
||||
Text("\(chapter.number)")
|
||||
.font(.caption.bold())
|
||||
.foregroundStyle(chapter.number == currentChapter ? .white : .secondary)
|
||||
.frame(width: 44, height: 44)
|
||||
.background(
|
||||
Circle()
|
||||
.fill(chapter.number == currentChapter ? Color.amber : Color.gray.opacity(0.2))
|
||||
)
|
||||
List {
|
||||
ForEach(chapters, id: \.number) { chapter in
|
||||
Button {
|
||||
onChapterSelect(chapter.number)
|
||||
} label: {
|
||||
HStack(spacing: 12) {
|
||||
// Chapter number badge
|
||||
Text("\(chapter.number)")
|
||||
.font(.caption.bold())
|
||||
.foregroundStyle(chapter.number == currentChapter ? .white : .secondary)
|
||||
.frame(width: 44, height: 44)
|
||||
.background(
|
||||
Circle()
|
||||
.fill(chapter.number == currentChapter ? Color.amber : Color.gray.opacity(0.2))
|
||||
)
|
||||
|
||||
// Chapter title
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text(chapter.title.strippingTrailingDate())
|
||||
.font(.subheadline.weight(chapter.number == currentChapter ? .semibold : .regular))
|
||||
.foregroundStyle(chapter.number == currentChapter ? .primary : .primary)
|
||||
.lineLimit(2)
|
||||
// Chapter title
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text(chapter.title.strippingTrailingDate())
|
||||
.font(.subheadline.weight(chapter.number == currentChapter ? .semibold : .regular))
|
||||
.foregroundStyle(chapter.number == currentChapter ? .primary : .primary)
|
||||
.lineLimit(2)
|
||||
|
||||
if chapter.number == currentChapter {
|
||||
Text("Now Playing")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.amber)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
// Checkmark for current chapter
|
||||
if chapter.number == currentChapter {
|
||||
Image(systemName: "checkmark")
|
||||
.font(.caption.bold())
|
||||
Text("Now Playing")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.amber)
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.listRowBackground(
|
||||
chapter.number == currentChapter
|
||||
? Color.amber.opacity(0.1)
|
||||
: Color.clear
|
||||
)
|
||||
.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)
|
||||
|
||||
Spacer()
|
||||
|
||||
// Checkmark for current chapter
|
||||
if chapter.number == currentChapter {
|
||||
Image(systemName: "checkmark")
|
||||
.font(.caption.bold())
|
||||
.foregroundStyle(.amber)
|
||||
}
|
||||
}
|
||||
.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")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
|
||||
Reference in New Issue
Block a user