@ -808,7 +808,8 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
// / U n f o r t u n a t e l y t h e U I T a b l e V i e w a l s o d o e s s o m e w e i r d t h i n g s w h e n u p d a t i n g ( w h e r e i t w o n ' t h a v e u p d a t e d i t ' s i n t e r n a l d a t a u n t i l
// / a f t e r i t p e r f o r m s t h e n e x t l a y o u t ) ; t h e b e l o w c o d e c h e c k s a c o n d i t i o n o n l a y o u t a n d i f i t p a s s e s i t c a l l s a c l o s u r e
if let itemChangeInfo : ItemChangeInfo = itemChangeInfo , itemChangeInfo . isInsertAtTop {
let oldCellHeight : CGFloat = self . tableView . rectForRow ( at : itemChangeInfo . oldVisibleIndexPath ) . height
let oldCellRect : CGRect = self . tableView . rectForRow ( at : itemChangeInfo . oldVisibleIndexPath )
let oldCellTopOffset : CGFloat = ( self . tableView . frame . minY - self . tableView . convert ( oldCellRect , to : self . tableView . superview ) . minY )
// T h e t h e u s e r t r i g g e r e d t h e ' s c r o l l T o T o p ' a n i m a t i o n ( b y t a p p i n g i n t h e n a v b a r ) t h e n w e
// n e e d t o s t o p t h e a n i m a t i o n b e f o r e a t t e m p t i n g t o l o c k t h e o f f s e t ( o t h e r w i s e t h i n g s b r e a k )
@ -828,27 +829,13 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
// l o a d e d w a s s m a l l e r t h a n 2 p a g e s ( t h i s w i l l p r e v e n t c a l c u l a t i n g t h e f r a m e s o f
// a l a r g e n u m b e r o f c e l l s w h e n g e t t i n g s e a r c h r e s u l t s w h i c h a r e v e r y f a r a w a y
// o n l y t o i n s t a n t l y s t a r t s c r o l l i n g m a k i n g t h e c a l c u l a t i o n r e d u n d a n t )
if ( abs ( itemChangeInfo . visibleIndexPath . row - itemChangeInfo . oldVisibleIndexPath . row ) <= ( ConversationViewModel . pageSize * 2 ) ) {
UIView . performWithoutAnimation {
let calculatedRowHeights : CGFloat = ( 0. . < itemChangeInfo . visibleIndexPath . row )
. reduce ( into : 0 ) { result , next in
result += ( self ? . tableView
. rectForRow (
at : IndexPath (
row : next ,
section : itemChangeInfo . visibleIndexPath . section
)
)
. height )
. defaulting ( to : 0 )
}
let newTargetHeight : CGFloat ? = self ? . tableView
. rectForRow ( at : itemChangeInfo . visibleIndexPath )
. height
let heightDiff : CGFloat = ( oldCellHeight - ( newTargetHeight ? ? oldCellHeight ) )
self ? . tableView . contentOffset . y += ( calculatedRowHeights - heightDiff )
}
UIView . performWithoutAnimation {
self ? . tableView . scrollToRow (
at : itemChangeInfo . visibleIndexPath ,
at : . top ,
animated : false
)
self ? . tableView . contentOffset . y += oldCellTopOffset
}
if let focusedInteractionId : Int64 = self ? . focusedInteractionId {
@ -1327,6 +1314,15 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
return
}
// N o t e : I n t h i s c a s e w e n e e d t o f o r c e a t a b l e V i e w l a y o u t t o e n s u r e u p d a t i n g t h e
// s c r o l l p o s i t i o n h a s t h e c o r r e c t o f f s e t ( o t h e r w i s e t h e r e a r e s o m e c a s e s w h e r e
// t h e s c r e e n w i l l j u m p u p - e g . w h e n s e n d i n g a r e p l y w h i l e t h e s o f t k e y b o a r d
// i s v i s i b l e )
UIView . performWithoutAnimation {
self . tableView . setNeedsLayout ( )
self . tableView . layoutIfNeeded ( )
}
let targetIndexPath : IndexPath = IndexPath (
row : ( self . viewModel . interactionData [ messagesSectionIndex ] . elements . count - 1 ) ,
section : messagesSectionIndex
@ -1337,7 +1333,6 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
animated : isAnimated
)
self . handleInitialOffsetBounceBug ( targetIndexPath : targetIndexPath , at : . bottom )
self . viewModel . markAsRead ( beforeInclusive : nil )
}
@ -1577,7 +1572,6 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
at : position ,
animated : ( self . didFinishInitialLayout && isAnimated )
)
self . handleInitialOffsetBounceBug ( targetIndexPath : targetIndexPath , at : position )
// I f w e h a v e n ' t f i n i s h e d t h e i n i t i a l l a y o u t t h e n w e w a n t t o d e l a y t h e h i g h l i g h t s l i g h t l y
// s o i t d o e s n ' t l o o k b u g g y w i t h t h e p u s h t r a n s i t i o n
@ -1604,7 +1598,6 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
}
self . tableView . scrollToRow ( at : targetIndexPath , at : position , animated : true )
self . handleInitialOffsetBounceBug ( targetIndexPath : targetIndexPath , at : position )
}
func highlightCellIfNeeded ( interactionId : Int64 ) {
@ -1620,37 +1613,4 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
. highlight ( )
}
}
private func handleInitialOffsetBounceBug ( targetIndexPath : IndexPath , at position : UITableView . ScrollPosition ) {
// / N o t e : T h i s c o d e i s a h a c k t o p r e v e n t a w e i r d ' b o u n c e ' b e h a v i o u r t h a t o c c u r s w h e n t r i g g e r i n g t h e i n i t i a l s c r o l l d u e
// / t o t h e U I T a b l e V i e w p r o p e r l y c a l c u l a t i n g i t ' s c e l l s i z e s ( i t s e e m s t o l a y o u t ~ 3 t i m e s e a c h w i t h s l i g h t l y d i f f e r e n t s i z e s )
if ! self . hasPerformedInitialScroll {
let initialUpdateTime : CFTimeInterval = CACurrentMediaTime ( )
var lastSize : CGSize = . zero
self . tableView . afterNextLayoutSubviews (
when : { [ weak self ] numSections , numRowInSections , updatedContentSize in
// I f t o o m u c h t i m e h a s p a s s e d o r t h e s e c t i o n / r o w c o u n t d o e s n ' t m a t c h t h e n
// j u s t s t o p t h e c a l l b a c k
guard
( CACurrentMediaTime ( ) - initialUpdateTime ) < 2 &&
lastSize != updatedContentSize &&
numSections > targetIndexPath . section &&
numRowInSections [ targetIndexPath . section ] > targetIndexPath . row
else { return true }
lastSize = updatedContentSize
self ? . tableView . scrollToRow (
at : targetIndexPath ,
at : position ,
animated : false
)
return false
} ,
then : { }
)
}
}
}