@@ -47,11 +47,14 @@ import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
4747import Spinner from "../views/elements/Spinner" ;
4848import EditorStateTransfer from '../../utils/EditorStateTransfer' ;
4949import ErrorDialog from '../views/dialogs/ErrorDialog' ;
50+ import { debounce } from 'lodash' ;
5051
5152const PAGINATE_SIZE = 20 ;
5253const INITIAL_SIZE = 20 ;
5354const READ_RECEIPT_INTERVAL_MS = 500 ;
5455
56+ const READ_MARKER_DEBOUNCE_MS = 100 ;
57+
5558const DEBUG = false ;
5659
5760let debuglog = function ( ...s : any [ ] ) { } ;
@@ -475,22 +478,35 @@ class TimelinePanel extends React.Component<IProps, IState> {
475478 }
476479
477480 if ( this . props . manageReadMarkers ) {
478- const rmPosition = this . getReadMarkerPosition ( ) ;
479- // we hide the read marker when it first comes onto the screen, but if
480- // it goes back off the top of the screen (presumably because the user
481- // clicks on the 'jump to bottom' button), we need to re-enable it.
482- if ( rmPosition < 0 ) {
483- this . setState ( { readMarkerVisible : true } ) ;
484- }
485-
486- // if read marker position goes between 0 and -1/1,
487- // (and user is active), switch timeout
488- const timeout = this . readMarkerTimeout ( rmPosition ) ;
489- // NO-OP when timeout already has set to the given value
490- this . readMarkerActivityTimer . changeTimeout ( timeout ) ;
481+ this . doManageReadMarkers ( ) ;
491482 }
492483 } ;
493484
485+ /*
486+ * Debounced function to manage read markers because we don't need to
487+ * do this on every tiny scroll update. It also sets state which causes
488+ * a component update, which can in turn reset the scroll position, so
489+ * it's important we allow the browser to scroll a bit before running this
490+ * (hence trailing edge only and debounce rather than throttle because
491+ * we really only need to update this once the user has finished scrolling,
492+ * not periodically while they scroll).
493+ */
494+ private doManageReadMarkers = debounce ( ( ) => {
495+ const rmPosition = this . getReadMarkerPosition ( ) ;
496+ // we hide the read marker when it first comes onto the screen, but if
497+ // it goes back off the top of the screen (presumably because the user
498+ // clicks on the 'jump to bottom' button), we need to re-enable it.
499+ if ( rmPosition < 0 ) {
500+ this . setState ( { readMarkerVisible : true } ) ;
501+ }
502+
503+ // if read marker position goes between 0 and -1/1,
504+ // (and user is active), switch timeout
505+ const timeout = this . readMarkerTimeout ( rmPosition ) ;
506+ // NO-OP when timeout already has set to the given value
507+ this . readMarkerActivityTimer . changeTimeout ( timeout ) ;
508+ } , READ_MARKER_DEBOUNCE_MS , { leading : false , trailing : true } ) ;
509+
494510 private onAction = ( payload : ActionPayload ) : void => {
495511 switch ( payload . action ) {
496512 case "ignore_state_changed" :
0 commit comments