[decompose] extract helpers from js/ui/components/VideoModal.js

Decomposed js/ui/components/VideoModal.js by extracting "Similar Video" and "Pointer Key" logic into a new helper module js/ui/components/VideoModalSimilarHelpers.js.

- Reduced VideoModal.js line count from 6334 to 6045.
- Added comprehensive unit tests for extracted helpers.
- Updated check-file-size.mjs baseline.

Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
google-labs-jules[bot]andPR0M3TH3AN committed 2026-02-14 11:46:47 +00:00
1 parent 288beb424f
commit 54be0efcac
9 files changed
+576 -312

No files matched your search

+22 -311
View File
@@ -22,6 +22,12 @@ import {
trimTagPillStripToFit,
} from "./tagPillList.js";
import { SimilarContentCard } from "./SimilarContentCard.js";
import {
buildSimilarCardIdentity,
prepareSimilarVideoCard,
attachSimilarCardViewCounter,
derivePointerKeyFromInput,
} from "./VideoModalSimilarHelpers.js";
import {
subscribeToVideoViewCount,
unsubscribeFromVideoViewCount,
@@ -3878,7 +3884,7 @@ export class VideoModal {
}
if (!key && pointer) {
key = this.derivePointerKeyFromInput(pointer);
key = derivePointerKeyFromInput(pointer);
}
return Boolean(key);
@@ -5589,9 +5595,13 @@ export class VideoModal {
Boolean(item?.capabilities?.canEdit),
};
const identity = this.buildSimilarCardIdentity(
const identity = buildSimilarCardIdentity(
baseVideo,
item?.identity || null
item?.identity || null,
{
helpers: this.helpers,
defaultAvatar: this.DEFAULT_PROFILE_AVATAR,
}
);
let card;
@@ -5616,10 +5626,13 @@ export class VideoModal {
}
const cardIndex = renderedCards.length;
this.prepareSimilarVideoCard(
prepareSimilarVideoCard(
card,
{ video: baseVideo, pointerInfo, shareUrl },
cardIndex
cardIndex,
{
dispatchCallback: (type, detail) => this.dispatch(type, detail),
}
);
// Wire up moderation callbacks
@@ -5653,9 +5666,10 @@ export class VideoModal {
fragment.appendChild(listItem);
renderedCards.push(card);
const viewSubscription = this.attachSimilarCardViewCounter(
const viewSubscription = attachSimilarCardViewCounter(
card,
pointerInfo
pointerInfo,
{ logger: this }
);
if (viewSubscription) {
viewSubscriptions.push(viewSubscription);
@@ -5979,315 +5993,12 @@ export class VideoModal {
}
if (!key) {
key = this.derivePointerKeyFromInput(pointer);
key = derivePointerKeyFromInput(pointer);
}
return { pointer, key };
}
derivePointerKeyFromInput(pointer) {
if (!pointer) {
return "";
}
if (Array.isArray(pointer)) {
const [type, value] = pointer;
if (typeof value === "string" && value.trim()) {
const normalizedType = type === "a" ? "a" : "e";
return `${normalizedType}:${value.trim()}`;
}
return "";
}
if (typeof pointer === "object") {
if (typeof pointer.key === "string" && pointer.key.trim()) {
return pointer.key.trim();
}
if (
typeof pointer.pointerKey === "string" &&
pointer.pointerKey.trim()
) {
return pointer.pointerKey.trim();
}
if (
typeof pointer.type === "string" &&
typeof pointer.value === "string" &&
pointer.value.trim()
) {
const normalizedType = pointer.type === "a" ? "a" : "e";
return `${normalizedType}:${pointer.value.trim()}`;
}
if (Array.isArray(pointer.tag)) {
return this.derivePointerKeyFromInput(pointer.tag);
}
return "";
}
if (typeof pointer === "string") {
const trimmed = pointer.trim();
if (!trimmed) {
return "";
}
if (/^(?:naddr|nevent)/i.test(trimmed)) {
return "";
}
if (trimmed.includes(":")) {
return trimmed;
}
return `e:${trimmed}`;
}
return "";
}
prepareSimilarVideoCard(card, meta, index) {
if (!card) {
return;
}
const pointerInfo = meta?.pointerInfo || null;
const shareUrl = typeof meta?.shareUrl === "string" ? meta.shareUrl : "#";
const fallbackVideo = meta?.video || null;
card.onPlay = ({ event, video: selectedVideo, card: sourceCard }) => {
this.dispatch("similar:select", {
event,
video: selectedVideo || fallbackVideo,
card: sourceCard || card,
index,
pointerInfo: pointerInfo,
shareUrl,
});
};
if (card.moreMenuButton) {
const button = card.moreMenuButton;
const parent = button.parentElement;
if (parent) {
parent.removeChild(button);
if (!parent.childElementCount) {
parent.remove();
}
} else {
button.remove();
}
card.moreMenuButton = null;
}
}
buildSimilarCardIdentity(video, overrides) {
const override = overrides && typeof overrides === "object" ? overrides : {};
const pubkeyCandidates = [
override.pubkey,
video?.pubkey,
video?.author?.pubkey,
video?.creator?.pubkey,
];
let pubkey = "";
for (const candidate of pubkeyCandidates) {
if (typeof candidate !== "string") {
continue;
}
const trimmed = candidate.trim();
if (trimmed) {
pubkey = trimmed;
break;
}
}
const npubCandidates = [
override.npub,
video?.npub,
video?.authorNpub,
video?.creatorNpub,
video?.profile?.npub,
];
let npub = "";
for (const candidate of npubCandidates) {
if (typeof candidate !== "string") {
continue;
}
const trimmed = candidate.trim();
if (trimmed) {
npub = trimmed;
break;
}
}
if (!npub && pubkey) {
try {
const encoded = this.helpers.safeEncodeNpub(pubkey);
if (typeof encoded === "string" && encoded.trim()) {
npub = encoded.trim();
}
} catch {
/* noop */
}
}
const shortNpubCandidates = [override.shortNpub, video?.shortNpub];
let shortNpub = "";
for (const candidate of shortNpubCandidates) {
if (typeof candidate !== "string") {
continue;
}
const trimmed = candidate.trim();
if (trimmed) {
shortNpub = trimmed;
break;
}
}
if (!shortNpub && npub) {
shortNpub = this.helpers.formatShortNpub(npub) || npub;
}
const nameCandidates = [
override.name,
override.displayName,
override.username,
video?.authorName,
video?.creatorName,
video?.creator?.name,
video?.author?.name,
video?.profile?.display_name,
video?.profile?.name,
video?.profile?.username,
];
let name = "";
for (const candidate of nameCandidates) {
if (typeof candidate !== "string") {
continue;
}
const trimmed = candidate.trim();
if (!trimmed) {
continue;
}
if (HEX64_REGEX.test(trimmed)) {
continue;
}
name = trimmed;
break;
}
if (!name && shortNpub) {
name = shortNpub;
}
if (!name && npub) {
name = npub;
}
const pictureCandidates = [
override.picture,
override.image,
override.photo,
video?.picture,
video?.authorPicture,
video?.creatorPicture,
video?.author?.picture,
video?.creator?.picture,
video?.profile?.picture,
];
let picture = "";
for (const candidate of pictureCandidates) {
if (typeof candidate !== "string") {
continue;
}
const trimmed = candidate.trim();
if (!trimmed) {
continue;
}
const sanitized = sanitizeProfileMediaUrl(trimmed);
if (sanitized) {
picture = sanitized;
break;
}
}
if (!picture && pubkey) {
const robohash = `https://robohash.org/${pubkey}`;
picture = sanitizeProfileMediaUrl(robohash) || robohash;
}
if (!picture) {
const fallbackAvatar =
typeof this.DEFAULT_PROFILE_AVATAR === "string" &&
this.DEFAULT_PROFILE_AVATAR.trim()
? this.DEFAULT_PROFILE_AVATAR.trim()
: "assets/svg/default-profile.svg";
picture = sanitizeProfileMediaUrl(fallbackAvatar) || fallbackAvatar;
}
return {
name,
npub,
shortNpub,
pubkey,
picture,
};
}
attachSimilarCardViewCounter(card, pointerInfo) {
if (!card || typeof card.getViewCountElement !== "function") {
return null;
}
const viewEl = card.getViewCountElement();
if (!viewEl) {
return null;
}
if (pointerInfo?.key) {
viewEl.dataset.viewPointer = pointerInfo.key;
} else if (viewEl.dataset?.viewPointer) {
delete viewEl.dataset.viewPointer;
}
if (!pointerInfo || !pointerInfo.pointer) {
viewEl.textContent = "– views";
return null;
}
viewEl.textContent = "Loading views…";
try {
const token = subscribeToVideoViewCount(
pointerInfo.pointer,
({ total, status, partial }) => {
if (!viewEl || !viewEl.isConnected) {
return;
}
viewEl.textContent = this.getViewCountLabel(total, status, partial);
if (partial) {
viewEl.dataset.viewCountState = "partial";
} else {
viewEl.dataset.viewCountState = status;
}
}
);
return { pointer: pointerInfo.pointer, token };
} catch (error) {
this.log("[VideoModal] Failed to subscribe similar view counter", error);
viewEl.textContent = "– views";
return null;
}
}
getViewCountLabel(total, status, partial) {
if (Number.isFinite(total)) {
const label = this.formatViewCountLabel(Number(total));
return partial ? `${label} (partial)` : label;
}
if (status === "hydrating") {
return "Loading…";
}
return "–";
}
formatViewCountLabel(total) {
const numeric = Number.isFinite(total) ? Math.max(0, Number(total)) : 0;
return formatViewCount(numeric);
}
syncMoreMenuData({ currentVideo, canManageBlacklist }) {
this.modalMoreMenuContext.video = currentVideo || null;
this.modalMoreMenuContext.canManageBlacklist = !!canManageBlacklist;