Merge branch 'master' into glitch-soc/merge-upstream
This commit is contained in:
		
						commit
						e5fd4939ff
					
				
					 6 changed files with 44 additions and 24 deletions
				
			
		|  | @ -19,6 +19,7 @@ export function fetchCustomEmojis() { | ||||||
| export function fetchCustomEmojisRequest() { | export function fetchCustomEmojisRequest() { | ||||||
|   return { |   return { | ||||||
|     type: CUSTOM_EMOJIS_FETCH_REQUEST, |     type: CUSTOM_EMOJIS_FETCH_REQUEST, | ||||||
|  |     skipLoading: true, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -26,6 +27,7 @@ export function fetchCustomEmojisSuccess(custom_emojis) { | ||||||
|   return { |   return { | ||||||
|     type: CUSTOM_EMOJIS_FETCH_SUCCESS, |     type: CUSTOM_EMOJIS_FETCH_SUCCESS, | ||||||
|     custom_emojis, |     custom_emojis, | ||||||
|  |     skipLoading: true, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -33,5 +35,6 @@ export function fetchCustomEmojisFail(error) { | ||||||
|   return { |   return { | ||||||
|     type: CUSTOM_EMOJIS_FETCH_FAIL, |     type: CUSTOM_EMOJIS_FETCH_FAIL, | ||||||
|     error, |     error, | ||||||
|  |     skipLoading: true, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -30,6 +30,7 @@ export function fetchFavouritedStatuses() { | ||||||
| export function fetchFavouritedStatusesRequest() { | export function fetchFavouritedStatusesRequest() { | ||||||
|   return { |   return { | ||||||
|     type: FAVOURITED_STATUSES_FETCH_REQUEST, |     type: FAVOURITED_STATUSES_FETCH_REQUEST, | ||||||
|  |     skipLoading: true, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -38,6 +39,7 @@ export function fetchFavouritedStatusesSuccess(statuses, next) { | ||||||
|     type: FAVOURITED_STATUSES_FETCH_SUCCESS, |     type: FAVOURITED_STATUSES_FETCH_SUCCESS, | ||||||
|     statuses, |     statuses, | ||||||
|     next, |     next, | ||||||
|  |     skipLoading: true, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -45,6 +47,7 @@ export function fetchFavouritedStatusesFail(error) { | ||||||
|   return { |   return { | ||||||
|     type: FAVOURITED_STATUSES_FETCH_FAIL, |     type: FAVOURITED_STATUSES_FETCH_FAIL, | ||||||
|     error, |     error, | ||||||
|  |     skipLoading: true, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -93,6 +93,7 @@ const noOp = () => {}; | ||||||
| export function expandNotifications({ maxId } = {}, done = noOp) { | export function expandNotifications({ maxId } = {}, done = noOp) { | ||||||
|   return (dispatch, getState) => { |   return (dispatch, getState) => { | ||||||
|     const notifications = getState().get('notifications'); |     const notifications = getState().get('notifications'); | ||||||
|  |     const isLoadingMore = !!maxId; | ||||||
| 
 | 
 | ||||||
|     if (notifications.get('isLoading')) { |     if (notifications.get('isLoading')) { | ||||||
|       done(); |       done(); | ||||||
|  | @ -108,7 +109,7 @@ export function expandNotifications({ maxId } = {}, done = noOp) { | ||||||
|       params.since_id = notifications.getIn(['items', 0]); |       params.since_id = notifications.getIn(['items', 0]); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     dispatch(expandNotificationsRequest()); |     dispatch(expandNotificationsRequest(isLoadingMore)); | ||||||
| 
 | 
 | ||||||
|     api(getState).get('/api/v1/notifications', { params }).then(response => { |     api(getState).get('/api/v1/notifications', { params }).then(response => { | ||||||
|       const next = getLinks(response).refs.find(link => link.rel === 'next'); |       const next = getLinks(response).refs.find(link => link.rel === 'next'); | ||||||
|  | @ -116,34 +117,37 @@ export function expandNotifications({ maxId } = {}, done = noOp) { | ||||||
|       dispatch(importFetchedAccounts(response.data.map(item => item.account))); |       dispatch(importFetchedAccounts(response.data.map(item => item.account))); | ||||||
|       dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status))); |       dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status))); | ||||||
| 
 | 
 | ||||||
|       dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null)); |       dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore)); | ||||||
|       fetchRelatedRelationships(dispatch, response.data); |       fetchRelatedRelationships(dispatch, response.data); | ||||||
|       done(); |       done(); | ||||||
|     }).catch(error => { |     }).catch(error => { | ||||||
|       dispatch(expandNotificationsFail(error)); |       dispatch(expandNotificationsFail(error, isLoadingMore)); | ||||||
|       done(); |       done(); | ||||||
|     }); |     }); | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export function expandNotificationsRequest() { | export function expandNotificationsRequest(isLoadingMore) { | ||||||
|   return { |   return { | ||||||
|     type: NOTIFICATIONS_EXPAND_REQUEST, |     type: NOTIFICATIONS_EXPAND_REQUEST, | ||||||
|  |     skipLoading: !isLoadingMore, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export function expandNotificationsSuccess(notifications, next) { | export function expandNotificationsSuccess(notifications, next, isLoadingMore) { | ||||||
|   return { |   return { | ||||||
|     type: NOTIFICATIONS_EXPAND_SUCCESS, |     type: NOTIFICATIONS_EXPAND_SUCCESS, | ||||||
|     notifications, |     notifications, | ||||||
|     next, |     next, | ||||||
|  |     skipLoading: !isLoadingMore, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export function expandNotificationsFail(error) { | export function expandNotificationsFail(error, isLoadingMore) { | ||||||
|   return { |   return { | ||||||
|     type: NOTIFICATIONS_EXPAND_FAIL, |     type: NOTIFICATIONS_EXPAND_FAIL, | ||||||
|     error, |     error, | ||||||
|  |     skipLoading: !isLoadingMore, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -16,8 +16,6 @@ export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT'; | ||||||
| 
 | 
 | ||||||
| export function updateTimeline(timeline, status, accept) { | export function updateTimeline(timeline, status, accept) { | ||||||
|   return (dispatch, getState) => { |   return (dispatch, getState) => { | ||||||
|     const references = status.reblog ? getState().get('statuses').filter((item, itemId) => (itemId === status.reblog.id || item.get('reblog') === status.reblog.id)).map((_, itemId) => itemId) : []; |  | ||||||
| 
 |  | ||||||
|     if (typeof accept === 'function' && !accept(status)) { |     if (typeof accept === 'function' && !accept(status)) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  | @ -28,7 +26,6 @@ export function updateTimeline(timeline, status, accept) { | ||||||
|       type: TIMELINE_UPDATE, |       type: TIMELINE_UPDATE, | ||||||
|       timeline, |       timeline, | ||||||
|       status, |       status, | ||||||
|       references, |  | ||||||
|     }); |     }); | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
|  | @ -66,6 +63,7 @@ const parseTags = (tags = {}, mode) => { | ||||||
| export function expandTimeline(timelineId, path, params = {}, done = noOp) { | export function expandTimeline(timelineId, path, params = {}, done = noOp) { | ||||||
|   return (dispatch, getState) => { |   return (dispatch, getState) => { | ||||||
|     const timeline = getState().getIn(['timelines', timelineId], ImmutableMap()); |     const timeline = getState().getIn(['timelines', timelineId], ImmutableMap()); | ||||||
|  |     const isLoadingMore = !!params.max_id; | ||||||
| 
 | 
 | ||||||
|     if (timeline.get('isLoading')) { |     if (timeline.get('isLoading')) { | ||||||
|       done(); |       done(); | ||||||
|  | @ -76,15 +74,15 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) { | ||||||
|       params.since_id = timeline.getIn(['items', 0]); |       params.since_id = timeline.getIn(['items', 0]); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     dispatch(expandTimelineRequest(timelineId)); |     dispatch(expandTimelineRequest(timelineId, isLoadingMore)); | ||||||
| 
 | 
 | ||||||
|     api(getState).get(path, { params }).then(response => { |     api(getState).get(path, { params }).then(response => { | ||||||
|       const next = getLinks(response).refs.find(link => link.rel === 'next'); |       const next = getLinks(response).refs.find(link => link.rel === 'next'); | ||||||
|       dispatch(importFetchedStatuses(response.data)); |       dispatch(importFetchedStatuses(response.data)); | ||||||
|       dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.code === 206)); |       dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.code === 206, isLoadingMore)); | ||||||
|       done(); |       done(); | ||||||
|     }).catch(error => { |     }).catch(error => { | ||||||
|       dispatch(expandTimelineFail(timelineId, error)); |       dispatch(expandTimelineFail(timelineId, error, isLoadingMore)); | ||||||
|       done(); |       done(); | ||||||
|     }); |     }); | ||||||
|   }; |   }; | ||||||
|  | @ -106,31 +104,31 @@ export const expandHashtagTimeline         = (hashtag, { maxId, tags } = {}, don | ||||||
|   }, done); |   }, done); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export function expandTimelineRequest(timeline) { | export function expandTimelineRequest(timeline, isLoadingMore) { | ||||||
|   return { |   return { | ||||||
|     type: TIMELINE_EXPAND_REQUEST, |     type: TIMELINE_EXPAND_REQUEST, | ||||||
|     timeline, |     timeline, | ||||||
|     skipLoading: true, |     skipLoading: !isLoadingMore, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export function expandTimelineSuccess(timeline, statuses, next, partial) { | export function expandTimelineSuccess(timeline, statuses, next, partial, isLoadingMore) { | ||||||
|   return { |   return { | ||||||
|     type: TIMELINE_EXPAND_SUCCESS, |     type: TIMELINE_EXPAND_SUCCESS, | ||||||
|     timeline, |     timeline, | ||||||
|     statuses, |     statuses, | ||||||
|     next, |     next, | ||||||
|     partial, |     partial, | ||||||
|     skipLoading: true, |     skipLoading: !isLoadingMore, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export function expandTimelineFail(timeline, error) { | export function expandTimelineFail(timeline, error, isLoadingMore) { | ||||||
|   return { |   return { | ||||||
|     type: TIMELINE_EXPAND_FAIL, |     type: TIMELINE_EXPAND_FAIL, | ||||||
|     timeline, |     timeline, | ||||||
|     error, |     error, | ||||||
|     skipLoading: true, |     skipLoading: !isLoadingMore, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -59,6 +59,13 @@ export default class ScrollableList extends PureComponent { | ||||||
|       } else if (this.props.onScroll) { |       } else if (this.props.onScroll) { | ||||||
|         this.props.onScroll(); |         this.props.onScroll(); | ||||||
|       } |       } | ||||||
|  | 
 | ||||||
|  |       if (!this.lastScrollWasSynthetic) { | ||||||
|  |         // If the last scroll wasn't caused by setScrollTop(), assume it was
 | ||||||
|  |         // intentional and cancel any pending scroll reset on mouse idle
 | ||||||
|  |         this.scrollToTopOnMouseIdle = false; | ||||||
|  |       } | ||||||
|  |       this.lastScrollWasSynthetic = false; | ||||||
|     } |     } | ||||||
|   }, 150, { |   }, 150, { | ||||||
|     trailing: true, |     trailing: true, | ||||||
|  | @ -66,8 +73,16 @@ export default class ScrollableList extends PureComponent { | ||||||
| 
 | 
 | ||||||
|   mouseIdleTimer = null; |   mouseIdleTimer = null; | ||||||
|   mouseMovedRecently = false; |   mouseMovedRecently = false; | ||||||
|  |   lastScrollWasSynthetic = false; | ||||||
|   scrollToTopOnMouseIdle = false; |   scrollToTopOnMouseIdle = false; | ||||||
| 
 | 
 | ||||||
|  |   setScrollTop = newScrollTop => { | ||||||
|  |     if (this.node.scrollTop !== newScrollTop) { | ||||||
|  |       this.lastScrollWasSynthetic = true; | ||||||
|  |       this.node.scrollTop = newScrollTop; | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|   clearMouseIdleTimer = () => { |   clearMouseIdleTimer = () => { | ||||||
|     if (this.mouseIdleTimer === null) { |     if (this.mouseIdleTimer === null) { | ||||||
|       return; |       return; | ||||||
|  | @ -99,7 +114,7 @@ export default class ScrollableList extends PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleMouseIdle = () => { |   handleMouseIdle = () => { | ||||||
|     if (this.scrollToTopOnMouseIdle) { |     if (this.scrollToTopOnMouseIdle) { | ||||||
|       this.node.scrollTop = 0; |       this.setScrollTop(0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.mouseMovedRecently = false; |     this.mouseMovedRecently = false; | ||||||
|  | @ -132,11 +147,7 @@ export default class ScrollableList extends PureComponent { | ||||||
|     // Reset the scroll position when a new child comes in in order not to
 |     // Reset the scroll position when a new child comes in in order not to
 | ||||||
|     // jerk the scrollbar around if you're already scrolled down the page.
 |     // jerk the scrollbar around if you're already scrolled down the page.
 | ||||||
|     if (snapshot !== null) { |     if (snapshot !== null) { | ||||||
|       const newScrollTop = this.node.scrollHeight - snapshot; |       this.setScrollTop(this.node.scrollHeight - snapshot); | ||||||
| 
 |  | ||||||
|       if (this.node.scrollTop !== newScrollTop) { |  | ||||||
|         this.node.scrollTop = newScrollTop; |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -153,6 +153,7 @@ class Notifications extends React.PureComponent { | ||||||
|         scrollKey={`notifications-${columnId}`} |         scrollKey={`notifications-${columnId}`} | ||||||
|         trackScroll={!pinned} |         trackScroll={!pinned} | ||||||
|         isLoading={isLoading} |         isLoading={isLoading} | ||||||
|  |         showLoading={isLoading && notifications.size === 0} | ||||||
|         hasMore={hasMore} |         hasMore={hasMore} | ||||||
|         emptyMessage={emptyMessage} |         emptyMessage={emptyMessage} | ||||||
|         onLoadMore={this.handleLoadOlder} |         onLoadMore={this.handleLoadOlder} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue