Skip to content

Feat: Add toggle for showing unreleased games in wishlist + reorder sections#460

Open
Doezer wants to merge 3 commits intorelease/1.3.0from
1.3.0/wishlist-page-updates
Open

Feat: Add toggle for showing unreleased games in wishlist + reorder sections#460
Doezer wants to merge 3 commits intorelease/1.3.0from
1.3.0/wishlist-page-updates

Conversation

@Doezer
Copy link
Owner

@Doezer Doezer commented Mar 15, 2026

This PR modifies the wishlist page

  • Adding a toggle in the page to hide TBA/Upcoming games (not available to download)
  • Reorder sections to display released games first

@codecov
Copy link

codecov bot commented Mar 15, 2026

Codecov Report

❌ Patch coverage is 93.33333% with 2 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
client/src/hooks/use-local-storage-state.ts 91.66% 1 Missing ⚠️
client/src/pages/wishlist.tsx 91.66% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces significant new features and improvements across the application, primarily focusing on enhancing the wishlist experience, integrating with Steam, and bolstering security. It also includes performance optimizations, a new statistics dashboard, and a substantial increase in test coverage to ensure stability and reliability.

Highlights

  • Wishlist Enhancements: Implemented a toggle on the wishlist page to hide or show unreleased games (TBA/Upcoming), and reordered sections to display released games first for better visibility.
  • Steam Integration: Added functionality to link a Steam ID and sync the Steam Wishlist, automatically adding wanted games to the Questarr library. This includes new API routes, cron jobs, and database fields.
  • Accessibility Improvements: Enhanced UI components like CompactGameCard and GameCard with more descriptive aria-labels for buttons, improving screen reader navigation and overall accessibility.
  • Performance Optimization: Introduced lazy loading for heavy modal components (GameDetailsModal, GameDownloadDialog) to reduce initial bundle size and improve page load performance.
  • Security Hardening: Implemented SSRF (Server-Side Request Forgery) protection for RSS feed URLs and external downloader URLs, preventing access to internal network resources. Also, improved error handling to prevent sensitive information leakage in production environments.
  • Library Statistics Page: Added a new dedicated 'Stats' page to provide detailed insights into the game collection, including average rating, completion rate, metadata health, and status breakdowns.
  • Automated Search Refinements: The auto-search cron job now respects a new user setting to include or exclude unreleased games, and also searches owned games for available update packs.
  • Codebase Modernization & Testing: Refactored API request handling with credentials: 'include' for better session management, introduced a useHiddenMutation hook for consistent game visibility toggling, and added extensive unit and integration tests across client and server for new and existing features.
Changelog
  • .github/SECURITY.md
    • Removed SESSION_SECRET from the list of recommended environment variables.
  • .gitignore
    • Added pr_status.json to ignored files.
  • .jules/palette.md
    • Added a new learning note about contextual aria-labels for buttons in lists.
  • .jules/sentinel.md
    • Added a new vulnerability entry regarding SSRF in RSS Feeds and its prevention.
  • Dockerfile
    • Updated the Docker image version from 1.2.2 to 1.3.0.
  • client/tests/Accessibility.test.tsx
    • Added new accessibility tests for CompactGameCard and GameCard to verify descriptive aria-labels.
  • client/tests/CompactGameCard.test.tsx
    • Updated mock game type assertion for Vitest compatibility.
    • Changed aria-label for the info button to be more descriptive.
    • Added a test case for the loading fallback when opening game details.
  • client/tests/GameCard.test.tsx
    • Added new accessibility tests for GameCard to verify descriptive aria-labels for status, details, and hide buttons.
  • client/tests/GameDetailsModal.test.tsx
    • Updated mock game type assertion for Vitest compatibility.
    • Added Eye and EyeOff icons to the mock for lucide-react.
    • Integrated useHiddenMutation for hide/unhide functionality.
    • Lazy-loaded GameDownloadDialog to improve modal performance.
  • client/tests/GameDownloadDialog.test.tsx
    • Updated mock game type assertion for Vitest compatibility.
    • Added as unknown as import(...) for fetch mock to resolve type issues.
    • Improved download success toast message to include the downloader's name.
  • client/tests/LazyModalFallback.test.tsx
    • Added new tests for the LazyModalFallback component.
  • client/tests/PagesHiddenWiring.test.tsx
    • Added new tests to verify the onToggleHidden wiring in WishlistPage and LibraryPage.
  • client/tests/discover-hidden-mutation.test.ts
    • Added new tests for the hideDiscoveryGame utility function, covering PATCH, POST, and 409 conflict scenarios.
  • client/tests/indexers-cache.test.ts
    • Added new tests for the refreshIndexerQueries utility function.
  • client/tests/tsconfig.json
    • Added a new tsconfig.json for client-side tests, extending the root config and adding Vitest/Testing Library types.
  • client/tests/use-hidden-mutation.test.tsx
    • Added new tests for the useHiddenMutation hook, covering default and custom mutation functions.
  • client/tests/usenet-utils.test.ts
    • Reformated code for consistency.
  • client/tests/utils.test.ts
    • Added new tests for safeUrl and getNextStatusLabel utility functions.
  • client/tests/versionService.test.ts
    • Updated fetchLatestQuestarrVersion to use the GitHub Releases API instead of package.json.
    • Added comprehensive error handling and logging for GitHub API requests.
  • client/src/App.tsx
    • Added a new /stats route and corresponding StatsPage component.
    • Updated the header title logic to include 'Statistics' for the new page.
  • client/src/tests/SetupPage.test.tsx
    • Increased the timeout for a test case to prevent flakiness.
  • client/src/tests/auth-provider.test.tsx
    • Added new tests for AuthProvider's handling of /api/auth/me responses, including token clearing on 401 and retries on transient failures.
  • client/src/components/AddGameModal.tsx
    • Added aria-live="polite" to the search results container for improved accessibility.
    • Added aria-label to the 'Add' button for better screen reader context.
  • client/src/components/AppSidebar.tsx
    • Added a 'Stats' navigation item with a PieChart icon.
  • client/src/components/CompactGameCard.tsx
    • Lazy-loaded GameDetailsModal and GameDownloadDialog components.
    • Integrated LazyModalFallback for loading states in modals.
    • Updated aria-labels for download, status, details, and hide buttons to be more descriptive.
  • client/src/components/CompactRssFeedItem.tsx
    • Used the new safeUrl utility for the item link to prevent SSRF.
  • client/src/components/Dashboard.tsx
    • Refactored game fetching to use apiRequest for consistent API calls.
    • Integrated useHiddenMutation for game visibility toggling.
    • Replaced manual statistics calculation with the new calculateLibraryStats utility.
    • Adjusted the stats card grid layout for better presentation.
  • client/src/components/GameCard.tsx
    • Lazy-loaded GameDetailsModal and GameDownloadDialog components.
    • Integrated LazyModalFallback for loading states in modals.
    • Updated aria-labels for download, details, hide, track, and status buttons to be more descriptive.
  • client/src/components/GameDetailsModal.tsx
    • Integrated useHiddenMutation for hide/unhide functionality, adding Eye/EyeOff icons.
    • Lazy-loaded GameDownloadDialog to keep the details modal lightweight.
  • client/src/components/GameDownloadDialog.tsx
    • Improved the download success toast message to include the downloader's name.
  • client/src/components/Header.tsx
    • Added a 'Sync Steam' button that triggers Steam Wishlist synchronization.
    • Updated useQuery for user data to include steamId64.
  • client/src/components/LazyModalFallback.tsx
    • Added a new component for displaying a loading message within lazy-loaded modals.
  • client/src/components/RssFeedList.tsx
    • Used the new safeUrl utility for item links to prevent SSRF.
  • client/src/components/ui/badge.tsx
    • Minor formatting adjustment.
  • client/src/hooks/use-hidden-mutation.ts
    • Added a new hook useHiddenMutation for handling game visibility mutations with customizable messages.
  • client/src/lib/tests/queryClient.test.ts
    • Added comprehensive tests for queryClient utilities, ApiError, apiRequest, getQueryFn, and clearSearchCache.
  • client/src/lib/tests/stats.test.ts
    • Added new tests for the calculateLibraryStats utility function.
  • client/src/lib/auth.tsx
    • Refactored AuthProvider to use useQuery for the /api/auth/me endpoint, improving token handling and session validation.
  • client/src/lib/discover-hidden-mutation.ts
    • Added a new utility hideDiscoveryGame for hiding discovery games, handling both existing and new games.
  • client/src/lib/indexers-cache.ts
    • Added a new utility refreshIndexerQueries for invalidating indexer-related queries.
  • client/src/lib/queryClient.ts
    • Added credentials: "include" to fetch calls in apiRequest and getQueryFn for proper cookie handling.
    • Added clearSearchCache function to remove cached search results.
  • client/src/lib/stats.ts
    • Added a new utility calculateLibraryStats for calculating and returning various library statistics.
  • client/src/lib/utils.ts
    • Added safeUrl function for URL validation to prevent XSS attacks.
    • Added getNextStatusLabel function to determine the next game status label.
  • client/src/lib/versionService.ts
    • Updated fetchLatestQuestarrVersion to use the GitHub Releases API for more reliable version checks.
    • Added detailed error logging for GitHub API requests.
  • client/src/pages/auth/login.tsx
    • Added the Questarr logo to the login page for branding.
  • client/src/pages/discover.tsx
    • Integrated useHiddenMutation and hideDiscoveryGame for hiding games from discovery.
  • client/src/pages/indexers.tsx
    • Integrated refreshIndexerQueries and clearSearchCache for better cache management when indexer configurations change.
  • client/src/pages/library.tsx
    • Updated useQuery to filter games by status for the library view.
    • Integrated useHiddenMutation for game visibility toggling.
    • Passed onToggleHidden prop to GameGrid for handling game hiding/unhiding.
  • client/src/pages/rss.tsx
    • Minor formatting adjustments.
  • client/src/pages/settings.tsx
    • Added a new autoSearchUnreleased setting to control searching for unreleased games.
    • Introduced a Steam integration section with input for steamIdInput and handleSaveSteamId.
    • Fetched igdbSettings separately for better modularity.
    • Added a 'Clear Downloads Cache' button for manual cache invalidation.
  • client/src/pages/stats.tsx
    • Added a new page to display library statistics using calculateLibraryStats and Recharts for data visualization.
  • client/src/pages/wishlist.tsx
    • Updated useQuery to filter games by status for the wishlist view.
    • Added a showUnreleased toggle to hide/show unreleased games.
    • Reordered sections to display released games first.
    • Integrated useHiddenMutation for game visibility toggling.
  • client/src/pages/xrel-releases.tsx
    • Minor formatting adjustments.
  • eslint.config.js
    • Added test directories to the ignores list.
  • migrations/0004_thin_wendigo.sql
    • Added auto_search_unreleased column to the user_settings table.
  • migrations/0005_steam_integration.sql
    • Added steam_id_64 column to users table.
    • Added steam_sync_failures column to user_settings table.
    • Added steam_appid column to games table.
  • migrations/0006_hidden_not_null.sql
    • Migrated the hidden column in the games table to be NOT NULL with a default value of 0.
  • migrations/meta/0004_snapshot.json
    • Added Drizzle ORM snapshot for migration 0004.
  • migrations/meta/_journal.json
    • Updated the migration journal to include new migrations.
  • package.json
    • Updated application version to 1.3.0.
    • Added @types/express-session, express-session, passport, passport-steam, @types/passport, and @types/passport-steam dependencies.
  • playwright.config.ts
    • Minor formatting adjustments.
  • scripts/debug-igdb.ts
    • Minor formatting adjustments.
  • server/tests/api_routes.test.ts
    • Expanded API route tests to cover auth, health, game filtering by status/hidden, IGDB endpoints, indexer/downloader CRUD, notifications, config, user settings, RSS, and SSRF prevention for RSS.
    • Added tests for parseCategories helper function.
  • server/tests/auth.test.ts
    • Updated JWT secret handling to use a constant for consistency.
    • Fixed type assertions for req.user.
  • server/tests/cron_autosearch.test.ts
    • Added new tests for the checkAutoSearch cron job, focusing on the autoSearchUnreleased setting and update notifications for owned games.
  • server/tests/cron_updates.test.ts
    • Added new tests for the checkGameUpdates cron job, covering batch updates, notifications, and error handling.
  • server/tests/cron_xrel.test.ts
    • Added new tests for the checkXrelReleases cron job, including optimized matching and user preferences for scene/p2p releases.
  • server/tests/database_storage_integration.test.ts
    • Added a new integration test for DatabaseStorage focusing on getUserGames status filtering.
  • server/tests/downloaders.test.ts
    • Improved Transmission client error messages for addDownload to include detailed RPC errors.
  • server/tests/igdb.test.ts
    • Added new tests for batch Steam App ID to IGDB ID lookups.
  • server/tests/path_traversal.test.ts
    • Added mock for steamRoutes.
  • server/tests/rss-routes.test.ts
    • Added mock for steamRoutes.
  • server/tests/rss-ssrf.test.ts
    • Added new tests specifically for SSRF prevention in RSS feed creation and update routes.
  • server/tests/rss.test.ts
    • Switched from parser.parseURL to safeFetch + parser.parseString for SSRF protection in RSS feed processing.
  • server/tests/search_utils.test.ts
    • Added mock for steamRoutes.
  • server/tests/security.test.ts
    • Updated getSystemConfig mock to return null by default.
    • Added mock for steamRoutes.
    • Added tests for credential exposure prevention in the /api/config endpoint.
  • server/tests/security_error_handling.test.ts
    • Added new tests for the global error handler middleware, covering error sanitization in production and detailed errors in development.
  • server/tests/ssrf.test.ts
    • Modified isSafeUrl to default allowPrivate to true.
    • Improved DNS lookup to check all resolved IPs for DNS rebinding attacks.
    • Fixed IPv6 link-local address check.
  • server/tests/ssrf_routes.test.ts
    • Added mock for steamRoutes.
  • server/tests/steam_routes.test.ts
    • Added a new file for Steam-related API routes, including updating Steam ID and syncing wishlists.
  • server/tests/steam_service.test.ts
    • Added a new file for Steam API service tests, covering validateSteamId and getWishlist functionality.
  • server/tests/steam_wishlist.test.ts
    • Added new tests for the syncUserSteamWishlist cron job, covering adding games, avoiding duplicates, and error handling.
  • server/tests/storage.test.ts
    • Added tests for getUserGames filtering by status.
    • Added new tests for user settings management, including autoSearchUnreleased.
  • server/tests/usenet_integration.test.ts
    • Added mock for ssrf.js.
  • server/auth.ts
    • Modified getJwtSecret to prioritize the environment variable JWT_SECRET regardless of its value.
    • Removed the legacy default check for JWT_SECRET.
  • server/config.ts
    • Added LEGACY_DEFAULT_JWT_SECRET constant.
    • Refined JWT_SECRET validation to warn against insecure legacy defaults.
    • Added APP_URL to the environment schema.
  • server/cron.ts
    • Refactored checkGameUpdates to use batch updates and notifications for efficiency.
    • Updated checkAutoSearch logic to respect the autoSearchUnreleased setting and to search owned games for update packs.
    • Optimized checkXrelReleases matching logic for performance.
    • Added checkSteamWishlist and syncUserSteamWishlist functions for Steam integration.
  • server/downloaders.ts
    • Improved error messages for the Transmission client to include detailed RPC errors when adding downloads.
  • server/igdb.ts
    • Added getGameIdBySteamAppId and getGameIdsBySteamAppIds methods for batch Steam App ID to IGDB ID lookups, supporting Steam integration.
  • server/index.ts
    • Added app.set("trust proxy", 1) for production environments.
    • Added credentials: true to CORS configuration for proper cookie handling.
    • Replaced the custom error handler with the new errorHandler middleware for standardized error responses.
  • server/middleware.ts
    • Added a new errorHandler middleware for standardized error responses, including sanitization in production and detailed errors in development.
  • server/routes.ts
    • Integrated steamRoutes for Steam-related API endpoints.
    • Added steamId64 to the /api/auth/me response.
    • Hardened the /api/config endpoint to prevent sensitive information disclosure.
    • Added isSafeUrl checks to RSS feed creation and update routes to prevent SSRF.
    • Replaced custom error handling with next(error) in several routes for consistent error propagation.
    • Optimized xREL matching logic for performance.
  • server/rss.ts
    • Switched from parser.parseURL to safeFetch + parser.parseString for SSRF protection when fetching RSS feeds.
  • server/run-migrations.ts
    • Added dotenv/config import for environment variable loading.
  • server/ssrf.ts
    • Modified isSafeUrl to default allowPrivate to true.
    • Improved DNS lookup to check all resolved IPs for DNS rebinding attacks.
    • Fixed the IPv6 link-local address check.
  • server/steam-routes.ts
    • Added a new file defining API routes for Steam integration, including updating Steam ID and syncing wishlists.
  • server/steam.ts
    • Added a new file defining the Steam API service, including validateSteamId and getWishlist functionality.
  • server/storage.ts
    • Added updateUserSteamId and getAllUsers methods for user management.
    • Added addNotificationsBatch method for efficient notification handling.
    • Modified getUserGames to accept an optional statuses filter.
    • Updated InsertGame and User types to include steamAppId and steamId64 respectively.
  • shared/tests/title_utils.test.ts
    • Added new tests for title utility functions, including normalizeTitle, cleanReleaseName, titleMatches, releaseMatchesGame, and parseReleaseMetadata.
  • shared/schema.ts
    • Added steamId64 column to the users table.
    • Added autoSearchUnreleased and steamSyncFailures columns to the userSettings table.
    • Added steamAppId column to the games table.
    • Changed userSettings.updatedAt mode to timestamp.
    • Made games.hidden column NOT NULL.
  • test-report.junit.xml
    • Added a new JUnit test report file.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/ci.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@Doezer Doezer changed the base branch from main to release/1.3.0 March 15, 2026 13:29
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant set of features and improvements, most notably the ability to toggle unreleased games in the wishlist and sync with a Steam wishlist. The code quality is high, with excellent refactoring into reusable hooks like useHiddenMutation, performance optimizations through lazy loading, and major security enhancements like SSRF protection and a standardized error handler. The test suite has also been substantially expanded. I've identified one critical security vulnerability and a couple of areas for improvement to align with the codebase's patterns and enhance maintainability.

I am having trouble creating individual review comments. Click here to see my feedback.

server/routes.ts (2183)

security-critical critical

This endpoint is not protected by the authenticateToken middleware, making it a public endpoint. This allows any unauthenticated user to change the application-wide IGDB credentials, which is a critical security vulnerability. The setup page already handles the initial credential configuration via the /api/auth/setup endpoint. This endpoint should only be accessible to authenticated users on the settings page and must be protected.

app.post("/api/settings/igdb", authenticateToken, async (req, res) => {
References
  1. A global settings endpoint accessible by any authenticated user is acceptable if the application's user model ensures only admin-level users can be created, effectively making any authenticated user an administrator. This implies that such an endpoint, if not public, must be protected.

client/src/components/Header.tsx (140-173)

high

The onClick handler for the Steam sync button implements the API call logic directly using fetch. This duplicates logic for handling authentication, API requests, and displaying toasts, which is already abstracted away in apiRequest and useMutation. Refactoring this into a dedicated useMutation hook would improve consistency, centralize API logic, and make the component cleaner by handling loading/error states more gracefully.

References
  1. Extract duplicated logic from similar processing loops into a shared helper function to improve maintainability, reduce redundancy, and ensure consistent behavior (e.g., error handling).
  2. When a user action triggers an asynchronous operation, provide immediate visual feedback by disabling the interactive element and showing a loading indicator to improve user experience.

server/cron.ts (854-981)

medium

The syncUserSteamWishlist function is quite long and handles multiple distinct steps: fetching user data, fetching the wishlist, mapping Steam IDs to IGDB IDs, filtering existing games, fetching details for new games, and finally adding them. Consider breaking this down into smaller, more focused helper functions. For example, a function to resolve Steam App IDs to new InsertGame objects, and another to handle the database interactions. This would improve readability, testability, and maintainability of this complex feature.

References
  1. Extract duplicated logic from similar processing loops into a shared helper function to improve maintainability, reduce redundancy, and ensure consistent behavior (e.g., error handling).

@Doezer
Copy link
Owner Author

Doezer commented Mar 15, 2026

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request enhances the wishlist page by adding a feature to toggle the display of unreleased games (Upcoming and To Be Announced). This involves introducing a showUnreleased state, which is persisted in local storage, a new button with Eye/EyeOff icons to control this state, and conditional rendering for the unreleased game sections. Additionally, the 'Released' games section is now displayed first with an updated badge style. A review comment suggests refactoring the repeated useState and useEffect pattern for localStorage persistence into a reusable custom hook to reduce boilerplate and improve maintainability.

@Doezer Doezer force-pushed the 1.3.0/wishlist-page-updates branch from 41bca22 to 8150ee3 Compare March 15, 2026 14:30
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant