sforkowany z mirror/soapbox
Use ScrollableList for search results
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>draftjs
rodzic
dde588faa8
commit
742b1f2b58
|
@ -95,7 +95,7 @@ export const expandSearch = type => (dispatch, getState) => {
|
|||
const value = getState().getIn(['search', 'value']);
|
||||
const offset = getState().getIn(['search', 'results', type]).size;
|
||||
|
||||
dispatch(expandSearchRequest());
|
||||
dispatch(expandSearchRequest(type));
|
||||
|
||||
api(getState).get('/api/v2/search', {
|
||||
params: {
|
||||
|
@ -119,8 +119,9 @@ export const expandSearch = type => (dispatch, getState) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const expandSearchRequest = () => ({
|
||||
export const expandSearchRequest = (searchType) => ({
|
||||
type: SEARCH_EXPAND_REQUEST,
|
||||
searchType,
|
||||
});
|
||||
|
||||
export const expandSearchSuccess = (results, searchTerm, searchType) => ({
|
||||
|
|
|
@ -6,12 +6,13 @@ import AccountContainer from '../../../containers/account_container';
|
|||
import StatusContainer from '../../../containers/status_container';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import Hashtag from '../../../components/hashtag';
|
||||
import LoadingIndicator from 'soapbox/components/loading_indicator';
|
||||
import FilterBar from '../../search/components/filter_bar';
|
||||
import LoadMore from '../../../components/load_more';
|
||||
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
|
||||
import { WhoToFollowPanel } from 'soapbox/features/ui/util/async-components';
|
||||
import classNames from 'classnames';
|
||||
import ScrollableList from 'soapbox/components/scrollable_list';
|
||||
import PlaceholderAccount from 'soapbox/features/placeholder/components/placeholder_account';
|
||||
import PlaceholderHashtag from 'soapbox/features/placeholder/components/placeholder_hashtag';
|
||||
import PlaceholderStatus from 'soapbox/features/placeholder/components/placeholder_status';
|
||||
|
||||
export default class SearchResults extends ImmutablePureComponent {
|
||||
|
||||
|
@ -32,13 +33,7 @@ export default class SearchResults extends ImmutablePureComponent {
|
|||
render() {
|
||||
const { value, results, submitted, selectedFilter, features } = this.props;
|
||||
|
||||
if (submitted && results.isEmpty()) {
|
||||
return (
|
||||
<div className='search-results'>
|
||||
<LoadingIndicator />
|
||||
</div>
|
||||
);
|
||||
} else if (features.suggestions && results.isEmpty()) {
|
||||
if (!submitted && features.suggestions && results.isEmpty()) {
|
||||
return (
|
||||
<BundleContainer fetchComponent={WhoToFollowPanel}>
|
||||
{Component => <Component limit={5} />}
|
||||
|
@ -48,15 +43,19 @@ export default class SearchResults extends ImmutablePureComponent {
|
|||
|
||||
let searchResults;
|
||||
let hasMore = false;
|
||||
let loaded;
|
||||
let noResultsMessage;
|
||||
let placeholderComponent = PlaceholderStatus;
|
||||
|
||||
if (selectedFilter === 'accounts' && results.get('accounts')) {
|
||||
hasMore = results.get('accountsHasMore');
|
||||
loaded = results.get('accountsLoaded');
|
||||
placeholderComponent = PlaceholderAccount;
|
||||
|
||||
searchResults = results.get('accounts').size > 0 ? (
|
||||
<div className={classNames('search-results__section', { 'has-more': hasMore })}>
|
||||
{results.get('accounts').map(accountId => <AccountContainer key={accountId} id={accountId} />)}
|
||||
</div>
|
||||
) : (
|
||||
if (results.get('accounts').size > 0) {
|
||||
searchResults = results.get('accounts').map(accountId => <AccountContainer key={accountId} id={accountId} />);
|
||||
} else {
|
||||
noResultsMessage = (
|
||||
<div className='empty-column-indicator'>
|
||||
<FormattedMessage
|
||||
id='empty_column.search.accounts'
|
||||
|
@ -66,15 +65,16 @@ export default class SearchResults extends ImmutablePureComponent {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedFilter === 'statuses' && results.get('statuses')) {
|
||||
hasMore = results.get('statusesHasMore');
|
||||
loaded = results.get('statusesLoaded');
|
||||
|
||||
searchResults = results.get('statuses').size > 0 ? (
|
||||
<div className={classNames('search-results__section', { 'has-more': hasMore })}>
|
||||
{results.get('statuses').map(statusId => <StatusContainer key={statusId} id={statusId} />)}
|
||||
</div>
|
||||
) : (
|
||||
if (results.get('statuses').size > 0) {
|
||||
searchResults = results.get('statuses').map(statusId => <StatusContainer key={statusId} id={statusId} />);
|
||||
} else {
|
||||
noResultsMessage = (
|
||||
<div className='empty-column-indicator'>
|
||||
<FormattedMessage
|
||||
id='empty_column.search.statuses'
|
||||
|
@ -84,15 +84,17 @@ export default class SearchResults extends ImmutablePureComponent {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedFilter === 'hashtags' && results.get('hashtags')) {
|
||||
hasMore = results.get('hashtagsHasMore');
|
||||
loaded = results.get('hashtagsLoaded');
|
||||
placeholderComponent = PlaceholderHashtag;
|
||||
|
||||
searchResults = results.get('hashtags').size > 0 ? (
|
||||
<div className={classNames('search-results__section', { 'has-more': hasMore })}>
|
||||
{results.get('hashtags').map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)}
|
||||
</div>
|
||||
) : (
|
||||
if (results.get('hashtags').size > 0) {
|
||||
searchResults = results.get('hashtags').map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />);
|
||||
} else {
|
||||
noResultsMessage = (
|
||||
<div className='empty-column-indicator'>
|
||||
<FormattedMessage
|
||||
id='empty_column.search.hashtags'
|
||||
|
@ -102,14 +104,26 @@ export default class SearchResults extends ImmutablePureComponent {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{submitted && <FilterBar selectedFilter={submitted ? selectedFilter : null} selectFilter={this.handleSelectFilter} />}
|
||||
|
||||
{noResultsMessage || (
|
||||
<ScrollableList
|
||||
key={selectedFilter}
|
||||
scrollKey={`${selectedFilter}:${value}`}
|
||||
isLoading={submitted && !loaded}
|
||||
showLoading={submitted && !loaded && results.isEmpty()}
|
||||
hasMore={hasMore}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
placeholderComponent={placeholderComponent}
|
||||
placeholderCount={20}
|
||||
>
|
||||
{searchResults}
|
||||
|
||||
{hasMore && <LoadMore visible onClick={this.handleLoadMore} />}
|
||||
</ScrollableList>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import React from 'react';
|
||||
import { generateText, randomIntFromInterval } from '../utils';
|
||||
|
||||
export default class PlaceholderHashtag extends React.Component {
|
||||
|
||||
render() {
|
||||
const length = randomIntFromInterval(15, 30);
|
||||
|
||||
return (
|
||||
<div className='placeholder-hashtag'>
|
||||
<div className='trends__item'>
|
||||
<div className='trends__item__name'>
|
||||
{generateText(length)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@ import {
|
|||
SEARCH_FETCH_SUCCESS,
|
||||
SEARCH_SHOW,
|
||||
SEARCH_FILTER_SET,
|
||||
SEARCH_EXPAND_REQUEST,
|
||||
SEARCH_EXPAND_SUCCESS,
|
||||
} from '../actions/search';
|
||||
import {
|
||||
|
@ -28,7 +29,6 @@ export default function search(state = initialState, action) {
|
|||
case SEARCH_CHANGE:
|
||||
return state.withMutations(map => {
|
||||
map.set('value', action.value);
|
||||
map.set('submitted', false);
|
||||
});
|
||||
case SEARCH_CLEAR:
|
||||
return state.withMutations(map => {
|
||||
|
@ -58,6 +58,9 @@ export default function search(state = initialState, action) {
|
|||
accountsHasMore: action.results.accounts.length >= 20,
|
||||
statusesHasMore: action.results.statuses.length >= 20,
|
||||
hashtagsHasMore: action.results.hashtags.length >= 20,
|
||||
accountsLoaded: true,
|
||||
statusesLoaded: true,
|
||||
hashtagsLoaded: true,
|
||||
})).set('submitted', true).set('filter', action.results.accounts.length > 0
|
||||
? 'accounts'
|
||||
: action.results.statuses.length > 0
|
||||
|
@ -67,9 +70,12 @@ export default function search(state = initialState, action) {
|
|||
: 'accounts');
|
||||
case SEARCH_FILTER_SET:
|
||||
return state.set('filter', action.value);
|
||||
case SEARCH_EXPAND_REQUEST:
|
||||
return state.setIn(['results', `${action.searchType}Loaded`], false);
|
||||
case SEARCH_EXPAND_SUCCESS:
|
||||
return state.withMutations((state) => {
|
||||
state.setIn(['results', `${action.searchType}HasMore`], action.results[action.searchType].length >= 20);
|
||||
state.setIn(['results', `${action.searchType}Loaded`], true);
|
||||
state.updateIn(['results', action.searchType], list => list.concat(action.results[action.searchType].map(item => item.id)));
|
||||
});
|
||||
default:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
.placeholder-status,
|
||||
.placeholder-hashtag,
|
||||
.notification--placeholder {
|
||||
position: relative;
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue