Skip to content

[Feature] Tagger performer match improvements#6854

Open
Stash-KennyG wants to merge 30 commits intostashapp:developfrom
Stash-KennyG:feature/6853-performer-hover-preview
Open

[Feature] Tagger performer match improvements#6854
Stash-KennyG wants to merge 30 commits intostashapp:developfrom
Stash-KennyG:feature/6853-performer-hover-preview

Conversation

@Stash-KennyG
Copy link
Copy Markdown
Contributor

Enhance Tagger performer match UX with hover previews and mismatch warnings

Closes #6853

Functionality

  • Adds a hover preview for matched performer selection in Scene Tagger by attaching the preview to the picker control, when a match is suggested by name
image
  • Adds a stashbox performer hover preview on the left performer label using scraped/remote data, while rendering through shared performer card UI for visual consistency.
image
  • Adds mismatch context in the matched performer hover card for non-matching performer fields (including aliases/URLs as counts), to make potential cross-linkage easier to spot before save.
image
  • Adds stash ID conflict warning inside the hover card when the local selected performer already has a stash ID for the same endpoint but with a different GUID. Uses a compact red endpoint chip for stash ID conflict warning, with full conflicting GUID available via chip tooltip.
image

Behavior Details

  • Picker hover target: hover card opens from the selected picker control.
  • Left-side scraped hover: hover on scraped performer text shows card built from scraped data (image/name/etc.) but styled with shared PerformerCard.
  • Mismatch rows: shown only for fields where scraped has a value and differs from selected local value.
  • Aliases / URLs: reported as counts only.
  • Stash ID conflict warning:
    • shown only when attached stash_id != incoming remote_site_id AND attached stash_endpoint == incoming stash_endpoint
    • displayed inside card, above mismatch rows
    • compact red endpoint chip; GUID is tooltip text.

Mismatch Fields Covers

  • Birthdate
  • Death Date
  • Ethnicity
  • Hair Color
  • Eye Color
  • Height
  • Weight
  • Penis Length
  • Circumcised
  • Measurements
  • Fake Tits
  • Tattoos
  • Piercings
  • Career Start
  • Career End
  • Aliases (count)
  • URLs (count)

Test Plan

  • [✅] Hover selected performer picker in Scene Tagger matched result and confirm card opens below picker.
  • [✅] Hover left scraped performer name and confirm scraped preview card appears and matches shared performer card styling.
  • [✅] Confirm mismatch rows render only for differing values and are hidden for exact matches.
  • [✅] Confirm aliases/URLs mismatch rows show only in Remote > Local.
  • [✅] Confirm stash ID warning appears only when endpoint matches and GUID differs.
  • [✅] Confirm warning chip is compact red endpoint chip and GUID is visible in tooltip.
  • [✅] Confirm no stash ID warning appears when GUIDs match.
  • [✅] Check regressions
    • Performer card on scene details unaffected
    • Performer popover on scene card unaffected
    • Tagger workflow unaffected on scenes and performer view
  • [✅] Confirm lint/build checks pass.

Notes

  • This feature is designed to improve confidence in match correctness before save, especially in larger datasets where name collisions are more common.

LLM Details

[✔] LLM use is openly disclosed. Made with Cursor
[✔] Code is reviewed by a human.
[✔] Human testing and validation was performed.
[✔] You take full responsibility for the code (including license compliance).

KennyG and others added 18 commits April 21, 2026 13:10
…rmerPreview component

- Added cardClassName prop to PerformerPopoverCard and PerformerPopover for customizable styling.
- Introduced MatchedPerformerPreview component to encapsulate PerformerPopover usage with a performerID.
- Updated PerformerResult to utilize MatchedPerformerPreview for improved structure and styling.
…component

- Added delta row functionality to display differences between local and remote performer data in MatchedPerformerPreview.
- Introduced ScrapedPerformerPreview component for displaying scraped performer details with hover functionality.
- Updated PerformerResult to integrate ScrapedPerformerPreview and pass necessary props for delta rows and warnings.
- Enhanced styling for performer popovers to improve user experience.
- Simplified conditions for displaying remote aliases and URLs by removing unnecessary checks against local counts.
- Ensured that rows are only pushed when remote counts exceed local counts, improving clarity and performance.
Document summary, test plan, and compatibility note for card class shape changes.

Made-with: Cursor
Use full findPerformer data for mismatch comparisons and selected hover content, and normalize scraped card mapping to satisfy PerformerDataFragment shape.

Made-with: Cursor
Apply Prettier-compatible formatting updates in matched preview, performer result, and scraped preview components.

Made-with: Cursor
Normalize formatting patterns to align with repository Prettier output.

Made-with: Cursor
Restructure imports and helper formatting to better match repository Prettier conventions.

Made-with: Cursor
Rework formatting structure in performer result and scraped preview to match established Prettier output style.

Made-with: Cursor
Format PerformerResult and ScrapedPerformerPreview with Prettier to satisfy validate-ui format checks.

Made-with: Cursor
Use repository Prettier version to align with CI format-check expectations.

Made-with: Cursor
Copy link
Copy Markdown
Collaborator

@Gykes Gykes left a comment

Choose a reason for hiding this comment

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

Static review only, no actual testing was done.

Comment thread ui/v2.5/src/components/Tagger/scenes/PerformerResult.tsx Outdated
Comment thread ui/v2.5/src/components/Tagger/scenes/ScrapedPerformerPreview.tsx Outdated
Comment thread ui/v2.5/src/components/Tagger/scenes/PerformerResult.tsx Outdated
Comment thread ui/v2.5/src/components/Tagger/scenes/PerformerResult.tsx Outdated
Comment thread ui/v2.5/src/components/Tagger/scenes/PerformerResult.tsx Outdated
Comment thread ui/v2.5/src/components/Tagger/scenes/ScrapedPerformerPreview.tsx Outdated
Comment thread ui/v2.5/src/components/Tagger/scenes/ScrapedPerformerPreview.tsx Outdated
KennyG added 6 commits April 22, 2026 08:48
- Refactored buildPerformerDeltaRows to utilize `intl` for label formatting, improving localization.
- Updated loading state message to use `FormattedMessage` for better internationalization.
- Ensured all performer attributes are displayed with localized labels, enhancing user experience across different languages.
- Added `useIntl` hook to support localized performer names.
- Updated `toPerformerCardData` function to utilize `intl` for formatting unknown performer names, enhancing user experience across different languages.
…tionality.

- Replaced `PerformerCard` with `LocalPerformerCard` in `MatchedPerformerPreview` for better encapsulation.
- Introduced `RemotePerformerCard` in `ScrapedPerformerPreview` to enhance the display of performer details, including gender and country flag.
- Updated content rendering in `ScrapedPerformerPreview` to utilize the new `RemotePerformerCard` component.
…roved value handling.

- Enhanced the normalizeValue function to handle numeric-like strings, converting them to numbers when applicable.
- Maintained existing functionality for trimming and lowercasing non-numeric strings, ensuring consistent value normalization.
Convert scraped performer gender strings to GenderEnum using stringToGender before rendering GenderIcon so UI type-check passes in CI.

Made-with: Cursor
…azy/async functionality

- Updated MatchedPerformerPreview to utilize scraped performer data and handle loading states more effectively.
- Introduced delta row calculations for displaying differences between local and scraped performer data.
- Removed redundant code and improved the overall organization of the components for better maintainability.
@Stash-KennyG Stash-KennyG requested a review from Gykes April 22, 2026 18:23
Copy link
Copy Markdown
Collaborator

@Gykes Gykes left a comment

Choose a reason for hiding this comment

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

Another static review.

Looking better, once these are addressed/chatted about I will do app testing.

Comment thread ui/v2.5/src/components/Tagger/scenes/MatchedPerformerPreview.tsx Outdated
Comment thread ui/v2.5/src/components/Tagger/styles.scss Outdated
Comment thread ui/v2.5/src/components/Performers/PerformerPopover.tsx Outdated
Comment thread ui/v2.5/src/components/Tagger/styles.scss Outdated
Comment thread ui/v2.5/src/components/Tagger/scenes/MatchedPerformerPreview.tsx
Comment thread ui/v2.5/src/components/Tagger/scenes/MatchedPerformerPreview.tsx Outdated
Comment thread ui/v2.5/src/components/Tagger/scenes/ScrapedPerformerPreview.tsx Outdated
KennyG added 3 commits April 23, 2026 10:39
Refactor PerformerPopover and related components for improved functionality and structure

- Updated PerformerPopover to accept preview data, loading states, and additional card extras for enhanced flexibility.
- Replaced PerformerCard with PerformerPreviewCard in PerformerPopoverCard for better encapsulation and display of performer details.
- Refactored MatchedPerformerPreview and ScrapedPerformerPreview to utilize PerformerPopover, streamlining the rendering of performer information and loading states.
- Improved styling by renaming CSS classes for consistency and clarity.
- Replaced PerformerPreviewCard with PerformerCard in PerformerPopover for better encapsulation and display.
- Simplified MatchedPerformerPreview by removing unnecessary loading state handling and age calculations.
- Enhanced styling in Tagger component with additional padding for better layout consistency.
- Updated CSS class names from `tagger-performer-popover` to `performer-preview-popover` for clarity.
- Enhanced styling for the new `performer-preview-popover` class to ensure consistent dimensions and image handling.
- Removed outdated styles related to the previous tagger popover implementation.
KennyG added 3 commits April 23, 2026 11:30
Reorder padding declarations in the matched performer popover extra block to satisfy alphabetical property order enforced by stylelint.

Made-with: Cursor
Use full PerformerCard in PerformerPopover ID mode so favorites and card button overlays render again, while keeping previewData mode for scraped/tagger previews.

Made-with: Cursor
Normalize import formatting in ScrapedPerformerPreview to match repository Prettier output and unblock validate-ui format-check.

Made-with: Cursor
@Stash-KennyG
Copy link
Copy Markdown
Contributor Author

Stash-KennyG commented Apr 23, 2026

What Changed Since PR Opened

  • Refactored hover rendering so PerformerPopover is now the shared hover controller for this feature path.
  • Added previewData support to PerformerPopover to safely render scraped performer previews without unsafe casting.
  • Added PerformerPreviewCard in components/Performers as a shared typed preview renderer.
  • Moved shared preview-popover styling ownership to components/Performers/styles.scss (.performer-preview-popover) and removed Tagger-owned shared styling.
  • Preserved full PerformerCard behavior for ID-based popovers (favorite icon, counters/chips, overlays) by restoring PerformerCard in PerformerPopover local-ID mode.
  • Kept Tagger-specific extras (stash ID conflict chip + mismatch rows) as appended card content inside matched popovers.

Data Shape Strategy (No Unsafe Casts)

  • PerformerDataFragment and ScrapedPerformer are intentionally handled through separate adapters.
  • Scraped/remote preview uses typed previewData mapping.
  • Local/matched preview uses id mode in PerformerPopover plus lazy details fetch for mismatch/warning logic.
  • No as unknown as style casting is used to coerce incompatible performer types.

Hover/Lazy-Load Behavior

  • Matched performer detail query is hover-scoped:
    • Opens on hover (onOpen)
    • Stops querying on close (onClose)
  • Prevents eager fetching for large scrape result pages while preserving content.

UI/Styling Adjustments

  • Consolidated duplicate preview card CSS.
  • Updated border color to theme token ($secondary) for consistency with dark theme styling.

CI/Validation Fixes Applied

  • Fixed stylelint property ordering in Tagger/styles.scss.
  • Applied Prettier formatting fixes for updated files.
  • Confirmed latest PR checks pass after these adjustments.

@Stash-KennyG Stash-KennyG requested a review from Gykes April 28, 2026 22:07
@Gykes
Copy link
Copy Markdown
Collaborator

Gykes commented Apr 28, 2026

So, after some quick testing of the feature it looks okay. There is a small UX thing that I noticed and not sure if it is intended.

  1. Search for a scene that has greater than 1 performer
  2. Hover the first performer
  3. The new modal is considered part of the hover and does not go away if you are hovering the name or the new modal
  4. To hover the next performer you need to move outside of the box and it feels a little clunky.

From a UX standpoint I would image that, since there is no hyperlinked information in this modal, then it should go away when you remove your hover from the name of the performer on the tagger card. This is, of course, opinionated and I think no matter what way you do it you will get pushback.

In my opinion, the hover should disappear when you move your mouse off of the performer name. With that in mind lets go ahead and go that route and if there is a large enough of a pushback then we can revert.

@Stash-KennyG
Copy link
Copy Markdown
Contributor Author

Stash-KennyG commented May 1, 2026

Current behavior is intentional. When you hover a performer and the modal appears, it remains active if the cursor moves into the modal. That allows click or ctrl/middle-click actions directly from the modal (open stash or stashdb).

The primary driver was the right side where that interaction did not exist before. The left side already supported it, but I kept behavior consistent across both sides rather than introducing different hover models.

Implementation differs slightly (inline block vs box picker), but both treat the modal as part of the hover region by design.

Net effect: dismissal is lateral movement, not vertical.

The suggestion is valid from a simplicity standpoint. Current design prioritizes interaction over quick dismissal. If that tradeoff proves wrong, it can be adjusted, but would lose the ability to interact with the card in case someone wanted to get more details. Also, in highlighting performer mis-matches - interaction with middle click may be necssary...

@Gykes
Copy link
Copy Markdown
Collaborator

Gykes commented May 1, 2026

If it is intentional then you can keep it as is. I imagine that people will want to be directed to the Stash Box link to verify performer at some point. Off the top of my head I don't have a solution for the issue I was having but I don't think it's a massive one. I think this is mostly ready for WP review anyway so will probably give it another quick look over and test then send it his way,

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.

Feature Request: Performer Match Preview Card in Tagger

2 participants