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.

134 lines
5.0 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import ImmutablePropTypes from 'react-immutable-proptypes';
  4. import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
  5. import AccountContainer from '../../../containers/account_container';
  6. import StatusContainer from '../../../containers/status_container';
  7. import ImmutablePureComponent from 'react-immutable-pure-component';
  8. import Hashtag from '../../../components/hashtag';
  9. import Icon from 'mastodon/components/icon';
  10. import { searchEnabled } from '../../../initial_state';
  11. import LoadMore from 'mastodon/components/load_more';
  12. const messages = defineMessages({
  13. dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' },
  14. });
  15. export default @injectIntl
  16. class SearchResults extends ImmutablePureComponent {
  17. static propTypes = {
  18. results: ImmutablePropTypes.map.isRequired,
  19. suggestions: ImmutablePropTypes.list.isRequired,
  20. fetchSuggestions: PropTypes.func.isRequired,
  21. expandSearch: PropTypes.func.isRequired,
  22. dismissSuggestion: PropTypes.func.isRequired,
  23. searchTerm: PropTypes.string,
  24. intl: PropTypes.object.isRequired,
  25. };
  26. componentDidMount () {
  27. if (this.props.searchTerm === '') {
  28. this.props.fetchSuggestions();
  29. }
  30. }
  31. handleLoadMoreAccounts = () => this.props.expandSearch('accounts');
  32. handleLoadMoreStatuses = () => this.props.expandSearch('statuses');
  33. handleLoadMoreHashtags = () => this.props.expandSearch('hashtags');
  34. render () {
  35. const { intl, results, suggestions, dismissSuggestion, searchTerm } = this.props;
  36. if (results.isEmpty() && !suggestions.isEmpty()) {
  37. return (
  38. <div className='search-results'>
  39. <div className='trends'>
  40. <div className='trends__header'>
  41. <Icon id='user-plus' fixedWidth />
  42. <FormattedMessage id='suggestions.header' defaultMessage='You might be interested in…' />
  43. </div>
  44. {suggestions && suggestions.map(accountId => (
  45. <AccountContainer
  46. key={accountId}
  47. id={accountId}
  48. actionIcon='times'
  49. actionTitle={intl.formatMessage(messages.dismissSuggestion)}
  50. onActionClick={dismissSuggestion}
  51. />
  52. ))}
  53. </div>
  54. </div>
  55. );
  56. }
  57. let accounts, statuses, hashtags;
  58. let count = 0;
  59. if (results.get('accounts') && results.get('accounts').size > 0) {
  60. count += results.get('accounts').size;
  61. accounts = (
  62. <div className='search-results__section'>
  63. <h5><Icon id='users' fixedWidth /><FormattedMessage id='search_results.accounts' defaultMessage='People' /></h5>
  64. {results.get('accounts').map(accountId => <AccountContainer key={accountId} id={accountId} />)}
  65. {results.get('accounts').size >= 5 && <LoadMore visible onClick={this.handleLoadMoreAccounts} />}
  66. </div>
  67. );
  68. }
  69. if (results.get('statuses') && results.get('statuses').size > 0) {
  70. count += results.get('statuses').size;
  71. statuses = (
  72. <div className='search-results__section'>
  73. <h5><Icon id='quote-right' fixedWidth /><FormattedMessage id='search_results.statuses' defaultMessage='Toots' /></h5>
  74. {results.get('statuses').map(statusId => <StatusContainer key={statusId} id={statusId} />)}
  75. {results.get('statuses').size >= 5 && <LoadMore visible onClick={this.handleLoadMoreStatuses} />}
  76. </div>
  77. );
  78. } else if(results.get('statuses') && results.get('statuses').size === 0 && !searchEnabled && !(searchTerm.startsWith('@') || searchTerm.startsWith('#') || searchTerm.includes(' '))) {
  79. statuses = (
  80. <div className='search-results__section'>
  81. <h5><Icon id='quote-right' fixedWidth /><FormattedMessage id='search_results.statuses' defaultMessage='Toots' /></h5>
  82. <div className='search-results__info'>
  83. <FormattedMessage id='search_results.statuses_fts_disabled' defaultMessage='Searching toots by their content is not enabled on this Mastodon server.' />
  84. </div>
  85. </div>
  86. );
  87. }
  88. if (results.get('hashtags') && results.get('hashtags').size > 0) {
  89. count += results.get('hashtags').size;
  90. hashtags = (
  91. <div className='search-results__section'>
  92. <h5><Icon id='hashtag' fixedWidth /><FormattedMessage id='search_results.hashtags' defaultMessage='Hashtags' /></h5>
  93. {results.get('hashtags').map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)}
  94. {results.get('hashtags').size >= 5 && <LoadMore visible onClick={this.handleLoadMoreHashtags} />}
  95. </div>
  96. );
  97. }
  98. return (
  99. <div className='search-results'>
  100. <div className='search-results__header'>
  101. <Icon id='search' fixedWidth />
  102. <FormattedMessage id='search_results.total' defaultMessage='{count, number} {count, plural, one {result} other {results}}' values={{ count }} />
  103. </div>
  104. {accounts}
  105. {statuses}
  106. {hashtags}
  107. </div>
  108. );
  109. }
  110. }