mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-15 16:20:03 +00:00
Added filter for player perspective
This commit is contained in:
@@ -100,6 +100,18 @@
|
|||||||
color="primary">{{theme.name}}</mat-checkbox>
|
color="primary">{{theme.name}}</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
</mat-expansion-panel>
|
</mat-expansion-panel>
|
||||||
|
|
||||||
|
<mat-expansion-panel *ngIf="availablePlayerPerspectives.length > 0">
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<h3 class="filter-category-title">Player Perspectives</h3>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
|
||||||
|
<div fxLayout="column">
|
||||||
|
<mat-checkbox *ngFor="let playerPerspective of availablePlayerPerspectives" (change)="togglePlayerPerspectiveFilter(playerPerspective.slug)"
|
||||||
|
[checked]="activePlayerPerspectiveFilters.includes(playerPerspective.slug)"
|
||||||
|
color="primary">{{playerPerspective.name}}</mat-checkbox>
|
||||||
|
</div>
|
||||||
|
</mat-expansion-panel>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fxFlex="0 1 1"><!--SPACER--></div>
|
<div fxFlex="0 1 1"><!--SPACER--></div>
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import {GenreDto} from "../../models/dtos/GenreDto";
|
|||||||
import {ThemeDto} from "../../models/dtos/ThemeDto";
|
import {ThemeDto} from "../../models/dtos/ThemeDto";
|
||||||
import {firstValueFrom, forkJoin, Observable, pipe} from "rxjs";
|
import {firstValueFrom, forkJoin, Observable, pipe} from "rxjs";
|
||||||
import {SortDirection} from "@angular/material/sort";
|
import {SortDirection} from "@angular/material/sort";
|
||||||
|
import {CompanyDto} from "../../models/dtos/CompanyDto";
|
||||||
|
import {PlayerPerspectiveDto} from "../../models/dtos/PlayerPerspectiveDto";
|
||||||
|
|
||||||
class SortOption {
|
class SortOption {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -48,10 +50,12 @@ export class LibraryOverviewComponent implements AfterContentInit {
|
|||||||
lanSupportFilterEnabled: boolean = false;
|
lanSupportFilterEnabled: boolean = false;
|
||||||
activeThemeFilters: string[] = [];
|
activeThemeFilters: string[] = [];
|
||||||
activeGenreFilters: string[] = [];
|
activeGenreFilters: string[] = [];
|
||||||
|
activePlayerPerspectiveFilters: string[] = [];
|
||||||
|
|
||||||
games: DetectedGameDto[] = [];
|
games: DetectedGameDto[] = [];
|
||||||
availableGenres: GenreDto[] = [];
|
availableGenres: GenreDto[] = [];
|
||||||
availableThemes: ThemeDto[] = [];
|
availableThemes: ThemeDto[] = [];
|
||||||
|
availablePlayerPerspectives: PlayerPerspectiveDto[] = [];
|
||||||
|
|
||||||
loading: boolean = true;
|
loading: boolean = true;
|
||||||
gameLibraryIsEmpty: boolean = false;
|
gameLibraryIsEmpty: boolean = false;
|
||||||
@@ -72,10 +76,13 @@ export class LibraryOverviewComponent implements AfterContentInit {
|
|||||||
|
|
||||||
let genreObservable: Observable<ThemeDto[]> = this.gameServerService.getAvailableGenres();
|
let genreObservable: Observable<ThemeDto[]> = this.gameServerService.getAvailableGenres();
|
||||||
let themeObservable: Observable<GenreDto[]> = this.gameServerService.getAvailableThemes();
|
let themeObservable: Observable<GenreDto[]> = this.gameServerService.getAvailableThemes();
|
||||||
|
let playerPerspectiveObservable: Observable<PlayerPerspectiveDto[]> = this.gameServerService.getAvailablePlayerPerspectives();
|
||||||
|
|
||||||
|
forkJoin([genreObservable, themeObservable, playerPerspectiveObservable]).subscribe(result => {
|
||||||
|
this.availableGenres = result[0];
|
||||||
|
this.availableThemes = result[1];
|
||||||
|
this.availablePlayerPerspectives = result[2];
|
||||||
|
|
||||||
forkJoin([themeObservable, genreObservable]).subscribe(result => {
|
|
||||||
this.availableThemes = result[0];
|
|
||||||
this.availableGenres = result[1];
|
|
||||||
this.refreshLibraryView().then(() => this.loading = false);
|
this.refreshLibraryView().then(() => this.loading = false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -109,6 +116,10 @@ export class LibraryOverviewComponent implements AfterContentInit {
|
|||||||
games = games.filter(game => this.activeThemeFilters.every(activeThemeFilter => game.themes?.map(g => g.slug).includes(activeThemeFilter)));
|
games = games.filter(game => this.activeThemeFilters.every(activeThemeFilter => game.themes?.map(g => g.slug).includes(activeThemeFilter)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.activePlayerPerspectiveFilters.length > 0) {
|
||||||
|
games = games.filter(game => this.activePlayerPerspectiveFilters.every(activePlayerPerspectiveFilter => game.playerPerspectives?.map(g => g.slug).includes(activePlayerPerspectiveFilter)));
|
||||||
|
}
|
||||||
|
|
||||||
return games;
|
return games;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,4 +168,19 @@ export class LibraryOverviewComponent implements AfterContentInit {
|
|||||||
this.refreshLibraryView();
|
this.refreshLibraryView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
togglePlayerPerspectiveFilter(slug: string) {
|
||||||
|
if (this.activePlayerPerspectiveFilters.includes(slug)) {
|
||||||
|
|
||||||
|
const index = this.activePlayerPerspectiveFilters.indexOf(slug, 0);
|
||||||
|
if (index > -1) {
|
||||||
|
this.activePlayerPerspectiveFilters.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.activePlayerPerspectiveFilters.push(slug);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.refreshLibraryView();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export class PlayerPerspectiveDto {
|
export class PlayerPerspectiveDto {
|
||||||
slug!: string;
|
slug!: string;
|
||||||
name?: string;
|
name!: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import {DetectedGameDto} from "../models/dtos/DetectedGameDto";
|
|||||||
import {GameOverviewDto} from "../models/dtos/GameOverviewDto";
|
import {GameOverviewDto} from "../models/dtos/GameOverviewDto";
|
||||||
import {GenreDto} from "../models/dtos/GenreDto";
|
import {GenreDto} from "../models/dtos/GenreDto";
|
||||||
import {ThemeDto} from "../models/dtos/ThemeDto";
|
import {ThemeDto} from "../models/dtos/ThemeDto";
|
||||||
|
import {CompanyDto} from "../models/dtos/CompanyDto";
|
||||||
|
import {PlayerPerspectiveDto} from "../models/dtos/PlayerPerspectiveDto";
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -64,7 +66,7 @@ export class GamesService implements GamesApi {
|
|||||||
return this.getAllGames().pipe(
|
return this.getAllGames().pipe(
|
||||||
map<DetectedGameDto[], ThemeDto[]>(
|
map<DetectedGameDto[], ThemeDto[]>(
|
||||||
games => {
|
games => {
|
||||||
let availableThemesMap: Map<string, ThemeDto> = new Map<string, GenreDto>;
|
let availableThemesMap: Map<string, ThemeDto> = new Map<string, ThemeDto>;
|
||||||
games.map(game => game.themes === undefined ? [] : game.themes).flat().forEach(theme => availableThemesMap.set(theme.slug, theme));
|
games.map(game => game.themes === undefined ? [] : game.themes).flat().forEach(theme => availableThemesMap.set(theme.slug, theme));
|
||||||
return Array.from(availableThemesMap.values()).sort((t1, t2) => t1.name.localeCompare(t2.name));
|
return Array.from(availableThemesMap.values()).sort((t1, t2) => t1.name.localeCompare(t2.name));
|
||||||
}
|
}
|
||||||
@@ -72,6 +74,20 @@ export class GamesService implements GamesApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This method of removing duplicates is most certainly an anti-pattern in RxJS
|
||||||
|
// TODO: However, I did not get the 'distinct()' pipe to work properly, so I have to take another look in the future
|
||||||
|
getAvailablePlayerPerspectives(): Observable<PlayerPerspectiveDto[]> {
|
||||||
|
return this.getAllGames().pipe(
|
||||||
|
map<DetectedGameDto[], PlayerPerspectiveDto[]>(
|
||||||
|
games => {
|
||||||
|
let availablePlayerPerspectivesMap: Map<string, PlayerPerspectiveDto> = new Map<string, PlayerPerspectiveDto>;
|
||||||
|
games.map(game => game.playerPerspectives === undefined ? [] : game.playerPerspectives).flat().forEach(playerPerspective => availablePlayerPerspectivesMap.set(playerPerspective.slug, playerPerspective));
|
||||||
|
return Array.from(availablePlayerPerspectivesMap.values()).sort((t1, t2) => t1.name.localeCompare(t2.name));
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
downloadGame(slug: String): void {
|
downloadGame(slug: String): void {
|
||||||
window.open(`v1${this.apiPath}/game/${slug}/download`, '_top');
|
window.open(`v1${this.apiPath}/game/${slug}/download`, '_top');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user