mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-16 16:20:04 +00:00
Implement RecentlyAddedView and LibraryView
This commit is contained in:
@@ -141,7 +141,8 @@
|
|||||||
"react-markdown": "$react-markdown",
|
"react-markdown": "$react-markdown",
|
||||||
"remark-breaks": "$remark-breaks",
|
"remark-breaks": "$remark-breaks",
|
||||||
"valtio": "$valtio",
|
"valtio": "$valtio",
|
||||||
"valtio-reactive": "$valtio-reactive"
|
"valtio-reactive": "$valtio-reactive",
|
||||||
|
"fzf": "$fzf"
|
||||||
},
|
},
|
||||||
"vaadin": {
|
"vaadin": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -202,6 +203,6 @@
|
|||||||
"workbox-core": "7.3.0",
|
"workbox-core": "7.3.0",
|
||||||
"workbox-precaching": "7.3.0"
|
"workbox-precaching": "7.3.0"
|
||||||
},
|
},
|
||||||
"hash": "dc682332ca36d64f455f6e13888e1ffcca97e888cbad8d356973e830f7463a10"
|
"hash": "5946db89f1666178a141f4993199185e21c2d2fba31f8cbe64550829f8450c78"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ export default function SearchBar() {
|
|||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const state = useSnapshot(gameState);
|
const state = useSnapshot(gameState);
|
||||||
const games = state.sortedByMostRecentlyUpdated as GameDto[];
|
const games = state.recentlyUpdated as GameDto[];
|
||||||
|
|
||||||
return <Autocomplete
|
return <Autocomplete
|
||||||
aria-label="Search for games"
|
aria-label="Search for games"
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import {SystemManagement} from "Frontend/components/administration/SystemManagem
|
|||||||
import GameView from "Frontend/views/GameView";
|
import GameView from "Frontend/views/GameView";
|
||||||
import LibraryManagementView from "Frontend/views/LibraryManagementView";
|
import LibraryManagementView from "Frontend/views/LibraryManagementView";
|
||||||
import SearchView from "Frontend/views/SearchView";
|
import SearchView from "Frontend/views/SearchView";
|
||||||
|
import RecentlyAddedView from "Frontend/views/RecentlyAddedView";
|
||||||
|
import LibraryView from "Frontend/views/LibraryView";
|
||||||
|
|
||||||
export const routes = protectRoutes([
|
export const routes = protectRoutes([
|
||||||
{
|
{
|
||||||
@@ -35,14 +37,22 @@ export const routes = protectRoutes([
|
|||||||
{
|
{
|
||||||
index: true, element: <HomeView/>
|
index: true, element: <HomeView/>
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'game/:gameId',
|
|
||||||
element: <GameView/>
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/search',
|
path: '/search',
|
||||||
element: <SearchView/>
|
element: <SearchView/>
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'recently-added',
|
||||||
|
element: <RecentlyAddedView/>
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'library/:libraryId',
|
||||||
|
element: <LibraryView/>
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'game/:gameId',
|
||||||
|
element: <GameView/>
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'settings',
|
path: 'settings',
|
||||||
element: <ProfileView/>,
|
element: <ProfileView/>,
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ type GameState = {
|
|||||||
games: GameDto[];
|
games: GameDto[];
|
||||||
gamesByLibraryId: Record<number, GameDto[]>;
|
gamesByLibraryId: Record<number, GameDto[]>;
|
||||||
sortedAlphabetically: GameDto[];
|
sortedAlphabetically: GameDto[];
|
||||||
sortedByMostRecentlyAdded: GameDto[];
|
recentlyAdded: GameDto[];
|
||||||
sortedByMostRecentlyUpdated: GameDto[];
|
recentlyUpdated: GameDto[];
|
||||||
randomlyOrderedGamesByLibraryId: Record<number, GameDto[]>;
|
randomlyOrderedGamesByLibraryId: Record<number, GameDto[]>;
|
||||||
knownPublishers: Set<string>;
|
knownPublishers: Set<string>;
|
||||||
knownDevelopers: Set<string>;
|
knownDevelopers: Set<string>;
|
||||||
@@ -33,7 +33,7 @@ export const gameState = proxy<GameState>({
|
|||||||
return Object.values<GameDto>(this.state);
|
return Object.values<GameDto>(this.state);
|
||||||
},
|
},
|
||||||
get gamesByLibraryId() {
|
get gamesByLibraryId() {
|
||||||
return this.games.reduce((acc: Record<number, GameDto[]>, game: GameDto) => {
|
return this.sortedAlphabetically.reduce((acc: Record<number, GameDto[]>, game: GameDto) => {
|
||||||
(acc[game.libraryId] ||= []).push(game);
|
(acc[game.libraryId] ||= []).push(game);
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
@@ -42,13 +42,15 @@ export const gameState = proxy<GameState>({
|
|||||||
return this.games
|
return this.games
|
||||||
.sort((a: GameDto, b: GameDto) => a.title.localeCompare(b.title, undefined, {sensitivity: 'base'}));
|
.sort((a: GameDto, b: GameDto) => a.title.localeCompare(b.title, undefined, {sensitivity: 'base'}));
|
||||||
},
|
},
|
||||||
get sortedByMostRecentlyAdded() {
|
get recentlyAdded() {
|
||||||
return this.games
|
return this.games
|
||||||
.sort((a: GameDto, b: GameDto) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
.sort((a: GameDto, b: GameDto) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime())
|
||||||
|
.slice(0, 25);
|
||||||
},
|
},
|
||||||
get sortedByMostRecentlyUpdated() {
|
get recentlyUpdated() {
|
||||||
return this.games
|
return this.games
|
||||||
.sort((a: GameDto, b: GameDto) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
.sort((a: GameDto, b: GameDto) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime())
|
||||||
|
.slice(0, 25);
|
||||||
},
|
},
|
||||||
get randomlyOrderedGamesByLibraryId() {
|
get randomlyOrderedGamesByLibraryId() {
|
||||||
const result: Record<number, GameDto[]> = {};
|
const result: Record<number, GameDto[]> = {};
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export default function GameView() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initializeGameState().then((state) => {
|
initializeGameState().then((state) => {
|
||||||
if (!gameId || !state.state[parseInt(gameId)]) {
|
if (!gameId || !state.state[parseInt(gameId)]) {
|
||||||
navigate("/");
|
navigate("/", {replace: true});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [gameId]);
|
}, [gameId]);
|
||||||
|
|||||||
@@ -3,22 +3,24 @@ import {CoverRow} from "Frontend/components/general/covers/CoverRow";
|
|||||||
import {useSnapshot} from "valtio/react";
|
import {useSnapshot} from "valtio/react";
|
||||||
import {libraryState} from "Frontend/state/LibraryState";
|
import {libraryState} from "Frontend/state/LibraryState";
|
||||||
import {gameState} from "Frontend/state/GameState";
|
import {gameState} from "Frontend/state/GameState";
|
||||||
|
import {useNavigate} from "react-router";
|
||||||
|
|
||||||
export default function HomeView() {
|
export default function HomeView() {
|
||||||
|
const navigate = useNavigate();
|
||||||
const librariesState = useSnapshot(libraryState);
|
const librariesState = useSnapshot(libraryState);
|
||||||
const gamesState = useSnapshot(gameState);
|
const gamesState = useSnapshot(gameState);
|
||||||
const recentlyAddedGames = gamesState.sortedByMostRecentlyAdded as GameDto[];
|
const recentlyAddedGames = gamesState.recentlyAdded as GameDto[];
|
||||||
const gamesByLibrary = gamesState.gamesByLibraryId as Record<number, GameDto[]>;
|
const gamesByLibrary = gamesState.gamesByLibraryId as Record<number, GameDto[]>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<CoverRow title="Recently added" games={recentlyAddedGames}
|
<CoverRow title="Recently added" games={recentlyAddedGames}
|
||||||
onPressShowMore={() => alert("show more of 'Recently added'")}/>
|
onPressShowMore={() => navigate("/recently-added")}/>
|
||||||
{librariesState.libraries.map((library) => (
|
{librariesState.libraries.map((library) => (
|
||||||
<CoverRow key={library.id} title={library.name}
|
<CoverRow key={library.id} title={library.name}
|
||||||
games={gamesByLibrary[library.id] || []}
|
games={gamesByLibrary[library.id] || []}
|
||||||
onPressShowMore={() => alert(`show more of library '${library.name}'`)}
|
onPressShowMore={() => navigate("/library/" + library.id)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import {useSnapshot} from "valtio/react";
|
||||||
|
import {initializeLibraryState, libraryState} from "Frontend/state/LibraryState";
|
||||||
|
import {gameState} from "Frontend/state/GameState";
|
||||||
|
import React, {useEffect} from "react";
|
||||||
|
import {useNavigate, useParams} from "react-router";
|
||||||
|
import CoverGrid from "Frontend/components/general/covers/CoverGrid";
|
||||||
|
import GameDto from "Frontend/generated/de/grimsi/gameyfin/games/dto/GameDto";
|
||||||
|
|
||||||
|
export default function LibraryView() {
|
||||||
|
const {libraryId} = useParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const libraries = useSnapshot(libraryState);
|
||||||
|
const games = (libraryId ? useSnapshot(gameState).gamesByLibraryId[parseInt(libraryId!!)] || [] : []) as GameDto[];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
initializeLibraryState().then((state) => {
|
||||||
|
if (!libraryId || !state.state[parseInt(libraryId)]) {
|
||||||
|
navigate("/", {replace: true});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [libraryId]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-6">
|
||||||
|
<p className="text-4xl font-bold text-center">{libraries.state[parseInt(libraryId!!)]?.name}</p>
|
||||||
|
<CoverGrid games={games}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import {useSnapshot} from "valtio/react";
|
||||||
|
import {gameState} from "Frontend/state/GameState";
|
||||||
|
import GameDto from "Frontend/generated/de/grimsi/gameyfin/games/dto/GameDto";
|
||||||
|
import React from "react";
|
||||||
|
import CoverGrid from "Frontend/components/general/covers/CoverGrid";
|
||||||
|
|
||||||
|
export default function RecentlyAddedView() {
|
||||||
|
const games = useSnapshot(gameState).recentlyAdded as GameDto[];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<p className="text-4xl font-bold text-center">Recently added</p>
|
||||||
|
<CoverGrid games={games}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user