Fix updates being hidden behind pending items on unmounted components (#11898)
This commit is contained in:
		
							parent
							
								
									a90243a712
								
							
						
					
					
						commit
						ba0de8fb68
					
				
					 4 changed files with 33 additions and 4 deletions
				
			
		|  | @ -28,6 +28,9 @@ export const NOTIFICATIONS_CLEAR        = 'NOTIFICATIONS_CLEAR'; | |||
| export const NOTIFICATIONS_SCROLL_TOP   = 'NOTIFICATIONS_SCROLL_TOP'; | ||||
| export const NOTIFICATIONS_LOAD_PENDING = 'NOTIFICATIONS_LOAD_PENDING'; | ||||
| 
 | ||||
| export const NOTIFICATIONS_MOUNT   = 'NOTIFICATIONS_MOUNT'; | ||||
| export const NOTIFICATIONS_UNMOUNT = 'NOTIFICATIONS_UNMOUNT'; | ||||
| 
 | ||||
| defineMessages({ | ||||
|   mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' }, | ||||
|   group: { id: 'notifications.group', defaultMessage: '{count} notifications' }, | ||||
|  | @ -215,3 +218,11 @@ export function setFilter (filterType) { | |||
|     dispatch(saveSettings()); | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| export const mountNotifications = () => ({ | ||||
|   type: NOTIFICATIONS_MOUNT, | ||||
| }); | ||||
| 
 | ||||
| export const unmountNotifications = () => ({ | ||||
|   type: NOTIFICATIONS_UNMOUNT, | ||||
| }); | ||||
|  |  | |||
|  | @ -199,7 +199,12 @@ export default class ScrollableList extends PureComponent { | |||
|     this.clearMouseIdleTimer(); | ||||
|     this.detachScrollListener(); | ||||
|     this.detachIntersectionObserver(); | ||||
| 
 | ||||
|     detachFullscreenListener(this.onFullScreenChange); | ||||
| 
 | ||||
|     if (this.props.onScrollToTop) { | ||||
|       this.props.onScrollToTop(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   onFullScreenChange = () => { | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import PropTypes from 'prop-types'; | |||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||
| import Column from '../../components/column'; | ||||
| import ColumnHeader from '../../components/column_header'; | ||||
| import { expandNotifications, scrollTopNotifications, loadPending } from '../../actions/notifications'; | ||||
| import { expandNotifications, scrollTopNotifications, loadPending, mountNotifications, unmountNotifications } from '../../actions/notifications'; | ||||
| import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; | ||||
| import NotificationContainer from './containers/notification_container'; | ||||
| import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; | ||||
|  | @ -66,11 +66,16 @@ class Notifications extends React.PureComponent { | |||
|     trackScroll: true, | ||||
|   }; | ||||
| 
 | ||||
|   componentWillMount() { | ||||
|     this.props.dispatch(mountNotifications()); | ||||
|   } | ||||
| 
 | ||||
|   componentWillUnmount () { | ||||
|     this.handleLoadOlder.cancel(); | ||||
|     this.handleScrollToTop.cancel(); | ||||
|     this.handleScroll.cancel(); | ||||
|     this.props.dispatch(scrollTopNotifications(false)); | ||||
|     this.props.dispatch(unmountNotifications()); | ||||
|   } | ||||
| 
 | ||||
|   handleLoadGap = (maxId) => { | ||||
|  |  | |||
|  | @ -7,6 +7,8 @@ import { | |||
|   NOTIFICATIONS_CLEAR, | ||||
|   NOTIFICATIONS_SCROLL_TOP, | ||||
|   NOTIFICATIONS_LOAD_PENDING, | ||||
|   NOTIFICATIONS_MOUNT, | ||||
|   NOTIFICATIONS_UNMOUNT, | ||||
| } from '../actions/notifications'; | ||||
| import { | ||||
|   ACCOUNT_BLOCK_SUCCESS, | ||||
|  | @ -22,6 +24,7 @@ const initialState = ImmutableMap({ | |||
|   items: ImmutableList(), | ||||
|   hasMore: true, | ||||
|   top: false, | ||||
|   mounted: false, | ||||
|   unread: 0, | ||||
|   isLoading: false, | ||||
| }); | ||||
|  | @ -35,9 +38,10 @@ const notificationToMap = notification => ImmutableMap({ | |||
| }); | ||||
| 
 | ||||
| const normalizeNotification = (state, notification, usePendingItems) => { | ||||
|   const top = state.get('top'); | ||||
|   const top     = state.get('top'); | ||||
|   const mounted = state.get('mounted'); | ||||
| 
 | ||||
|   if (usePendingItems || !top || !state.get('pendingItems').isEmpty()) { | ||||
|   if (usePendingItems || (!top && mounted) || !state.get('pendingItems').isEmpty()) { | ||||
|     return state.update('pendingItems', list => list.unshift(notificationToMap(notification))).update('unread', unread => unread + 1); | ||||
|   } | ||||
| 
 | ||||
|  | @ -63,7 +67,7 @@ const expandNormalizedNotifications = (state, notifications, next, isLoadingRece | |||
| 
 | ||||
|   return state.withMutations(mutable => { | ||||
|     if (!items.isEmpty()) { | ||||
|       usePendingItems = isLoadingRecent && (usePendingItems || !mutable.get('top') || !mutable.get('pendingItems').isEmpty()); | ||||
|       usePendingItems = isLoadingRecent && (usePendingItems || (!mutable.get('top') && mutable.get('mounted')) || !mutable.get('pendingItems').isEmpty()); | ||||
| 
 | ||||
|       mutable.update(usePendingItems ? 'pendingItems' : 'items', list => { | ||||
|         const lastIndex = 1 + list.findLastIndex( | ||||
|  | @ -134,6 +138,10 @@ export default function notifications(state = initialState, action) { | |||
|     return action.timeline === 'home' ? | ||||
|       state.update(action.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(null) : items) : | ||||
|       state; | ||||
|   case NOTIFICATIONS_MOUNT: | ||||
|     return state.set('mounted', true); | ||||
|   case NOTIFICATIONS_UNMOUNT: | ||||
|     return state.set('mounted', false); | ||||
|   default: | ||||
|     return state; | ||||
|   } | ||||
|  |  | |||
		Reference in a new issue