@@ -4,6 +4,7 @@ import AutomatticTracks
44import WordPressReader
55import WordPressData
66import WordPressKit
7+ import Combine
78@preconcurrency import WebKit
89
910typealias RelatedPostsSection = ( postType: RemoteReaderSimplePost . PostType , posts: [ RemoteReaderSimplePost ] )
@@ -88,6 +89,8 @@ class ReaderDetailViewController: UIViewController, ReaderDetailView {
8889 private var lastContentOffset : CGFloat = 0
8990
9091 private var toolbarUpdateTimer : Timer ?
92+ private let toolbarHiddenDebouncer = PassthroughSubject < Bool , Never > ( )
93+ private var toolbarHiddenDebounceCancellable : AnyCancellable ?
9194
9295 /// Likes summary view
9396 private let likesSummary : ReaderDetailLikesView = . loadFromNib( )
@@ -184,6 +187,17 @@ class ReaderDetailViewController: UIViewController, ReaderDetailView {
184187
185188 // When comments are moderated or edited from the Comments view, update the Comments snippet here.
186189 NotificationCenter . default. addObserver ( self , selector: #selector( fetchComments) , name: . ReaderCommentModifiedNotification, object: nil )
190+
191+ // In the `scrollViewDidScroll` function, "toolbar hidden" is toggled repeatedly when the scroll view in the
192+ // middle of scrolling animation. This debouncer is introduced to avoid toggling
193+ // `navigationController.toolbarHidden`, which causes inifity loops.
194+ // Sentry issue: https://a8c.sentry.io/issues/6884521550
195+ toolbarHiddenDebounceCancellable = toolbarHiddenDebouncer
196+ . removeDuplicates ( )
197+ . debounce ( for: . milliseconds( 100 ) , scheduler: DispatchQueue . main)
198+ . sink { [ weak self] isHidden in
199+ self ? . setToolbarHidden ( isHidden, animated: true )
200+ }
187201 }
188202
189203 override func viewWillAppear( _ animated: Bool ) {
@@ -895,11 +909,11 @@ extension ReaderDetailViewController: UIScrollViewDelegate {
895909 // Using `safeAreaLayoutGuide.layoutFrame.height` because it doesn't
896910 // change when we extend the scroll view size by hiding the toolbar
897911 if ( currentOffset + view. safeAreaLayoutGuide. layoutFrame. height) > likesContainerView. frame. minY {
898- setToolbarHidden ( false , animated : true ) // Reached bottom (controls, comments, etc)
912+ toolbarHiddenDebouncer . send ( false ) // Reached bottom (controls, comments, etc)
899913 } else if currentOffset > lastContentOffset && currentOffset > 0 {
900- setToolbarHidden ( true , animated : true ) // Scrolling down
914+ toolbarHiddenDebouncer . send ( true ) // Scrolling down
901915 } else if currentOffset < lastContentOffset {
902- setToolbarHidden ( false , animated : true ) // Scrolling up
916+ toolbarHiddenDebouncer . send ( false ) // Scrolling up
903917 }
904918 lastContentOffset = currentOffset
905919 layoutHeroView ( )
0 commit comments