Allow clients to fetch notifications made while they were offline (#6886)
This commit is contained in:
parent
9a1a55ce52
commit
cbf97c03bb
5 changed files with 82 additions and 114 deletions
|
@ -13,6 +13,7 @@ import { createSelector } from 'reselect';
|
|||
import { List as ImmutableList } from 'immutable';
|
||||
import { debounce } from 'lodash';
|
||||
import ScrollableList from '../../components/scrollable_list';
|
||||
import LoadMore from '../../components/load_more';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'column.notifications', defaultMessage: 'Notifications' },
|
||||
|
@ -21,13 +22,31 @@ const messages = defineMessages({
|
|||
const getNotifications = createSelector([
|
||||
state => ImmutableList(state.getIn(['settings', 'notifications', 'shows']).filter(item => !item).keys()),
|
||||
state => state.getIn(['notifications', 'items']),
|
||||
], (excludedTypes, notifications) => notifications.filterNot(item => excludedTypes.includes(item.get('type'))));
|
||||
], (excludedTypes, notifications) => notifications.filterNot(item => item !== null && excludedTypes.includes(item.get('type'))));
|
||||
|
||||
class LoadGap extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
disabled: PropTypes.bool,
|
||||
maxId: PropTypes.string,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onClick(this.props.maxId);
|
||||
}
|
||||
|
||||
render () {
|
||||
return <LoadMore onClick={this.handleClick} disabled={this.props.disabled} />;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
notifications: getNotifications(state),
|
||||
isLoading: state.getIn(['notifications', 'isLoading'], true),
|
||||
isUnread: state.getIn(['notifications', 'unread']) > 0,
|
||||
hasMore: !!state.getIn(['notifications', 'next']),
|
||||
hasMore: state.getIn(['notifications', 'hasMore']),
|
||||
});
|
||||
|
||||
@connect(mapStateToProps)
|
||||
|
@ -51,14 +70,19 @@ export default class Notifications extends React.PureComponent {
|
|||
};
|
||||
|
||||
componentWillUnmount () {
|
||||
this.handleLoadMore.cancel();
|
||||
this.handleLoadOlder.cancel();
|
||||
this.handleScrollToTop.cancel();
|
||||
this.handleScroll.cancel();
|
||||
this.props.dispatch(scrollTopNotifications(false));
|
||||
}
|
||||
|
||||
handleLoadMore = debounce(() => {
|
||||
this.props.dispatch(expandNotifications());
|
||||
handleLoadGap = (maxId) => {
|
||||
this.props.dispatch(expandNotifications({ maxId }));
|
||||
};
|
||||
|
||||
handleLoadOlder = debounce(() => {
|
||||
const last = this.props.notifications.last();
|
||||
this.props.dispatch(expandNotifications({ maxId: last && last.get('id') }));
|
||||
}, 300, { leading: true });
|
||||
|
||||
handleScrollToTop = debounce(() => {
|
||||
|
@ -93,12 +117,12 @@ export default class Notifications extends React.PureComponent {
|
|||
}
|
||||
|
||||
handleMoveUp = id => {
|
||||
const elementIndex = this.props.notifications.findIndex(item => item.get('id') === id) - 1;
|
||||
const elementIndex = this.props.notifications.findIndex(item => item !== null && item.get('id') === id) - 1;
|
||||
this._selectChild(elementIndex);
|
||||
}
|
||||
|
||||
handleMoveDown = id => {
|
||||
const elementIndex = this.props.notifications.findIndex(item => item.get('id') === id) + 1;
|
||||
const elementIndex = this.props.notifications.findIndex(item => item !== null && item.get('id') === id) + 1;
|
||||
this._selectChild(elementIndex);
|
||||
}
|
||||
|
||||
|
@ -120,7 +144,14 @@ export default class Notifications extends React.PureComponent {
|
|||
if (isLoading && this.scrollableContent) {
|
||||
scrollableContent = this.scrollableContent;
|
||||
} else if (notifications.size > 0 || hasMore) {
|
||||
scrollableContent = notifications.map((item) => (
|
||||
scrollableContent = notifications.map((item, index) => item === null ? (
|
||||
<LoadGap
|
||||
key={'gap:' + notifications.getIn([index + 1, 'id'])}
|
||||
disabled={isLoading}
|
||||
maxId={index > 0 ? notifications.getIn([index - 1, 'id']) : null}
|
||||
onClick={this.handleLoadGap}
|
||||
/>
|
||||
) : (
|
||||
<NotificationContainer
|
||||
key={item.get('id')}
|
||||
notification={item}
|
||||
|
@ -142,7 +173,7 @@ export default class Notifications extends React.PureComponent {
|
|||
isLoading={isLoading}
|
||||
hasMore={hasMore}
|
||||
emptyMessage={emptyMessage}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
onLoadMore={this.handleLoadOlder}
|
||||
onScrollToTop={this.handleScrollToTop}
|
||||
onScroll={this.handleScroll}
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
|
|
|
@ -11,7 +11,7 @@ import { isMobile } from '../../is_mobile';
|
|||
import { debounce } from 'lodash';
|
||||
import { uploadCompose, resetCompose } from '../../actions/compose';
|
||||
import { expandHomeTimeline } from '../../actions/timelines';
|
||||
import { refreshNotifications } from '../../actions/notifications';
|
||||
import { expandNotifications } from '../../actions/notifications';
|
||||
import { clearHeight } from '../../actions/height_cache';
|
||||
import { WrappedSwitch, WrappedRoute } from './util/react_router_helpers';
|
||||
import UploadArea from './components/upload_area';
|
||||
|
@ -285,7 +285,7 @@ export default class UI extends React.PureComponent {
|
|||
}
|
||||
|
||||
this.props.dispatch(expandHomeTimeline());
|
||||
this.props.dispatch(refreshNotifications());
|
||||
this.props.dispatch(expandNotifications());
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue