diff --git a/frontend/src/graphql/fragments/SceneFragment.gql b/frontend/src/graphql/fragments/SceneFragment.gql index f4ad192f3..afd46c1aa 100644 --- a/frontend/src/graphql/fragments/SceneFragment.gql +++ b/frontend/src/graphql/fragments/SceneFragment.gql @@ -35,7 +35,9 @@ fragment SceneFragment on Scene { algorithm duration submissions + reports user_submitted + user_reported created updated } diff --git a/frontend/src/graphql/mutations/UnmatchFingerprint.gql b/frontend/src/graphql/mutations/UnmatchFingerprint.gql index 25a2c12f2..39c90f04b 100644 --- a/frontend/src/graphql/mutations/UnmatchFingerprint.gql +++ b/frontend/src/graphql/mutations/UnmatchFingerprint.gql @@ -6,7 +6,7 @@ mutation UnmatchFingerprint( ) { unmatchFingerprint: submitFingerprint( input: { - unmatch: true + vote: REMOVE scene_id: $scene_id fingerprint: { hash: $hash, algorithm: $algorithm, duration: $duration } } diff --git a/frontend/src/graphql/types.ts b/frontend/src/graphql/types.ts index f3b57789b..68e4329b2 100644 --- a/frontend/src/graphql/types.ts +++ b/frontend/src/graphql/types.ts @@ -283,8 +283,14 @@ export type Fingerprint = { created: Scalars["Time"]; duration: Scalars["Int"]; hash: Scalars["String"]; + /** number of times this fingerprint has been reported */ + reports: Scalars["Int"]; + /** number of times this fingerprint has been submitted (excluding reports) */ submissions: Scalars["Int"]; updated: Scalars["Time"]; + /** true if the current user reported this fingerprint */ + user_reported: Scalars["Boolean"]; + /** true if the current user submitted this fingerprint */ user_submitted: Scalars["Boolean"]; }; @@ -322,9 +328,20 @@ export type FingerprintQueryInput = { export type FingerprintSubmission = { fingerprint: FingerprintInput; scene_id: Scalars["ID"]; + /** @deprecated Use `vote` with REMOVE instead */ unmatch?: InputMaybe; + vote?: InputMaybe; }; +export enum FingerprintSubmissionType { + /** Report as invalid */ + INVALID = "INVALID", + /** Remove vote */ + REMOVE = "REMOVE", + /** Positive vote */ + VALID = "VALID", +} + export type FuzzyDate = { __typename: "FuzzyDate"; accuracy: DateAccuracyEnum; @@ -2024,7 +2041,9 @@ export type EditFragment = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -2795,7 +2814,9 @@ export type EditFragment = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -2996,7 +3017,9 @@ export type SceneFragment = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -3357,7 +3380,9 @@ export type ApplyEditMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -4183,7 +4208,9 @@ export type ApplyEditMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -4567,7 +4594,9 @@ export type PerformerEditMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -5393,7 +5422,9 @@ export type PerformerEditMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -5596,7 +5627,9 @@ export type PerformerEditUpdateMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -6422,7 +6455,9 @@ export type PerformerEditUpdateMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -6660,7 +6695,9 @@ export type SceneEditMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -7486,7 +7523,9 @@ export type SceneEditMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -7689,7 +7728,9 @@ export type SceneEditUpdateMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -8515,7 +8556,9 @@ export type SceneEditUpdateMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -8717,7 +8760,9 @@ export type StudioEditMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -9543,7 +9588,9 @@ export type StudioEditMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -9746,7 +9793,9 @@ export type StudioEditUpdateMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -10572,7 +10621,9 @@ export type StudioEditUpdateMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -10774,7 +10825,9 @@ export type TagEditMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -11600,7 +11653,9 @@ export type TagEditMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -11803,7 +11858,9 @@ export type TagEditUpdateMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -12629,7 +12686,9 @@ export type TagEditUpdateMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -12965,7 +13024,9 @@ export type VoteMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -13791,7 +13852,9 @@ export type VoteMutation = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -14252,7 +14315,9 @@ export type EditQuery = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -15078,7 +15143,9 @@ export type EditQuery = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -15274,7 +15341,9 @@ export type EditUpdateQuery = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -15721,7 +15790,9 @@ export type EditsQuery = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -16567,7 +16638,9 @@ export type EditsQuery = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -16916,7 +16989,9 @@ export type QueryExistingSceneQuery = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -17064,7 +17139,9 @@ export type QueryExistingSceneQuery = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -17910,7 +17987,9 @@ export type QueryExistingSceneQuery = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -18028,7 +18107,9 @@ export type SceneQuery = { algorithm: FingerprintAlgorithm; duration: number; submissions: number; + reports: number; user_submitted: boolean; + user_reported: boolean; created: string; updated: string; }>; @@ -19057,10 +19138,15 @@ export const SceneFragmentDoc = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -20664,10 +20750,15 @@ export const EditFragmentDoc = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -21884,10 +21975,15 @@ export const ApplyEditDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -24319,10 +24415,15 @@ export const PerformerEditDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -25927,10 +26028,15 @@ export const PerformerEditUpdateDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -27699,10 +27805,15 @@ export const SceneEditDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -29304,10 +29415,15 @@ export const SceneEditUpdateDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -30896,10 +31012,15 @@ export const StudioEditDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -32501,10 +32622,15 @@ export const StudioEditUpdateDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -34093,10 +34219,15 @@ export const TagEditDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -35698,10 +35829,15 @@ export const TagEditUpdateDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -36946,8 +37082,8 @@ export const UnmatchFingerprintDocument = { fields: [ { kind: "ObjectField", - name: { kind: "Name", value: "unmatch" }, - value: { kind: "BooleanValue", value: true }, + name: { kind: "Name", value: "vote" }, + value: { kind: "EnumValue", value: "REMOVE" }, }, { kind: "ObjectField", @@ -37899,10 +38035,15 @@ export const VoteDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -40342,10 +40483,15 @@ export const EditDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -42505,10 +42651,15 @@ export const EditUpdateDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -42974,10 +43125,15 @@ export const EditsDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -45444,10 +45600,15 @@ export const QueryExistingSceneDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], @@ -46827,10 +46988,15 @@ export const SceneDocument = { { kind: "Field", name: { kind: "Name", value: "algorithm" } }, { kind: "Field", name: { kind: "Name", value: "duration" } }, { kind: "Field", name: { kind: "Name", value: "submissions" } }, + { kind: "Field", name: { kind: "Name", value: "reports" } }, { kind: "Field", name: { kind: "Name", value: "user_submitted" }, }, + { + kind: "Field", + name: { kind: "Name", value: "user_reported" }, + }, { kind: "Field", name: { kind: "Name", value: "created" } }, { kind: "Field", name: { kind: "Name", value: "updated" } }, ], diff --git a/frontend/src/pages/scenes/Scene.tsx b/frontend/src/pages/scenes/Scene.tsx index 544b526d1..ab7aad3e1 100644 --- a/frontend/src/pages/scenes/Scene.tsx +++ b/frontend/src/pages/scenes/Scene.tsx @@ -1,10 +1,11 @@ -import { FC, useContext } from "react"; +import { FC, useContext, useMemo } from "react"; import { Link, useLocation, useNavigate } from "react-router-dom"; import { Button, Card, Tabs, Tab, Table } from "react-bootstrap"; import { faCheckCircle, faTimesCircle, faSpinner, + faTriangleExclamation, } from "@fortawesome/free-solid-svg-icons"; import { @@ -83,70 +84,90 @@ const SceneComponent: FC = ({ scene }) => { }) .map((p, index) => (index % 2 === 2 ? [" • ", p] : p)); - async function handleFingerprintUnmatch(fingerprint: Fingerprint) { - if (unmatching) return; + const fingerprints = useMemo(() => { + async function handleFingerprintUnmatch(fingerprint: Fingerprint) { + if (unmatching) return; - const { data } = await unmatchFingerprint({ - variables: { - scene_id: scene.id, - algorithm: fingerprint.algorithm, - hash: fingerprint.hash, - duration: fingerprint.duration, - }, - }); - const success = data?.unmatchFingerprint; - addToast({ - variant: success ? "success" : "danger", - content: `${ - success ? "Removed" : "Failed to remove" - } fingerprint submission`, - }); - } + const { data } = await unmatchFingerprint({ + variables: { + scene_id: scene.id, + algorithm: fingerprint.algorithm, + hash: fingerprint.hash, + duration: fingerprint.duration, + }, + }); + const success = data?.unmatchFingerprint; + addToast({ + variant: success ? "success" : "danger", + content: `${ + success ? "Removed" : "Failed to remove" + } fingerprint submission`, + }); + } + + function maybeRenderSubmitted(fingerprint: Fingerprint, reported: boolean) { + if ( + (!reported && fingerprint.user_submitted) || + (reported && fingerprint.user_reported) + ) { + return ( + handleFingerprintUnmatch(fingerprint)} + > + {!unmatching ? ( + <> + + + + ) : ( + + )} + + ); + } + } - function maybeRenderSubmitted(fingerprint: Fingerprint) { - if (fingerprint.user_submitted) { + function renderSubmissions(fingerprint: Fingerprint) { return ( - handleFingerprintUnmatch(fingerprint)} - > - {!unmatching ? ( - <> - - - - ) : ( - + + + {fingerprint.submissions} + + {fingerprint.reports > 0 && ( + + {fingerprint.reports} + {maybeRenderSubmitted(fingerprint, true)} + )} + {maybeRenderSubmitted(fingerprint, false)} ); } - } - const fingerprints = scene.fingerprints.map((fingerprint) => ( - - {fingerprint.algorithm} - - - {fingerprint.hash} - - - - - {formatDuration(fingerprint.duration)} - - - - {fingerprint.submissions} - {maybeRenderSubmitted(fingerprint)} - - {formatDateTime(fingerprint.created)} - {formatDateTime(fingerprint.updated)} - - )); + return scene.fingerprints.map((fingerprint) => ( + + {fingerprint.algorithm} + + + {fingerprint.hash} + + + + + {formatDuration(fingerprint.duration)} + + + {renderSubmissions(fingerprint)} + {formatDateTime(fingerprint.created)} + {formatDateTime(fingerprint.updated)} + + )); + }, [scene.fingerprints, unmatchFingerprint, unmatching, addToast, scene.id]); + const tags = [...scene.tags].sort(compareByName).map((tag) => (