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