diff --git a/internal/api/resolver_mutation_stash_box.go b/internal/api/resolver_mutation_stash_box.go index 017a79c90..05012c166 100644 --- a/internal/api/resolver_mutation_stash_box.go +++ b/internal/api/resolver_mutation_stash_box.go @@ -239,6 +239,10 @@ func (r *mutationResolver) QueueFingerprintSubmission(ctx context.Context, input } if err := r.withTxn(ctx, func(ctx context.Context) error { + // Remove any existing submission for this stash ID before creating a new one + if err := r.repository.FingerprintSubmission.Delete(ctx, input.Endpoint, input.StashID); err != nil { + return err + } return r.repository.FingerprintSubmission.Create(ctx, submission) }); err != nil { return false, err diff --git a/ui/v2.5/src/components/Tagger/context.tsx b/ui/v2.5/src/components/Tagger/context.tsx index 0dc25ed86..a0bc31368 100644 --- a/ui/v2.5/src/components/Tagger/context.tsx +++ b/ui/v2.5/src/components/Tagger/context.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useRef, useCallback, useMemo } from "react"; +import React, { useState, useEffect, useRef, useMemo } from "react"; import { initialConfig, ITaggerConfig, @@ -27,7 +27,7 @@ import { errorToString } from "src/utils"; import { mergeStudioStashIDs } from "./utils"; import { useTaggerConfig } from "./config"; -interface PendingSubmission { +interface IPendingSubmission { sceneId: string; stashId: string; vote: GQL.FingerprintVote; @@ -75,7 +75,7 @@ export interface ITaggerContextState { scene: IScrapedScene ) => Promise; submitFingerprints: () => Promise; - pendingFingerprints: PendingSubmission[]; + pendingFingerprints: IPendingSubmission[]; saveScene: ( sceneCreateInput: GQL.SceneUpdateInput, queueFingerprint: boolean, @@ -249,7 +249,7 @@ export const TaggerContext: React.FC = ({ children }) => { skip: !endpoint, }); - const pendingFingerprints = useMemo((): PendingSubmission[] => { + const pendingFingerprints = useMemo((): IPendingSubmission[] => { if (!pendingData?.pendingFingerprintSubmissions) return []; return pendingData.pendingFingerprintSubmissions.map((s) => ({ @@ -295,23 +295,6 @@ export const TaggerContext: React.FC = ({ children }) => { if (!endpoint) return; try { - // If queueing an INVALID vote, first remove any existing submission for this stash ID - if (vote === GQL.FingerprintVote.Invalid) { - const existingSubmission = pendingFingerprints.find( - (fp) => fp.stashId === stashBoxSceneId - ); - if (existingSubmission) { - await removeFingerprintMutation({ - variables: { - input: { - endpoint, - stash_id: stashBoxSceneId, - }, - }, - }); - } - } - await queueFingerprintMutation({ variables: { input: { diff --git a/ui/v2.5/src/components/Tagger/scenes/StashSearchResult.tsx b/ui/v2.5/src/components/Tagger/scenes/StashSearchResult.tsx index 7be3a3bbd..0db62481b 100755 --- a/ui/v2.5/src/components/Tagger/scenes/StashSearchResult.tsx +++ b/ui/v2.5/src/components/Tagger/scenes/StashSearchResult.tsx @@ -99,7 +99,7 @@ const getDurationStatus = ( ); }; -interface PhashMatch { +interface IPhashMatch { hash: string; distance: number; reports: number; @@ -110,10 +110,10 @@ interface PhashMatch { function matchPhashes( scenePhashes: Pick[], fingerprints: GQL.StashBoxFingerprint[] -): PhashMatch[] { +): IPhashMatch[] { const phashes = fingerprints.filter((f) => f.algorithm === "PHASH"); - const matches: PhashMatch[] = []; + const matches: IPhashMatch[] = []; phashes.forEach((p) => { let bestMatch = -1; scenePhashes.forEach((fp) => { @@ -141,7 +141,7 @@ function matchPhashes( return matches; } -interface ChecksumMatch { +interface IChecksumMatch { hash: string; reports: number; userSubmitted: boolean; @@ -151,8 +151,8 @@ interface ChecksumMatch { function matchChecksums( stashScene: GQL.SlimSceneDataFragment, fingerprints: GQL.StashBoxFingerprint[] -): ChecksumMatch[] { - const matches: ChecksumMatch[] = []; +): IChecksumMatch[] { + const matches: IChecksumMatch[] = []; fingerprints.forEach((f) => { if (f.algorithm !== "OSHASH" && f.algorithm !== "MD5") return; @@ -317,7 +317,7 @@ interface IStashSearchResultProps { stashScene: GQL.SlimSceneDataFragment; index: number; isActive: boolean; - onMarkWrong?: () => void; + onReportWrong?: () => void; } const StashSearchResult: React.FC = ({ @@ -325,7 +325,7 @@ const StashSearchResult: React.FC = ({ stashScene, index, isActive, - onMarkWrong, + onReportWrong, }) => { const intl = useIntl(); @@ -541,7 +541,7 @@ const StashSearchResult: React.FC = ({ async function handleMarkWrong() { if (!scene.remote_site_id) return; await queueFingerprintSubmission(stashScene.id, scene.remote_site_id, GQL.FingerprintVote.Invalid); - onMarkWrong?.(); + onReportWrong?.(); } async function handleRemoveReport() { @@ -1088,7 +1088,7 @@ export const SceneSearchResults: React.FC = ({ isActive={i === selectedResult} scene={s} stashScene={target} - onMarkWrong={ + onReportWrong={ i === selectedResult ? () => setSelectedResult(undefined) : undefined } /> diff --git a/ui/v2.5/src/components/Tagger/styles.scss b/ui/v2.5/src/components/Tagger/styles.scss index 11ae108fd..974ba7c78 100644 --- a/ui/v2.5/src/components/Tagger/styles.scss +++ b/ui/v2.5/src/components/Tagger/styles.scss @@ -89,6 +89,16 @@ margin-right: 10px; width: var(--fa-fw-width, 1.25em); } + + .marked-wrong { + opacity: 0.6; + + .scene-link, + h4, + h5 { + text-decoration: line-through; + } + } } .selected-result { @@ -427,13 +437,3 @@ li.active .optional-field.excluded .scene-link { display: inline-block; text-decoration: underline dotted; } - -.marked-wrong { - opacity: 0.6; - - .scene-link, - h4, - h5 { - text-decoration: line-through; - } -}