From d1ee64d36f8373b47d96f4473592123331eeaecb Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Fri, 28 Nov 2025 13:51:20 +1100 Subject: [PATCH] Change show male performers option into list of gender checkboxes (#6321) --- ui/v2.5/src/components/Tagger/constants.ts | 5 +-- .../src/components/Tagger/scenes/Config.tsx | 42 ++++++++++++++----- .../Tagger/scenes/StashSearchResult.tsx | 14 +++---- ui/v2.5/src/locales/en-GB.json | 6 ++- ui/v2.5/src/utils/gender.ts | 11 ++++- 5 files changed, 53 insertions(+), 25 deletions(-) diff --git a/ui/v2.5/src/components/Tagger/constants.ts b/ui/v2.5/src/components/Tagger/constants.ts index e519fb884..d499062aa 100644 --- a/ui/v2.5/src/components/Tagger/constants.ts +++ b/ui/v2.5/src/components/Tagger/constants.ts @@ -1,4 +1,4 @@ -import { ScraperSourceInput } from "src/core/generated-graphql"; +import { GenderEnum, ScraperSourceInput } from "src/core/generated-graphql"; export const STASH_BOX_PREFIX = "stashbox:"; export const SCRAPER_PREFIX = "scraper:"; @@ -27,7 +27,6 @@ export const DEFAULT_EXCLUDED_STUDIO_FIELDS = ["name"]; export const initialConfig: ITaggerConfig = { blacklist: DEFAULT_BLACKLIST, - showMales: true, mode: "auto", setCoverImage: true, setTags: true, @@ -43,7 +42,7 @@ export type ParseMode = "auto" | "filename" | "dir" | "path" | "metadata"; export type TagOperation = "merge" | "overwrite"; export interface ITaggerConfig { blacklist: string[]; - showMales: boolean; + performerGenders?: GenderEnum[]; mode: ParseMode; setCoverImage: boolean; setTags: boolean; diff --git a/ui/v2.5/src/components/Tagger/scenes/Config.tsx b/ui/v2.5/src/components/Tagger/scenes/Config.tsx index f15fbd250..5dd0e29d4 100644 --- a/ui/v2.5/src/components/Tagger/scenes/Config.tsx +++ b/ui/v2.5/src/components/Tagger/scenes/Config.tsx @@ -13,6 +13,8 @@ import { FormattedMessage, useIntl } from "react-intl"; import { Icon } from "src/components/Shared/Icon"; import { ParseMode, TagOperation } from "../constants"; import { TaggerStateContext } from "../context"; +import { GenderEnum } from "src/core/generated-graphql"; +import { genderList } from "src/utils/gender"; const Blacklist: React.FC<{ list: string[]; @@ -118,6 +120,26 @@ const Config: React.FC = ({ show }) => { const { config, setConfig } = useContext(TaggerStateContext); const intl = useIntl(); + function renderGenderCheckbox(gender: GenderEnum) { + const performerGenders = config.performerGenders || genderList.slice(); + return ( + } + checked={performerGenders.includes(gender)} + onChange={(e) => { + const isChecked = e.currentTarget.checked; + setConfig({ + ...config, + performerGenders: isChecked + ? [...performerGenders, gender] + : performerGenders.filter((g) => g !== gender), + }); + }} + /> + ); + } + return ( @@ -127,18 +149,16 @@ const Config: React.FC = ({ show }) => {
- - - } - checked={config.showMales} - onChange={(e) => - setConfig({ ...config, showMales: e.currentTarget.checked }) - } - /> + + + + + {genderList.map(renderGenderCheckbox)} - + diff --git a/ui/v2.5/src/components/Tagger/scenes/StashSearchResult.tsx b/ui/v2.5/src/components/Tagger/scenes/StashSearchResult.tsx index a3429be9a..d9f05b875 100755 --- a/ui/v2.5/src/components/Tagger/scenes/StashSearchResult.tsx +++ b/ui/v2.5/src/components/Tagger/scenes/StashSearchResult.tsx @@ -21,7 +21,7 @@ import { TagSelect } from "src/components/Shared/Select"; import { TruncatedText } from "src/components/Shared/TruncatedText"; import { OperationButton } from "src/components/Shared/OperationButton"; import * as FormUtils from "src/utils/form"; -import { stringToGender } from "src/utils/gender"; +import { genderList, stringToGender } from "src/utils/gender"; import { IScrapedScene, TaggerStateContext } from "../context"; import { OptionalField } from "../IncludeButton"; import { SceneTaggerModalsState } from "./sceneTaggerModals"; @@ -237,17 +237,15 @@ const StashSearchResult: React.FC = ({ saveScene, } = React.useContext(TaggerStateContext); + const performerGenders = config.performerGenders || genderList; + const performers = useMemo( () => scene.performers?.filter((p) => { - if (!config.showMales) { - return ( - !p.gender || stringToGender(p.gender, true) !== GQL.GenderEnum.Male - ); - } - return true; + const gender = p.gender ? stringToGender(p.gender, true) : undefined; + return !gender || performerGenders.includes(gender); }) ?? [], - [config, scene] + [scene, performerGenders] ); const { createPerformerModal, createStudioModal } = React.useContext( diff --git a/ui/v2.5/src/locales/en-GB.json b/ui/v2.5/src/locales/en-GB.json index be50fc8da..37ef0d12b 100644 --- a/ui/v2.5/src/locales/en-GB.json +++ b/ui/v2.5/src/locales/en-GB.json @@ -190,6 +190,10 @@ }, "mark_organized_desc": "Immediately mark the scene as Organized after the Save button is clicked.", "mark_organized_label": "Mark as Organized on save", + "performer_genders": { + "heading": "Performer genders", + "description": "Performers with these genders will be shown when tagging scenes." + }, "query_mode_auto": "Auto", "query_mode_auto_desc": "Uses metadata if present, or filename", "query_mode_dir": "Dir", @@ -205,8 +209,6 @@ "set_cover_label": "Set scene cover image", "set_tag_desc": "Attach tags to scene, either by overwriting or merging with existing tags on scene.", "set_tag_label": "Set tags", - "show_male_desc": "Toggle whether male performers will be available to tag.", - "show_male_label": "Show male performers", "source": "Source" }, "noun_query": "Query", diff --git a/ui/v2.5/src/utils/gender.ts b/ui/v2.5/src/utils/gender.ts index 29502695c..09d3eddec 100644 --- a/ui/v2.5/src/utils/gender.ts +++ b/ui/v2.5/src/utils/gender.ts @@ -1,14 +1,23 @@ import * as GQL from "../core/generated-graphql"; export const stringGenderMap = new Map([ - ["Male", GQL.GenderEnum.Male], ["Female", GQL.GenderEnum.Female], + ["Male", GQL.GenderEnum.Male], ["Transgender Male", GQL.GenderEnum.TransgenderMale], ["Transgender Female", GQL.GenderEnum.TransgenderFemale], ["Intersex", GQL.GenderEnum.Intersex], ["Non-Binary", GQL.GenderEnum.NonBinary], ]); +export const genderList = [ + GQL.GenderEnum.Female, + GQL.GenderEnum.Male, + GQL.GenderEnum.TransgenderFemale, + GQL.GenderEnum.TransgenderMale, + GQL.GenderEnum.Intersex, + GQL.GenderEnum.NonBinary, +]; + export const genderToString = (value?: GQL.GenderEnum | string | null) => { if (!value) { return undefined;