Add SFW content mode option (#6262)

* Use more neutral language for content
* Add sfw mode setting
* Make configuration context mandatory
* Add sfw class when sfw mode active
* Hide nsfw performer fields in sfw mode
* Hide nsfw sort options
* Hide nsfw filter/sort options in sfw mode
* Replace o-count with like counter in sfw mode
* Use sfw label for o-counter filter in sfw mode
* Use likes instead of o-count in sfw mode in other places
* Rename sfw mode to sfw content mode
* Use sfw image for default performers in sfw mode
* Document SFW content mode
* Add SFW mode setting to setup
* Clarify README
* Change wording of sfw mode description
* Handle configuration loading error correctly
* Hide age in performer cards
This commit is contained in:
WithoutPants
2025-11-18 11:13:35 +11:00
committed by GitHub
parent bb56b619f5
commit 51999135be
105 changed files with 843 additions and 370 deletions

View File

@@ -372,27 +372,32 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
return (
<>
<ScrapedInputGroupRow
field="title"
title={intl.formatMessage({ id: "title" })}
result={title}
onChange={(value) => setTitle(value)}
/>
<ScrapedInputGroupRow
field="code"
title={intl.formatMessage({ id: "scene_code" })}
result={code}
onChange={(value) => setCode(value)}
/>
<ScrapedStringListRow
field="urls"
title={intl.formatMessage({ id: "urls" })}
result={url}
onChange={(value) => setURL(value)}
/>
<ScrapedInputGroupRow
field="date"
title={intl.formatMessage({ id: "date" })}
placeholder="YYYY-MM-DD"
result={date}
onChange={(value) => setDate(value)}
/>
<ScrapeDialogRow
field="rating"
title={intl.formatMessage({ id: "rating" })}
result={rating}
renderOriginalField={() => (
@@ -404,6 +409,7 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
onChange={(value) => setRating(value)}
/>
<ScrapeDialogRow
field="o_count"
title={intl.formatMessage({ id: "o_count" })}
result={oCounter}
renderOriginalField={() => (
@@ -425,6 +431,7 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
onChange={(value) => setOCounter(value)}
/>
<ScrapeDialogRow
field="play_count"
title={intl.formatMessage({ id: "play_count" })}
result={playCount}
renderOriginalField={() => (
@@ -446,6 +453,7 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
onChange={(value) => setPlayCount(value)}
/>
<ScrapeDialogRow
field="play_duration"
title={intl.formatMessage({ id: "play_duration" })}
result={playDuration}
renderOriginalField={() => (
@@ -469,6 +477,7 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
onChange={(value) => setPlayDuration(value)}
/>
<ScrapeDialogRow
field="galleries"
title={intl.formatMessage({ id: "galleries" })}
result={galleries}
renderOriginalField={() => (
@@ -492,32 +501,38 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
onChange={(value) => setGalleries(value)}
/>
<ScrapedStudioRow
field="studio"
title={intl.formatMessage({ id: "studios" })}
result={studio}
onChange={(value) => setStudio(value)}
/>
<ScrapedPerformersRow
field="performers"
title={intl.formatMessage({ id: "performers" })}
result={performers}
onChange={(value) => setPerformers(value)}
ageFromDate={date.useNewValue ? date.newValue : date.originalValue}
/>
<ScrapedGroupsRow
field="groups"
title={intl.formatMessage({ id: "groups" })}
result={groups}
onChange={(value) => setGroups(value)}
/>
<ScrapedTagsRow
field="tags"
title={intl.formatMessage({ id: "tags" })}
result={tags}
onChange={(value) => setTags(value)}
/>
<ScrapedTextAreaRow
field="details"
title={intl.formatMessage({ id: "details" })}
result={details}
onChange={(value) => setDetails(value)}
/>
<ScrapeDialogRow
field="organized"
title={intl.formatMessage({ id: "organized" })}
result={organized}
renderOriginalField={() => (
@@ -539,6 +554,7 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
onChange={(value) => setOrganized(value)}
/>
<ScrapeDialogRow
field="stash_ids"
title={intl.formatMessage({ id: "stash_id" })}
result={stashIDs}
renderOriginalField={() => (
@@ -550,6 +566,7 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
onChange={(value) => setStashIDs(value)}
/>
<ScrapedImageRow
field="cover_image"
title={intl.formatMessage({ id: "cover_image" })}
className="scene-cover"
result={image}