diff --git a/src/BaGet.UI/src/SearchResults.tsx b/src/BaGet.UI/src/SearchResults.tsx index ce2094d4..683cb566 100644 --- a/src/BaGet.UI/src/SearchResults.tsx +++ b/src/BaGet.UI/src/SearchResults.tsx @@ -6,6 +6,8 @@ import { Link } from 'react-router-dom'; import './SearchResults.css'; import DefaultPackageIcon from "./default-package-icon-256x256.png"; +const defaultSearchTake = 20; + interface ISearchResultsProps { input: string; } @@ -24,6 +26,7 @@ interface ISearchResultsState { includePrerelease: boolean; packageType: string; targetFramework: string; + page: number; items: IPackage[]; loading: boolean; } @@ -41,15 +44,16 @@ class SearchResults extends React.Component
@@ -161,9 +169,21 @@ class SearchResults extends React.Component - + {(() => { - if (this.state.loading || this.state.items.length > 0) { + if (noResultsFound) { + return ( +
+

Oops, nothing here...

+

+ It looks like there's no package here to see. Take a look below for useful links. +

+

Upload a package

+

BaGet documentation

+

BaGet issues

+
+ ); + } else { return this.state.items.map(value => (
@@ -207,42 +227,103 @@ class SearchResults extends React.Component )); } - else - { - return ( -
-

Oops, nothing here...

-

- It looks like there's no package here to see. Take a look below for useful links. -

-

Upload a package

-

BaGet documentation

-

BaGet issues

-
- ); - } })()} + {showLoadMore && +
+
+

+ +

+
+
+ } +
); } - private _loadItems(query: string, includePrerelease: boolean, packageType: string, targetFramework: string): void { + private loadItems( + query: string, + includePrerelease: boolean, + packageType: string, + targetFramework: string + ): void { + const url = this.buildUrl( + query, + 0, + includePrerelease, + packageType, + targetFramework + ); + + let resetItems = () => + this.setState({ + page: 1, + items: [], + includePrerelease: includePrerelease, + packageType: packageType, + targetFramework: targetFramework, + loading: true, + }); + + let setItems = (results: ISearchResponse) => + this.setState({ + page: 1, + items: results.data, + includePrerelease: includePrerelease, + packageType: packageType, + targetFramework: targetFramework, + loading: false, + }); + + this.fetchSearchResults(url, resetItems, setItems); + } + + private loadMoreItems(): void { + const url = this.buildUrl( + this.props.input, + this.state.page * defaultSearchTake, + this.state.includePrerelease, + this.state.packageType, + this.state.targetFramework); + + let showLoading = () => + this.setState({ + ...this.state, + loading: true + }); + + let addPage = (results: ISearchResponse) => + this.setState({ + page: this.state.page + 1, + items: this.state.items.concat(results.data), + includePrerelease: this.state.includePrerelease, + packageType: this.state.packageType, + targetFramework: this.state.targetFramework, + loading: false + }); + + this.fetchSearchResults( + url, + showLoading, + addPage); + } + + private fetchSearchResults( + url: string, + onStart: () => void, + onComplete: (results: ISearchResponse) => void + ): void { if (this.resultsController) { this.resultsController.abort(); } this.resultsController = new AbortController(); - this.setState({ - includePrerelease, - items: [], - packageType, - targetFramework, - loading: true - }); - - const url = this.buildUrl(query, includePrerelease, packageType, targetFramework); + onStart(); fetch(url, {signal: this.resultsController.signal}).then(response => { return response.ok @@ -255,12 +336,7 @@ class SearchResults extends React.Component { var ex = e as DOMException; @@ -270,15 +346,26 @@ class SearchResults extends React.Component, option?: IDropdownOption) : void => { - this._loadItems( + this.loadItems( this.props.input, this.state.includePrerelease, (option) ? option.key.toString() : 'any', @@ -311,7 +398,7 @@ class SearchResults extends React.Component, option?: IDropdownOption) : void => { - this._loadItems( + this.loadItems( this.props.input, this.state.includePrerelease, this.state.packageType, @@ -319,12 +406,14 @@ class SearchResults extends React.Component { - this._loadItems( + this.loadItems( this.props.input, !this.state.includePrerelease, this.state.packageType, this.state.targetFramework); } + + private loadMore = () : void => this.loadMoreItems(); } export default SearchResults;