This commit is contained in:
InfiniteStash 2026-03-31 14:07:35 +02:00
parent 49b673dcd0
commit 972efda577
4 changed files with 28 additions and 41 deletions

View file

@ -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

View file

@ -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<void>;
submitFingerprints: () => Promise<void>;
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: {

View file

@ -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<GQL.Fingerprint, "type" | "value">[],
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<IStashSearchResultProps> = ({
@ -325,7 +325,7 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
stashScene,
index,
isActive,
onMarkWrong,
onReportWrong,
}) => {
const intl = useIntl();
@ -541,7 +541,7 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
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<ISceneSearchResults> = ({
isActive={i === selectedResult}
scene={s}
stashScene={target}
onMarkWrong={
onReportWrong={
i === selectedResult ? () => setSelectedResult(undefined) : undefined
}
/>

View file

@ -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;
}
}