Skip to content

Commit

Permalink
feat(discover): ✨ Added infinite scroll on advanced search results
Browse files Browse the repository at this point in the history
* feat(discover): ✨ Added infinite scroll on advanced search results
  • Loading branch information
tidusjar committed Jul 22, 2022
1 parent e00e39a commit 898bc89
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 40 deletions.
14 changes: 7 additions & 7 deletions src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs
Expand Up @@ -152,15 +152,15 @@ public async Task<IEnumerable<SearchMovieViewModel>> AdvancedSearch(DiscoverMode
{
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>
Expand Down
2 changes: 1 addition & 1 deletion src/Ombi.TheMovieDbApi/IMovieDbApi.cs
Expand Up @@ -45,6 +45,6 @@ public interface IMovieDbApi
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);
}
}
20 changes: 12 additions & 8 deletions src/Ombi.TheMovieDbApi/TheMovieDbApi.cs
Expand Up @@ -70,11 +70,11 @@ public async Task<TheMovieDbContainer<DiscoverMovies>> DiscoverMovies(string lan



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());
}
Expand All @@ -92,6 +92,9 @@ public async Task<List<MovieDbSearchResult>> AdvancedSearch(DiscoverModel model,
}
//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);
}
Expand Down Expand Up @@ -139,7 +142,7 @@ public async Task<ActorCredits> GetActorMovieCredits(int actorId, string langCod
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);
Expand Down Expand Up @@ -281,7 +284,7 @@ private async Task<List<MovieDbSearchResult>> TopRated(string type, string langC
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);
Expand All @@ -295,7 +298,7 @@ private async Task<List<MovieDbSearchResult>> Trending(string type, string langC
{
// 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);

Expand Down Expand Up @@ -413,8 +416,8 @@ public async Task<List<MovieDbSearchResult>> GetMoviesViaKeywords(string keyword
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
Expand Down Expand Up @@ -530,7 +533,8 @@ private async Task AddGenreFilter(Request request, string media_type)
var settings = await Settings;
List<int> excludedGenres;

switch (media_type) {
switch (media_type)
{
case "tv":
excludedGenres = settings.ExcludedTvGenreIds;
break;
Expand Down
2 changes: 1 addition & 1 deletion src/Ombi/ClientApp/package.json
Expand Up @@ -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",
Expand Down
Expand Up @@ -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>
Expand Down
Expand Up @@ -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,
Expand Down Expand Up @@ -65,7 +66,7 @@ export class DiscoverSearchResultsComponent implements OnInit {
}
});

if (this.advancedDataService) {
if (this.isAdvancedSearch) {
return;
}
this.loadingFlag = true;
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/Ombi/ClientApp/src/app/search/tvsearch.component.ts
Expand Up @@ -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
Expand Down
Expand Up @@ -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) {
Expand All @@ -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;
}
Expand Down
Expand Up @@ -33,7 +33,6 @@ <h1 id="advancedOptionsTitle">


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

Expand Down
Expand Up @@ -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);
}
Expand Down
21 changes: 5 additions & 16 deletions src/Ombi/ClientApp/yarn.lock
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions tests/cypress/fixtures/api/v1/tv-search-extra-info.json
Expand Up @@ -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
},
Expand Down

0 comments on commit 898bc89

Please sign in to comment.