diff --git a/gameyfin/package.json b/gameyfin/package.json index d422e7b..aef632f 100644 --- a/gameyfin/package.json +++ b/gameyfin/package.json @@ -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" } -} +} \ No newline at end of file diff --git a/gameyfin/src/main/frontend/components/general/SearchBar.tsx b/gameyfin/src/main/frontend/components/general/SearchBar.tsx index 1755e4c..ed90002 100644 --- a/gameyfin/src/main/frontend/components/general/SearchBar.tsx +++ b/gameyfin/src/main/frontend/components/general/SearchBar.tsx @@ -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 }, - { - path: 'game/:gameId', - element: - }, { path: '/search', element: }, + { + path: 'recently-added', + element: + }, + { + path: 'library/:libraryId', + element: + }, + { + path: 'game/:gameId', + element: + }, { path: 'settings', element: , diff --git a/gameyfin/src/main/frontend/state/GameState.ts b/gameyfin/src/main/frontend/state/GameState.ts index b3d63dc..80f7d9c 100644 --- a/gameyfin/src/main/frontend/state/GameState.ts +++ b/gameyfin/src/main/frontend/state/GameState.ts @@ -12,8 +12,8 @@ type GameState = { games: GameDto[]; gamesByLibraryId: Record; sortedAlphabetically: GameDto[]; - sortedByMostRecentlyAdded: GameDto[]; - sortedByMostRecentlyUpdated: GameDto[]; + recentlyAdded: GameDto[]; + recentlyUpdated: GameDto[]; randomlyOrderedGamesByLibraryId: Record; knownPublishers: Set; knownDevelopers: Set; @@ -33,7 +33,7 @@ export const gameState = proxy({ return Object.values(this.state); }, get gamesByLibraryId() { - return this.games.reduce((acc: Record, game: GameDto) => { + return this.sortedAlphabetically.reduce((acc: Record, game: GameDto) => { (acc[game.libraryId] ||= []).push(game); return acc; }, {}); @@ -42,13 +42,15 @@ export const gameState = proxy({ 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 = {}; diff --git a/gameyfin/src/main/frontend/views/GameView.tsx b/gameyfin/src/main/frontend/views/GameView.tsx index ccb25ef..3173016 100644 --- a/gameyfin/src/main/frontend/views/GameView.tsx +++ b/gameyfin/src/main/frontend/views/GameView.tsx @@ -38,7 +38,7 @@ export default function GameView() { useEffect(() => { initializeGameState().then((state) => { if (!gameId || !state.state[parseInt(gameId)]) { - navigate("/"); + navigate("/", {replace: true}); } }); }, [gameId]); diff --git a/gameyfin/src/main/frontend/views/HomeView.tsx b/gameyfin/src/main/frontend/views/HomeView.tsx index e68085b..107219f 100644 --- a/gameyfin/src/main/frontend/views/HomeView.tsx +++ b/gameyfin/src/main/frontend/views/HomeView.tsx @@ -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; return (
alert("show more of 'Recently added'")}/> + onPressShowMore={() => navigate("/recently-added")}/> {librariesState.libraries.map((library) => ( alert(`show more of library '${library.name}'`)} + onPressShowMore={() => navigate("/library/" + library.id)} /> ))}
diff --git a/gameyfin/src/main/frontend/views/LibraryView.tsx b/gameyfin/src/main/frontend/views/LibraryView.tsx new file mode 100644 index 0000000..4069167 --- /dev/null +++ b/gameyfin/src/main/frontend/views/LibraryView.tsx @@ -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 ( +
+

{libraries.state[parseInt(libraryId!!)]?.name}

+ +
+ ); +} \ No newline at end of file diff --git a/gameyfin/src/main/frontend/views/RecentlyAddedView.tsx b/gameyfin/src/main/frontend/views/RecentlyAddedView.tsx new file mode 100644 index 0000000..45603bf --- /dev/null +++ b/gameyfin/src/main/frontend/views/RecentlyAddedView.tsx @@ -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 ( +
+

Recently added

+ +
+ ); +} \ No newline at end of file