export const SEARCH_FETCH_SUCCESS = 'SEARCH_FETCH_SUCCESS';
export const SEARCH_FETCH_FAIL = 'SEARCH_FETCH_FAIL';
+export const SEARCH_EXPAND_REQUEST = 'SEARCH_EXPAND_REQUEST';
+export const SEARCH_EXPAND_SUCCESS = 'SEARCH_EXPAND_SUCCESS';
+export const SEARCH_EXPAND_FAIL = 'SEARCH_EXPAND_FAIL';
+
export function changeSearch(value) {
return {
type: SEARCH_CHANGE,
};
};
-export function showSearch() {
- return {
- type: SEARCH_SHOW,
- };
+export const expandSearch = type => (dispatch, getState) => {
+ const value = getState().getIn(['search', 'value']);
+ const offset = getState().getIn(['search', 'results', type]).size;
+
+ dispatch(expandSearchRequest());
+
+ api(getState).get('/api/v2/search', {
+ params: {
+ q: value,
+ type,
+ offset,
+ },
+ }).then(({ data }) => {
+ if (data.accounts) {
+ dispatch(importFetchedAccounts(data.accounts));
+ }
+
+ if (data.statuses) {
+ dispatch(importFetchedStatuses(data.statuses));
+ }
+
+ dispatch(expandSearchSuccess(data, value, type));
+ dispatch(fetchRelationships(data.accounts.map(item => item.id)));
+ }).catch(error => {
+ dispatch(expandSearchFail(error));
+ });
};
+
+export const expandSearchRequest = () => ({
+ type: SEARCH_EXPAND_REQUEST,
+});
+
+export const expandSearchSuccess = (results, searchTerm, searchType) => ({
+ type: SEARCH_EXPAND_SUCCESS,
+ results,
+ searchTerm,
+ searchType,
+});
+
+export const expandSearchFail = error => ({
+ type: SEARCH_EXPAND_FAIL,
+ error,
+});
+
+export const showSearch = () => ({
+ type: SEARCH_SHOW,
+});
import Hashtag from '../../../components/hashtag';
import Icon from 'mastodon/components/icon';
import { searchEnabled } from '../../../initial_state';
+import LoadMore from 'mastodon/components/load_more';
const messages = defineMessages({
dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' },
results: ImmutablePropTypes.map.isRequired,
suggestions: ImmutablePropTypes.list.isRequired,
fetchSuggestions: PropTypes.func.isRequired,
+ expandSearch: PropTypes.func.isRequired,
dismissSuggestion: PropTypes.func.isRequired,
searchTerm: PropTypes.string,
intl: PropTypes.object.isRequired,
};
componentDidMount () {
- this.props.fetchSuggestions();
+ if (this.props.searchTerm === '') {
+ this.props.fetchSuggestions();
+ }
}
+ handleLoadMoreAccounts = () => this.props.expandSearch('accounts');
+
+ handleLoadMoreStatuses = () => this.props.expandSearch('statuses');
+
+ handleLoadMoreHashtags = () => this.props.expandSearch('hashtags');
+
render () {
const { intl, results, suggestions, dismissSuggestion, searchTerm } = this.props;
<h5><Icon id='users' fixedWidth /><FormattedMessage id='search_results.accounts' defaultMessage='People' /></h5>
{results.get('accounts').map(accountId => <AccountContainer key={accountId} id={accountId} />)}
+
+ {results.get('accounts').size >= 5 && <LoadMore visible onClick={this.handleLoadMoreAccounts} />}
</div>
);
}
<h5><Icon id='quote-right' fixedWidth /><FormattedMessage id='search_results.statuses' defaultMessage='Toots' /></h5>
{results.get('statuses').map(statusId => <StatusContainer key={statusId} id={statusId} />)}
+
+ {results.get('statuses').size >= 5 && <LoadMore visible onClick={this.handleLoadMoreStatuses} />}
</div>
);
} else if(results.get('statuses') && results.get('statuses').size === 0 && !searchEnabled && !(searchTerm.startsWith('@') || searchTerm.startsWith('#') || searchTerm.includes(' '))) {
<h5><Icon id='hashtag' fixedWidth /><FormattedMessage id='search_results.hashtags' defaultMessage='Hashtags' /></h5>
{results.get('hashtags').map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)}
+
+ {results.get('hashtags').size >= 5 && <LoadMore visible onClick={this.handleLoadMoreHashtags} />}
</div>
);
}
import { connect } from 'react-redux';
import SearchResults from '../components/search_results';
-import { fetchSuggestions, dismissSuggestion } from '../../../actions/suggestions';
+import { fetchSuggestions, dismissSuggestion } from 'mastodon/actions/suggestions';
+import { expandSearch } from 'mastodon/actions/search';
const mapStateToProps = state => ({
results: state.getIn(['search', 'results']),
const mapDispatchToProps = dispatch => ({
fetchSuggestions: () => dispatch(fetchSuggestions()),
+ expandSearch: type => dispatch(expandSearch(type)),
dismissSuggestion: account => dispatch(dismissSuggestion(account.get('id'))),
});
SEARCH_CLEAR,
SEARCH_FETCH_SUCCESS,
SEARCH_SHOW,
+ SEARCH_EXPAND_SUCCESS,
} from '../actions/search';
import {
COMPOSE_MENTION,
statuses: ImmutableList(action.results.statuses.map(item => item.id)),
hashtags: fromJS(action.results.hashtags),
})).set('submitted', true).set('searchTerm', action.searchTerm);
+ case SEARCH_EXPAND_SUCCESS:
+ return state.updateIn(['results', action.searchType], list => list.concat(action.results[action.searchType].map(item => item.id)));
default:
return state;
}
}
.search-results__info {
- padding: 10px;
- color: $secondary-text-color;
+ padding: 20px;
+ color: $darker-text-color;
+ text-align: center;
}
.modal-root {