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.

108 lines
3.3 KiB

  1. import { debounce } from 'lodash';
  2. import PropTypes from 'prop-types';
  3. import React from 'react';
  4. import { Helmet } from 'react-helmet';
  5. import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
  6. import ImmutablePropTypes from 'react-immutable-proptypes';
  7. import ImmutablePureComponent from 'react-immutable-pure-component';
  8. import { connect } from 'react-redux';
  9. import { fetchBookmarkedStatuses, expandBookmarkedStatuses } from 'mastodon/actions/bookmarks';
  10. import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
  11. import ColumnHeader from 'mastodon/components/column_header';
  12. import StatusList from 'mastodon/components/status_list';
  13. import Column from 'mastodon/features/ui/components/column';
  14. const messages = defineMessages({
  15. heading: { id: 'column.bookmarks', defaultMessage: 'Bookmarks' },
  16. });
  17. const mapStateToProps = state => ({
  18. statusIds: state.getIn(['status_lists', 'bookmarks', 'items']),
  19. isLoading: state.getIn(['status_lists', 'bookmarks', 'isLoading'], true),
  20. hasMore: !!state.getIn(['status_lists', 'bookmarks', 'next']),
  21. });
  22. class Bookmarks extends ImmutablePureComponent {
  23. static propTypes = {
  24. dispatch: PropTypes.func.isRequired,
  25. statusIds: ImmutablePropTypes.list.isRequired,
  26. intl: PropTypes.object.isRequired,
  27. columnId: PropTypes.string,
  28. multiColumn: PropTypes.bool,
  29. hasMore: PropTypes.bool,
  30. isLoading: PropTypes.bool,
  31. };
  32. componentWillMount () {
  33. this.props.dispatch(fetchBookmarkedStatuses());
  34. }
  35. handlePin = () => {
  36. const { columnId, dispatch } = this.props;
  37. if (columnId) {
  38. dispatch(removeColumn(columnId));
  39. } else {
  40. dispatch(addColumn('BOOKMARKS', {}));
  41. }
  42. };
  43. handleMove = (dir) => {
  44. const { columnId, dispatch } = this.props;
  45. dispatch(moveColumn(columnId, dir));
  46. };
  47. handleHeaderClick = () => {
  48. this.column.scrollTop();
  49. };
  50. setRef = c => {
  51. this.column = c;
  52. };
  53. handleLoadMore = debounce(() => {
  54. this.props.dispatch(expandBookmarkedStatuses());
  55. }, 300, { leading: true });
  56. render () {
  57. const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props;
  58. const pinned = !!columnId;
  59. const emptyMessage = <FormattedMessage id='empty_column.bookmarked_statuses' defaultMessage="You don't have any bookmarked posts yet. When you bookmark one, it will show up here." />;
  60. return (
  61. <Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)}>
  62. <ColumnHeader
  63. icon='bookmark'
  64. title={intl.formatMessage(messages.heading)}
  65. onPin={this.handlePin}
  66. onMove={this.handleMove}
  67. onClick={this.handleHeaderClick}
  68. pinned={pinned}
  69. multiColumn={multiColumn}
  70. showBackButton
  71. />
  72. <StatusList
  73. trackScroll={!pinned}
  74. statusIds={statusIds}
  75. scrollKey={`bookmarked_statuses-${columnId}`}
  76. hasMore={hasMore}
  77. isLoading={isLoading}
  78. onLoadMore={this.handleLoadMore}
  79. emptyMessage={emptyMessage}
  80. bindToDocument={!multiColumn}
  81. />
  82. <Helmet>
  83. <title>{intl.formatMessage(messages.heading)}</title>
  84. <meta name='robots' content='noindex' />
  85. </Helmet>
  86. </Column>
  87. );
  88. }
  89. }
  90. export default connect(mapStateToProps)(injectIntl(Bookmarks));