ENGINE (ScrollViewDriver.swift): - UIViewRepresentable placed inside ScrollView (zero size) - Finds parent UIScrollView via view hierarchy traversal - CADisplayLink at 60fps drives contentOffset.y smoothly - Speed: 1.0x = 60pt/sec, adjustable 0.25x–3.0x in 0.25 steps - User touch detection: intercepts UIScrollViewDelegate scrollViewWillBeginDragging → stops auto-scroll immediately - Stops at bottom (contentOffset >= maxOffset) - Forwards all delegate methods to SwiftUI's original delegate INTEGRATION (EntryListView): - Accepts @Binding isAutoScrolling + scrollSpeed - ScrollViewDriver placed as first child in ScrollView - Auto-scroll stops on: user touch, navigation back (onAppear), filter change, sub-tab change, reaching bottom CONTROLS (ReaderTabView — temporary, Phase 1): - Play/Stop button in toolbar (play.fill / stop.fill) - When playing: [-] speed [+] controls appear inline - Speed shown as "1.00x" with monospacedDigit MARK-AS-READ: - Auto-scroll drives real UIScrollView contentOffset - This moves LazyVStack rows, triggering their GeometryReader onChange callbacks — the existing mark-as-read system fires naturally with no special case or bypass needed Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
30 KiB
30 KiB