mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Merge pull request #401 from PR0M3TH3AN/codex/add-version-metadata-display-in-revertmodal
Display audience flags in revert modal
This commit is contained in:
3 files changed
+133
-4
No files matched your search
@@ -62,7 +62,7 @@
|
||||
<p class="mt-2 text-xs text-gray-400">
|
||||
Versions are grouped by their <code class="px-1 py-0.5 bg-gray-900/60 rounded border border-gray-700 text-[0.7rem]">d</code>
|
||||
tag or shared <code class="px-1 py-0.5 bg-gray-900/60 rounded border border-gray-700 text-[0.7rem]">videoRootId</code>. This ensures legacy
|
||||
clients see consistent history when multiple edits were published.
|
||||
clients see consistent history when multiple edits were published, and keeps audience flags (NSFW / for kids) aligned with the Upload modal.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -117,6 +117,22 @@
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
<section class="space-y-2">
|
||||
<h4 class="text-xs font-semibold uppercase tracking-wide text-gray-400">
|
||||
Audience flags
|
||||
</h4>
|
||||
<dl class="grid gap-2 text-xs text-gray-400 sm:grid-cols-2">
|
||||
<div>
|
||||
<dt class="font-semibold text-gray-300">NSFW flag</dt>
|
||||
<dd class="mt-1 text-gray-500">Awaiting selection</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="font-semibold text-gray-300">For kids flag</dt>
|
||||
<dd class="mt-1 text-gray-500">Awaiting selection</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
<section class="space-y-2">
|
||||
<h4 class="text-xs font-semibold uppercase tracking-wide text-gray-400">
|
||||
NIP-71 event metadata
|
||||
|
||||
@@ -249,9 +249,44 @@ export class EditModal {
|
||||
});
|
||||
}
|
||||
|
||||
if (this.fields.isNsfw && this.fields.isForKids) {
|
||||
this.setupMutuallyExclusiveCheckboxes(
|
||||
this.fields.isNsfw,
|
||||
this.fields.isForKids
|
||||
);
|
||||
}
|
||||
|
||||
this.nip71FormManager.bindSection(this.nip71SectionKey);
|
||||
}
|
||||
|
||||
setupMutuallyExclusiveCheckboxes(firstInput, secondInput) {
|
||||
if (!firstInput || !secondInput) {
|
||||
return;
|
||||
}
|
||||
|
||||
const enforceExclusion = (primary, secondary) => {
|
||||
if (primary.checked) {
|
||||
secondary.checked = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleFirstChange = () => enforceExclusion(firstInput, secondInput);
|
||||
const handleSecondChange = () => enforceExclusion(secondInput, firstInput);
|
||||
|
||||
if (firstInput.checked && secondInput.checked) {
|
||||
secondInput.checked = false;
|
||||
}
|
||||
|
||||
firstInput.addEventListener("change", handleFirstChange);
|
||||
secondInput.addEventListener("change", handleSecondChange);
|
||||
}
|
||||
|
||||
sanitizeAudienceFlags(flags = {}) {
|
||||
const isNsfw = flags?.isNsfw === true;
|
||||
const isForKids = flags?.isForKids === true && !isNsfw;
|
||||
return { isNsfw, isForKids };
|
||||
}
|
||||
|
||||
reset() {
|
||||
if (!this.root) {
|
||||
this.activeVideo = null;
|
||||
@@ -322,10 +357,14 @@ export class EditModal {
|
||||
const enableCommentsValue =
|
||||
typeof video.enableComments === "boolean" ? video.enableComments : true;
|
||||
const isPrivateValue = video.isPrivate === true;
|
||||
const isNsfwValue =
|
||||
typeof video.isNsfw === "boolean" ? video.isNsfw : false;
|
||||
const isForKidsValue =
|
||||
const rawIsNsfw = typeof video.isNsfw === "boolean" ? video.isNsfw : false;
|
||||
const rawIsForKids =
|
||||
typeof video.isForKids === "boolean" ? video.isForKids : false;
|
||||
const { isNsfw: isNsfwValue, isForKids: isForKidsValue } =
|
||||
this.sanitizeAudienceFlags({
|
||||
isNsfw: rawIsNsfw,
|
||||
isForKids: rawIsForKids,
|
||||
});
|
||||
|
||||
const editContext = {
|
||||
...video,
|
||||
@@ -361,6 +400,13 @@ export class EditModal {
|
||||
return;
|
||||
}
|
||||
|
||||
const sanitizedFlags = this.sanitizeAudienceFlags({
|
||||
isNsfw: editContext.isNsfw,
|
||||
isForKids: editContext.isForKids,
|
||||
});
|
||||
editContext.isNsfw = sanitizedFlags.isNsfw;
|
||||
editContext.isForKids = sanitizedFlags.isForKids;
|
||||
|
||||
const fieldMap = {
|
||||
title: editContext.title || "",
|
||||
url: editContext.url || "",
|
||||
@@ -831,6 +877,12 @@ export class EditModal {
|
||||
}
|
||||
}
|
||||
|
||||
({ isNsfw: finalIsNsfw, isForKids: finalIsForKids } =
|
||||
this.sanitizeAudienceFlags({
|
||||
isNsfw: finalIsNsfw,
|
||||
isForKids: finalIsForKids,
|
||||
}));
|
||||
|
||||
if (!finalTitle || (!finalUrl && !finalMagnet && !hasImetaSource)) {
|
||||
this.showError(
|
||||
"Title and at least one of URL, Magnet, or a NIP-71 media variant is required."
|
||||
|
||||
@@ -571,6 +571,9 @@ export class RevertModal {
|
||||
}
|
||||
|
||||
const chips = [];
|
||||
const nsfwFlag = version.isNsfw === true;
|
||||
const forKidsFlag = version.isForKids === true;
|
||||
const conflictingAudienceFlags = nsfwFlag && forKidsFlag;
|
||||
if (version.deleted) {
|
||||
chips.push(
|
||||
'<span class="inline-flex items-center rounded-full border border-red-700/70 bg-red-900/40 px-2 py-0.5 text-xs text-red-200/90">Marked deleted</span>'
|
||||
@@ -581,6 +584,22 @@ export class RevertModal {
|
||||
'<span class="inline-flex items-center rounded-full border border-purple-600/60 bg-purple-900/40 px-2 py-0.5 text-xs text-purple-200/90">Private</span>'
|
||||
);
|
||||
}
|
||||
if (conflictingAudienceFlags) {
|
||||
chips.push(
|
||||
'<span class="inline-flex items-center rounded-full border border-amber-700/70 bg-amber-900/40 px-2 py-0.5 text-xs text-amber-200/90">NSFW + For kids conflict</span>'
|
||||
);
|
||||
} else {
|
||||
if (nsfwFlag) {
|
||||
chips.push(
|
||||
'<span class="inline-flex items-center rounded-full border border-red-700/70 bg-red-900/40 px-2 py-0.5 text-xs text-red-200/90">Marked NSFW</span>'
|
||||
);
|
||||
}
|
||||
if (forKidsFlag) {
|
||||
chips.push(
|
||||
'<span class="inline-flex items-center rounded-full border border-emerald-700/70 bg-emerald-900/40 px-2 py-0.5 text-xs text-emerald-200/90">For kids</span>'
|
||||
);
|
||||
}
|
||||
}
|
||||
if (version.version !== undefined) {
|
||||
chips.push(
|
||||
`<span class="inline-flex items-center rounded-full border border-gray-700 bg-gray-800/80 px-2 py-0.5 text-xs text-gray-200">Schema v${escape(
|
||||
@@ -589,6 +608,35 @@ export class RevertModal {
|
||||
);
|
||||
}
|
||||
|
||||
const renderFlagStatus = (value, {
|
||||
yesLabel = "Yes",
|
||||
noLabel = "No",
|
||||
unspecifiedLabel = "Not specified",
|
||||
} = {}) => {
|
||||
if (value === true) {
|
||||
return `<span class="text-gray-200">${escape(yesLabel)}</span>`;
|
||||
}
|
||||
if (value === false) {
|
||||
return `<span class="text-gray-200">${escape(noLabel)}</span>`;
|
||||
}
|
||||
return this.renderPlaceholder(unspecifiedLabel);
|
||||
};
|
||||
|
||||
const nsfwStatusHtml = renderFlagStatus(version.isNsfw, {
|
||||
yesLabel: "Yes — marked NSFW",
|
||||
noLabel: "No — not flagged as NSFW",
|
||||
unspecifiedLabel: "Not specified",
|
||||
});
|
||||
const kidsStatusHtml = renderFlagStatus(version.isForKids, {
|
||||
yesLabel: "Yes — marked for kids",
|
||||
noLabel: "No — not marked for kids",
|
||||
unspecifiedLabel: "Not specified",
|
||||
});
|
||||
|
||||
const audienceConflictNotice = conflictingAudienceFlags
|
||||
? '<p class="text-xs text-amber-300">Conflicting flags detected — this revision is marked both NSFW and for kids. Review before reverting.</p>'
|
||||
: "";
|
||||
|
||||
const descriptionHtml = description
|
||||
? `<p class="whitespace-pre-wrap text-gray-200">${escape(description)}</p>`
|
||||
: '<p class="text-gray-500">No description provided.</p>';
|
||||
@@ -718,6 +766,11 @@ export class RevertModal {
|
||||
definition("Alt text", altHtml, { span: 2 }),
|
||||
].join("");
|
||||
|
||||
const audienceRows = [
|
||||
definition("NSFW flag", nsfwStatusHtml),
|
||||
definition("For kids flag", kidsStatusHtml),
|
||||
].join("");
|
||||
|
||||
this.details.innerHTML = `
|
||||
<div class="space-y-6">
|
||||
<div class="flex flex-col gap-4 lg:flex-row lg:items-start">
|
||||
@@ -759,6 +812,14 @@ export class RevertModal {
|
||||
${descriptionHtml}
|
||||
</section>
|
||||
|
||||
<section class="space-y-2">
|
||||
<h4 class="text-sm font-semibold text-gray-200">Audience flags</h4>
|
||||
<dl class="grid gap-3 sm:grid-cols-2 text-xs text-gray-300">
|
||||
${audienceRows}
|
||||
</dl>
|
||||
${audienceConflictNotice}
|
||||
</section>
|
||||
|
||||
<section class="space-y-2">
|
||||
<h4 class="text-sm font-semibold text-gray-200">NIP-71 event metadata</h4>
|
||||
<dl class="grid gap-3 sm:grid-cols-2 text-xs text-gray-300">
|
||||
|
||||
Reference in new issue
Block a user