Intervention flag display
This commit is contained in:
parent
8f8ae3cae9
commit
9b9ad90292
5 changed files with 74 additions and 24 deletions
|
|
@ -520,6 +520,17 @@
|
|||
"cc_info_link": "Content Credentials Verify",
|
||||
"cc_no_info": "Details for this image cannot be verified.",
|
||||
"metadata-stripped": "The image has been compressed and its metadata removed. If you’d like more context, ask the sender for the original file.",
|
||||
"download_image": "Download image"
|
||||
"download_image": "Download image",
|
||||
"contains_modified_and_ai_generated": "Contains modified and AI generated media.",
|
||||
"take_a_closer_look": "Take a closer look.",
|
||||
"contains_modified": "Contains modified media.",
|
||||
"contains_ai_generated": "Contains AI generated media.",
|
||||
"information_available": "Information is available for the media shared.",
|
||||
"captured_with_camera": "Captured with a camera.",
|
||||
"screenshot": "Screenshot.",
|
||||
"screenshot_probably": "Image looks like a screenshot.",
|
||||
"generated_with_ai": "Generated with AI.",
|
||||
"modified": "Modified.",
|
||||
"older_than_n_months": "Older than {n} months"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="cc-summary" v-if="flags.length > 0 && infoText.length > 0">
|
||||
<div class="cc-summary bubble-inset" v-if="flags.length > 0 && infoText.length > 0">
|
||||
<v-icon class="intervention-icon">{{
|
||||
showCheck ? "$vuetify.icons.ic_intervention_check" : "$vuetify.icons.ic_intervention"
|
||||
}}</v-icon
|
||||
|
|
@ -10,6 +10,10 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { ProofHintFlags } from "../../models/proof";
|
||||
import dayjs from "dayjs";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const { multiple, flags } = defineProps<{
|
||||
multiple: boolean;
|
||||
|
|
@ -27,21 +31,56 @@ const showCheck = computed(() => {
|
|||
|
||||
const infoText = computed(() => {
|
||||
if (!multiple && flags.length == 1) {
|
||||
if (flags[0].generator === "ai") {
|
||||
return "<b>This image is generated by AI.</b> Take a closer look at the file details.";
|
||||
} else if (flags[0].generator === "screenshot") {
|
||||
return "<b>This is a screenshot.</b> Take a closer look at the file details.";
|
||||
} else if (flags[0].edits) {
|
||||
return "<b>This image has been modified.</b> Take a closer look at the file details.";
|
||||
const f = flags[0];
|
||||
let res = "";
|
||||
|
||||
if (f.generator !== "unknown" && f.generatorSource === "c2pa") {
|
||||
if (f.generator === "camera") {
|
||||
res += "<b>" + t("cc.captured_with_camera") + "</b> ";
|
||||
} else if (f.generator === "screenshot") {
|
||||
res += "<b>" + t("cc.screenshot") + "</b> ";
|
||||
} else if (f.generator === "ai") {
|
||||
res += "<b>" + t("cc.generated_with_ai") + "</b> ";
|
||||
}
|
||||
if ((f.edits?.length ?? 0) > 0) {
|
||||
res += "<b>" + t("cc.modified") + "</b> ";
|
||||
}
|
||||
if (f.creationDate && dayjs().diff(f.creationDate, "month") >= 3) {
|
||||
res += "<b>" + t("cc.older_than_n_months", {n: 3}) + "</b> ";
|
||||
}
|
||||
return res;
|
||||
} else if (f.generator !== "unknown") {
|
||||
if (f.generator === "camera") {
|
||||
res += "<b>" + t("cc.captured_with_camera") + "</b> ";
|
||||
} else if (f.generator === "screenshot") {
|
||||
res += "<b>" + t("cc.screenshot_probably") + "</b> ";
|
||||
return res;
|
||||
} else if (f.generator === "ai") {
|
||||
res += "<b>" + t("cc.generated_with_ai") + "</b> ";
|
||||
}
|
||||
if ((f.edits?.length ?? 0) > 0) {
|
||||
res += "<b>" + t("cc.modified") + "</b> ";
|
||||
}
|
||||
if (f.creationDate && dayjs().diff(f.creationDate, "month") >= 3) {
|
||||
res += "<b>" + t("cc.older_than_n_months", {n: 3}) + "</b> ";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
} else if (multiple && flags.length >= 1) {
|
||||
const modifiedMedia = flags.some((f) => f.edits?.length);
|
||||
const aiGeneratedMedia = flags.some((f) => f.generator === "ai");
|
||||
|
||||
if (aiGeneratedMedia && modifiedMedia) {
|
||||
return "<b>" + t("cc.contains_modified_and_ai_generated") + "</b> " + t("cc.take_a_closer_look");
|
||||
} else if (modifiedMedia) {
|
||||
return "<b>" + t("cc.contains_modified") + "</b>";
|
||||
} else if (aiGeneratedMedia) {
|
||||
return "<b>" + t("cc.contains_ai_generated") + "</b>";
|
||||
} else {
|
||||
return "<b>" + t("cc.information_available") + "</b>";
|
||||
}
|
||||
} else if (flags.some((f) => f.generator === "ai")) {
|
||||
return "<b>Contains AI generated media.</b> Take a closer look at the file details for each.";
|
||||
} else if (flags.some((f) => f.generator === "screenshot")) {
|
||||
return "<b>Contains screenshots.</b> Take a closer look at the file details for each.";
|
||||
} else if (flags.some((f) => f.edits?.length)) {
|
||||
return "<b>Contains modified media.</b> Take a closer look at the file details for each.";
|
||||
}
|
||||
return "TODO - Content Credentials Info";
|
||||
return "";
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@
|
|||
v-bind="{ ...$props, ...$attrs }"
|
||||
>
|
||||
<div class="bubble image-bubble" ref="imageRef">
|
||||
<div class="bubble-inset" v-if="attachment?.proofHintFlags">
|
||||
<CCSummary :multiple="false" :flags="attachment.proofHintFlags ? [attachment.proofHintFlags] : []" />
|
||||
</div>
|
||||
<CCSummary :multiple="false" :flags="attachment?.proofHintFlags ? [attachment.proofHintFlags] : []" />
|
||||
|
||||
<ImageWithProgress v-if="attachment"
|
||||
:aspect-ratio="16 / 9"
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
<template>
|
||||
<component :is="rootComponent" ref="root" v-bind="{ ...$props, ...$attrs }" v-if="showMultiview">
|
||||
<div class="bubble">
|
||||
<div class="bubble-inset" v-if="showCCSummary">
|
||||
<CCSummary :multiple="items.length > 1" :flags="proofHintFlags" />
|
||||
</div>
|
||||
<CCSummary :multiple="items.length > 1" :flags="proofHintFlags" />
|
||||
<div class="original-message bubble-inset" v-if="inReplyToText">
|
||||
<div class="original-message-sender">{{ inReplyToSender }}</div>
|
||||
<div class="original-message-text" v-html="linkify($$sanitize(inReplyToText))" />
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ export type Proof = {
|
|||
};
|
||||
|
||||
export type ProofHintFlagsGenerator = "unknown" | "camera" | "screenshot" | "ai";
|
||||
export type ProofHintFlagsGeneratorSource = "c2pa" | "exif" | "metadata";
|
||||
export type ProofHintFlagSource = "c2pa" | "exif" | "metadata";
|
||||
//export type ProofHintFlagsEditor = "unknown" | "manual" | "ai";
|
||||
|
||||
export type ProofHintFlagsEdit = {
|
||||
|
|
@ -71,8 +71,9 @@ export type ProofHintFlagsEdit = {
|
|||
export type ProofHintFlags = {
|
||||
device?: string;
|
||||
creationDate?: Date;
|
||||
creationDateSource?: ProofHintFlagSource;
|
||||
generator?: ProofHintFlagsGenerator;
|
||||
generatorSource?: ProofHintFlagsGeneratorSource;
|
||||
generatorSource?: ProofHintFlagSource;
|
||||
edits?: ProofHintFlagsEdit[];
|
||||
containsC2PA?: boolean;
|
||||
containsEXIF?: boolean;
|
||||
|
|
@ -316,6 +317,7 @@ export const extractProofHintFlags = (proof?: Proof): ProofHintFlags | undefined
|
|||
|
||||
let source: string | undefined = undefined;
|
||||
let dateCreated: Date | undefined = undefined;
|
||||
let dateCreatedSource: ProofHintFlagSource | undefined = undefined;
|
||||
|
||||
const creationAction = extractFlagValues(
|
||||
"integrity/c2pa/manifest_info/manifests[]/assertions[label=c2pa.actions]/data/actions[action=c2pa.created]",
|
||||
|
|
@ -324,11 +326,12 @@ export const extractProofHintFlags = (proof?: Proof): ProofHintFlags | undefined
|
|||
if (creationAction.length > 0) {
|
||||
source = softwareAgentFromAction(creationAction[0]);
|
||||
dateCreated = getFirstWithDataAsDate(["when", "../../metadata/dateTime", "../../../signature_info/time"], creationAction[0].path);
|
||||
dateCreatedSource = "c2pa";
|
||||
}
|
||||
console.log("DATE CREATED", dateCreated);
|
||||
|
||||
let generator: ProofHintFlagsGenerator = matchFlag(ruleAiGenerated(), rootMatchPath).result ? "ai" : matchFlag(ruleScreenshotC2PA(), rootMatchPath).result ? "screenshot" : matchFlag(ruleCamera(), rootMatchPath).result ? "camera" : "unknown";
|
||||
let generatorSource: ProofHintFlagsGeneratorSource | undefined = undefined;
|
||||
let generatorSource: ProofHintFlagSource | undefined = undefined;
|
||||
|
||||
if (generator !== "unknown" && valid) {
|
||||
generatorSource = "c2pa";
|
||||
|
|
@ -365,6 +368,7 @@ export const extractProofHintFlags = (proof?: Proof): ProofHintFlags | undefined
|
|||
const flags: ProofHintFlags = {
|
||||
device: source,
|
||||
creationDate: dateCreated,
|
||||
creationDateSource: dateCreatedSource,
|
||||
generator: generator,
|
||||
generatorSource: generatorSource,
|
||||
edits: edits,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue