From 35488c706fe051c2a317cd21c7528f2b673ac509 Mon Sep 17 00:00:00 2001 From: Gykes Date: Wed, 22 Apr 2026 23:25:01 -0700 Subject: [PATCH 1/8] initial work for autotag skip warning --- graphql/schema/types/config.graphql | 6 +++ internal/api/resolver_mutation_configure.go | 2 + internal/api/resolver_query_configuration.go | 3 ++ internal/manager/config/config.go | 6 +++ ui/v2.5/graphql/data/config.graphql | 1 + .../Settings/Tasks/LibraryTasks.tsx | 25 ++++++++++- .../Shared/AutoTagConfirmDialog.tsx | 43 ++++++++++++++++++- .../components/Shared/DetailsEditNavbar.tsx | 17 +++++++- ui/v2.5/src/docs/en/Manual/AutoTagging.md | 4 ++ ui/v2.5/src/locales/en-GB.json | 7 ++- 10 files changed, 108 insertions(+), 6 deletions(-) diff --git a/graphql/schema/types/config.graphql b/graphql/schema/types/config.graphql index 5ab7fdfea..99caf9614 100644 --- a/graphql/schema/types/config.graphql +++ b/graphql/schema/types/config.graphql @@ -428,6 +428,9 @@ input ConfigInterfaceInput { "Set to true to disable creating new objects via the dropdown menus" disableDropdownCreate: ConfigDisableDropdownCreateInput + "Set to true to skip the auto tag confirmation warning" + disableAutoTagWarning: Boolean + "Handy Connection Key" handyKey: String "Funscript Time Offset" @@ -505,6 +508,9 @@ type ConfigInterfaceResult { "Fields are true if creating via dropdown menus are disabled" disableDropdownCreate: ConfigDisableDropdownCreate! + "True if the auto tag confirmation warning should be skipped" + disableAutoTagWarning: Boolean + "Handy Connection Key" handyKey: String "Funscript Time Offset" diff --git a/internal/api/resolver_mutation_configure.go b/internal/api/resolver_mutation_configure.go index 3df1c9114..747e8f9e9 100644 --- a/internal/api/resolver_mutation_configure.go +++ b/internal/api/resolver_mutation_configure.go @@ -538,6 +538,8 @@ func (r *mutationResolver) ConfigureInterface(ctx context.Context, input ConfigI r.setConfigBool(config.DisableDropdownCreateGallery, ddc.Gallery) } + r.setConfigBool(config.DisableAutoTagWarning, input.DisableAutoTagWarning) + r.setConfigString(config.HandyKey, input.HandyKey) r.setConfigInt(config.FunscriptOffset, input.FunscriptOffset) r.setConfigBool(config.UseStashHostedFunscript, input.UseStashHostedFunscript) diff --git a/internal/api/resolver_query_configuration.go b/internal/api/resolver_query_configuration.go index cf2c0e3cc..6bd83ca42 100644 --- a/internal/api/resolver_query_configuration.go +++ b/internal/api/resolver_query_configuration.go @@ -168,6 +168,7 @@ func makeConfigInterfaceResult() *ConfigInterfaceResult { useStashHostedFunscript := config.GetUseStashHostedFunscript() imageLightboxOptions := config.GetImageLightboxOptions() disableDropdownCreate := config.GetDisableDropdownCreate() + disableAutoTagWarning := config.GetDisableAutoTagWarning() return &ConfigInterfaceResult{ SfwContentMode: config.GetSFWContentMode(), @@ -196,6 +197,8 @@ func makeConfigInterfaceResult() *ConfigInterfaceResult { DisableDropdownCreate: disableDropdownCreate, + DisableAutoTagWarning: &disableAutoTagWarning, + HandyKey: &handyKey, FunscriptOffset: &scriptOffset, UseStashHostedFunscript: &useStashHostedFunscript, diff --git a/internal/manager/config/config.go b/internal/manager/config/config.go index 19e263810..5788933e4 100644 --- a/internal/manager/config/config.go +++ b/internal/manager/config/config.go @@ -237,6 +237,8 @@ const ( DisableDropdownCreateMovie = "disable_dropdown_create.movie" DisableDropdownCreateGallery = "disable_dropdown_create.gallery" + DisableAutoTagWarning = "disable_auto_tag_warning" + HandyKey = "handy_key" FunscriptOffset = "funscript_offset" UseStashHostedFunscript = "use_stash_hosted_funscript" @@ -1311,6 +1313,10 @@ func (i *Config) GetShowStudioAsText() bool { return i.getBool(ShowStudioAsText) } +func (i *Config) GetDisableAutoTagWarning() bool { + return i.getBool(DisableAutoTagWarning) +} + func (i *Config) getSlideshowDelay() int { // assume have lock diff --git a/ui/v2.5/graphql/data/config.graphql b/ui/v2.5/graphql/data/config.graphql index ba8215fe3..35b0c2b99 100644 --- a/ui/v2.5/graphql/data/config.graphql +++ b/ui/v2.5/graphql/data/config.graphql @@ -115,6 +115,7 @@ fragment ConfigInterfaceData on ConfigInterfaceResult { movie gallery } + disableAutoTagWarning handyKey funscriptOffset useStashHostedFunscript diff --git a/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx b/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx index eace4b7dc..6bf8924ad 100644 --- a/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx +++ b/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx @@ -75,7 +75,13 @@ const AutoTagOptions: React.FC = ({ export const LibraryTasks: React.FC = () => { const intl = useIntl(); const Toast = useToast(); - const { ui, saveUI, loading } = useSettings(); + const { + ui, + saveUI, + interface: iface, + saveInterface, + loading, + } = useSettings(); const { taskDefaults } = ui; @@ -195,6 +201,14 @@ export const LibraryTasks: React.FC = () => { }); } + function onAutoTagClick() { + if (configuration?.interface.disableAutoTagWarning) { + runAutoTag(); + return; + } + setDialogOpen({ autoTagAlert: true }); + } + function renderScanDialog() { if (!dialogOpen.scan) { return; @@ -449,7 +463,7 @@ export const LibraryTasks: React.FC = () => { variant="secondary" type="submit" className="mr-2" - onClick={() => setDialogOpen({ autoTagAlert: true })} + onClick={onAutoTagClick} > … @@ -468,6 +482,13 @@ export const LibraryTasks: React.FC = () => { options={autoTagOptions} setOptions={onSetAutoTagOptions} /> + saveInterface({ disableAutoTagWarning: v })} + /> diff --git a/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx b/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx index 0290c7e07..ece07735f 100644 --- a/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx +++ b/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx @@ -1,6 +1,9 @@ -import React from "react"; +import React, { useContext, useEffect, useState } from "react"; +import { Form } from "react-bootstrap"; import { FormattedMessage, useIntl } from "react-intl"; import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons"; +import { useConfigureInterface } from "src/core/StashService"; +import { SettingStateContext } from "src/components/Settings/context"; import { ModalComponent } from "./Modal"; import { Icon } from "./Icon"; @@ -31,6 +34,34 @@ export const AutoTagConfirmDialog: React.FC = ({ onCancel, }) => { const intl = useIntl(); + const [dontShowAgain, setDontShowAgain] = useState(false); + const [configureInterface] = useConfigureInterface(); + + useEffect(() => { + if (show) { + setDontShowAgain(false); + } + }, [show]); + // route through SettingsContext when available so the Settings panel's + // local state reflects the change without a page refresh + const settingsContext = useContext(SettingStateContext); + + async function handleConfirm() { + if (dontShowAgain) { + try { + if (settingsContext) { + settingsContext.saveInterface({ disableAutoTagWarning: true }); + } else { + await configureInterface({ + variables: { input: { disableAutoTagWarning: true } }, + }); + } + } catch (e) { + // preference persistence failure must not block the confirmed action + } + } + onConfirm(); + } return ( = ({ accept={{ text: intl.formatMessage({ id: "actions.confirm" }), variant: "danger", - onClick: onConfirm, + onClick: handleConfirm, }} cancel={{ onClick: onCancel, }} > + setDontShowAgain(e.currentTarget.checked)} + label={intl.formatMessage({ + id: "dialogs.dont_show_again", + })} + /> ); }; diff --git a/ui/v2.5/src/components/Shared/DetailsEditNavbar.tsx b/ui/v2.5/src/components/Shared/DetailsEditNavbar.tsx index 159bb9f09..e6196e4a9 100644 --- a/ui/v2.5/src/components/Shared/DetailsEditNavbar.tsx +++ b/ui/v2.5/src/components/Shared/DetailsEditNavbar.tsx @@ -1,6 +1,7 @@ import { Button, Dropdown, Modal, SplitButton } from "react-bootstrap"; import React, { useState } from "react"; import { FormattedMessage, useIntl } from "react-intl"; +import { useConfigurationContext } from "src/hooks/Config"; import { ImageInput } from "./ImageInput"; import { AutoTagConfirmDialog } from "./AutoTagConfirmDialog"; import cx from "classnames"; @@ -30,9 +31,23 @@ interface IProps { export const DetailsEditNavbar: React.FC = (props: IProps) => { const intl = useIntl(); + const { configuration } = useConfigurationContext(); const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false); const [isAutoTagAlertOpen, setIsAutoTagAlertOpen] = useState(false); + const skipAutoTagWarning = + configuration?.interface.disableAutoTagWarning ?? false; + + function onAutoTagClick() { + if (skipAutoTagWarning) { + if (props.onAutoTag) { + props.onAutoTag(); + } + return; + } + setIsAutoTagAlertOpen(true); + } + function renderEditButton() { if (props.isNew) return; return ( @@ -116,7 +131,7 @@ export const DetailsEditNavbar: React.FC = (props: IProps) => { diff --git a/ui/v2.5/src/docs/en/Manual/AutoTagging.md b/ui/v2.5/src/docs/en/Manual/AutoTagging.md index 4725020d1..3b2cc6914 100644 --- a/ui/v2.5/src/docs/en/Manual/AutoTagging.md +++ b/ui/v2.5/src/docs/en/Manual/AutoTagging.md @@ -48,3 +48,7 @@ Performers or Tags that have Ignore Auto tag flag added to them will be skipped - **Auto tag:** You can run the Auto tag task on your entire library from the Tasks page. - **Selective auto tag:** You can run the Auto tag task on specific directories from the Tasks page. - **Individual pages:** You can run Auto tag tasks for specific Performers, Studios, and Tags from their respective pages. + +### Skip the confirmation warning + +A confirmation warning is shown before Auto tag runs. If you use Auto tag frequently you can bypass this warning by ticking the **Don't show this warning again** checkbox on the warning dialog, or by enabling **Settings → Tasks → Auto Tag → Skip auto tag warning**. diff --git a/ui/v2.5/src/locales/en-GB.json b/ui/v2.5/src/locales/en-GB.json index 4974c06ca..4327df68c 100644 --- a/ui/v2.5/src/locales/en-GB.json +++ b/ui/v2.5/src/locales/en-GB.json @@ -509,7 +509,11 @@ "anonymising_database": "Anonymising database", "auto_tag": { "auto_tagging_all_paths": "Auto tagging all paths", - "auto_tagging_paths": "Auto tagging the following paths" + "auto_tagging_paths": "Auto tagging the following paths", + "skip_warning": { + "description": "Skip the confirmation warning shown before running auto tag.", + "heading": "Skip auto tag warning" + } }, "auto_tag_based_on_filenames": "Auto tag content based on file paths.", "auto_tag_confirm": "This will attempt to match your content against existing metadata.", @@ -1002,6 +1006,7 @@ "delete_object_desc": "Are you sure you want to delete {count, plural, one {this {singularEntity}} other {these {pluralEntity}}}?", "delete_object_overflow": "…and {count} other {count, plural, one {{singularEntity}} other {{pluralEntity}}}.", "delete_object_title": "Delete {count, plural, one {{singularEntity}} other {{pluralEntity}}}", + "dont_show_again": "Don't show this warning again", "dont_show_until_updated": "Don't show until next update", "edit_entity_title": "Edit {count, plural, one {{singularEntity}} other {{pluralEntity}}}", "edit_entity_count_title": "Edit {count} {count, plural, one {{singularEntity}} other {{pluralEntity}}}", From 5ad17ee69121ec970c50bbc300ae2f2f2c865502 Mon Sep 17 00:00:00 2001 From: Gykes Date: Wed, 22 Apr 2026 23:35:53 -0700 Subject: [PATCH 2/8] change up verbage and break out hook --- .../Settings/Tasks/LibraryTasks.tsx | 16 +++++----- .../Shared/AutoTagConfirmDialog.tsx | 29 +++++++++---------- .../components/Shared/DetailsEditNavbar.tsx | 19 ++++-------- ui/v2.5/src/docs/en/Manual/AutoTagging.md | 2 +- ui/v2.5/src/hooks/useAutoTagTrigger.ts | 17 +++++++++++ ui/v2.5/src/locales/en-GB.json | 4 +-- 6 files changed, 46 insertions(+), 41 deletions(-) create mode 100644 ui/v2.5/src/hooks/useAutoTagTrigger.ts diff --git a/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx b/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx index 6bf8924ad..6fd2f2a29 100644 --- a/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx +++ b/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx @@ -8,6 +8,7 @@ import { } from "src/core/StashService"; import { withoutTypename } from "src/utils/data"; import { useConfigurationContext } from "src/hooks/Config"; +import { useAutoTagTrigger } from "src/hooks/useAutoTagTrigger"; import { IdentifyDialog } from "../../Dialogs/IdentifyDialog/IdentifyDialog"; import * as GQL from "src/core/generated-graphql"; import { DirectorySelectionDialog } from "./DirectorySelectionDialog"; @@ -201,13 +202,10 @@ export const LibraryTasks: React.FC = () => { }); } - function onAutoTagClick() { - if (configuration?.interface.disableAutoTagWarning) { - runAutoTag(); - return; - } - setDialogOpen({ autoTagAlert: true }); - } + const onAutoTagClick = useAutoTagTrigger( + () => runAutoTag(), + () => setDialogOpen({ autoTagAlert: true }) + ); function renderScanDialog() { if (!dialogOpen.scan) { @@ -484,8 +482,8 @@ export const LibraryTasks: React.FC = () => { /> saveInterface({ disableAutoTagWarning: v })} /> diff --git a/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx b/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx index ece07735f..c466efeed 100644 --- a/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx +++ b/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx @@ -4,6 +4,7 @@ import { FormattedMessage, useIntl } from "react-intl"; import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons"; import { useConfigureInterface } from "src/core/StashService"; import { SettingStateContext } from "src/components/Settings/context"; +import { useToast } from "src/hooks/Toast"; import { ModalComponent } from "./Modal"; import { Icon } from "./Icon"; @@ -34,30 +35,28 @@ export const AutoTagConfirmDialog: React.FC = ({ onCancel, }) => { const intl = useIntl(); + const Toast = useToast(); const [dontShowAgain, setDontShowAgain] = useState(false); const [configureInterface] = useConfigureInterface(); + // route through SettingsContext when available so the Settings panel's + // local state reflects the change without a page refresh + const settingsContext = useContext(SettingStateContext); useEffect(() => { if (show) { setDontShowAgain(false); } }, [show]); - // route through SettingsContext when available so the Settings panel's - // local state reflects the change without a page refresh - const settingsContext = useContext(SettingStateContext); - async function handleConfirm() { + function handleConfirm() { if (dontShowAgain) { - try { - if (settingsContext) { - settingsContext.saveInterface({ disableAutoTagWarning: true }); - } else { - await configureInterface({ - variables: { input: { disableAutoTagWarning: true } }, - }); - } - } catch (e) { - // preference persistence failure must not block the confirmed action + if (settingsContext) { + // context's saveInterface already surfaces errors via its own toast + settingsContext.saveInterface({ disableAutoTagWarning: true }); + } else { + configureInterface({ + variables: { input: { disableAutoTagWarning: true } }, + }).catch((e) => Toast.error(e)); } } onConfirm(); @@ -88,4 +87,4 @@ export const AutoTagConfirmDialog: React.FC = ({ /> ); -}; +}; \ No newline at end of file diff --git a/ui/v2.5/src/components/Shared/DetailsEditNavbar.tsx b/ui/v2.5/src/components/Shared/DetailsEditNavbar.tsx index e6196e4a9..d4b0c9114 100644 --- a/ui/v2.5/src/components/Shared/DetailsEditNavbar.tsx +++ b/ui/v2.5/src/components/Shared/DetailsEditNavbar.tsx @@ -1,7 +1,7 @@ import { Button, Dropdown, Modal, SplitButton } from "react-bootstrap"; import React, { useState } from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import { useConfigurationContext } from "src/hooks/Config"; +import { useAutoTagTrigger } from "src/hooks/useAutoTagTrigger"; import { ImageInput } from "./ImageInput"; import { AutoTagConfirmDialog } from "./AutoTagConfirmDialog"; import cx from "classnames"; @@ -31,22 +31,13 @@ interface IProps { export const DetailsEditNavbar: React.FC = (props: IProps) => { const intl = useIntl(); - const { configuration } = useConfigurationContext(); const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false); const [isAutoTagAlertOpen, setIsAutoTagAlertOpen] = useState(false); - const skipAutoTagWarning = - configuration?.interface.disableAutoTagWarning ?? false; - - function onAutoTagClick() { - if (skipAutoTagWarning) { - if (props.onAutoTag) { - props.onAutoTag(); - } - return; - } - setIsAutoTagAlertOpen(true); - } + const onAutoTagClick = useAutoTagTrigger( + () => props.onAutoTag?.(), + () => setIsAutoTagAlertOpen(true) + ); function renderEditButton() { if (props.isNew) return; diff --git a/ui/v2.5/src/docs/en/Manual/AutoTagging.md b/ui/v2.5/src/docs/en/Manual/AutoTagging.md index 3b2cc6914..cc70c7b1f 100644 --- a/ui/v2.5/src/docs/en/Manual/AutoTagging.md +++ b/ui/v2.5/src/docs/en/Manual/AutoTagging.md @@ -51,4 +51,4 @@ Performers or Tags that have Ignore Auto tag flag added to them will be skipped ### Skip the confirmation warning -A confirmation warning is shown before Auto tag runs. If you use Auto tag frequently you can bypass this warning by ticking the **Don't show this warning again** checkbox on the warning dialog, or by enabling **Settings → Tasks → Auto Tag → Skip auto tag warning**. +A confirmation warning is shown before Auto tag runs. If you use Auto tag frequently you can bypass this warning by ticking the **Don't show this warning again** checkbox on the warning dialog, or by enabling **Settings → Tasks → Auto Tag → Disable auto tag warning**. diff --git a/ui/v2.5/src/hooks/useAutoTagTrigger.ts b/ui/v2.5/src/hooks/useAutoTagTrigger.ts new file mode 100644 index 000000000..fdd659b77 --- /dev/null +++ b/ui/v2.5/src/hooks/useAutoTagTrigger.ts @@ -0,0 +1,17 @@ +import { useConfigurationContext } from "./Config"; + +// Centralises the "skip warning" check so every entry point to auto tag +// consults the same interface flag. +export function useAutoTagTrigger( + onRun: () => void, + onOpenConfirm: () => void +) { + const { configuration } = useConfigurationContext(); + return () => { + if (configuration?.interface.disableAutoTagWarning) { + onRun(); + return; + } + onOpenConfirm(); + }; +} \ No newline at end of file diff --git a/ui/v2.5/src/locales/en-GB.json b/ui/v2.5/src/locales/en-GB.json index 4327df68c..9d390d993 100644 --- a/ui/v2.5/src/locales/en-GB.json +++ b/ui/v2.5/src/locales/en-GB.json @@ -510,9 +510,9 @@ "auto_tag": { "auto_tagging_all_paths": "Auto tagging all paths", "auto_tagging_paths": "Auto tagging the following paths", - "skip_warning": { + "disable_warning": { "description": "Skip the confirmation warning shown before running auto tag.", - "heading": "Skip auto tag warning" + "heading": "Disable auto tag warning" } }, "auto_tag_based_on_filenames": "Auto tag content based on file paths.", From a6d6613f09797791812c3ab58b236ea3c209e2de Mon Sep 17 00:00:00 2001 From: Gykes Date: Wed, 22 Apr 2026 23:40:13 -0700 Subject: [PATCH 3/8] fix word usage --- ui/v2.5/src/docs/en/Manual/AutoTagging.md | 4 ++-- ui/v2.5/src/locales/en-GB.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/v2.5/src/docs/en/Manual/AutoTagging.md b/ui/v2.5/src/docs/en/Manual/AutoTagging.md index cc70c7b1f..0cfbd6f84 100644 --- a/ui/v2.5/src/docs/en/Manual/AutoTagging.md +++ b/ui/v2.5/src/docs/en/Manual/AutoTagging.md @@ -49,6 +49,6 @@ Performers or Tags that have Ignore Auto tag flag added to them will be skipped - **Selective auto tag:** You can run the Auto tag task on specific directories from the Tasks page. - **Individual pages:** You can run Auto tag tasks for specific Performers, Studios, and Tags from their respective pages. -### Skip the confirmation warning +### Disable the confirmation warning -A confirmation warning is shown before Auto tag runs. If you use Auto tag frequently you can bypass this warning by ticking the **Don't show this warning again** checkbox on the warning dialog, or by enabling **Settings → Tasks → Auto Tag → Disable auto tag warning**. +A confirmation warning is shown before Auto tag runs. If you use Auto tag frequently you can disable this warning by ticking the **Don't show this warning again** checkbox on the warning dialog, or by enabling **Settings → Tasks → Auto Tag → Disable auto tag warning**. diff --git a/ui/v2.5/src/locales/en-GB.json b/ui/v2.5/src/locales/en-GB.json index 9d390d993..b3d05fed7 100644 --- a/ui/v2.5/src/locales/en-GB.json +++ b/ui/v2.5/src/locales/en-GB.json @@ -511,7 +511,7 @@ "auto_tagging_all_paths": "Auto tagging all paths", "auto_tagging_paths": "Auto tagging the following paths", "disable_warning": { - "description": "Skip the confirmation warning shown before running auto tag.", + "description": "Disable the confirmation warning shown before running auto tag.", "heading": "Disable auto tag warning" } }, From 80dc38bc6fd57960bb58be77eb4cc6ecf3fa0b96 Mon Sep 17 00:00:00 2001 From: Gykes Date: Wed, 22 Apr 2026 23:45:36 -0700 Subject: [PATCH 4/8] lint --- ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx | 2 +- ui/v2.5/src/hooks/useAutoTagTrigger.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx b/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx index c466efeed..ad517f1ed 100644 --- a/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx +++ b/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx @@ -87,4 +87,4 @@ export const AutoTagConfirmDialog: React.FC = ({ /> ); -}; \ No newline at end of file +}; diff --git a/ui/v2.5/src/hooks/useAutoTagTrigger.ts b/ui/v2.5/src/hooks/useAutoTagTrigger.ts index fdd659b77..5ce7d7579 100644 --- a/ui/v2.5/src/hooks/useAutoTagTrigger.ts +++ b/ui/v2.5/src/hooks/useAutoTagTrigger.ts @@ -14,4 +14,4 @@ export function useAutoTagTrigger( } onOpenConfirm(); }; -} \ No newline at end of file +} From 76140b1437c9fd94c1d5815fe0b1d9bcce2bd99d Mon Sep 17 00:00:00 2001 From: Gykes Date: Wed, 22 Apr 2026 23:52:19 -0700 Subject: [PATCH 5/8] remove my thought process --- ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx b/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx index ad517f1ed..7765165a4 100644 --- a/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx +++ b/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx @@ -38,8 +38,6 @@ export const AutoTagConfirmDialog: React.FC = ({ const Toast = useToast(); const [dontShowAgain, setDontShowAgain] = useState(false); const [configureInterface] = useConfigureInterface(); - // route through SettingsContext when available so the Settings panel's - // local state reflects the change without a page refresh const settingsContext = useContext(SettingStateContext); useEffect(() => { @@ -51,7 +49,6 @@ export const AutoTagConfirmDialog: React.FC = ({ function handleConfirm() { if (dontShowAgain) { if (settingsContext) { - // context's saveInterface already surfaces errors via its own toast settingsContext.saveInterface({ disableAutoTagWarning: true }); } else { configureInterface({ From 9aac8b30adc24cb3e4793905e1a74c124ed8d031 Mon Sep 17 00:00:00 2001 From: Gykes Date: Thu, 23 Apr 2026 00:08:06 -0700 Subject: [PATCH 6/8] namespace autotag config key and memoize trigger hook --- internal/manager/config/config.go | 2 +- .../src/components/Settings/Tasks/LibraryTasks.tsx | 3 ++- ui/v2.5/src/hooks/useAutoTagTrigger.ts | 14 ++++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/internal/manager/config/config.go b/internal/manager/config/config.go index 5788933e4..e35a44132 100644 --- a/internal/manager/config/config.go +++ b/internal/manager/config/config.go @@ -237,7 +237,7 @@ const ( DisableDropdownCreateMovie = "disable_dropdown_create.movie" DisableDropdownCreateGallery = "disable_dropdown_create.gallery" - DisableAutoTagWarning = "disable_auto_tag_warning" + DisableAutoTagWarning = "auto_tag.disable_warning" HandyKey = "handy_key" FunscriptOffset = "funscript_offset" diff --git a/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx b/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx index 6fd2f2a29..8846809d6 100644 --- a/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx +++ b/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx @@ -204,7 +204,8 @@ export const LibraryTasks: React.FC = () => { const onAutoTagClick = useAutoTagTrigger( () => runAutoTag(), - () => setDialogOpen({ autoTagAlert: true }) + () => setDialogOpen({ autoTagAlert: true }), + iface.disableAutoTagWarning ); function renderScanDialog() { diff --git a/ui/v2.5/src/hooks/useAutoTagTrigger.ts b/ui/v2.5/src/hooks/useAutoTagTrigger.ts index 5ce7d7579..ed34104b7 100644 --- a/ui/v2.5/src/hooks/useAutoTagTrigger.ts +++ b/ui/v2.5/src/hooks/useAutoTagTrigger.ts @@ -1,17 +1,19 @@ +import { useCallback } from "react"; import { useConfigurationContext } from "./Config"; -// Centralises the "skip warning" check so every entry point to auto tag -// consults the same interface flag. export function useAutoTagTrigger( onRun: () => void, - onOpenConfirm: () => void + onOpenConfirm: () => void, + override?: boolean | null ) { const { configuration } = useConfigurationContext(); - return () => { - if (configuration?.interface.disableAutoTagWarning) { + const disabled = + override ?? configuration?.interface.disableAutoTagWarning ?? false; + return useCallback(() => { + if (disabled) { onRun(); return; } onOpenConfirm(); - }; + }, [disabled, onRun, onOpenConfirm]); } From ad355496ed4ebe4f6708fd89598c133f56e4e665 Mon Sep 17 00:00:00 2001 From: DogmaDragon <103123951+DogmaDragon@users.noreply.github.com> Date: Thu, 23 Apr 2026 10:30:19 +0300 Subject: [PATCH 7/8] Update wording for auto tag warning instructions --- ui/v2.5/src/docs/en/Manual/AutoTagging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/v2.5/src/docs/en/Manual/AutoTagging.md b/ui/v2.5/src/docs/en/Manual/AutoTagging.md index 0cfbd6f84..540a4b508 100644 --- a/ui/v2.5/src/docs/en/Manual/AutoTagging.md +++ b/ui/v2.5/src/docs/en/Manual/AutoTagging.md @@ -51,4 +51,4 @@ Performers or Tags that have Ignore Auto tag flag added to them will be skipped ### Disable the confirmation warning -A confirmation warning is shown before Auto tag runs. If you use Auto tag frequently you can disable this warning by ticking the **Don't show this warning again** checkbox on the warning dialog, or by enabling **Settings → Tasks → Auto Tag → Disable auto tag warning**. +A confirmation warning is shown before the auto tag task runs. If you use auto tag frequently, you can disable this warning by ticking the **Don't show this warning again** checkbox on the warning dialog, or by enabling **Settings** > **Tasks** > **Auto tag** > **Disable auto-tag warning**. From d421948e0ad981772845584c53bd8451396028ab Mon Sep 17 00:00:00 2001 From: Gykes Date: Sun, 26 Apr 2026 16:26:29 -0700 Subject: [PATCH 8/8] swap to UIConfig --- graphql/schema/types/config.graphql | 6 ------ internal/api/resolver_mutation_configure.go | 2 -- internal/api/resolver_query_configuration.go | 3 --- internal/manager/config/config.go | 6 ------ ui/v2.5/graphql/data/config.graphql | 1 - .../src/components/Settings/Tasks/LibraryTasks.tsx | 14 ++++---------- .../src/components/Shared/AutoTagConfirmDialog.tsx | 12 ++++++------ ui/v2.5/src/core/config.ts | 3 +++ ui/v2.5/src/hooks/useAutoTagTrigger.ts | 5 +++-- 9 files changed, 16 insertions(+), 36 deletions(-) diff --git a/graphql/schema/types/config.graphql b/graphql/schema/types/config.graphql index 99caf9614..5ab7fdfea 100644 --- a/graphql/schema/types/config.graphql +++ b/graphql/schema/types/config.graphql @@ -428,9 +428,6 @@ input ConfigInterfaceInput { "Set to true to disable creating new objects via the dropdown menus" disableDropdownCreate: ConfigDisableDropdownCreateInput - "Set to true to skip the auto tag confirmation warning" - disableAutoTagWarning: Boolean - "Handy Connection Key" handyKey: String "Funscript Time Offset" @@ -508,9 +505,6 @@ type ConfigInterfaceResult { "Fields are true if creating via dropdown menus are disabled" disableDropdownCreate: ConfigDisableDropdownCreate! - "True if the auto tag confirmation warning should be skipped" - disableAutoTagWarning: Boolean - "Handy Connection Key" handyKey: String "Funscript Time Offset" diff --git a/internal/api/resolver_mutation_configure.go b/internal/api/resolver_mutation_configure.go index 747e8f9e9..3df1c9114 100644 --- a/internal/api/resolver_mutation_configure.go +++ b/internal/api/resolver_mutation_configure.go @@ -538,8 +538,6 @@ func (r *mutationResolver) ConfigureInterface(ctx context.Context, input ConfigI r.setConfigBool(config.DisableDropdownCreateGallery, ddc.Gallery) } - r.setConfigBool(config.DisableAutoTagWarning, input.DisableAutoTagWarning) - r.setConfigString(config.HandyKey, input.HandyKey) r.setConfigInt(config.FunscriptOffset, input.FunscriptOffset) r.setConfigBool(config.UseStashHostedFunscript, input.UseStashHostedFunscript) diff --git a/internal/api/resolver_query_configuration.go b/internal/api/resolver_query_configuration.go index 6bd83ca42..cf2c0e3cc 100644 --- a/internal/api/resolver_query_configuration.go +++ b/internal/api/resolver_query_configuration.go @@ -168,7 +168,6 @@ func makeConfigInterfaceResult() *ConfigInterfaceResult { useStashHostedFunscript := config.GetUseStashHostedFunscript() imageLightboxOptions := config.GetImageLightboxOptions() disableDropdownCreate := config.GetDisableDropdownCreate() - disableAutoTagWarning := config.GetDisableAutoTagWarning() return &ConfigInterfaceResult{ SfwContentMode: config.GetSFWContentMode(), @@ -197,8 +196,6 @@ func makeConfigInterfaceResult() *ConfigInterfaceResult { DisableDropdownCreate: disableDropdownCreate, - DisableAutoTagWarning: &disableAutoTagWarning, - HandyKey: &handyKey, FunscriptOffset: &scriptOffset, UseStashHostedFunscript: &useStashHostedFunscript, diff --git a/internal/manager/config/config.go b/internal/manager/config/config.go index e35a44132..19e263810 100644 --- a/internal/manager/config/config.go +++ b/internal/manager/config/config.go @@ -237,8 +237,6 @@ const ( DisableDropdownCreateMovie = "disable_dropdown_create.movie" DisableDropdownCreateGallery = "disable_dropdown_create.gallery" - DisableAutoTagWarning = "auto_tag.disable_warning" - HandyKey = "handy_key" FunscriptOffset = "funscript_offset" UseStashHostedFunscript = "use_stash_hosted_funscript" @@ -1313,10 +1311,6 @@ func (i *Config) GetShowStudioAsText() bool { return i.getBool(ShowStudioAsText) } -func (i *Config) GetDisableAutoTagWarning() bool { - return i.getBool(DisableAutoTagWarning) -} - func (i *Config) getSlideshowDelay() int { // assume have lock diff --git a/ui/v2.5/graphql/data/config.graphql b/ui/v2.5/graphql/data/config.graphql index 35b0c2b99..ba8215fe3 100644 --- a/ui/v2.5/graphql/data/config.graphql +++ b/ui/v2.5/graphql/data/config.graphql @@ -115,7 +115,6 @@ fragment ConfigInterfaceData on ConfigInterfaceResult { movie gallery } - disableAutoTagWarning handyKey funscriptOffset useStashHostedFunscript diff --git a/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx b/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx index 8846809d6..cd89ed953 100644 --- a/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx +++ b/ui/v2.5/src/components/Settings/Tasks/LibraryTasks.tsx @@ -76,13 +76,7 @@ const AutoTagOptions: React.FC = ({ export const LibraryTasks: React.FC = () => { const intl = useIntl(); const Toast = useToast(); - const { - ui, - saveUI, - interface: iface, - saveInterface, - loading, - } = useSettings(); + const { ui, saveUI, loading } = useSettings(); const { taskDefaults } = ui; @@ -205,7 +199,7 @@ export const LibraryTasks: React.FC = () => { const onAutoTagClick = useAutoTagTrigger( () => runAutoTag(), () => setDialogOpen({ autoTagAlert: true }), - iface.disableAutoTagWarning + ui.disableAutoTagWarning ); function renderScanDialog() { @@ -485,8 +479,8 @@ export const LibraryTasks: React.FC = () => { id="disable_auto_tag_warning" headingID="config.tasks.auto_tag.disable_warning.heading" subHeadingID="config.tasks.auto_tag.disable_warning.description" - checked={iface.disableAutoTagWarning ?? undefined} - onChange={(v) => saveInterface({ disableAutoTagWarning: v })} + checked={ui.disableAutoTagWarning ?? undefined} + onChange={(v) => saveUI({ disableAutoTagWarning: v })} /> diff --git a/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx b/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx index 7765165a4..b4fcd21bd 100644 --- a/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx +++ b/ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx @@ -2,7 +2,7 @@ import React, { useContext, useEffect, useState } from "react"; import { Form } from "react-bootstrap"; import { FormattedMessage, useIntl } from "react-intl"; import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons"; -import { useConfigureInterface } from "src/core/StashService"; +import { useConfigureUISetting } from "src/core/StashService"; import { SettingStateContext } from "src/components/Settings/context"; import { useToast } from "src/hooks/Toast"; import { ModalComponent } from "./Modal"; @@ -37,7 +37,7 @@ export const AutoTagConfirmDialog: React.FC = ({ const intl = useIntl(); const Toast = useToast(); const [dontShowAgain, setDontShowAgain] = useState(false); - const [configureInterface] = useConfigureInterface(); + const [saveUISetting] = useConfigureUISetting(); const settingsContext = useContext(SettingStateContext); useEffect(() => { @@ -49,11 +49,11 @@ export const AutoTagConfirmDialog: React.FC = ({ function handleConfirm() { if (dontShowAgain) { if (settingsContext) { - settingsContext.saveInterface({ disableAutoTagWarning: true }); + settingsContext.saveUI({ disableAutoTagWarning: true }); } else { - configureInterface({ - variables: { input: { disableAutoTagWarning: true } }, - }).catch((e) => Toast.error(e)); + saveUISetting({ + variables: { key: "disableAutoTagWarning", value: true }, + }).catch((e: unknown) => Toast.error(e)); } } onConfirm(); diff --git a/ui/v2.5/src/core/config.ts b/ui/v2.5/src/core/config.ts index e0cf008b5..3978d1887 100644 --- a/ui/v2.5/src/core/config.ts +++ b/ui/v2.5/src/core/config.ts @@ -105,6 +105,9 @@ export interface IUIConfig { taskDefaults?: Record; + // if true the auto tag confirmation warning is skipped + disableAutoTagWarning?: boolean; + defaultFilters?: DefaultFilters; taggerConfig?: ITaggerConfig; diff --git a/ui/v2.5/src/hooks/useAutoTagTrigger.ts b/ui/v2.5/src/hooks/useAutoTagTrigger.ts index ed34104b7..4cb3ca38c 100644 --- a/ui/v2.5/src/hooks/useAutoTagTrigger.ts +++ b/ui/v2.5/src/hooks/useAutoTagTrigger.ts @@ -1,4 +1,5 @@ import { useCallback } from "react"; +import { IUIConfig } from "src/core/config"; import { useConfigurationContext } from "./Config"; export function useAutoTagTrigger( @@ -7,8 +8,8 @@ export function useAutoTagTrigger( override?: boolean | null ) { const { configuration } = useConfigurationContext(); - const disabled = - override ?? configuration?.interface.disableAutoTagWarning ?? false; + const ui = configuration?.ui as IUIConfig | undefined; + const disabled = override ?? ui?.disableAutoTagWarning ?? false; return useCallback(() => { if (disabled) { onRun();