fix: scroll mark-as-read — delta filter and threshold tuned from logs
EVIDENCE (from xcode.txt): - down=false ALWAYS: per-entry deltas are ~1-2pt per callback, but filter required >2pt. Every delta was rejected. - cumDown stuck at 129: threshold was max(100, 956*0.2) = 191. With most deltas rejected, cumulative barely grew. FIXES: 1. Delta filter: >2pt → >0.5pt for direction detection. Cumulative accumulation accepts any delta >0 (no filter). Per-entry callbacks deliver small deltas — filtering at 2pt discarded virtually all genuine scroll events. 2. Threshold: removed 20% viewport scaling, fixed at 100pt. The scaling made sense for a global offset tracker (large deltas), not per-entry tracking (small deltas). Removed debug logging. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,8 +15,9 @@ struct EntryListView: View {
|
||||
// Safe because this view only appears on iPhone in portrait/landscape.
|
||||
private var viewportHeight: CGFloat { UIScreen.main.bounds.height }
|
||||
|
||||
// Dynamic threshold: max(100pt, 20% of viewport)
|
||||
private var activationThreshold: CGFloat { max(100, viewportHeight * 0.2) }
|
||||
// Fixed threshold — per-entry deltas are small (~1-2pt each),
|
||||
// so 100pt accumulates after scrolling roughly one screenful.
|
||||
private let activationThreshold: CGFloat = 100
|
||||
|
||||
var body: some View {
|
||||
if vm.isLoading && vm.entries.isEmpty {
|
||||
@@ -73,8 +74,10 @@ struct EntryListView: View {
|
||||
let isScrollingDown: Bool
|
||||
if let prev = prevMinY {
|
||||
let delta = prev - newMinY // positive = scrolling down
|
||||
isScrollingDown = delta > 2
|
||||
if isScrollingDown {
|
||||
// Per-entry deltas are small (~1-2pt per callback).
|
||||
// Accept anything > 0.5 as genuine downward scroll.
|
||||
isScrollingDown = delta > 0.5
|
||||
if delta > 0 {
|
||||
cumulativeDown += delta
|
||||
if cumulativeDown > activationThreshold {
|
||||
trackingActive = true
|
||||
@@ -96,17 +99,12 @@ struct EntryListView: View {
|
||||
}
|
||||
|
||||
// --- Mark-as-read ---
|
||||
let debugThis = vm.entries.prefix(3).contains(where: { $0.id == entryId })
|
||||
if debugThis {
|
||||
print("[SCROLL] id=\(entryId) minY=\(Int(newMinY)) maxY=\(Int(frame.maxY)) down=\(isScrollingDown) active=\(trackingActive) cumDown=\(Int(cumulativeDown)) wasVis=\(wasVisible.contains(entryId)) visR=\(String(format:"%.2f",visibleRatio)) vpH=\(Int(viewportHeight)) read=\(entry.isRead) marked=\(markedByScroll.contains(entryId))")
|
||||
}
|
||||
guard trackingActive,
|
||||
isScrollingDown,
|
||||
!entry.isRead,
|
||||
!markedByScroll.contains(entryId),
|
||||
wasVisible.contains(entryId),
|
||||
frame.maxY < 0 else { return }
|
||||
if debugThis { print("[SCROLL-READ] ✅ id=\(entryId)") }
|
||||
|
||||
markedByScroll.insert(entryId)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user