Generalized the infinite scrollable list (#4697)
This commit is contained in:
parent
938cd2875b
commit
0827c09c44
8 changed files with 376 additions and 320 deletions
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import StatusContainer from '../../../containers/status_container';
|
||||
import AccountContainer from '../../../containers/account_container';
|
||||
|
@ -10,6 +11,7 @@ export default class Notification extends ImmutablePureComponent {
|
|||
|
||||
static propTypes = {
|
||||
notification: ImmutablePropTypes.map.isRequired,
|
||||
hidden: PropTypes.bool,
|
||||
};
|
||||
|
||||
renderFollow (account, link) {
|
||||
|
@ -23,13 +25,13 @@ export default class Notification extends ImmutablePureComponent {
|
|||
<FormattedMessage id='notification.follow' defaultMessage='{name} followed you' values={{ name: link }} />
|
||||
</div>
|
||||
|
||||
<AccountContainer id={account.get('id')} withNote={false} />
|
||||
<AccountContainer id={account.get('id')} withNote={false} hidden={this.props.hidden} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderMention (notification) {
|
||||
return <StatusContainer id={notification.get('status')} withDismiss />;
|
||||
return <StatusContainer id={notification.get('status')} withDismiss hidden={this.props.hidden} />;
|
||||
}
|
||||
|
||||
renderFavourite (notification, link) {
|
||||
|
@ -42,7 +44,7 @@ export default class Notification extends ImmutablePureComponent {
|
|||
<FormattedMessage id='notification.favourite' defaultMessage='{name} favourited your status' values={{ name: link }} />
|
||||
</div>
|
||||
|
||||
<StatusContainer id={notification.get('status')} account={notification.get('account')} muted withDismiss />
|
||||
<StatusContainer id={notification.get('status')} account={notification.get('account')} muted withDismiss hidden={!!this.props.hidden} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -57,7 +59,7 @@ export default class Notification extends ImmutablePureComponent {
|
|||
<FormattedMessage id='notification.reblog' defaultMessage='{name} boosted your status' values={{ name: link }} />
|
||||
</div>
|
||||
|
||||
<StatusContainer id={notification.get('status')} account={notification.get('account')} muted withDismiss />
|
||||
<StatusContainer id={notification.get('status')} account={notification.get('account')} muted withDismiss hidden={this.props.hidden} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,13 +7,12 @@ import ColumnHeader from '../../components/column_header';
|
|||
import { expandNotifications, scrollTopNotifications } from '../../actions/notifications';
|
||||
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||
import NotificationContainer from './containers/notification_container';
|
||||
import { ScrollContainer } from 'react-router-scroll';
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import ColumnSettingsContainer from './containers/column_settings_container';
|
||||
import { createSelector } from 'reselect';
|
||||
import { List as ImmutableList } from 'immutable';
|
||||
import LoadMore from '../../components/load_more';
|
||||
import { debounce } from 'lodash';
|
||||
import ScrollableList from '../../components/scrollable_list';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'column.notifications', defaultMessage: 'Notifications' },
|
||||
|
@ -51,40 +50,18 @@ export default class Notifications extends React.PureComponent {
|
|||
trackScroll: true,
|
||||
};
|
||||
|
||||
dispatchExpandNotifications = debounce(() => {
|
||||
handleScrollToBottom = debounce(() => {
|
||||
this.props.dispatch(scrollTopNotifications(false));
|
||||
this.props.dispatch(expandNotifications());
|
||||
}, 300, { leading: true });
|
||||
|
||||
dispatchScrollToTop = debounce((top) => {
|
||||
this.props.dispatch(scrollTopNotifications(top));
|
||||
handleScrollToTop = debounce(() => {
|
||||
this.props.dispatch(scrollTopNotifications(true));
|
||||
}, 100);
|
||||
|
||||
handleScroll = (e) => {
|
||||
const { scrollTop, scrollHeight, clientHeight } = e.target;
|
||||
const offset = scrollHeight - scrollTop - clientHeight;
|
||||
this._oldScrollPosition = scrollHeight - scrollTop;
|
||||
|
||||
if (250 > offset && this.props.hasMore && !this.props.isLoading) {
|
||||
this.dispatchExpandNotifications();
|
||||
}
|
||||
|
||||
if (scrollTop < 100) {
|
||||
this.dispatchScrollToTop(true);
|
||||
} else {
|
||||
this.dispatchScrollToTop(false);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps) {
|
||||
if (this.node.scrollTop > 0 && (prevProps.notifications.size < this.props.notifications.size && prevProps.notifications.first() !== this.props.notifications.first() && !!this._oldScrollPosition)) {
|
||||
this.node.scrollTop = this.node.scrollHeight - this._oldScrollPosition;
|
||||
}
|
||||
}
|
||||
|
||||
handleLoadMore = (e) => {
|
||||
e.preventDefault();
|
||||
this.dispatchExpandNotifications();
|
||||
}
|
||||
handleScroll = debounce(() => {
|
||||
this.props.dispatch(scrollTopNotifications(false));
|
||||
}, 100);
|
||||
|
||||
handlePin = () => {
|
||||
const { columnId, dispatch } = this.props;
|
||||
|
@ -105,10 +82,6 @@ export default class Notifications extends React.PureComponent {
|
|||
this.column.scrollTop();
|
||||
}
|
||||
|
||||
setRef = (c) => {
|
||||
this.node = c;
|
||||
}
|
||||
|
||||
setColumnRef = c => {
|
||||
this.column = c;
|
||||
}
|
||||
|
@ -116,52 +89,34 @@ export default class Notifications extends React.PureComponent {
|
|||
render () {
|
||||
const { intl, notifications, shouldUpdateScroll, isLoading, isUnread, columnId, multiColumn, hasMore } = this.props;
|
||||
const pinned = !!columnId;
|
||||
const emptyMessage = <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. Interact with others to start the conversation." />;
|
||||
|
||||
let loadMore = '';
|
||||
let scrollableArea = '';
|
||||
let unread = '';
|
||||
let scrollContainer = '';
|
||||
let scrollableContent = null;
|
||||
|
||||
if (!isLoading && hasMore) {
|
||||
loadMore = <LoadMore onClick={this.handleLoadMore} />;
|
||||
}
|
||||
|
||||
if (isUnread) {
|
||||
unread = <div className='notifications__unread-indicator' />;
|
||||
}
|
||||
|
||||
if (isLoading && this.scrollableArea) {
|
||||
scrollableArea = this.scrollableArea;
|
||||
if (isLoading && this.scrollableContent) {
|
||||
scrollableContent = this.scrollableContent;
|
||||
} else if (notifications.size > 0 || hasMore) {
|
||||
scrollableArea = (
|
||||
<div className='scrollable' onScroll={this.handleScroll} ref={this.setRef}>
|
||||
{unread}
|
||||
|
||||
<div>
|
||||
{notifications.map(item => <NotificationContainer key={item.get('id')} notification={item} accountId={item.get('account')} />)}
|
||||
{loadMore}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
scrollableContent = notifications.map((item) => <NotificationContainer key={item.get('id')} notification={item} accountId={item.get('account')} />);
|
||||
} else {
|
||||
scrollableArea = (
|
||||
<div className='empty-column-indicator' ref={this.setRef}>
|
||||
<FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. Interact with others to start the conversation." />
|
||||
</div>
|
||||
);
|
||||
scrollableContent = null;
|
||||
}
|
||||
|
||||
if (pinned) {
|
||||
scrollContainer = scrollableArea;
|
||||
} else {
|
||||
scrollContainer = (
|
||||
<ScrollContainer scrollKey={`notifications-${columnId}`} shouldUpdateScroll={shouldUpdateScroll}>
|
||||
{scrollableArea}
|
||||
</ScrollContainer>
|
||||
);
|
||||
}
|
||||
this.scrollableContent = scrollableContent;
|
||||
|
||||
this.scrollableArea = scrollableArea;
|
||||
const scrollContainer = (
|
||||
<ScrollableList
|
||||
scrollKey={`notifications-${columnId}`}
|
||||
isLoading={isLoading}
|
||||
hasMore={hasMore}
|
||||
emptyMessage={emptyMessage}
|
||||
onScrollToBottom={this.handleScrollToBottom}
|
||||
onScrollToTop={this.handleScrollToTop}
|
||||
onScroll={this.handleScroll}
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
>
|
||||
{scrollableContent}
|
||||
</ScrollableList>
|
||||
);
|
||||
|
||||
return (
|
||||
<Column ref={this.setColumnRef}>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue