Skip to content

feat(gallery): filter gallery and image map by media type - #9886

Open
lstein wants to merge 2 commits into
invoke-ai:mainfrom
lstein:feat/gallery-media-type-filter
Open

lstein wants to merge 2 commits into
invoke-ai:mainfrom
lstein:feat/gallery-media-type-filter

Conversation

@lstein

@lstein lstein commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The Gallery and Image Map always showed images and videos together. This adds a media-type filter, Both (default), Images only and Videos only, as a menu in two places that share one setting:

  • Gallery titlebar, between the starred toggle and the Newest/Oldest sort menu, in both the stacked and wide layouts. The filter applies to every board, date boards, the starred strip and similarity-search results. The trigger is highlighted while a filter is active. When nothing matches, the grid says so and offers Show all media in place of the upload drop zone.
  • Image Map header, directly left of the settings icon. The map serves and clusters only the selected kind, and refetches when the filter changes while the map is visible.

The setting is saved per project with the other Gallery settings, such as sort order.

Backend: an optional media_kind query parameter (image | video) on these endpoints:

  • /api/v1/gallery/items/, /items/location, /items/names, /item_names
  • /api/v1/virtual_boards/by_date/{date}/item_names
  • the image map's /points, /cluster_labels, /status, /search and /search_by_image

Gallery listings use sparse pages with authoritative totals and absolute positions, so the filter is applied in SQL. Totals, names, pages and location ranks all cover only the requested kind. On the image map, media_kind overrides include_videos. Cluster cache keys and visible_hash are computed over the served kinds.

Other behavior:

  • The asset picker ignores the filter.
  • Revealing an item the filter hides, for example with Find in Gallery from the Preview, resets the filter to Both.
  • Preview navigation follows the media kind under the same rule as the semantic ranking. While ranked, it uses the live filter. Otherwise it uses the kind recorded when the item was selected.

Related Issues / Discussions

None.

QA Instructions

Manual (pnpm dev:mock in invokeai/frontend/webv2, or against a real backend with images and videos on the same board):

  1. Open the Gallery on a board with both images and videos. Open the layers-icon menu between the star and Newest, then choose Videos only. Only videos show, and the trigger is highlighted. Repeat with Images only.
  2. On a board with no videos, choose Videos only. The grid shows "No videos match…" with Show all media. Clicking it restores Both and moves focus to the menu trigger.
  3. Open the Image Map. The same menu sits left of the settings icon and shows the Gallery's current choice. Change it there. The map reloads with only that kind, and the Gallery reflects the change.
  4. Select an item, change the filter, and step with Preview next/prev. Preview stays within the listing the item was selected from.
  5. Narrow the Gallery panel to its minimum width. The toolbar controls wrap below the Media/Uploads tabs without overflowing.

Automated:

  • pnpm check:release in invokeai/frontend/webv2 passes. That covers lint, all unit and browser tests, architecture performance and build budgets (no baselines re-recorded), project-file journeys and accessibility.
  • pnpm lint && pnpm test in invokeai/frontend/api pass after regenerating openapi.json and schema.ts.
  • uv tool run ruff@0.11.2 check and format --check pass.
  • uv run --no-sync pytest -n 4: all pass except 3 tests in tests/app/routers/test_app_info.py. Those fail on main too whenever a built invokeai/frontend/webv2/dist is present, because routes added inside the test land after the UI catch-all. With dist absent, all 36 tests in that file pass.
  • Backend tests ran on SQLite only. The generated SQL was compiled with the MySQL dialect and checked, but not executed on MySQL or MariaDB.

Screenshots of both menus in dark and light themes, and of the Gallery at 280px and 350px, were checked during development. I can attach them on request.

Review

Findings resolved before opening:

  • The Image Map menu originally lazy-loaded the whole Gallery widget chunk (about 47 KB gzipped), had no recovery if the import failed, and popped in late. Both widgets now render a platform IconRadioMenu from @platform/ui/Menu, fed by a shared Gallery options definition. This adds no modules or requests to the editor's initial graph.
  • Selection stamps for routed generation results and for Preview host steps did not match the listing Preview navigated, so a step could reveal the wrong page or slot. Stamps now record the media kind by the same rule Preview navigates with.
  • After a filter change, the map kept drawing and accepting clicks on the previous kind's points. A click revealed the item and reset the filter. The map now drops to a loading state. It refetches only while a map view is mounted, and pushes the filter before its first load.
  • Focus is handed off explicitly after Show all media in both widgets. The stacked toolbar no longer overflows at the minimum docked width.

Remaining limitations:

  • Board counts and the Media/Uploads tab counts stay unfiltered. They come from board summaries that do not split by kind.
  • The new Image Map empty-state strings are hard-coded English, following that widget's existing convention. The menu itself is localized.
  • After a filter change the map shows a spinner until the new points arrive.

Compatibility / Rollout

  • media_kind is optional on every endpoint. Omitting it reproduces the previous queries exactly, so webv1 and older clients are unaffected.
  • openapi.json and schema.ts were regenerated. The diff is additive.
  • No database migration.
  • The new mediaFilter value lives in the Gallery widget's persisted values. A missing or unknown value parses to Both.
  • Selections persisted before this change have no media kind and are read as Both.

Checklist

  • The PR has a short but descriptive title, suitable for a changelog
  • Meaningful regression coverage added / updated where needed; obsolete tests/code removed
  • Persisted-state and API changes include required migrations / compatibility validation
  • Relevant performance/efficiency opportunities considered; material claims have evidence
  • Material review findings resolved and relevant checks rerun
  • Documentation added / updated (if applicable)
  • Updated What's New copy (if doing a release after this PR)

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

Adds an Images only / Videos only / Both menu to the Gallery titlebar and Image Map header, sharing one per-project setting.
Gallery, date-board and image-map endpoints accept an optional media_kind filter applied server-side; omitted keeps both kinds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added api python PRs that change python files services PRs that change app services frontend PRs that change frontend files python-tests PRs that change python tests docs PRs that change docs labels Oct 16, 2026
@lstein
lstein requested a review from joshistoast October 16, 2026 16:31
@lstein lstein added the 7.0.0 label Oct 16, 2026
@lstein lstein moved this to 7.0 Theme: Modular Design in Invoke - Community Roadmap Oct 16, 2026

This branch has not been deployed

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

Labels

7.0.0 api docs PRs that change docs frontend PRs that change frontend files python PRs that change python files python-tests PRs that change python tests services PRs that change app services

Projects

Status: 7.0 Theme: Modular Design

Development

Successfully merging this pull request may close these issues.

2 participants