feat(discover): Added infinite scroll on advanced search results

* feat(discover):  Added infinite scroll on advanced search results
pull/4694/head
Jamie 2 years ago committed by GitHub
parent e00e39a1be
commit 898bc89fa7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -152,15 +152,15 @@ namespace Ombi.Core.Engine.V2
{
var langCode = await DefaultLanguageCode(null);
//var pages = PaginationHelper.GetNextPages(currentlyLoaded, toLoad, _theMovieDbMaxPageItems);
var pages = PaginationHelper.GetNextPages(currentlyLoaded, toLoad, _theMovieDbMaxPageItems);
var results = new List<MovieDbSearchResult>();
//foreach (var pagesToLoad in pages)
//{
var apiResult = await MovieApi.AdvancedSearch(model, cancellationToken);
//results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take));
//}
return await TransformMovieResultsToResponse(apiResult);
foreach (var pagesToLoad in pages)
{
var apiResult = await MovieApi.AdvancedSearch(model, pagesToLoad.Page, cancellationToken);
results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take));
}
return await TransformMovieResultsToResponse(results);
}
/// <summary>

@ -45,6 +45,6 @@ namespace Ombi.Api.TheMovieDb
Task<List<Genre>> GetGenres(string media, CancellationToken cancellationToken, string languageCode);
Task<List<Language>> GetLanguages(CancellationToken cancellationToken);
Task<List<WatchProvidersResults>> SearchWatchProviders(string media, string searchTerm, CancellationToken cancellationToken);
Task<List<MovieDbSearchResult>> AdvancedSearch(DiscoverModel model, CancellationToken cancellationToken);
Task<List<MovieDbSearchResult>> AdvancedSearch(DiscoverModel model, int page, CancellationToken cancellationToken);
}
}

@ -70,11 +70,11 @@ namespace Ombi.Api.TheMovieDb
public async Task<List<MovieDbSearchResult>> AdvancedSearch(DiscoverModel model, CancellationToken cancellationToken)
public async Task<List<MovieDbSearchResult>> AdvancedSearch(DiscoverModel model, int page, CancellationToken cancellationToken)
{
var request = new Request($"discover/{model.Type}", BaseUri, HttpMethod.Get);
request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken);
if(model.ReleaseYear.HasValue && model.ReleaseYear.Value > 1900)
if (model.ReleaseYear.HasValue && model.ReleaseYear.Value > 1900)
{
request.FullUri = request.FullUri.AddQueryParameter("year", model.ReleaseYear.Value.ToString());
}
@ -92,6 +92,9 @@ namespace Ombi.Api.TheMovieDb
}
//request.FullUri = request.FullUri.AddQueryParameter("sort_by", "popularity.desc");
request.AddQueryString("page", page.ToString());
var result = await Api.Request<TheMovieDbContainer<SearchResult>>(request, cancellationToken);
return Mapper.Map<List<MovieDbSearchResult>>(result.results);
}
@ -139,7 +142,7 @@ namespace Ombi.Api.TheMovieDb
var result = await Api.Request<ActorCredits>(request);
return result;
}
public async Task<ActorCredits> GetActorTvCredits(int actorId, string langCode)
{
var request = new Request($"person/{actorId}/tv_credits", BaseUri, HttpMethod.Get);
@ -281,7 +284,7 @@ namespace Ombi.Api.TheMovieDb
var result = await Api.Request<TheMovieDbContainer<SearchResult>>(request);
return Mapper.Map<List<MovieDbSearchResult>>(result.results);
}
public Task<List<MovieDbSearchResult>> TrendingMovies(string langCode, int? page = null)
{
return Trending("movie", langCode, page);
@ -295,7 +298,7 @@ namespace Ombi.Api.TheMovieDb
{
// https://developers.themoviedb.org/3/trending/get-trending
var timeWindow = "week"; // another option can be 'day'
var request = new Request($"trending/{type}/{timeWindow}", BaseUri, HttpMethod.Get);
var request = new Request($"trending/{type}/{timeWindow}", BaseUri, HttpMethod.Get);
request.AddQueryString("api_key", ApiToken);
request.AddQueryString("language", langCode);
@ -413,8 +416,8 @@ namespace Ombi.Api.TheMovieDb
request.AddQueryString("language", langCode);
request.AddQueryString("sort_by", "vote_average.desc");
request.AddQueryString("with_keywords", keywordId);
request.AddQueryString("with_keywords", keywordId);
// `vote_count` consideration isn't explicitly documented, but using only the `sort_by` filter
// does not provide the same results as `/movie/top_rated`. This appears to be adequate enough
// to filter out extremely high-rated movies due to very little votes
@ -530,7 +533,8 @@ namespace Ombi.Api.TheMovieDb
var settings = await Settings;
List<int> excludedGenres;
switch (media_type) {
switch (media_type)
{
case "tv":
excludedGenres = settings.ExcludedTvGenreIds;
break;

@ -47,7 +47,7 @@
"moment": "^2.29.1",
"ng2-cookies": "^1.0.12",
"ngx-clipboard": "^12.1.0",
"ngx-infinite-scroll": "^9.0.0",
"ngx-infinite-scroll": "^14.0.0",
"ngx-moment": "^3.0.1",
"ngx-order-pipe": "^2.2.0",
"popper.js": "^1.14.3",

@ -2,7 +2,13 @@
<div *ngIf="loadingFlag" class="row justify-content-md-center top-spacing loading-spinner">
<mat-spinner [color]="'accent'"></mat-spinner>
</div>
<div *ngIf="discoverResults.length > 0" class="row full-height discoverResults col" >
<div *ngIf="discoverResults.length > 0"
class="row full-height discoverResults col"
infiniteScroll
[infiniteScrollDistance]="3"
[infiniteScrollThrottle]="200"
(scrolled)="onScroll()">
<div id="searchResults" class="col-xl-2 col-lg-3 col-md-3 col-6 col-sm-4 small-padding" *ngFor="let result of discoverResults" data-test="searchResultsCount" attr.search-count="{{discoverResults.length}}">
<discover-card [isAdmin]="isAdmin" [result]="result" [is4kEnabled]="is4kEnabled"></discover-card>
</div>

@ -29,6 +29,7 @@ export class DiscoverSearchResultsComponent implements OnInit {
public filter: SearchFilter;
private isAdvancedSearch: boolean;
private loadPosition: number = 30;
constructor(private searchService: SearchV2Service,
private route: ActivatedRoute,
@ -65,7 +66,7 @@ export class DiscoverSearchResultsComponent implements OnInit {
}
});
if (this.advancedDataService) {
if (this.isAdvancedSearch) {
return;
}
this.loadingFlag = true;
@ -179,6 +180,31 @@ export class DiscoverSearchResultsComponent implements OnInit {
});
}
public onScroll() {
console.log("scrolled");
if (this.advancedDataService) {
this.loadMoreAdvancedSearch();
return;
}
}
private loadMoreAdvancedSearch() {
const advancedOptions = this.advancedDataService.getOptions();
this.searchService.advancedSearch({
type: advancedOptions.type == RequestType.movie ? "movie" : "tv",
companies: advancedOptions.companies,
genreIds: advancedOptions.genres,
keywordIds : advancedOptions.keywords,
releaseYear: advancedOptions.releaseYear,
watchProviders: advancedOptions.watchProviders,
}, this.loadPosition, 30).then(x => {
this.loadPosition += 30;
this.mapAdvancedData(x);
});
}
private async search() {
this.clear();
this.results = await this.searchService

@ -37,7 +37,7 @@ export class TvSearchComponent implements OnInit {
private notificationService: NotificationService, private authService: AuthService,
private imageService: ImageService, private sanitizer: DomSanitizer,
@Inject(APP_BASE_HREF) href:string) {
this.href = href;
this.href = href;
this.searchChanged.pipe(
debounceTime(600), // Wait Xms after the last event before emitting last event
distinctUntilChanged(), // only emit if value is different from previous value

@ -8,7 +8,9 @@ import { RequestType } from "../../interfaces";
export class AdvancedSearchDialogDataService {
@Output() public onDataChange = new EventEmitter<any>();
@Output() public onOptionsChange = new EventEmitter<any>();
private _data: any;
private _options: any;
private _type: RequestType;
setData(data: any, type: RequestType) {
@ -17,10 +19,30 @@ export class AdvancedSearchDialogDataService {
this.onDataChange.emit(this._data);
}
setOptions(watchProviders: number[], genres: number[], keywords: number[], releaseYear: number, type: RequestType, position: number) {
this._options = {
watchProviders,
genres,
keywords,
releaseYear,
type,
position
};
this.onOptionsChange.emit(this._options);
}
getData(): any {
return this._data;
}
getOptions(): any {
return this._options;
}
getLoaded(): number {
return this._options.loaded;
}
getType(): RequestType {
return this._type;
}

@ -33,7 +33,6 @@
<div class="col-md-12">
<mat-label>{{ "Search.YearOfRelease" | translate }}</mat-label>
<genre-select [form]="form" [mediaType]="form.controls.type.value"></genre-select>
</div>

@ -49,7 +49,9 @@ export class AdvancedSearchDialogComponent implements OnInit {
type: formData.type,
}, 0, 30);
this.advancedSearchDialogService.setData(data, formData.type === 'movie' ? RequestType.movie : RequestType.tvShow);
const type = formData.type === 'movie' ? RequestType.movie : RequestType.tvShow;
this.advancedSearchDialogService.setData(data, type);
this.advancedSearchDialogService.setOptions(watchProviderIds, genres, keywords, formData.releaseYear, type, 30);
this.dialogRef.close(true);
}

@ -1902,11 +1902,6 @@
node-gyp "^8.4.1"
read-package-json-fast "^2.0.3"
"@scarf/scarf@^1.1.0":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@scarf/scarf/-/scarf-1.1.1.tgz#d8b9f20037b3a37dbf8dcdc4b3b72f9285bfce35"
integrity sha512-VGbKDbk1RFIaSmdVb0cNjjWJoRWRI/Weo23AjRCC2nryO0iAS8pzsToJfPVPtVs74WHw4L1UTADNdIYRLkirZQ==
"@schematics/angular@14.0.0":
version "14.0.0"
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-14.0.0.tgz#de6cb4c86586ed5b06adfd7a759cc9908e627787"
@ -5619,13 +5614,12 @@ ngx-clipboard@^12.1.0:
ngx-window-token "^2.0.0"
tslib "^1.9.0"
ngx-infinite-scroll@^9.0.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-9.1.0.tgz#6716a47613ff59f236b85c3ce291b2fd57106824"
integrity sha512-ZulbahgFsoPmP8cz7qPGDeFX9nKiSm74aav8vXNSI1ZoPiGYY5FQd8AK+yXqygY7tyCJRyt8Wp3DIg7zgP5dPA==
ngx-infinite-scroll@^14.0.0:
version "14.0.0"
resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-14.0.0.tgz#395b15be5f451c3e3d2ad7ce2aeb66f8c66aba5d"
integrity sha512-YZB5PBPXSERNtCGQRZTVflbgkh5asp01NPfC8KPItemmQik1Ip8ZCCbcyHA77TDTdilmaiu8TbguA3geg/LMWw==
dependencies:
"@scarf/scarf" "^1.1.0"
opencollective-postinstall "^2.0.2"
tslib "^2.3.0"
ngx-moment@^3.0.1:
version "3.5.0"
@ -5901,11 +5895,6 @@ open@8.4.0, open@^8.0.9:
is-docker "^2.1.1"
is-wsl "^2.2.0"
opencollective-postinstall@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259"
integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==
ora@5.4.1, ora@^5.4.1:
version "5.4.1"
resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18"

@ -25,14 +25,14 @@
{
"episodeNumber": 1,
"title": "Our Cup Runneth Over",
"airDate": "2015-01-14T01:00:00+00:00",
"airDate": "2015-01-13T00:00:00",
"url": "https://www.tvmaze.com/episodes/153107/schitts-creek-1x01-our-cup-runneth-over",
"available": false,
"approved": false,
"requested": false,
"seasonId": 0,
"season": null,
"airDateDisplay": "01/14/2015 01:00:00",
"airDateDisplay": "01/13/2015 00:00:00",
"requestStatus": "",
"id": 0
},

Loading…
Cancel
Save