You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
2.7 KiB

  1. import { connect } from 'react-redux';
  2. import PureRenderMixin from 'react-addons-pure-render-mixin';
  3. import ImmutablePropTypes from 'react-immutable-proptypes';
  4. import Column from '../ui/components/column';
  5. import { expandNotifications } from '../../actions/notifications';
  6. import NotificationContainer from './containers/notification_container';
  7. import { ScrollContainer } from 'react-router-scroll';
  8. import { defineMessages, injectIntl } from 'react-intl';
  9. import ColumnSettingsContainer from './containers/column_settings_container';
  10. import { createSelector } from 'reselect';
  11. import Immutable from 'immutable';
  12. const messages = defineMessages({
  13. title: { id: 'column.notifications', defaultMessage: 'Notifications' }
  14. });
  15. const getNotifications = createSelector([
  16. state => Immutable.List(state.getIn(['settings', 'notifications', 'shows']).filter(item => !item).keys()),
  17. state => state.getIn(['notifications', 'items'])
  18. ], (excludedTypes, notifications) => notifications.filterNot(item => excludedTypes.includes(item.get('type'))));
  19. const mapStateToProps = state => ({
  20. notifications: getNotifications(state),
  21. isLoading: state.getIn(['notifications', 'isLoading'], true)
  22. });
  23. const Notifications = React.createClass({
  24. propTypes: {
  25. notifications: ImmutablePropTypes.list.isRequired,
  26. dispatch: React.PropTypes.func.isRequired,
  27. trackScroll: React.PropTypes.bool,
  28. intl: React.PropTypes.object.isRequired,
  29. isLoading: React.PropTypes.bool
  30. },
  31. getDefaultProps () {
  32. return {
  33. trackScroll: true
  34. };
  35. },
  36. mixins: [PureRenderMixin],
  37. handleScroll (e) {
  38. const { scrollTop, scrollHeight, clientHeight } = e.target;
  39. const offset = scrollHeight - scrollTop - clientHeight;
  40. if (250 > offset && !this.props.isLoading) {
  41. this.props.dispatch(expandNotifications());
  42. }
  43. },
  44. render () {
  45. const { intl, notifications, trackScroll } = this.props;
  46. const scrollableArea = (
  47. <div className='scrollable' onScroll={this.handleScroll}>
  48. <div>
  49. {notifications.map(item => <NotificationContainer key={item.get('id')} notification={item} accountId={item.get('account')} />)}
  50. </div>
  51. </div>
  52. );
  53. if (trackScroll) {
  54. return (
  55. <Column icon='bell' heading={intl.formatMessage(messages.title)}>
  56. <ColumnSettingsContainer />
  57. <ScrollContainer scrollKey='notifications'>
  58. {scrollableArea}
  59. </ScrollContainer>
  60. </Column>
  61. );
  62. } else {
  63. return (
  64. <Column icon='bell' heading={intl.formatMessage(messages.title)}>
  65. <ColumnSettingsContainer />
  66. {scrollableArea}
  67. </Column>
  68. );
  69. }
  70. }
  71. });
  72. export default connect(mapStateToProps)(injectIntl(Notifications));