mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
Handle trusted hide moderation state
This commit is contained in:
1 parent
a8d72eb399
commit
a2f74ac13f
3 files changed
+468
-43
No files matched your search
@@ -5148,15 +5148,71 @@ class Application {
|
||||
const computedBlockAutoplay = trustedCount >= thresholds.autoplayBlockThreshold;
|
||||
const computedBlurThumbnail = trustedCount >= thresholds.blurThreshold;
|
||||
|
||||
const muteHideThreshold = Number.isFinite(thresholds.trustedMuteHideThreshold)
|
||||
? Math.max(0, Math.floor(thresholds.trustedMuteHideThreshold))
|
||||
: Number.POSITIVE_INFINITY;
|
||||
const reportHideThreshold = Number.isFinite(thresholds.trustedSpamHideThreshold)
|
||||
? Math.max(0, Math.floor(thresholds.trustedSpamHideThreshold))
|
||||
: Number.POSITIVE_INFINITY;
|
||||
|
||||
const existingHideReason =
|
||||
typeof existingModeration.hideReason === "string"
|
||||
? existingModeration.hideReason.trim()
|
||||
: "";
|
||||
const existingHideBypass =
|
||||
typeof existingModeration.hideBypass === "string"
|
||||
? existingModeration.hideBypass.trim()
|
||||
: "";
|
||||
const existingHideCounts =
|
||||
existingModeration.hideCounts && typeof existingModeration.hideCounts === "object"
|
||||
? existingModeration.hideCounts
|
||||
: null;
|
||||
|
||||
let hideReason = "";
|
||||
let hideTriggered = false;
|
||||
|
||||
if (trustedMuted && trustedMuteCount >= muteHideThreshold) {
|
||||
hideReason = "trusted-mute-hide";
|
||||
hideTriggered = true;
|
||||
} else if (trustedCount >= reportHideThreshold) {
|
||||
hideReason = "trusted-report-hide";
|
||||
hideTriggered = true;
|
||||
} else if (existingHideReason && existingHideCounts) {
|
||||
hideReason = existingHideReason;
|
||||
hideTriggered = true;
|
||||
}
|
||||
|
||||
const hideCounts = hideTriggered
|
||||
? {
|
||||
trustedMuteCount,
|
||||
trustedReportCount: trustedCount,
|
||||
}
|
||||
: null;
|
||||
|
||||
let hideBypass = hideTriggered ? existingHideBypass : "";
|
||||
const computedHidden = hideTriggered && !hideBypass;
|
||||
|
||||
const overrideEntry = getModerationOverride(video.id);
|
||||
const overrideActive = overrideEntry?.showAnyway === true;
|
||||
const overrideUpdatedAt = Number.isFinite(overrideEntry?.updatedAt)
|
||||
? Math.floor(overrideEntry.updatedAt)
|
||||
: Date.now();
|
||||
|
||||
const originalHideCounts = hideCounts
|
||||
? {
|
||||
trustedMuteCount: Math.max(0, Math.floor(hideCounts.trustedMuteCount)),
|
||||
trustedReportCount: Math.max(0, Math.floor(hideCounts.trustedReportCount)),
|
||||
}
|
||||
: null;
|
||||
|
||||
const originalState = {
|
||||
blockAutoplay: computedBlockAutoplay,
|
||||
blurThumbnail: computedBlurThumbnail,
|
||||
hidden: computedHidden,
|
||||
hideReason: hideTriggered ? hideReason : "",
|
||||
hideCounts: originalHideCounts,
|
||||
hideBypass,
|
||||
hideTriggered,
|
||||
};
|
||||
|
||||
const decoratedModeration = {
|
||||
@@ -5173,12 +5229,27 @@ class Application {
|
||||
original: {
|
||||
blockAutoplay: originalState.blockAutoplay,
|
||||
blurThumbnail: originalState.blurThumbnail,
|
||||
hidden: originalState.hidden,
|
||||
hideReason: originalState.hideReason,
|
||||
hideCounts: originalState.hideCounts,
|
||||
hideBypass: originalState.hideBypass,
|
||||
hideTriggered: originalState.hideTriggered,
|
||||
},
|
||||
};
|
||||
|
||||
if (overrideActive) {
|
||||
decoratedModeration.blockAutoplay = false;
|
||||
decoratedModeration.blurThumbnail = false;
|
||||
decoratedModeration.hidden = false;
|
||||
if (decoratedModeration.hideReason) {
|
||||
delete decoratedModeration.hideReason;
|
||||
}
|
||||
if (decoratedModeration.hideCounts) {
|
||||
delete decoratedModeration.hideCounts;
|
||||
}
|
||||
if (decoratedModeration.hideBypass) {
|
||||
delete decoratedModeration.hideBypass;
|
||||
}
|
||||
decoratedModeration.viewerOverride = {
|
||||
showAnyway: true,
|
||||
updatedAt: overrideUpdatedAt,
|
||||
@@ -5186,6 +5257,22 @@ class Application {
|
||||
} else {
|
||||
decoratedModeration.blockAutoplay = originalState.blockAutoplay;
|
||||
decoratedModeration.blurThumbnail = originalState.blurThumbnail;
|
||||
decoratedModeration.hidden = originalState.hidden;
|
||||
if (originalState.hideReason) {
|
||||
decoratedModeration.hideReason = originalState.hideReason;
|
||||
} else if (decoratedModeration.hideReason) {
|
||||
delete decoratedModeration.hideReason;
|
||||
}
|
||||
if (originalState.hideCounts) {
|
||||
decoratedModeration.hideCounts = { ...originalState.hideCounts };
|
||||
} else if (decoratedModeration.hideCounts) {
|
||||
delete decoratedModeration.hideCounts;
|
||||
}
|
||||
if (originalState.hideBypass) {
|
||||
decoratedModeration.hideBypass = originalState.hideBypass;
|
||||
} else if (decoratedModeration.hideBypass) {
|
||||
delete decoratedModeration.hideBypass;
|
||||
}
|
||||
if (decoratedModeration.viewerOverride) {
|
||||
delete decoratedModeration.viewerOverride;
|
||||
}
|
||||
@@ -5214,10 +5301,38 @@ class Application {
|
||||
const target = storedVideo || video;
|
||||
|
||||
if (target) {
|
||||
if (target.moderation && typeof target.moderation === "object") {
|
||||
if (target.moderation.hidden) {
|
||||
delete target.moderation.hidden;
|
||||
}
|
||||
if (target.moderation.hideReason) {
|
||||
delete target.moderation.hideReason;
|
||||
}
|
||||
if (target.moderation.hideCounts) {
|
||||
delete target.moderation.hideCounts;
|
||||
}
|
||||
if (target.moderation.hideBypass) {
|
||||
delete target.moderation.hideBypass;
|
||||
}
|
||||
}
|
||||
this.decorateVideoModeration(target);
|
||||
}
|
||||
|
||||
if (this.currentVideo && this.currentVideo.id === video.id) {
|
||||
if (this.currentVideo.moderation && typeof this.currentVideo.moderation === "object") {
|
||||
if (this.currentVideo.moderation.hidden) {
|
||||
delete this.currentVideo.moderation.hidden;
|
||||
}
|
||||
if (this.currentVideo.moderation.hideReason) {
|
||||
delete this.currentVideo.moderation.hideReason;
|
||||
}
|
||||
if (this.currentVideo.moderation.hideCounts) {
|
||||
delete this.currentVideo.moderation.hideCounts;
|
||||
}
|
||||
if (this.currentVideo.moderation.hideBypass) {
|
||||
delete this.currentVideo.moderation.hideBypass;
|
||||
}
|
||||
}
|
||||
this.decorateVideoModeration(this.currentVideo);
|
||||
}
|
||||
|
||||
|
||||
+339
-42
@@ -114,6 +114,7 @@ export class VideoCard {
|
||||
this.moderationActionButton = null;
|
||||
this.moderationBadgeId = "";
|
||||
this.badgesContainerEl = null;
|
||||
this.hiddenSummaryEl = null;
|
||||
this.boundShowAnywayHandler = (event) => this.handleShowAnywayClick(event);
|
||||
|
||||
this.root = null;
|
||||
@@ -425,6 +426,7 @@ export class VideoCard {
|
||||
|
||||
this.applyPlaybackDatasets();
|
||||
this.bindEvents();
|
||||
this.refreshModerationUi();
|
||||
}
|
||||
|
||||
setCardBackdropImage(src) {
|
||||
@@ -975,6 +977,50 @@ export class VideoCard {
|
||||
? moderation.original
|
||||
: {};
|
||||
|
||||
const activeHidden = moderation?.hidden === true;
|
||||
const originalHidden = original.hidden === true;
|
||||
const hideReasonActive =
|
||||
typeof moderation?.hideReason === "string" ? moderation.hideReason.trim() : "";
|
||||
const hideBypassActive =
|
||||
typeof moderation?.hideBypass === "string" ? moderation.hideBypass.trim() : "";
|
||||
const originalHideReason =
|
||||
typeof original.hideReason === "string" ? original.hideReason.trim() : "";
|
||||
const originalHideBypass =
|
||||
typeof original.hideBypass === "string" ? original.hideBypass.trim() : "";
|
||||
const originalHideTriggered = original.hideTriggered === true;
|
||||
|
||||
const normalizeHideCounts = (input) => {
|
||||
if (!input || typeof input !== "object") {
|
||||
return null;
|
||||
}
|
||||
const normalized = {};
|
||||
let hasValue = false;
|
||||
if (Number.isFinite(input.trustedMuteCount)) {
|
||||
normalized.trustedMuteCount = Math.max(0, Math.floor(input.trustedMuteCount));
|
||||
hasValue = true;
|
||||
}
|
||||
if (Number.isFinite(input.trustedReportCount)) {
|
||||
normalized.trustedReportCount = Math.max(0, Math.floor(input.trustedReportCount));
|
||||
hasValue = true;
|
||||
}
|
||||
return hasValue ? normalized : null;
|
||||
};
|
||||
|
||||
const baseHideCounts = {
|
||||
trustedMuteCount,
|
||||
trustedReportCount: trustedCount,
|
||||
};
|
||||
|
||||
const activeHideCounts =
|
||||
normalizeHideCounts(moderation?.hideCounts) ||
|
||||
(activeHidden || hideReasonActive ? { ...baseHideCounts } : null);
|
||||
const originalHideCounts =
|
||||
normalizeHideCounts(original?.hideCounts) ||
|
||||
(originalHideTriggered ? { ...baseHideCounts } : null);
|
||||
|
||||
const effectiveHideReason = hideReasonActive || originalHideReason;
|
||||
const effectiveHideCounts = activeHideCounts || originalHideCounts;
|
||||
|
||||
const context = {
|
||||
reportType,
|
||||
friendlyType: reportType ? reportType.replace(/[_-]+/g, " ").trim() : "",
|
||||
@@ -988,6 +1034,17 @@ export class VideoCard {
|
||||
activeBlur: moderation?.blurThumbnail === true,
|
||||
activeBlockAutoplay: moderation?.blockAutoplay === true,
|
||||
overrideActive: moderation?.viewerOverride?.showAnyway === true,
|
||||
activeHidden,
|
||||
originalHidden,
|
||||
originalHideTriggered,
|
||||
hideReason: hideReasonActive,
|
||||
hideCounts: activeHideCounts,
|
||||
hideBypass: hideBypassActive,
|
||||
originalHideReason,
|
||||
originalHideCounts,
|
||||
originalHideBypass,
|
||||
effectiveHideReason,
|
||||
effectiveHideCounts,
|
||||
};
|
||||
|
||||
context.shouldShow =
|
||||
@@ -995,9 +1052,13 @@ export class VideoCard {
|
||||
context.originalBlockAutoplay ||
|
||||
context.trustedCount > 0 ||
|
||||
context.trustedMuted ||
|
||||
context.overrideActive;
|
||||
context.overrideActive ||
|
||||
context.originalHidden ||
|
||||
context.activeHidden ||
|
||||
context.originalHideTriggered;
|
||||
|
||||
context.allowOverride = context.originalBlur || context.originalBlockAutoplay;
|
||||
context.allowOverride =
|
||||
context.originalBlur || context.originalBlockAutoplay || context.originalHidden;
|
||||
|
||||
return context;
|
||||
}
|
||||
@@ -1032,19 +1093,82 @@ export class VideoCard {
|
||||
return combined.charAt(0).toUpperCase() + combined.slice(1);
|
||||
}
|
||||
|
||||
buildHiddenSummaryLabel(context) {
|
||||
if (!context) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const reason = context.effectiveHideReason;
|
||||
if (!reason) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const countsSource =
|
||||
context.effectiveHideCounts || context.originalHideCounts || context.hideCounts || null;
|
||||
const getCount = (key, fallback) => {
|
||||
if (countsSource && Number.isFinite(countsSource[key])) {
|
||||
return Math.max(0, Number(countsSource[key]));
|
||||
}
|
||||
if (Number.isFinite(context[key])) {
|
||||
return Math.max(0, Number(context[key]));
|
||||
}
|
||||
return Math.max(0, Number(fallback) || 0);
|
||||
};
|
||||
|
||||
if (reason === "trusted-mute-hide") {
|
||||
const count = getCount("trustedMuteCount", context.trustedMuteCount || 0);
|
||||
if (count > 0) {
|
||||
const label = count === 1 ? "trusted mute" : "trusted mutes";
|
||||
return `${count} ${label}`;
|
||||
}
|
||||
return "trusted mute";
|
||||
}
|
||||
|
||||
if (reason === "trusted-report-hide") {
|
||||
const count = getCount("trustedReportCount", context.trustedCount || 0);
|
||||
const type = typeof context.friendlyType === "string" ? context.friendlyType.trim() : "";
|
||||
const normalizedType = type ? type.toLowerCase() : "";
|
||||
if (count > 0) {
|
||||
const label = count === 1 ? "report" : "reports";
|
||||
if (normalizedType) {
|
||||
return `${count} trusted ${normalizedType} ${label}`;
|
||||
}
|
||||
const base = count === 1 ? "trusted report" : "trusted reports";
|
||||
return `${count} ${base}`;
|
||||
}
|
||||
if (normalizedType) {
|
||||
return `trusted ${normalizedType} reports`;
|
||||
}
|
||||
return "trusted reports";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
buildModerationBadgeText(context) {
|
||||
if (!context) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const hiddenLabel = this.buildHiddenSummaryLabel(context);
|
||||
const reason = this.buildModerationReasonText(context);
|
||||
if (context.overrideActive) {
|
||||
if (hiddenLabel) {
|
||||
return `Showing despite ${hiddenLabel}`;
|
||||
}
|
||||
if (reason) {
|
||||
return `Showing despite ${reason}`;
|
||||
}
|
||||
return "Showing despite reports";
|
||||
}
|
||||
|
||||
if (context.activeHidden || (context.originalHidden && !context.overrideActive)) {
|
||||
if (hiddenLabel) {
|
||||
return `Hidden · ${hiddenLabel}`;
|
||||
}
|
||||
return "Hidden";
|
||||
}
|
||||
|
||||
const parts = [];
|
||||
if (context.originalBlur) {
|
||||
parts.push("Blurred");
|
||||
@@ -1157,8 +1281,7 @@ export class VideoCard {
|
||||
});
|
||||
}
|
||||
|
||||
buildModerationBadge() {
|
||||
const context = this.getModerationContext();
|
||||
buildModerationBadge(context = this.getModerationContext()) {
|
||||
if (!context.shouldShow) {
|
||||
this.moderationBadgeEl = null;
|
||||
this.moderationBadgeTextEl = null;
|
||||
@@ -1177,12 +1300,18 @@ export class VideoCard {
|
||||
});
|
||||
badge.dataset.variant = context.overrideActive ? "neutral" : "warning";
|
||||
badge.dataset.moderationBadge = "true";
|
||||
const hiddenActive = context.activeHidden && !context.overrideActive;
|
||||
const state = context.overrideActive
|
||||
? "override"
|
||||
: context.trustedMuted
|
||||
? "trusted-mute"
|
||||
: "blocked";
|
||||
: hiddenActive
|
||||
? "hidden"
|
||||
: context.trustedMuted
|
||||
? "trusted-mute"
|
||||
: "blocked";
|
||||
badge.dataset.moderationState = state;
|
||||
if (hiddenActive && context.effectiveHideReason) {
|
||||
badge.dataset.moderationHideReason = context.effectiveHideReason;
|
||||
}
|
||||
|
||||
const badgeId = this.getModerationBadgeId();
|
||||
badge.id = badgeId;
|
||||
@@ -1248,9 +1377,9 @@ export class VideoCard {
|
||||
return badge;
|
||||
}
|
||||
|
||||
updateModerationBadge() {
|
||||
const context = this.getModerationContext();
|
||||
updateModerationBadge(context = this.getModerationContext()) {
|
||||
const badge = this.moderationBadgeEl;
|
||||
const hiddenActive = context.activeHidden && !context.overrideActive;
|
||||
|
||||
if (!context.shouldShow) {
|
||||
if (badge && badge.parentElement) {
|
||||
@@ -1265,32 +1394,42 @@ export class VideoCard {
|
||||
this.moderationBadgeEl = null;
|
||||
this.moderationBadgeTextEl = null;
|
||||
this.moderationActionButton = null;
|
||||
if (this.hiddenSummaryEl && this.hiddenSummaryEl.parentElement === this.root) {
|
||||
this.hiddenSummaryEl.remove();
|
||||
}
|
||||
this.updateModerationAria();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!badge) {
|
||||
const nextBadge = this.buildModerationBadge();
|
||||
const nextBadge = this.buildModerationBadge(context);
|
||||
if (nextBadge) {
|
||||
if (!this.badgesContainerEl) {
|
||||
this.badgesContainerEl = this.createElement("div", {
|
||||
classNames: ["flex", "flex-wrap", "items-center", "gap-sm"],
|
||||
});
|
||||
if (this.contentEl) {
|
||||
if (
|
||||
this.discussionCountEl &&
|
||||
this.discussionCountEl.parentElement === this.contentEl
|
||||
) {
|
||||
this.contentEl.insertBefore(
|
||||
this.badgesContainerEl,
|
||||
this.discussionCountEl,
|
||||
);
|
||||
} else {
|
||||
this.contentEl.appendChild(this.badgesContainerEl);
|
||||
if (hiddenActive) {
|
||||
const container = this.ensureHiddenSummaryContainer();
|
||||
if (container) {
|
||||
container.appendChild(nextBadge);
|
||||
}
|
||||
} else {
|
||||
if (!this.badgesContainerEl) {
|
||||
this.badgesContainerEl = this.createElement("div", {
|
||||
classNames: ["flex", "flex-wrap", "items-center", "gap-sm"],
|
||||
});
|
||||
if (this.contentEl) {
|
||||
if (
|
||||
this.discussionCountEl &&
|
||||
this.discussionCountEl.parentElement === this.contentEl
|
||||
) {
|
||||
this.contentEl.insertBefore(
|
||||
this.badgesContainerEl,
|
||||
this.discussionCountEl,
|
||||
);
|
||||
} else {
|
||||
this.contentEl.appendChild(this.badgesContainerEl);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.badgesContainerEl.appendChild(nextBadge);
|
||||
}
|
||||
this.badgesContainerEl.appendChild(nextBadge);
|
||||
}
|
||||
this.updateModerationAria();
|
||||
return;
|
||||
@@ -1299,10 +1438,17 @@ export class VideoCard {
|
||||
badge.dataset.variant = context.overrideActive ? "neutral" : "warning";
|
||||
const state = context.overrideActive
|
||||
? "override"
|
||||
: context.trustedMuted
|
||||
? "trusted-mute"
|
||||
: "blocked";
|
||||
: hiddenActive
|
||||
? "hidden"
|
||||
: context.trustedMuted
|
||||
? "trusted-mute"
|
||||
: "blocked";
|
||||
badge.dataset.moderationState = state;
|
||||
if (hiddenActive && context.effectiveHideReason) {
|
||||
badge.dataset.moderationHideReason = context.effectiveHideReason;
|
||||
} else if (badge.dataset.moderationHideReason) {
|
||||
delete badge.dataset.moderationHideReason;
|
||||
}
|
||||
|
||||
const textContent = this.buildModerationBadgeText(context);
|
||||
if (this.moderationBadgeTextEl) {
|
||||
@@ -1347,6 +1493,33 @@ export class VideoCard {
|
||||
badge.setAttribute("aria-label", `${textContent}.`);
|
||||
}
|
||||
|
||||
if (hiddenActive) {
|
||||
const container = this.ensureHiddenSummaryContainer();
|
||||
if (container && badge.parentElement !== container) {
|
||||
if (badge.parentElement) {
|
||||
badge.parentElement.removeChild(badge);
|
||||
}
|
||||
container.appendChild(badge);
|
||||
}
|
||||
} else if (this.badgesContainerEl) {
|
||||
if (!this.badgesContainerEl.parentElement && this.contentEl) {
|
||||
if (
|
||||
this.discussionCountEl &&
|
||||
this.discussionCountEl.parentElement === this.contentEl
|
||||
) {
|
||||
this.contentEl.insertBefore(this.badgesContainerEl, this.discussionCountEl);
|
||||
} else {
|
||||
this.contentEl.appendChild(this.badgesContainerEl);
|
||||
}
|
||||
}
|
||||
if (badge.parentElement !== this.badgesContainerEl) {
|
||||
if (badge.parentElement) {
|
||||
badge.parentElement.removeChild(badge);
|
||||
}
|
||||
this.badgesContainerEl.appendChild(badge);
|
||||
}
|
||||
}
|
||||
|
||||
if (context.overrideActive || !context.allowOverride) {
|
||||
if (this.moderationActionButton) {
|
||||
this.moderationActionButton.removeEventListener(
|
||||
@@ -1366,6 +1539,87 @@ export class VideoCard {
|
||||
}
|
||||
}
|
||||
|
||||
ensureHiddenSummaryContainer() {
|
||||
if (!this.root) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!this.hiddenSummaryEl) {
|
||||
this.hiddenSummaryEl = this.createElement("div", {
|
||||
classNames: ["p-md", "bv-stack", "bv-stack--tight"],
|
||||
});
|
||||
this.hiddenSummaryEl.dataset.moderationHiddenContainer = "true";
|
||||
this.hiddenSummaryEl.setAttribute("role", "group");
|
||||
this.hiddenSummaryEl.setAttribute("aria-live", "polite");
|
||||
}
|
||||
|
||||
const container = this.hiddenSummaryEl;
|
||||
container.hidden = false;
|
||||
container.removeAttribute("aria-hidden");
|
||||
|
||||
const referenceNode = this.anchorEl && this.anchorEl.parentElement === this.root ? this.anchorEl : this.root.firstChild;
|
||||
if (referenceNode && referenceNode.parentElement === this.root) {
|
||||
if (container.parentElement !== this.root || container.nextSibling !== referenceNode) {
|
||||
this.root.insertBefore(container, referenceNode);
|
||||
}
|
||||
} else if (container.parentElement !== this.root) {
|
||||
this.root.appendChild(container);
|
||||
}
|
||||
|
||||
const badgeId = this.getModerationBadgeId();
|
||||
if (badgeId) {
|
||||
container.setAttribute("aria-labelledby", badgeId);
|
||||
} else {
|
||||
container.removeAttribute("aria-labelledby");
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
updateHiddenState(context = this.getModerationContext()) {
|
||||
const hiddenActive = context.activeHidden && !context.overrideActive;
|
||||
const container = this.hiddenSummaryEl;
|
||||
|
||||
if (hiddenActive) {
|
||||
if (this.anchorEl) {
|
||||
this.anchorEl.setAttribute("hidden", "");
|
||||
this.anchorEl.setAttribute("aria-hidden", "true");
|
||||
}
|
||||
if (this.contentEl) {
|
||||
this.contentEl.setAttribute("hidden", "");
|
||||
this.contentEl.setAttribute("aria-hidden", "true");
|
||||
}
|
||||
|
||||
const summaryContainer = this.ensureHiddenSummaryContainer();
|
||||
if (summaryContainer) {
|
||||
const description = this.buildModerationBadgeText(context);
|
||||
if (description) {
|
||||
summaryContainer.setAttribute("aria-label", description);
|
||||
} else {
|
||||
summaryContainer.removeAttribute("aria-label");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.anchorEl) {
|
||||
this.anchorEl.removeAttribute("hidden");
|
||||
this.anchorEl.removeAttribute("aria-hidden");
|
||||
}
|
||||
if (this.contentEl) {
|
||||
this.contentEl.removeAttribute("hidden");
|
||||
this.contentEl.removeAttribute("aria-hidden");
|
||||
}
|
||||
if (container) {
|
||||
container.hidden = true;
|
||||
container.setAttribute("aria-hidden", "true");
|
||||
container.removeAttribute("aria-labelledby");
|
||||
container.removeAttribute("aria-label");
|
||||
if (container.parentElement === this.root) {
|
||||
this.root.removeChild(container);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateModerationAria() {
|
||||
const badgeId = this.moderationBadgeEl ? this.getModerationBadgeId() : "";
|
||||
const elements = [this.anchorEl, this.titleEl].filter(Boolean);
|
||||
@@ -1388,8 +1642,10 @@ export class VideoCard {
|
||||
}
|
||||
|
||||
refreshModerationUi() {
|
||||
this.applyModerationDatasets();
|
||||
this.updateModerationBadge();
|
||||
const context = this.getModerationContext();
|
||||
this.applyModerationDatasets(context);
|
||||
this.updateModerationBadge(context);
|
||||
this.updateHiddenState(context);
|
||||
this.updateModerationAria();
|
||||
}
|
||||
|
||||
@@ -1837,38 +2093,36 @@ export class VideoCard {
|
||||
updateVideoCardSourceVisibility(this.root);
|
||||
}
|
||||
|
||||
applyModerationDatasets() {
|
||||
applyModerationDatasets(context = this.getModerationContext()) {
|
||||
if (!this.root) {
|
||||
return;
|
||||
}
|
||||
|
||||
const moderationContext = this.getModerationContext();
|
||||
|
||||
if (moderationContext.originalBlockAutoplay && !moderationContext.overrideActive) {
|
||||
if (context.originalBlockAutoplay && !context.overrideActive) {
|
||||
this.root.dataset.autoplayPolicy = "blocked";
|
||||
} else if (this.root.dataset.autoplayPolicy) {
|
||||
delete this.root.dataset.autoplayPolicy;
|
||||
}
|
||||
|
||||
if (moderationContext.overrideActive) {
|
||||
if (context.overrideActive) {
|
||||
this.root.dataset.moderationOverride = "show-anyway";
|
||||
} else if (this.root.dataset.moderationOverride) {
|
||||
delete this.root.dataset.moderationOverride;
|
||||
}
|
||||
|
||||
if (this.thumbnailEl && !this.shouldMaskNsfwForOwner) {
|
||||
if (moderationContext.activeBlur) {
|
||||
if (context.activeBlur) {
|
||||
this.thumbnailEl.dataset.thumbnailState = "blurred";
|
||||
} else if (this.thumbnailEl.dataset.thumbnailState === "blurred") {
|
||||
delete this.thumbnailEl.dataset.thumbnailState;
|
||||
}
|
||||
}
|
||||
|
||||
const reportCount = Math.max(0, Number(moderationContext.trustedCount) || 0);
|
||||
const reportCount = Math.max(0, Number(context.trustedCount) || 0);
|
||||
if (reportCount > 0) {
|
||||
this.root.dataset.moderationReportCount = String(reportCount);
|
||||
if (moderationContext.reportType) {
|
||||
this.root.dataset.moderationReportType = moderationContext.reportType;
|
||||
if (context.reportType) {
|
||||
this.root.dataset.moderationReportType = context.reportType;
|
||||
} else if (this.root.dataset.moderationReportType) {
|
||||
delete this.root.dataset.moderationReportType;
|
||||
}
|
||||
@@ -1881,9 +2135,9 @@ export class VideoCard {
|
||||
}
|
||||
}
|
||||
|
||||
if (moderationContext.trustedMuted) {
|
||||
if (context.trustedMuted) {
|
||||
this.root.dataset.moderationTrustedMute = "true";
|
||||
const muteCount = Math.max(0, Number(moderationContext.trustedMuteCount) || 0);
|
||||
const muteCount = Math.max(0, Number(context.trustedMuteCount) || 0);
|
||||
if (muteCount > 0) {
|
||||
this.root.dataset.moderationTrustedMuteCount = String(muteCount);
|
||||
} else if (this.root.dataset.moderationTrustedMuteCount) {
|
||||
@@ -1897,6 +2151,49 @@ export class VideoCard {
|
||||
delete this.root.dataset.moderationTrustedMuteCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (context.activeHidden && !context.overrideActive) {
|
||||
this.root.dataset.moderationHidden = "true";
|
||||
const reason = context.effectiveHideReason || context.hideReason;
|
||||
if (reason) {
|
||||
this.root.dataset.moderationHideReason = reason;
|
||||
} else if (this.root.dataset.moderationHideReason) {
|
||||
delete this.root.dataset.moderationHideReason;
|
||||
}
|
||||
|
||||
const counts = context.hideCounts || context.effectiveHideCounts || null;
|
||||
const muteCount = counts && Number.isFinite(counts.trustedMuteCount)
|
||||
? Math.max(0, Number(counts.trustedMuteCount))
|
||||
: null;
|
||||
const reportCountHide = counts && Number.isFinite(counts.trustedReportCount)
|
||||
? Math.max(0, Number(counts.trustedReportCount))
|
||||
: null;
|
||||
|
||||
if (muteCount !== null) {
|
||||
this.root.dataset.moderationHideTrustedMuteCount = String(muteCount);
|
||||
} else if (this.root.dataset.moderationHideTrustedMuteCount) {
|
||||
delete this.root.dataset.moderationHideTrustedMuteCount;
|
||||
}
|
||||
|
||||
if (reportCountHide !== null) {
|
||||
this.root.dataset.moderationHideTrustedReportCount = String(reportCountHide);
|
||||
} else if (this.root.dataset.moderationHideTrustedReportCount) {
|
||||
delete this.root.dataset.moderationHideTrustedReportCount;
|
||||
}
|
||||
} else {
|
||||
if (this.root.dataset.moderationHidden) {
|
||||
delete this.root.dataset.moderationHidden;
|
||||
}
|
||||
if (this.root.dataset.moderationHideReason) {
|
||||
delete this.root.dataset.moderationHideReason;
|
||||
}
|
||||
if (this.root.dataset.moderationHideTrustedMuteCount) {
|
||||
delete this.root.dataset.moderationHideTrustedMuteCount;
|
||||
}
|
||||
if (this.root.dataset.moderationHideTrustedReportCount) {
|
||||
delete this.root.dataset.moderationHideTrustedReportCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
applyPlaybackDatasets() {
|
||||
|
||||
@@ -137,7 +137,14 @@ test("VideoCard renders moderation badges and respects viewer override", async (
|
||||
assert.equal(card.thumbnailEl.dataset.thumbnailState, "blurred");
|
||||
assert.equal(card.getRoot().dataset.moderationReportCount, "3");
|
||||
assert.ok(card.moderationBadgeEl);
|
||||
assert.equal(card.moderationBadgeEl.dataset.moderationState, "blocked");
|
||||
assert.equal(card.moderationBadgeEl.dataset.moderationState, "hidden");
|
||||
assert.equal(card.getRoot().dataset.moderationHidden, "true");
|
||||
assert.equal(card.getRoot().dataset.moderationHideReason, "trusted-report-hide");
|
||||
assert.equal(card.getRoot().dataset.moderationHideTrustedReportCount, "3");
|
||||
assert.ok(card.hiddenSummaryEl);
|
||||
assert.equal(card.hiddenSummaryEl.parentElement, card.getRoot());
|
||||
assert.equal(card.anchorEl.hasAttribute("hidden"), true);
|
||||
assert.equal(card.contentEl.hasAttribute("hidden"), true);
|
||||
assert.ok(card.moderationActionButton);
|
||||
|
||||
card.onModerationOverride = ({ video: overrideVideo }) => {
|
||||
@@ -160,5 +167,11 @@ test("VideoCard renders moderation badges and respects viewer override", async (
|
||||
assert.equal(card.getRoot().dataset.moderationOverride, "show-anyway");
|
||||
assert.equal(card.thumbnailEl.dataset.thumbnailState, undefined);
|
||||
assert.equal(card.moderationBadgeEl.dataset.moderationState, "override");
|
||||
assert.equal(card.getRoot().dataset.moderationHidden, undefined);
|
||||
assert.equal(card.getRoot().dataset.moderationHideReason, undefined);
|
||||
assert.equal(card.getRoot().dataset.moderationHideTrustedReportCount, undefined);
|
||||
assert.equal(card.anchorEl.hasAttribute("hidden"), false);
|
||||
assert.equal(card.contentEl.hasAttribute("hidden"), false);
|
||||
assert.ok(!card.hiddenSummaryEl || card.hiddenSummaryEl.parentElement !== card.getRoot());
|
||||
assert.ok(card.moderationBadgeEl.textContent.includes("Showing despite"));
|
||||
});
|
||||
Reference in new issue
Block a user