Fix browser glitch caused by two overlapping scroll animations in web UI (#31960)
This commit is contained in:
		
							parent
							
								
									efdc17513d
								
							
						
					
					
						commit
						ef4d6ab988
					
				| @ -4,8 +4,6 @@ import { Children, cloneElement, useCallback } from 'react'; | |||||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||||
| import ImmutablePureComponent from 'react-immutable-pure-component'; | import ImmutablePureComponent from 'react-immutable-pure-component'; | ||||||
| 
 | 
 | ||||||
| import { supportsPassiveEvents } from 'detect-passive-events'; |  | ||||||
| 
 |  | ||||||
| import { scrollRight } from '../../../scroll'; | import { scrollRight } from '../../../scroll'; | ||||||
| import BundleContainer from '../containers/bundle_container'; | import BundleContainer from '../containers/bundle_container'; | ||||||
| import { | import { | ||||||
| @ -71,10 +69,6 @@ export default class ColumnsArea extends ImmutablePureComponent { | |||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount() { |   componentDidMount() { | ||||||
|     if (!this.props.singleColumn) { |  | ||||||
|       this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (this.mediaQuery) { |     if (this.mediaQuery) { | ||||||
|       if (this.mediaQuery.addEventListener) { |       if (this.mediaQuery.addEventListener) { | ||||||
|         this.mediaQuery.addEventListener('change', this.handleLayoutChange); |         this.mediaQuery.addEventListener('change', this.handleLayoutChange); | ||||||
| @ -87,23 +81,7 @@ export default class ColumnsArea extends ImmutablePureComponent { | |||||||
|     this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl'); |     this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl'); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   UNSAFE_componentWillUpdate(nextProps) { |  | ||||||
|     if (this.props.singleColumn !== nextProps.singleColumn && nextProps.singleColumn) { |  | ||||||
|       this.node.removeEventListener('wheel', this.handleWheel); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   componentDidUpdate(prevProps) { |  | ||||||
|     if (this.props.singleColumn !== prevProps.singleColumn && !this.props.singleColumn) { |  | ||||||
|       this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   componentWillUnmount () { |   componentWillUnmount () { | ||||||
|     if (!this.props.singleColumn) { |  | ||||||
|       this.node.removeEventListener('wheel', this.handleWheel); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (this.mediaQuery) { |     if (this.mediaQuery) { | ||||||
|       if (this.mediaQuery.removeEventListener) { |       if (this.mediaQuery.removeEventListener) { | ||||||
|         this.mediaQuery.removeEventListener('change', this.handleLayoutChange); |         this.mediaQuery.removeEventListener('change', this.handleLayoutChange); | ||||||
| @ -116,7 +94,7 @@ export default class ColumnsArea extends ImmutablePureComponent { | |||||||
|   handleChildrenContentChange() { |   handleChildrenContentChange() { | ||||||
|     if (!this.props.singleColumn) { |     if (!this.props.singleColumn) { | ||||||
|       const modifier = this.isRtlLayout ? -1 : 1; |       const modifier = this.isRtlLayout ? -1 : 1; | ||||||
|       this._interruptScrollAnimation = scrollRight(this.node, (this.node.scrollWidth - window.innerWidth) * modifier); |       scrollRight(this.node, (this.node.scrollWidth - window.innerWidth) * modifier); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -124,14 +102,6 @@ export default class ColumnsArea extends ImmutablePureComponent { | |||||||
|     this.setState({ renderComposePanel: !e.matches }); |     this.setState({ renderComposePanel: !e.matches }); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   handleWheel = () => { |  | ||||||
|     if (typeof this._interruptScrollAnimation !== 'function') { |  | ||||||
|       return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     this._interruptScrollAnimation(); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   setRef = (node) => { |   setRef = (node) => { | ||||||
|     this.node = node; |     this.node = node; | ||||||
|   }; |   }; | ||||||
|  | |||||||
| @ -38,13 +38,20 @@ const scroll = ( | |||||||
| const isScrollBehaviorSupported = | const isScrollBehaviorSupported = | ||||||
|   'scrollBehavior' in document.documentElement.style; |   'scrollBehavior' in document.documentElement.style; | ||||||
| 
 | 
 | ||||||
| export const scrollRight = (node: Element, position: number) => { | export const scrollRight = (node: Element, position: number) => | ||||||
|   if (isScrollBehaviorSupported) |   requestIdleCallback(() => { | ||||||
|     node.scrollTo({ left: position, behavior: 'smooth' }); |     if (isScrollBehaviorSupported) { | ||||||
|   else scroll(node, 'scrollLeft', position); |       node.scrollTo({ left: position, behavior: 'smooth' }); | ||||||
| }; |     } else { | ||||||
|  |       scroll(node, 'scrollLeft', position); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
| 
 | 
 | ||||||
| export const scrollTop = (node: Element) => { | export const scrollTop = (node: Element) => | ||||||
|   if (isScrollBehaviorSupported) node.scrollTo({ top: 0, behavior: 'smooth' }); |   requestIdleCallback(() => { | ||||||
|   else scroll(node, 'scrollTop', 0); |     if (isScrollBehaviorSupported) { | ||||||
| }; |       node.scrollTo({ top: 0, behavior: 'smooth' }); | ||||||
|  |     } else { | ||||||
|  |       scroll(node, 'scrollTop', 0); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | |||||||
| @ -8,6 +8,14 @@ import { render as rtlRender } from '@testing-library/react'; | |||||||
| 
 | 
 | ||||||
| import { IdentityContext } from './identity_context'; | import { IdentityContext } from './identity_context'; | ||||||
| 
 | 
 | ||||||
|  | beforeEach(() => { | ||||||
|  |   global.requestIdleCallback = jest | ||||||
|  |     .fn() | ||||||
|  |     .mockImplementation((fn: () => void) => { | ||||||
|  |       fn(); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
| function render( | function render( | ||||||
|   ui: React.ReactElement, |   ui: React.ReactElement, | ||||||
|   { |   { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user