From 0df45de2b6c4c96ad1ff7388e9292772272285d6 Mon Sep 17 00:00:00 2001 From: Admin Date: Sun, 8 Mar 2026 13:34:33 +0500 Subject: [PATCH] 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. --- .../LibNovel/Views/Player/PlayerViews.swift | 100 +++++++++--------- 1 file changed, 48 insertions(+), 52 deletions(-) diff --git a/ios/LibNovel/LibNovel/Views/Player/PlayerViews.swift b/ios/LibNovel/LibNovel/Views/Player/PlayerViews.swift index 015d5a2..2a3062c 100644 --- a/ios/LibNovel/LibNovel/Views/Player/PlayerViews.swift +++ b/ios/LibNovel/LibNovel/Views/Player/PlayerViews.swift @@ -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 {