Skip to content

Commit eec7bdf

Browse files
Gargronhiyuki2578
authored andcommitted
Add search results pagination to web UI (mastodon#11409)
* Add search results pagination to web UI Fix mastodon#10737 * Fix code style issue
1 parent 2050863 commit eec7bdf

5 files changed

Lines changed: 76 additions & 8 deletions

File tree

app/javascript/mastodon/actions/search.js

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ export const SEARCH_FETCH_REQUEST = 'SEARCH_FETCH_REQUEST';
1010
export const SEARCH_FETCH_SUCCESS = 'SEARCH_FETCH_SUCCESS';
1111
export const SEARCH_FETCH_FAIL = 'SEARCH_FETCH_FAIL';
1212

13+
export const SEARCH_EXPAND_REQUEST = 'SEARCH_EXPAND_REQUEST';
14+
export const SEARCH_EXPAND_SUCCESS = 'SEARCH_EXPAND_SUCCESS';
15+
export const SEARCH_EXPAND_FAIL = 'SEARCH_EXPAND_FAIL';
16+
1317
export function changeSearch(value) {
1418
return {
1519
type: SEARCH_CHANGE,
@@ -77,8 +81,50 @@ export function fetchSearchFail(error) {
7781
};
7882
};
7983

80-
export function showSearch() {
81-
return {
82-
type: SEARCH_SHOW,
83-
};
84+
export const expandSearch = type => (dispatch, getState) => {
85+
const value = getState().getIn(['search', 'value']);
86+
const offset = getState().getIn(['search', 'results', type]).size;
87+
88+
dispatch(expandSearchRequest());
89+
90+
api(getState).get('/api/v2/search', {
91+
params: {
92+
q: value,
93+
type,
94+
offset,
95+
},
96+
}).then(({ data }) => {
97+
if (data.accounts) {
98+
dispatch(importFetchedAccounts(data.accounts));
99+
}
100+
101+
if (data.statuses) {
102+
dispatch(importFetchedStatuses(data.statuses));
103+
}
104+
105+
dispatch(expandSearchSuccess(data, value, type));
106+
dispatch(fetchRelationships(data.accounts.map(item => item.id)));
107+
}).catch(error => {
108+
dispatch(expandSearchFail(error));
109+
});
84110
};
111+
112+
export const expandSearchRequest = () => ({
113+
type: SEARCH_EXPAND_REQUEST,
114+
});
115+
116+
export const expandSearchSuccess = (results, searchTerm, searchType) => ({
117+
type: SEARCH_EXPAND_SUCCESS,
118+
results,
119+
searchTerm,
120+
searchType,
121+
});
122+
123+
export const expandSearchFail = error => ({
124+
type: SEARCH_EXPAND_FAIL,
125+
error,
126+
});
127+
128+
export const showSearch = () => ({
129+
type: SEARCH_SHOW,
130+
});

app/javascript/mastodon/features/compose/components/search_results.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
88
import Hashtag from '../../../components/hashtag';
99
import Icon from 'mastodon/components/icon';
1010
import { searchEnabled } from '../../../initial_state';
11+
import LoadMore from 'mastodon/components/load_more';
1112

1213
const messages = defineMessages({
1314
dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' },
@@ -20,15 +21,24 @@ class SearchResults extends ImmutablePureComponent {
2021
results: ImmutablePropTypes.map.isRequired,
2122
suggestions: ImmutablePropTypes.list.isRequired,
2223
fetchSuggestions: PropTypes.func.isRequired,
24+
expandSearch: PropTypes.func.isRequired,
2325
dismissSuggestion: PropTypes.func.isRequired,
2426
searchTerm: PropTypes.string,
2527
intl: PropTypes.object.isRequired,
2628
};
2729

2830
componentDidMount () {
29-
this.props.fetchSuggestions();
31+
if (this.props.searchTerm === '') {
32+
this.props.fetchSuggestions();
33+
}
3034
}
3135

36+
handleLoadMoreAccounts = () => this.props.expandSearch('accounts');
37+
38+
handleLoadMoreStatuses = () => this.props.expandSearch('statuses');
39+
40+
handleLoadMoreHashtags = () => this.props.expandSearch('hashtags');
41+
3242
render () {
3343
const { intl, results, suggestions, dismissSuggestion, searchTerm } = this.props;
3444

@@ -65,6 +75,8 @@ class SearchResults extends ImmutablePureComponent {
6575
<h5><Icon id='users' fixedWidth /><FormattedMessage id='search_results.accounts' defaultMessage='People' /></h5>
6676

6777
{results.get('accounts').map(accountId => <AccountContainer key={accountId} id={accountId} />)}
78+
79+
{results.get('accounts').size >= 5 && <LoadMore visible onClick={this.handleLoadMoreAccounts} />}
6880
</div>
6981
);
7082
}
@@ -76,6 +88,8 @@ class SearchResults extends ImmutablePureComponent {
7688
<h5><Icon id='quote-right' fixedWidth /><FormattedMessage id='search_results.statuses' defaultMessage='Toots' /></h5>
7789

7890
{results.get('statuses').map(statusId => <StatusContainer key={statusId} id={statusId} />)}
91+
92+
{results.get('statuses').size >= 5 && <LoadMore visible onClick={this.handleLoadMoreStatuses} />}
7993
</div>
8094
);
8195
} else if(results.get('statuses') && results.get('statuses').size === 0 && !searchEnabled && !(searchTerm.startsWith('@') || searchTerm.startsWith('#') || searchTerm.includes(' '))) {
@@ -97,6 +111,8 @@ class SearchResults extends ImmutablePureComponent {
97111
<h5><Icon id='hashtag' fixedWidth /><FormattedMessage id='search_results.hashtags' defaultMessage='Hashtags' /></h5>
98112

99113
{results.get('hashtags').map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)}
114+
115+
{results.get('hashtags').size >= 5 && <LoadMore visible onClick={this.handleLoadMoreHashtags} />}
100116
</div>
101117
);
102118
}

app/javascript/mastodon/features/compose/containers/search_results_container.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { connect } from 'react-redux';
22
import SearchResults from '../components/search_results';
3-
import { fetchSuggestions, dismissSuggestion } from '../../../actions/suggestions';
3+
import { fetchSuggestions, dismissSuggestion } from 'mastodon/actions/suggestions';
4+
import { expandSearch } from 'mastodon/actions/search';
45

56
const mapStateToProps = state => ({
67
results: state.getIn(['search', 'results']),
@@ -10,6 +11,7 @@ const mapStateToProps = state => ({
1011

1112
const mapDispatchToProps = dispatch => ({
1213
fetchSuggestions: () => dispatch(fetchSuggestions()),
14+
expandSearch: type => dispatch(expandSearch(type)),
1315
dismissSuggestion: account => dispatch(dismissSuggestion(account.get('id'))),
1416
});
1517

app/javascript/mastodon/reducers/search.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
SEARCH_CLEAR,
44
SEARCH_FETCH_SUCCESS,
55
SEARCH_SHOW,
6+
SEARCH_EXPAND_SUCCESS,
67
} from '../actions/search';
78
import {
89
COMPOSE_MENTION,
@@ -42,6 +43,8 @@ export default function search(state = initialState, action) {
4243
statuses: ImmutableList(action.results.statuses.map(item => item.id)),
4344
hashtags: fromJS(action.results.hashtags),
4445
})).set('submitted', true).set('searchTerm', action.searchTerm);
46+
case SEARCH_EXPAND_SUCCESS:
47+
return state.updateIn(['results', action.searchType], list => list.concat(action.results[action.searchType].map(item => item.id)));
4548
default:
4649
return state;
4750
}

app/javascript/styles/mastodon/components.scss

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4006,8 +4006,9 @@ a.status-card.compact:hover {
40064006
}
40074007

40084008
.search-results__info {
4009-
padding: 10px;
4010-
color: $secondary-text-color;
4009+
padding: 20px;
4010+
color: $darker-text-color;
4011+
text-align: center;
40114012
}
40124013

40134014
.modal-root {

0 commit comments

Comments
 (0)