[Feature]: Add Grid View to Duplicate Workbench #138

Closed
opened 2026-06-24 05:55:07 +00:00 by ValleyGeek · 4 comments
Owner

Problem or use case

Allow the user to quickly browse duplicate groups by thumbnail in a grid.

Proposed solution

Add a new vertical separator then button to the left of "Multi" on the duplicate workbench called "Dupe Grid" to enter a grid view comprised of duplicate groups.

  • The displayed thumbnail should be the first non-deleted image of the duplicate group.
  • If all images are deleted in the duplicate group then display the first image in the group as the thumbnail
  • If 'Hide Deleted' is enabled and all images in the duplicate group have been deleted, hide it from this "Dupe Grid" view. This does not apply to the duplicate group list in the toolbox, it should still display the full list regardless of filters.
  • Tag filters should apply to the "Dupe Grid" view as they do the normal grid with the exception that showing and hiding needs to use aggregated tags from all images in the group. If any image in the group would match a displayed tag filter then the group as a whole should be displayed in the "Dupe Grid" and all group images should remain in the Multi and Single views for the group.
  • Double-clicking or 'e' should now bounce between the last two views the user used based on what they select from the toolbar.
    • Default to Grid <> Multi
  • Display the duplicate group review state icon at the top right of the thumbnail cell.
  • Don't include the thumbnail size slider in the toolbar but reuse the setting from the main 'grid' view and allow CRTL+scroll to change the size still
  • "W" and "S" on the keyboard will need to be up and down in the "Dupe Grid" view but still next and previous group in the multi and single views
  • Ensure that when returning to the "Dupe Grid" view, the active image from the most recent view is selected
  • Pressing the "Delete" key in the "Dupe Grid" should set the entire group as deleted

Alternatives considered

No response

### Problem or use case Allow the user to quickly browse duplicate groups by thumbnail in a grid. ### Proposed solution Add a new vertical separator then button to the left of "Multi" on the duplicate workbench called "Dupe Grid" to enter a grid view comprised of duplicate groups. - The displayed thumbnail should be the first non-deleted image of the duplicate group. - If all images are deleted in the duplicate group then display the first image in the group as the thumbnail - If 'Hide Deleted' is enabled and all images in the duplicate group have been deleted, hide it from this "Dupe Grid" view. This does not apply to the duplicate group list in the toolbox, it should still display the full list regardless of filters. - Tag filters should apply to the "Dupe Grid" view as they do the normal grid with the exception that showing and hiding needs to use aggregated tags from all images in the group. If any image in the group would match a displayed tag filter then the group as a whole should be displayed in the "Dupe Grid" and all group images should remain in the Multi and Single views for the group. - Double-clicking or 'e' should now bounce between the last two views the user used based on what they select from the toolbar. - Default to Grid <> Multi - Display the duplicate group review state icon at the top right of the thumbnail cell. - Don't include the thumbnail size slider in the toolbar but reuse the setting from the main 'grid' view and allow CRTL+scroll to change the size still - "W" and "S" on the keyboard will need to be up and down in the "Dupe Grid" view but still next and previous group in the multi and single views - Ensure that when returning to the "Dupe Grid" view, the active image from the most recent view is selected - Pressing the "Delete" key in the "Dupe Grid" should set the entire group as deleted ### Alternatives considered _No response_
Member

Implemented on branch 0.2.4/issue-138-dupe-grid-view (pushed, awaiting PR to main):

  • New Dupe Grid button (left of Multi, with a separator) switches the Duplicates workbench into a one-thumbnail-per-group grid.
  • Thumbnail = first non-deleted image in the group, or the first image if every member is DELETE.
  • Hide Deleted hides a group from Dupe Grid only when every member is deleted; the toolbox group list is unaffected.
  • Tag filters apply via the existing any-member-matches dupe-tag-summary aggregation (no separate logic needed).
  • E/double-click now bounces between the last two distinct dupe views used (Grid/Multi/Single), defaulting to Grid ↔ Multi.
  • W/S move the grid selection up/down (next/previous group is preserved in Multi/Single).
  • Review-state icon (all-deleted / one-left / viewed) shown top-right of each thumbnail.
  • No separate size slider — reuses the main Grid workbench's thumbnail-size setting; Ctrl+scroll still resizes.
  • Returning to Dupe Grid reselects the most recently active group.
  • Delete key marks the whole selected group DELETE (reuses the existing Delete Group undo/advance logic).

Added unit/widget tests (tests/test_dupe_group_grid.py, tests/test_dupe_grid_view.py); full suite (566 passed), ruff, and the UI-exit smoke all pass. This is the first branch in the v0.3.0 tranche (VERSION bumped 0.2.4 → 0.3.0).

Implemented on branch `0.2.4/issue-138-dupe-grid-view` (pushed, awaiting PR to `main`): - New **Dupe Grid** button (left of Multi, with a separator) switches the Duplicates workbench into a one-thumbnail-per-group grid. - Thumbnail = first non-deleted image in the group, or the first image if every member is DELETE. - Hide Deleted hides a group from Dupe Grid only when *every* member is deleted; the toolbox group list is unaffected. - Tag filters apply via the existing any-member-matches dupe-tag-summary aggregation (no separate logic needed). - `E`/double-click now bounces between the last two distinct dupe views used (Grid/Multi/Single), defaulting to Grid ↔ Multi. - `W`/`S` move the grid selection up/down (next/previous group is preserved in Multi/Single). - Review-state icon (all-deleted / one-left / viewed) shown top-right of each thumbnail. - No separate size slider — reuses the main Grid workbench's thumbnail-size setting; Ctrl+scroll still resizes. - Returning to Dupe Grid reselects the most recently active group. - `Delete` key marks the whole selected group DELETE (reuses the existing Delete Group undo/advance logic). Added unit/widget tests (`tests/test_dupe_group_grid.py`, `tests/test_dupe_grid_view.py`); full suite (566 passed), ruff, and the UI-exit smoke all pass. This is the first branch in the v0.3.0 tranche (`VERSION` bumped 0.2.4 → 0.3.0).
Claude 2026-06-24 06:44:44 +00:00
Claude reopened this issue 2026-06-24 13:08:51 +00:00
Member

Follow-up after real-world testing at scale (2,200 images / 270 duplicate groups), pushed to the same branch (0.2.4/issue-138-dupe-grid-view):

  • Dupe Grid reload (switching back from Multi/Single) and group deletion were slow — _refresh_dupe_group_grid() issued one DB query per visible group; replaced with a single batched WorkingDB.get_dupe_group_representatives() call (~12x faster on a synthetic benchmark at this scale).
  • Selecting a group was slow — every click was also eagerly reloading the (invisible) Multi view's images; skipped while Dupe Grid is the active sub-view.
  • Clicking a group thumbnail no longer recenters the grid — select_tag() only scrolls (minimally, via EnsureVisible) when actually entering/returning to the view; routine resyncs leave the viewport alone.
  • Fixed W/S not working as group-navigation shortcuts when Single view is opened directly from Dupe Grid (skipping Multi) — the shortcut re-enable was only wired on the Multi-entry path.

Still open pending PR/merge to main.

Follow-up after real-world testing at scale (2,200 images / 270 duplicate groups), pushed to the same branch (`0.2.4/issue-138-dupe-grid-view`): - Dupe Grid reload (switching back from Multi/Single) and group deletion were slow — `_refresh_dupe_group_grid()` issued one DB query per visible group; replaced with a single batched `WorkingDB.get_dupe_group_representatives()` call (~12x faster on a synthetic benchmark at this scale). - Selecting a group was slow — every click was also eagerly reloading the (invisible) Multi view's images; skipped while Dupe Grid is the active sub-view. - Clicking a group thumbnail no longer recenters the grid — `select_tag()` only scrolls (minimally, via `EnsureVisible`) when actually entering/returning to the view; routine resyncs leave the viewport alone. - Fixed `W`/`S` not working as group-navigation shortcuts when Single view is opened directly from Dupe Grid (skipping Multi) — the shortcut re-enable was only wired on the Multi-entry path. Still open pending PR/merge to `main`.
Member

Fixed another bug found in testing, pushed to the same branch (0.2.4/issue-138-dupe-grid-view) and propagated forward through the stack (#136, #113, #131, #116 all rebased and re-verified):

Double-clicking an image tile inside the Multi comparison grid always opened Single, ignoring the "bounce to whichever of the last two distinct views isn't active" rule that double-click/E already use correctly everywhere else (Dupe Grid↔Single and Single↔Grid/Multi both consult that history). So if your last two views were Dupe Grid and Multi, double-clicking an image in Multi should land back in Dupe Grid, not Single — that case was hardcoded to Single. Fixed by routing it through the same toggle_target_view() check.

Still open pending PR/merge to main.

Fixed another bug found in testing, pushed to the same branch (`0.2.4/issue-138-dupe-grid-view`) and propagated forward through the stack (#136, #113, #131, #116 all rebased and re-verified): Double-clicking an image tile inside the Multi comparison grid always opened Single, ignoring the "bounce to whichever of the last two distinct views isn't active" rule that double-click/`E` already use correctly everywhere else (Dupe Grid↔Single and Single↔Grid/Multi both consult that history). So if your last two views were Dupe Grid and Multi, double-clicking an image in Multi should land back in Dupe Grid, not Single — that case was hardcoded to Single. Fixed by routing it through the same `toggle_target_view()` check. Still open pending PR/merge to `main`.
Member

Closing — PR #140 is open against main.

Closing — PR #140 is open against `main`.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ai-collab/bulk-image-organizer#138
No description provided.