From bef6a9dc2fc6a94b7da083f08d045e7e1c7edab7 Mon Sep 17 00:00:00 2001 From: Ilyas Hallak Date: Fri, 10 Oct 2025 20:27:17 +0200 Subject: [PATCH] fix: Use total content height for read progress calculation Added ContentHeightPreferenceKey to track the total ScrollView content height. The bug: Progress was calculated using only webViewHeight - containerHeight, which ignores the header, title, and other content above the webview. The fix: Use total content height (header + title + webview + archive section) instead of just webViewHeight for accurate progress calculation. Changes: - Added ContentHeightPreferenceKey preference key - Added contentHeight state variable - Added background GeometryReader to VStack to measure total content height - Changed progress calculation: contentHeight - containerHeight (not webViewHeight) Applied to both BookmarkDetailLegacyView and BookmarkDetailView2. --- .../BookmarkDetailLegacyView.swift | 22 ++++++++++++++++++- .../BookmarkDetail/BookmarkDetailView2.swift | 14 +++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/readeck/UI/BookmarkDetail/BookmarkDetailLegacyView.swift b/readeck/UI/BookmarkDetail/BookmarkDetailLegacyView.swift index bd03913..92736b3 100644 --- a/readeck/UI/BookmarkDetail/BookmarkDetailLegacyView.swift +++ b/readeck/UI/BookmarkDetail/BookmarkDetailLegacyView.swift @@ -9,6 +9,14 @@ struct ScrollOffsetPreferenceKey: PreferenceKey { } } +// PreferenceKey for content height tracking +struct ContentHeightPreferenceKey: PreferenceKey { + static var defaultValue: CGFloat = 0 + static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { + value = nextValue() + } +} + struct BookmarkDetailLegacyView: View { let bookmarkId: String @Binding var useNativeWebView: Bool @@ -17,6 +25,7 @@ struct BookmarkDetailLegacyView: View { @State private var viewModel: BookmarkDetailViewModel @State private var webViewHeight: CGFloat = 300 + @State private var contentHeight: CGFloat = 0 @State private var showingFontSettings = false @State private var showingLabelsSheet = false @State private var readingProgress: Double = 0.0 @@ -113,16 +122,27 @@ struct BookmarkDetailLegacyView: View { .frame(maxWidth: .infinity) } } + .background( + GeometryReader { contentGeo in + Color.clear.preference( + key: ContentHeightPreferenceKey.self, + value: contentGeo.size.height + ) + } + ) } .coordinateSpace(name: "scrollView") .clipped() .ignoresSafeArea(edges: .top) .scrollPosition($scrollPosition) + .onPreferenceChange(ContentHeightPreferenceKey.self) { height in + contentHeight = height + } .onPreferenceChange(ScrollOffsetPreferenceKey.self) { offset in // Calculate progress from scroll offset let scrollOffset = -offset.y // Negative because scroll goes down let containerHeight = geometry.size.height - let maxOffset = webViewHeight - containerHeight + let maxOffset = contentHeight - containerHeight guard maxOffset > 0 else { return } diff --git a/readeck/UI/BookmarkDetail/BookmarkDetailView2.swift b/readeck/UI/BookmarkDetail/BookmarkDetailView2.swift index 4f1117a..19b4483 100644 --- a/readeck/UI/BookmarkDetail/BookmarkDetailView2.swift +++ b/readeck/UI/BookmarkDetail/BookmarkDetailView2.swift @@ -10,6 +10,7 @@ struct BookmarkDetailView2: View { @State private var viewModel: BookmarkDetailViewModel @State private var webViewHeight: CGFloat = 300 + @State private var contentHeight: CGFloat = 0 @State private var showingFontSettings = false @State private var showingLabelsSheet = false @State private var readingProgress: Double = 0.0 @@ -120,16 +121,27 @@ struct BookmarkDetailView2: View { .frame(maxWidth: .infinity) } } + .background( + GeometryReader { contentGeo in + Color.clear.preference( + key: ContentHeightPreferenceKey.self, + value: contentGeo.size.height + ) + } + ) } .coordinateSpace(name: "scrollView") .clipped() .ignoresSafeArea(edges: .top) .scrollPosition($scrollPosition) + .onPreferenceChange(ContentHeightPreferenceKey.self) { height in + contentHeight = height + } .onPreferenceChange(ScrollOffsetPreferenceKey.self) { offset in // Calculate progress from scroll offset let scrollOffset = -offset.y let containerHeight = geometry.size.height - let maxOffset = webViewHeight - containerHeight + let maxOffset = contentHeight - containerHeight guard maxOffset > 0 else { return }