@@ -28,12 +28,11 @@ const DEBUG_SCROLL = false;
2828// The amount of extra scroll distance to allow prior to unfilling.
2929// See getExcessHeight.
3030const UNPAGINATION_PADDING = 6000 ;
31- // The number of milliseconds to debounce calls to onUnfillRequest, to prevent
32- // many scroll events causing many unfilling requests.
31+ // The number of milliseconds to debounce calls to onUnfillRequest,
32+ // to prevent many scroll events causing many unfilling requests.
3333const UNFILL_REQUEST_DEBOUNCE_MS = 200 ;
34- // _updateHeight makes the height a ceiled multiple of this so we
35- // don't have to update the height too often. It also allows the user
36- // to scroll past the pagination spinner a bit so they don't feel blocked so
34+ // updateHeight makes the height a ceiled multiple of this so we don't have to update the height too often.
35+ // It also allows the user to scroll past the pagination spinner a bit so they don't feel blocked so
3736// much while the content loads.
3837const PAGE_SIZE = 400 ;
3938
@@ -192,16 +191,14 @@ export default class ScrollPanel extends React.Component<IProps> {
192191 private preventShrinkingState : IPreventShrinkingState ;
193192 private unfillDebouncer : number ;
194193 private bottomGrowth : number ;
195- private pages : number ;
194+ private minListHeight : number ;
196195 private heightUpdateInProgress : boolean ;
197196 private divScroll : HTMLDivElement ;
198197
199198 constructor ( props , context ) {
200199 super ( props , context ) ;
201200
202- if ( this . props . resizeNotifier ) {
203- this . props . resizeNotifier . on ( "middlePanelResizedNoisy" , this . onResize ) ;
204- }
201+ this . props . resizeNotifier ?. on ( "middlePanelResizedNoisy" , this . onResize ) ;
205202
206203 this . resetScrollState ( ) ;
207204 }
@@ -227,9 +224,7 @@ export default class ScrollPanel extends React.Component<IProps> {
227224 // (We could use isMounted(), but facebook have deprecated that.)
228225 this . unmounted = true ;
229226
230- if ( this . props . resizeNotifier ) {
231- this . props . resizeNotifier . removeListener ( "middlePanelResizedNoisy" , this . onResize ) ;
232- }
227+ this . props . resizeNotifier ?. removeListener ( "middlePanelResizedNoisy" , this . onResize ) ;
233228 }
234229
235230 private onScroll = ev => {
@@ -541,7 +536,7 @@ export default class ScrollPanel extends React.Component<IProps> {
541536 stuckAtBottom : this . props . startAtBottom ,
542537 } ;
543538 this . bottomGrowth = 0 ;
544- this . pages = 0 ;
539+ this . minListHeight = 0 ;
545540 this . scrollTimeout = new Timer ( 100 ) ;
546541 this . heightUpdateInProgress = false ;
547542 } ;
@@ -734,9 +729,13 @@ export default class ScrollPanel extends React.Component<IProps> {
734729 const sn = this . getScrollNode ( ) ;
735730 const itemlist = this . itemlist . current ;
736731 const contentHeight = this . getMessagesHeight ( ) ;
737- const minHeight = sn . clientHeight ;
738- const height = Math . max ( minHeight , contentHeight ) ;
739- this . pages = Math . ceil ( height / PAGE_SIZE ) ;
732+ // Only round to the nearest page when we're basing the height off the content, not off the scrollNode height
733+ // otherwise it'll cause too much overscroll which makes it possible to entirely scroll content off-screen.
734+ if ( contentHeight < sn . clientHeight - PAGE_SIZE ) {
735+ this . minListHeight = sn . clientHeight ;
736+ } else {
737+ this . minListHeight = Math . ceil ( contentHeight / PAGE_SIZE ) * PAGE_SIZE ;
738+ }
740739 this . bottomGrowth = 0 ;
741740 const newHeight = `${ this . getListHeight ( ) } px` ;
742741
@@ -805,7 +804,7 @@ export default class ScrollPanel extends React.Component<IProps> {
805804 }
806805
807806 private getListHeight ( ) : number {
808- return this . bottomGrowth + ( this . pages * PAGE_SIZE ) ;
807+ return this . bottomGrowth + this . minListHeight ;
809808 }
810809
811810 private getMessagesHeight ( ) : number {
0 commit comments