mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-16 16:20:04 +00:00
+1
-1
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>gameyfin</artifactId>
|
<artifactId>gameyfin</artifactId>
|
||||||
<groupId>de.grimsi</groupId>
|
<groupId>de.grimsi</groupId>
|
||||||
<version>1.1.0</version>
|
<version>1.1.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>gameyfin-backend</artifactId>
|
<artifactId>gameyfin-backend</artifactId>
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>gameyfin</artifactId>
|
<artifactId>gameyfin</artifactId>
|
||||||
<groupId>de.grimsi</groupId>
|
<groupId>de.grimsi</groupId>
|
||||||
<version>1.1.0</version>
|
<version>1.1.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -28,14 +28,14 @@
|
|||||||
<div *ngIf="game.genres !== undefined && game.genres.length > 0">
|
<div *ngIf="game.genres !== undefined && game.genres.length > 0">
|
||||||
<h2>Genres</h2>
|
<h2>Genres</h2>
|
||||||
<mat-chip-list>
|
<mat-chip-list>
|
||||||
<mat-chip *ngFor="let genre of game.genres">{{genre.name}}</mat-chip>
|
<mat-chip *ngFor="let genre of game.genres" (click)="goToLibraryWithFilter('genres', genre.slug)">{{genre.name}}</mat-chip>
|
||||||
</mat-chip-list>
|
</mat-chip-list>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="game.themes !== undefined && game.themes.length > 0">
|
<div *ngIf="game.themes !== undefined && game.themes.length > 0">
|
||||||
<h2>Themes</h2>
|
<h2>Themes</h2>
|
||||||
<mat-chip-list>
|
<mat-chip-list>
|
||||||
<mat-chip *ngFor="let theme of game.themes">{{theme.name}}</mat-chip>
|
<mat-chip *ngFor="let theme of game.themes" (click)="goToLibraryWithFilter('themes', theme.slug)">{{theme.name}}</mat-chip>
|
||||||
</mat-chip-list>
|
</mat-chip-list>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import {ActivatedRoute, Router} from "@angular/router";
|
import {ActivatedRoute, Params, Router} from "@angular/router";
|
||||||
import {DetectedGameDto} from "../../models/dtos/DetectedGameDto";
|
import {DetectedGameDto} from "../../models/dtos/DetectedGameDto";
|
||||||
import {GamesService} from "../../services/games.service";
|
import {GamesService} from "../../services/games.service";
|
||||||
import {HttpErrorResponse} from "@angular/common/http";
|
|
||||||
import {takeWhile} from "rxjs";
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-game-detail-view',
|
selector: 'app-game-detail-view',
|
||||||
@@ -58,4 +56,10 @@ export class GameDetailViewComponent implements OnInit {
|
|||||||
return bytes.toFixed(dp) + ' ' + units[u];
|
return bytes.toFixed(dp) + ' ' + units[u];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goToLibraryWithFilter(field: string, value: string) {
|
||||||
|
let params: Params = {};
|
||||||
|
params[field] = value;
|
||||||
|
this.router.navigate(['/library'], {queryParams: params});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,33 @@
|
|||||||
<div *ngIf="loggedIn && (this.unmappedFiles.length > 0 || this.mappedGames.length > 0)" fxFlexFill fxLayoutAlign="center start">
|
<div fxFlexFill>
|
||||||
<mat-tab-group>
|
<div *ngIf="loggedIn && (this.unmappedFiles.length > 0 || this.mappedGames.length > 0)" fxFlex fxLayoutAlign="center start">
|
||||||
<mat-tab label="Game mappings">
|
<mat-tab-group>
|
||||||
<mapped-games-table [mappedGames]="mappedGames"></mapped-games-table>
|
<mat-tab label="Game mappings">
|
||||||
</mat-tab>
|
<mapped-games-table [mappedGames]="mappedGames"></mapped-games-table>
|
||||||
<mat-tab label="Unmapped files">
|
</mat-tab>
|
||||||
<unmapped-files-table [unmappedFiles]="unmappedFiles"></unmapped-files-table>
|
<mat-tab label="Unmapped files">
|
||||||
</mat-tab>
|
<unmapped-files-table [unmappedFiles]="unmappedFiles"></unmapped-files-table>
|
||||||
</mat-tab-group>
|
</mat-tab>
|
||||||
</div>
|
</mat-tab-group>
|
||||||
|
|
||||||
<div *ngIf="!loggedIn" fxFlex fxLayout="column" fxLayoutAlign="center center" style="height: calc(100vh - 64px)">
|
|
||||||
<div fxLayout="column" fxLayoutAlign="center center">
|
|
||||||
<mat-icon fontSet="material-icons-outlined" color="primary" style="font-size: 128px; height: 128px; width: 128px;">
|
|
||||||
lock
|
|
||||||
</mat-icon>
|
|
||||||
<h1>Please log in to manage your game library</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div *ngIf="loggedIn && this.unmappedFiles.length === 0 && this.mappedGames.length === 0" fxFlex fxLayout="column" fxLayoutAlign="center center" style="height: calc(100vh - 64px)">
|
|
||||||
<div class="library-management-hint" fxLayout="column" fxLayoutAlign="start end">
|
|
||||||
<mat-icon fontSet="material-icons-outlined">north_east</mat-icon>
|
|
||||||
<p>Use the library management to scan your file system for games</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fxLayout="column" fxLayoutAlign="center center">
|
<div *ngIf="!loggedIn" fxFlex fxLayout="column" fxLayoutAlign="center center">
|
||||||
<mat-icon fontSet="material-icons-outlined" color="primary" style="font-size: 128px; height: 128px; width: 128px;">videogame_asset_off</mat-icon>
|
<div fxLayout="column" fxLayoutAlign="center center">
|
||||||
<h1>Your game library is empty!</h1>
|
<mat-icon fontSet="material-icons-outlined" color="primary" style="font-size: 128px; height: 128px; width: 128px;">
|
||||||
|
lock
|
||||||
|
</mat-icon>
|
||||||
|
<h1>Please log in to manage your game library</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="loggedIn && this.unmappedFiles.length === 0 && this.mappedGames.length === 0" fxFlex fxLayout="column" fxLayoutAlign="center center">
|
||||||
|
<div class="library-management-hint" fxLayout="column" fxLayoutAlign="start end">
|
||||||
|
<mat-icon fontSet="material-icons-outlined">north_east</mat-icon>
|
||||||
|
<p>Use the library management to scan your file system for games</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxLayout="column" fxLayoutAlign="center center">
|
||||||
|
<mat-icon fontSet="material-icons-outlined" color="primary" style="font-size: 128px; height: 128px; width: 128px;">videogame_asset_off</mat-icon>
|
||||||
|
<h1>Your game library is empty!</h1>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,23 +4,21 @@
|
|||||||
<h2>Loading library...</h2>
|
<h2>Loading library...</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="!this.loading && this.gameLibraryIsEmpty" fxFlex fxLayout="column" fxLayoutAlign="center center"
|
<div *ngIf="!this.loading && this.gameLibraryIsEmpty" fxFlex fxLayout="column" fxLayoutAlign="center center">
|
||||||
style="height: calc(100vh - 64px)">
|
|
||||||
<div class="library-management-hint" fxLayout="column" fxLayoutAlign="start end">
|
<div class="library-management-hint" fxLayout="column" fxLayoutAlign="start end">
|
||||||
<mat-icon fontSet="material-icons-outlined">north_east</mat-icon>
|
<mat-icon fontSet="material-icons-outlined">north_east</mat-icon>
|
||||||
<p>Use the library management to scan your file system for games</p>
|
<p>Use the library management to scan your file system for games</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fxLayout="column" fxLayoutAlign="center center">
|
<div fxLayout="column" fxLayoutAlign="center center">
|
||||||
<mat-icon fontSet="material-icons-outlined" color="primary"
|
<mat-icon fontSet="material-icons-outlined" color="primary" style="font-size: 128px; height: 128px; width: 128px;">
|
||||||
style="font-size: 128px; height: 128px; width: 128px;">videogame_asset_off
|
videogame_asset_off
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
<h1>Your game library is empty!</h1>
|
<h1>Your game library is empty!</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content" fxLayout="row" fxLayout.lt-lg="column" fxFlexFill="100"
|
<div class="content" fxLayout="row" fxLayout.lt-lg="column" fxFlexFill="100" *ngIf="!this.loading && !this.gameLibraryIsEmpty">
|
||||||
*ngIf="!this.loading && !this.gameLibraryIsEmpty">
|
|
||||||
<div fxFlex="10" fxHide fxShow.gt-md><!--SPACER--></div>
|
<div fxFlex="10" fxHide fxShow.gt-md><!--SPACER--></div>
|
||||||
|
|
||||||
<div fxFlex.gt-md="0 1 15" fxLayout="column" fxLayoutGap="16px" fxLayoutAlign.lt-lg="start center"
|
<div fxFlex.gt-md="0 1 15" fxLayout="column" fxLayoutGap="16px" fxLayoutAlign.lt-lg="start center"
|
||||||
@@ -56,7 +54,7 @@
|
|||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
<mat-expansion-panel>
|
<mat-expansion-panel [expanded]="offlineCoopFilterEnabled || onlineCoopFilterEnabled || lanSupportFilterEnabled">
|
||||||
<mat-expansion-panel-header>
|
<mat-expansion-panel-header>
|
||||||
<mat-panel-title fxLayout="row" fxLayoutAlign="start start" fxLayoutGap="6px">
|
<mat-panel-title fxLayout="row" fxLayoutAlign="start start" fxLayoutGap="6px">
|
||||||
<h3 class="filter-category-title">Gamemodes</h3>
|
<h3 class="filter-category-title">Gamemodes</h3>
|
||||||
@@ -77,7 +75,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</mat-expansion-panel>
|
</mat-expansion-panel>
|
||||||
|
|
||||||
<mat-expansion-panel *ngIf="availableGenres.length > 0">
|
<mat-expansion-panel *ngIf="availableGenres.length > 0" [expanded]="activeGenreFilters.length > 0">
|
||||||
<mat-expansion-panel-header>
|
<mat-expansion-panel-header>
|
||||||
<h3 class="filter-category-title">Genres</h3>
|
<h3 class="filter-category-title">Genres</h3>
|
||||||
</mat-expansion-panel-header>
|
</mat-expansion-panel-header>
|
||||||
@@ -89,7 +87,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</mat-expansion-panel>
|
</mat-expansion-panel>
|
||||||
|
|
||||||
<mat-expansion-panel *ngIf="availableThemes.length > 0">
|
<mat-expansion-panel *ngIf="availableThemes.length > 0" [expanded]="activeThemeFilters.length > 0">
|
||||||
<mat-expansion-panel-header>
|
<mat-expansion-panel-header>
|
||||||
<h3 class="filter-category-title">Themes</h3>
|
<h3 class="filter-category-title">Themes</h3>
|
||||||
</mat-expansion-panel-header>
|
</mat-expansion-panel-header>
|
||||||
@@ -101,7 +99,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</mat-expansion-panel>
|
</mat-expansion-panel>
|
||||||
|
|
||||||
<mat-expansion-panel *ngIf="availablePlayerPerspectives.length > 0">
|
<mat-expansion-panel *ngIf="availablePlayerPerspectives.length > 0" [expanded]="activePlayerPerspectiveFilters.length > 0">
|
||||||
<mat-expansion-panel-header>
|
<mat-expansion-panel-header>
|
||||||
<h3 class="filter-category-title">Player Perspectives</h3>
|
<h3 class="filter-category-title">Player Perspectives</h3>
|
||||||
</mat-expansion-panel-header>
|
</mat-expansion-panel-header>
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ import {ThemeDto} from "../../models/dtos/ThemeDto";
|
|||||||
import {firstValueFrom, forkJoin, Observable} from "rxjs";
|
import {firstValueFrom, forkJoin, Observable} from "rxjs";
|
||||||
import {SortDirection} from "@angular/material/sort";
|
import {SortDirection} from "@angular/material/sort";
|
||||||
import {PlayerPerspectiveDto} from "../../models/dtos/PlayerPerspectiveDto";
|
import {PlayerPerspectiveDto} from "../../models/dtos/PlayerPerspectiveDto";
|
||||||
import {ActivatedRoute, Params, Router} from "@angular/router";
|
import {ActivatedRoute, ActivatedRouteSnapshot, Params, Router} from "@angular/router";
|
||||||
import {Location} from "@angular/common";
|
import {Location} from "@angular/common";
|
||||||
import {HttpParams} from "@angular/common/http";
|
|
||||||
|
|
||||||
class SortOption {
|
class SortOption {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -61,6 +60,7 @@ export class LibraryOverviewComponent implements AfterContentInit {
|
|||||||
|
|
||||||
loading: boolean = true;
|
loading: boolean = true;
|
||||||
gameLibraryIsEmpty: boolean = false;
|
gameLibraryIsEmpty: boolean = false;
|
||||||
|
private previousStateParams: Params = {};
|
||||||
|
|
||||||
constructor(private gameServerService: GamesService,
|
constructor(private gameServerService: GamesService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
@@ -88,16 +88,15 @@ export class LibraryOverviewComponent implements AfterContentInit {
|
|||||||
this.availableThemes = result[1];
|
this.availableThemes = result[1];
|
||||||
this.availablePlayerPerspectives = result[2];
|
this.availablePlayerPerspectives = result[2];
|
||||||
|
|
||||||
this.route.queryParams.subscribe(params => {
|
this.previousStateParams = this.route.snapshot.queryParams;
|
||||||
if (params['search'] !== undefined) this.searchTerm = params['search'];
|
if (this.previousStateParams['search'] !== undefined) this.searchTerm = this.previousStateParams['search'];
|
||||||
if (params['sort'] !== undefined) this.selectedSortOption = this.matchSelectedSortOptionFromParam(params['sort']);
|
if (this.previousStateParams['sort'] !== undefined) this.selectedSortOption = this.matchSelectedSortOptionFromParam(this.previousStateParams['sort']);
|
||||||
if (params['gamemodes'] !== undefined) this.setSelectedGamemodesFromParam(params['gamemodes']);
|
if (this.previousStateParams['gamemodes'] !== undefined) this.setSelectedGamemodesFromParam(this.previousStateParams['gamemodes']);
|
||||||
if (params['genres'] !== undefined) this.activeGenreFilters = this.matchSelectedFilters(this.availableGenres, params['genres']);
|
if (this.previousStateParams['genres'] !== undefined) this.activeGenreFilters = this.matchSelectedFilters(this.availableGenres, this.previousStateParams['genres']);
|
||||||
if (params['themes'] !== undefined) this.activeThemeFilters = this.matchSelectedFilters(this.availableThemes, params['themes']);
|
if (this.previousStateParams['themes'] !== undefined) this.activeThemeFilters = this.matchSelectedFilters(this.availableThemes, this.previousStateParams['themes']);
|
||||||
if (params['playerPerspectives'] !== undefined) this.activePlayerPerspectiveFilters = this.matchSelectedFilters(this.availablePlayerPerspectives, params['playerPerspectives']);
|
if (this.previousStateParams['playerPerspectives'] !== undefined) this.activePlayerPerspectiveFilters = this.matchSelectedFilters(this.availablePlayerPerspectives, this.previousStateParams['playerPerspectives']);
|
||||||
|
|
||||||
this.refreshLibraryView().then(() => this.loading = false);
|
this.refreshLibraryView().then(() => this.loading = false);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -199,25 +198,29 @@ export class LibraryOverviewComponent implements AfterContentInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private saveStateToRoute(): void {
|
private saveStateToRoute(): void {
|
||||||
let stateParams: Params = {};
|
let newStateParams: Params = {};
|
||||||
|
|
||||||
if (this.searchTerm.trim().length > 0) stateParams['search'] = this.searchTerm;
|
if (this.searchTerm.trim().length > 0) newStateParams['search'] = this.searchTerm;
|
||||||
if (this.selectedSortOption !== this.defaultSortOption) stateParams['sort'] = this.toParam(this.selectedSortOption);
|
if (this.selectedSortOption !== this.defaultSortOption) newStateParams['sort'] = LibraryOverviewComponent.toParam(this.selectedSortOption);
|
||||||
if (this.getActiveGameModesFilters().length > 0) stateParams['gamemodes'] = this.getActiveGameModesFilters().join(',');
|
if (this.getActiveGameModesFilters().length > 0) newStateParams['gamemodes'] = this.getActiveGameModesFilters().join(',');
|
||||||
if (this.activeGenreFilters.length > 0) stateParams['genres'] = this.activeGenreFilters.join(',');
|
if (this.activeGenreFilters.length > 0) newStateParams['genres'] = this.activeGenreFilters.join(',');
|
||||||
if (this.activeThemeFilters.length > 0) stateParams['themes'] = this.activeThemeFilters.join(',');
|
if (this.activeThemeFilters.length > 0) newStateParams['themes'] = this.activeThemeFilters.join(',');
|
||||||
if (this.activePlayerPerspectiveFilters.length > 0) stateParams['playerPerspectives'] = this.activePlayerPerspectiveFilters.join(',');
|
if (this.activePlayerPerspectiveFilters.length > 0) newStateParams['playerPerspectives'] = this.activePlayerPerspectiveFilters.join(',');
|
||||||
|
|
||||||
const url = this.router.createUrlTree([], {relativeTo: this.route, queryParams: stateParams}).toString();
|
// only update the route if it changed
|
||||||
this.location.go(url);
|
if (JSON.stringify(this.previousStateParams) !== JSON.stringify(newStateParams)) {
|
||||||
|
const url = this.router.createUrlTree([], {relativeTo: this.route, queryParams: newStateParams}).toString();
|
||||||
|
this.previousStateParams = newStateParams;
|
||||||
|
this.location.go(url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private toParam(sortOption: SortOption): string {
|
private static toParam(sortOption: SortOption): string {
|
||||||
return `${sortOption.field}_${sortOption.direction}`;
|
return `${sortOption.field}_${sortOption.direction}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private matchSelectedSortOptionFromParam(sortParam: string): SortOption {
|
private matchSelectedSortOptionFromParam(sortParam: string): SortOption {
|
||||||
return this.sortOptions.find(s => sortParam === this.toParam(s)) ?? this.defaultSortOption;
|
return this.sortOptions.find(s => sortParam === LibraryOverviewComponent.toParam(s)) ?? this.defaultSortOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
private matchSelectedFilters(options: any[], paramString: string): string[] {
|
private matchSelectedFilters(options: any[], paramString: string): string[] {
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
table {
|
table {
|
||||||
min-width: 50vw;
|
width: 50vw;
|
||||||
|
min-width: 750px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-column-path {
|
.mat-column-actions {
|
||||||
width: 50%;
|
width: 20%;
|
||||||
}
|
|
||||||
.mat-column-game {
|
|
||||||
width: 35%;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -1,8 +1,9 @@
|
|||||||
table {
|
table {
|
||||||
min-width: 50vw;
|
width: 50vw;
|
||||||
|
min-width: 750px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-column-path {
|
.mat-column-actions {
|
||||||
width: 85%;
|
width: 20%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<groupId>de.grimsi</groupId>
|
<groupId>de.grimsi</groupId>
|
||||||
<artifactId>gameyfin</artifactId>
|
<artifactId>gameyfin</artifactId>
|
||||||
<version>1.1.0</version>
|
<version>1.1.1</version>
|
||||||
<name>gameyfin</name>
|
<name>gameyfin</name>
|
||||||
<description>gameyfin</description>
|
<description>gameyfin</description>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user