Persist gallery filter/sort state across navigation#81
Merged
travisdock merged 16 commits intomainfrom Mar 18, 2026
Merged
Conversation
…tion Co-authored-by: travisdock <36681963+travisdock@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Add saved filter and sort state for image gallery
Persist gallery filter/sort state across navigation
Mar 17, 2026
ImageGallery and ImageView duplicated the same search filtering, review status filtering, and sort logic. Extract these into a shared utility to keep them in sync and reduce line counts. Add unit tests for state persistence (ImageGallery) and navigation filtering (ImageView).
- Extract duplicated filter/sort/search logic from ImageGallery and
ImageView into shared utils/galleryState.js
- Fix stale state when ImageGallery is reused with a different
galleryKey by detecting key changes and reloading from localStorage
- Fix fragile ungrouped gallery key detection in ImageView by passing
galleryKey explicitly as a URL search param instead of sniffing
localStorage; prev/next navigation preserves the param
- Add unit tests for the shared utility (23 tests), ImageGallery state
persistence and key-change behavior (7 tests), and ImageView
galleryKey URL handling (3 tests)
Contributor
There was a problem hiding this comment.
Pull request overview
Adds persistent, scoped gallery UI state (filter/sort/search/view mode) so it survives navigation away from the gallery and ensures ImageView prev/next navigation respects the same active filters and ordering.
Changes:
- Introduces shared
galleryStateutilities for localStorage persistence plus filter/sort application, with unit tests. - Persists/restores
ImageGallerycontrol state via a new optionalgalleryKey(project- or group-scoped), and includesgalleryKeyin navigation URLs. - Updates
ImageViewto apply saved gallery filters/sorts when building the navigation image list, with additional tests.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/utils/galleryState.js | New shared persistence + filter/sort utilities used by both gallery and ImageView navigation. |
| frontend/src/utils/tests/galleryState.test.js | Unit tests for persistence and filter/sort helpers. |
| frontend/src/components/ImageGallery.js | Loads/saves gallery control state to localStorage and appends galleryKey to ImageView navigation URLs. |
| frontend/src/components/GroupGalleryView.js | Provides a group-scoped galleryKey so each group’s gallery state is independent. |
| frontend/src/components/tests/ImageGallery.test.js | Extends component tests to validate localStorage persistence/restore and galleryKey URL behavior. |
| frontend/src/ImageView.js | Applies saved gallery filter/sort (and optional review status filtering) to prev/next navigation list and preserves galleryKey in navigation. |
| frontend/src/tests/ImageView.test.js | Adds tests around reading saved gallery state for navigation behavior. |
loadGalleryState was called separately for each useState initializer, parsing the same JSON five times on mount. Add GALLERY_STATE_DEFAULTS and loadGalleryStateWithDefaults to galleryState.js so defaults live in one place. ImageGallery now loads state once and initializes all controls from that object. The key-change reset effect uses the same helper.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds shared, persisted gallery filter/sort state so users keep their gallery configuration across navigation and ImageView prev/next respects the same filtered + ordered image set (project and group scoped).
Changes:
- Introduces
frontend/src/utils/galleryState.jsto centralize localStorage persistence, filtering, and sorting logic used by bothImageGalleryandImageView. - Updates
ImageGalleryto persist/restore controls viagalleryKey-scoped localStorage and to propagategalleryKeythrough the ImageView URL. - Updates
ImageViewnavigation list building to apply the saved gallery search/review/sort state, with added frontend test coverage.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| test/backend_tests.sh | Adds fallback UV_CACHE_DIR when default location isn’t writable. |
| frontend/src/utils/galleryState.js | New shared persistence + filter/sort utilities with TTL/cap cleanup. |
| frontend/src/utils/tests/galleryState.test.js | Unit tests for persistence, cleanup, filtering, and sorting helpers. |
| frontend/src/components/ImageGallery.js | Loads/saves gallery state from localStorage; adds galleryKey prop; appends galleryKey to ImageView links. |
| frontend/src/components/GroupGalleryView.js | Passes group-/ungrouped-scoped galleryKey to ImageGallery. |
| frontend/src/components/tests/ImageGallery.test.js | Adds tests covering persisted state behavior and galleryKey URL propagation. |
| frontend/src/ImageView.js | Applies saved gallery filters/sort to prev/next navigation list; preserves galleryKey across navigation. |
| frontend/src/tests/ImageView.test.js | Adds navigation tests validating sort/filter behavior and galleryKey preservation. |
When navigating prev/next from the ungrouped gallery, loadProjectImages was not passing ungrouped=true to the API, causing navigation to include grouped images. Detect the ungrouped gallery key from the URL and scope the fetch accordingly.
travisdock
approved these changes
Mar 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Gallery filter, sort, search, and view mode state resets whenever the user navigates away (e.g., clicks an image). State should survive round-trips to
ImageViewand next/prev navigation should respect the active filter.Changes
ImageGallery.jsgalleryKeyprop (falls back toprojectId) for scoped state storageviewMode,sortBy,searchField,searchValue,reviewFilter) initialized from and persisted tolocalStorageunder keygallery_state_${galleryKey}GroupGalleryView.jsgalleryKeytoImageGalleryso each group gallery maintains independent state:ImageView.jsloadProjectImages()now reads the saved gallery state and applies:ImageGallery(filename, metadata, content type, etc.)/api/projects/{id}/image-review-statusesif a non-allfilter is saved; silently skips on failureThis ensures the prev/next buttons navigate through the same ordered, filtered image set the user last configured.
Original prompt
💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.