Skip to content

[WIP] Add a Screenshots page to handle user captures - #23909

Draft
Pickysaurus wants to merge 64 commits into
Nexus-Mods:masterfrom
Pickysaurus:screenshots
Draft

Pickysaurus wants to merge 64 commits into
Nexus-Mods:masterfrom
Pickysaurus:screenshots

Conversation

@Pickysaurus

@Pickysaurus Pickysaurus commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Working progress: this PR adds a new page to Vortex that handles collating and displaying screenshots and video captures from multiple sources (e.g. Steam, Xbox, native game screenshot feature). Once an image upload API is available, it will also allow one-click sharing of images to the site image share.

Requires #23918 for full functionality

@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown

This PR has been marked as stale due to inactivity.

Pickysaurus and others added 15 commits September 7, 2026 07:48
…ith repo conventions

Review pass over the new Media extension.

Behaviour:

- setGameMediaSourceEnabled replaced the whole disabledSources map with the
  active game's entry, wiping every other game's list. Merge instead.
- deleteGameMediaModTag returned undefined for media with no tags, which
  clears the slice. Return state unchanged.
- The mod search GraphQL document carried a stray "Variables" token after
  the closing brace, so every query was rejected as a parse error.
- getSteamMedia was handed String(steamAppId), which is the truthy string
  "undefined" for games without a Steam id, so it preferred that over the
  id resolved from the install path.
- "Open Folder" called shell.openUrl, which does new URL(path) in main and
  throws on a Windows path. Use shell.openFile, which goes via pathToFileURL.
- ffmpeg's error listener was the promise's resolve, so a spawn failure
  resolved the Error as the thumbnail path; it also rejected inside
  Promise.all and took the whole scan down with it.
- collectMedia sorted on a possibly-undefined createdAt (NaN) and matched
  extensions case-sensitively, skipping .PNG and .JPG.
- Selectors returned a fresh [] for games with no disabled sources and media
  with no tags. Under react-redux's reference equality that re-rendered on
  every dispatch, and because the array feeds the collect effect's deps it
  re-scanned in a loop. Share module-level empties.
- Media paths go through pathToFileURL so filenames containing # or % load.

Structure and conventions:

- Split source discovery out of useGameMedia into useGameMediaSources, so
  opening Settings lists sources without triggering a disk scan.
- Add selectors.ts and drop the IStateWithGameMedia casts.
- Move reducerFor to util/ — it was never health-check specific.
- Drop the local joinClasses and XOr/ResponsiveScreenSizes copies in favour
  of @/ui/utils.
- Drop setupMocks for the shared renderer test-setup, extended with
  ResizeObserver and the window.api members the media tests need.
- Register the media_page namespace and move hardcoded strings into it;
  components call useTranslation rather than taking t as a prop.
- Route tag removal through deleteGameMediaModTag everywhere instead of
  rewriting the whole tag array.
- Cache the ffmpeg probe, group grid items by source once, use
  crypto.randomUUID, detect ENOENT by code, fix the page id and menu icon,
  and mark the custom source path read-only.
Added a new hook to watch the source folders and update the view if a new image is created or removed.
Show 24 items per page to prevent the page becoming massive when the user has lots of screenshots
Mock the Steam singleton to avoid Linux getting upset.
Changed the MediaListItem and FloatingSearchBarResult to buttons for accessibility
Previews generated for videos are now cleaned up on app start.
Fixed more tests for Linux
Fixed more Linux tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant