From 0388aec94294f4ce18c15ec65d4373067cd817d1 Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Thu, 20 Jan 2022 18:10:47 +1100 Subject: [PATCH] Only update tags if not dirtied (#2241) --- .../Tagger/scenes/StashSearchResult.tsx | 18 +++++++--- ui/v2.5/src/hooks/state.ts | 34 +++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 ui/v2.5/src/hooks/state.ts diff --git a/ui/v2.5/src/components/Tagger/scenes/StashSearchResult.tsx b/ui/v2.5/src/components/Tagger/scenes/StashSearchResult.tsx index 7debcbc90..f78b80ae7 100755 --- a/ui/v2.5/src/components/Tagger/scenes/StashSearchResult.tsx +++ b/ui/v2.5/src/components/Tagger/scenes/StashSearchResult.tsx @@ -23,6 +23,7 @@ import { OptionalField } from "../IncludeButton"; import { SceneTaggerModalsState } from "./sceneTaggerModals"; import PerformerResult from "./PerformerResult"; import StudioResult from "./StudioResult"; +import { useInitialState } from "src/hooks/state"; const getDurationStatus = ( scene: IScrapedScene, @@ -214,7 +215,9 @@ const StashSearchResult: React.FC = ({ const [excludedFields, setExcludedFields] = useState>( {} ); - const [tagIDs, setTagIDs] = useState(getInitialTags()); + const [tagIDs, setTagIDs, setInitialTagIDs] = useInitialState( + getInitialTags() + ); // map of original performer to id const [performerIDs, setPerformerIDs] = useState<(string | undefined)[]>( @@ -226,8 +229,8 @@ const StashSearchResult: React.FC = ({ ); useEffect(() => { - setTagIDs(getInitialTags()); - }, [getInitialTags]); + setInitialTagIDs(getInitialTags()); + }, [getInitialTags, setInitialTagIDs]); useEffect(() => { setPerformerIDs(getInitialPerformers()); @@ -566,6 +569,13 @@ const StashSearchResult: React.FC = ({ ); + async function onCreateTag(t: GQL.ScrapedTag) { + const newTagID = await createNewTag(t); + if (newTagID !== undefined) { + setTagIDs([...tagIDs, newTagID]); + } + } + const renderTagsField = () => (
@@ -592,7 +602,7 @@ const StashSearchResult: React.FC = ({ variant="secondary" key={t.name} onClick={() => { - createNewTag(t); + onCreateTag(t); }} > {t.name} diff --git a/ui/v2.5/src/hooks/state.ts b/ui/v2.5/src/hooks/state.ts new file mode 100644 index 000000000..00ee32a91 --- /dev/null +++ b/ui/v2.5/src/hooks/state.ts @@ -0,0 +1,34 @@ +import React, { useCallback, Dispatch, SetStateAction } from "react"; + +// useInitialState is an extension of the useState hook. +// It maintains a state, but additionally exposes a setInitialState function. +// When setInitialState is called, the current state is only updated if the current +// state is unchanged from the initial state. This means that the current state will +// only be updated if explicitly called, or if the initial state is changed and the current +// state is not dirty. +export function useInitialState( + initialValue: T +): [T, Dispatch>, Dispatch] { + const [, setInitialValueInternal] = React.useState(initialValue); + const [value, setValue] = React.useState(initialValue); + + const setInitialValue = useCallback((v: T) => { + setInitialValueInternal((currentInitial) => { + if (v === currentInitial) { + return currentInitial; + } + + setValue((currentValue) => { + if (currentInitial === currentValue) { + return v; + } + + return currentValue; + }); + + return v; + }); + }, []); + + return [value, setValue, setInitialValue]; +}