mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-28 16:32:28 +00:00
Refactor popular tag strip rendering
This commit is contained in:
1 parent
e29a93cc88
commit
a3a49742ca
3 files changed
+365
-272
No files matched your search
@@ -0,0 +1,327 @@
|
||||
import { userLogger } from "../../utils/logger.js";
|
||||
import { collectVideoTags } from "../../utils/videoTags.js";
|
||||
import {
|
||||
applyTagPreferenceState,
|
||||
renderTagPillStrip,
|
||||
trimTagPillStripToFit,
|
||||
} from "./tagPillList.js";
|
||||
|
||||
export class HashtagStripHelper {
|
||||
constructor({ document: doc = null, window: win = null, logger } = {}) {
|
||||
this.document = doc || (typeof document !== "undefined" ? document : null);
|
||||
this.window = win || this.document?.defaultView ||
|
||||
(typeof window !== "undefined" ? window : null);
|
||||
this.logger = logger || userLogger;
|
||||
|
||||
this.container = null;
|
||||
this._tagStrip = null;
|
||||
this._sortedTags = [];
|
||||
this._resizeObserver = null;
|
||||
this._resizeHandler = null;
|
||||
this._resizeCancel = null;
|
||||
this._resizeScheduled = false;
|
||||
this._isApplyingTrim = false;
|
||||
|
||||
this.tagStateResolver = null;
|
||||
this.activateHandler = null;
|
||||
|
||||
this._handleResize = () => {
|
||||
if (this._isApplyingTrim) {
|
||||
return;
|
||||
}
|
||||
this.render();
|
||||
};
|
||||
}
|
||||
|
||||
mount(container) {
|
||||
if (this.container === container) {
|
||||
return this.container;
|
||||
}
|
||||
|
||||
this._teardownResizeObserver();
|
||||
|
||||
if (this.container && this.container !== container) {
|
||||
this.container.textContent = "";
|
||||
this.container.hidden = true;
|
||||
}
|
||||
|
||||
this.container = container || null;
|
||||
this._tagStrip = null;
|
||||
|
||||
if (this.container) {
|
||||
this.container.textContent = "";
|
||||
this.container.hidden = true;
|
||||
if (this._sortedTags.length) {
|
||||
this.render();
|
||||
this._ensureResizeObserver();
|
||||
}
|
||||
}
|
||||
|
||||
return this.container;
|
||||
}
|
||||
|
||||
update(videos) {
|
||||
const root = this.container;
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Array.isArray(videos) || videos.length === 0) {
|
||||
this._sortedTags = [];
|
||||
this.render();
|
||||
this._teardownResizeObserver();
|
||||
return;
|
||||
}
|
||||
|
||||
const counts = new Map();
|
||||
const displayNames = new Map();
|
||||
|
||||
videos.forEach((video) => {
|
||||
const tags = collectVideoTags(video);
|
||||
tags.forEach((tag) => {
|
||||
if (typeof tag !== "string" || !tag) {
|
||||
return;
|
||||
}
|
||||
const lower = tag.toLowerCase();
|
||||
counts.set(lower, (counts.get(lower) || 0) + 1);
|
||||
if (!displayNames.has(lower)) {
|
||||
displayNames.set(lower, tag);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (!counts.size) {
|
||||
this._sortedTags = [];
|
||||
this.render();
|
||||
this._teardownResizeObserver();
|
||||
return;
|
||||
}
|
||||
|
||||
const tagEntries = Array.from(counts.entries()).map(([lower, count]) => ({
|
||||
count,
|
||||
tag: displayNames.get(lower) || lower,
|
||||
}));
|
||||
|
||||
tagEntries.sort((a, b) => {
|
||||
if (b.count !== a.count) {
|
||||
return b.count - a.count;
|
||||
}
|
||||
const lowerA = a.tag.toLowerCase();
|
||||
const lowerB = b.tag.toLowerCase();
|
||||
if (lowerA === lowerB) {
|
||||
return a.tag.localeCompare(b.tag);
|
||||
}
|
||||
return lowerA.localeCompare(lowerB);
|
||||
});
|
||||
|
||||
this._sortedTags = tagEntries.map((entry) => entry.tag);
|
||||
this.render();
|
||||
if (this._sortedTags.length) {
|
||||
this._ensureResizeObserver();
|
||||
} else {
|
||||
this._teardownResizeObserver();
|
||||
}
|
||||
}
|
||||
|
||||
setTagStateResolver(resolver) {
|
||||
this.tagStateResolver = typeof resolver === "function" ? resolver : null;
|
||||
this.refreshTagStates();
|
||||
}
|
||||
|
||||
setActivateHandler(handler) {
|
||||
this.activateHandler = typeof handler === "function" ? handler : null;
|
||||
}
|
||||
|
||||
refreshTagStates() {
|
||||
if (!this._tagStrip) {
|
||||
return;
|
||||
}
|
||||
|
||||
const buttons = this._tagStrip.querySelectorAll("button[data-tag]");
|
||||
buttons.forEach((button) => {
|
||||
const tag = button.dataset.tag || "";
|
||||
const state = this._resolveTagState(tag);
|
||||
applyTagPreferenceState(button, state);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const root = this.container;
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tags = Array.isArray(this._sortedTags) ? [...this._sortedTags] : [];
|
||||
|
||||
this._isApplyingTrim = true;
|
||||
|
||||
try {
|
||||
root.textContent = "";
|
||||
this._tagStrip = null;
|
||||
|
||||
if (!tags.length) {
|
||||
root.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const doc = this.document || root.ownerDocument || null;
|
||||
if (!doc) {
|
||||
root.hidden = true;
|
||||
this._teardownResizeObserver();
|
||||
return;
|
||||
}
|
||||
|
||||
const { root: strip } = renderTagPillStrip({
|
||||
document: doc,
|
||||
tags,
|
||||
onTagActivate: (tag, detail = {}) =>
|
||||
this._handleTagActivate(tag, detail),
|
||||
getTagState: (tag) => this._resolveTagState(tag),
|
||||
});
|
||||
|
||||
root.appendChild(strip);
|
||||
this._tagStrip = strip;
|
||||
trimTagPillStripToFit({ strip, container: root });
|
||||
root.hidden = strip.childElementCount === 0;
|
||||
} finally {
|
||||
this._isApplyingTrim = false;
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this._teardownResizeObserver();
|
||||
if (this.container) {
|
||||
this.container.textContent = "";
|
||||
this.container.hidden = true;
|
||||
}
|
||||
this.container = null;
|
||||
this._tagStrip = null;
|
||||
this._sortedTags = [];
|
||||
this.tagStateResolver = null;
|
||||
this.activateHandler = null;
|
||||
}
|
||||
|
||||
_resolveTagState(tag) {
|
||||
const resolver = this.tagStateResolver;
|
||||
if (typeof resolver !== "function") {
|
||||
return "neutral";
|
||||
}
|
||||
|
||||
try {
|
||||
return resolver(tag);
|
||||
} catch (error) {
|
||||
this.logger?.warn?.(
|
||||
"[HashtagStripHelper] Failed to resolve tag preference state:",
|
||||
error,
|
||||
);
|
||||
return "neutral";
|
||||
}
|
||||
}
|
||||
|
||||
_handleTagActivate(tag, detail) {
|
||||
if (typeof this.activateHandler !== "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.activateHandler(tag, detail);
|
||||
} catch (error) {
|
||||
this.logger?.warn?.(
|
||||
"[HashtagStripHelper] Tag activation handler threw an error:",
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_ensureResizeObserver() {
|
||||
const root = this.container;
|
||||
if (!root || this._resizeObserver || this._resizeHandler) {
|
||||
return;
|
||||
}
|
||||
|
||||
const resizeObserverCtor =
|
||||
(this.window && this.window.ResizeObserver) ||
|
||||
(typeof globalThis !== "undefined" ? globalThis.ResizeObserver : null);
|
||||
|
||||
if (typeof resizeObserverCtor === "function") {
|
||||
this._resizeObserver = new resizeObserverCtor(() => {
|
||||
this._handleResize();
|
||||
});
|
||||
this._resizeObserver.observe(root);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.window) {
|
||||
return;
|
||||
}
|
||||
|
||||
const schedule = (callback) => {
|
||||
if (this._resizeScheduled) {
|
||||
return;
|
||||
}
|
||||
this._resizeScheduled = true;
|
||||
|
||||
if (typeof this.window.requestAnimationFrame === "function") {
|
||||
const frameId = this.window.requestAnimationFrame(() => {
|
||||
this._resizeScheduled = false;
|
||||
this._resizeCancel = null;
|
||||
callback();
|
||||
});
|
||||
this._resizeCancel = () => {
|
||||
this.window.cancelAnimationFrame(frameId);
|
||||
this._resizeCancel = null;
|
||||
this._resizeScheduled = false;
|
||||
};
|
||||
} else {
|
||||
const timeoutId = this.window.setTimeout(() => {
|
||||
this._resizeScheduled = false;
|
||||
this._resizeCancel = null;
|
||||
callback();
|
||||
}, 50);
|
||||
this._resizeCancel = () => {
|
||||
this.window.clearTimeout(timeoutId);
|
||||
this._resizeCancel = null;
|
||||
this._resizeScheduled = false;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const handler = () => {
|
||||
schedule(() => {
|
||||
if (!this.container) {
|
||||
return;
|
||||
}
|
||||
this._handleResize();
|
||||
});
|
||||
};
|
||||
|
||||
this.window.addEventListener("resize", handler);
|
||||
this._resizeHandler = handler;
|
||||
}
|
||||
|
||||
_teardownResizeObserver() {
|
||||
if (this._resizeObserver) {
|
||||
try {
|
||||
this._resizeObserver.disconnect();
|
||||
} catch (error) {
|
||||
// Ignore disconnect errors.
|
||||
}
|
||||
}
|
||||
this._resizeObserver = null;
|
||||
|
||||
if (this._resizeHandler && this.window) {
|
||||
this.window.removeEventListener("resize", this._resizeHandler);
|
||||
}
|
||||
this._resizeHandler = null;
|
||||
|
||||
if (typeof this._resizeCancel === "function") {
|
||||
try {
|
||||
this._resizeCancel();
|
||||
} catch (error) {
|
||||
// Ignore cancellation errors.
|
||||
}
|
||||
}
|
||||
this._resizeCancel = null;
|
||||
this._resizeScheduled = false;
|
||||
}
|
||||
}
|
||||
@@ -17,14 +17,22 @@ export default class VideoListViewController {
|
||||
);
|
||||
}
|
||||
|
||||
mount({ container = null, view, currentVideoList = null, includeTags = true } = {}) {
|
||||
mount({
|
||||
container = null,
|
||||
popularTagsContainer = null,
|
||||
view,
|
||||
currentVideoList = null,
|
||||
includeTags = true,
|
||||
} = {}) {
|
||||
if (!view) {
|
||||
return { videoList: currentVideoList || null, popularTags: null };
|
||||
}
|
||||
|
||||
const target = container || this.getElementById("videoList");
|
||||
let popularTags = null;
|
||||
if (includeTags) {
|
||||
if (this.isElement(popularTagsContainer)) {
|
||||
popularTags = popularTagsContainer;
|
||||
} else if (includeTags) {
|
||||
popularTags = this.getElementById("recentVideoTags");
|
||||
}
|
||||
|
||||
@@ -45,6 +53,7 @@ export default class VideoListViewController {
|
||||
reason,
|
||||
postLoginResult,
|
||||
currentVideoList = null,
|
||||
popularTagsContainer = null,
|
||||
} = {}) {
|
||||
if (!view) {
|
||||
return {
|
||||
@@ -74,7 +83,12 @@ export default class VideoListViewController {
|
||||
? "Applying your filters…"
|
||||
: "Refreshing videos…";
|
||||
|
||||
const tagsRoot = this.getElementById("recentVideoTags");
|
||||
let tagsRoot = null;
|
||||
if (this.isElement(popularTagsContainer)) {
|
||||
tagsRoot = popularTagsContainer;
|
||||
} else {
|
||||
tagsRoot = this.getElementById("recentVideoTags");
|
||||
}
|
||||
if (typeof view.setPopularTagsContainer === "function") {
|
||||
view.setPopularTagsContainer(this.isElement(tagsRoot) ? tagsRoot : null);
|
||||
}
|
||||
|
||||
+21
-269
@@ -1,16 +1,11 @@
|
||||
import { VideoCard } from "../components/VideoCard.js";
|
||||
import {
|
||||
renderTagPillStrip,
|
||||
applyTagPreferenceState,
|
||||
trimTagPillStripToFit,
|
||||
} from "../components/tagPillList.js";
|
||||
import { HashtagStripHelper } from "../components/hashtagStripHelper.js";
|
||||
import {
|
||||
subscribeToVideoViewCount,
|
||||
unsubscribeFromVideoViewCount,
|
||||
} from "../../viewCounter.js";
|
||||
import { normalizeDesignSystemContext } from "../../designSystem.js";
|
||||
import { userLogger } from "../../utils/logger.js";
|
||||
import { collectVideoTags } from "../../utils/videoTags.js";
|
||||
|
||||
const EMPTY_VIDEO_LIST_SIGNATURE = "__EMPTY__";
|
||||
|
||||
@@ -180,20 +175,15 @@ export class VideoListView {
|
||||
this.currentVideos = [];
|
||||
this.lastRenderedVideoSignature = null;
|
||||
this._lastRenderedVideoListElement = null;
|
||||
this.popularTagsRoot = null;
|
||||
this._popularTagStrip = null;
|
||||
this._popularTagsSortedList = [];
|
||||
this._popularTagResizeObserver = null;
|
||||
this._popularTagResizeHandler = null;
|
||||
this._popularTagResizeCancel = null;
|
||||
this._popularTagResizeScheduled = false;
|
||||
this._isApplyingPopularTagTrim = false;
|
||||
this._handlePopularTagResize = () => {
|
||||
if (this._isApplyingPopularTagTrim) {
|
||||
return;
|
||||
}
|
||||
this.renderPopularTagStrip();
|
||||
};
|
||||
|
||||
this.popularTagHelper = new HashtagStripHelper({
|
||||
document: this.document,
|
||||
window: this.window,
|
||||
logger: userLogger,
|
||||
});
|
||||
this.popularTagHelper.setActivateHandler((tag, detail) =>
|
||||
this.handlePopularTagActivate(tag, detail),
|
||||
);
|
||||
|
||||
this.handlers = {
|
||||
playback: null,
|
||||
@@ -207,8 +197,6 @@ export class VideoListView {
|
||||
tagActivate: null,
|
||||
};
|
||||
|
||||
this.tagPreferenceStateResolver = null;
|
||||
|
||||
this.allowNsfw = allowNsfw !== false;
|
||||
this.designSystem = normalizeDesignSystemContext(designSystem);
|
||||
|
||||
@@ -281,14 +269,9 @@ export class VideoListView {
|
||||
this.currentVideos = [];
|
||||
this.lastRenderedVideoSignature = null;
|
||||
this._lastRenderedVideoListElement = null;
|
||||
this._teardownPopularTagResizeObserver();
|
||||
if (this.popularTagsRoot) {
|
||||
this.popularTagsRoot.textContent = "";
|
||||
this.popularTagsRoot.hidden = true;
|
||||
if (this.popularTagHelper) {
|
||||
this.popularTagHelper.destroy();
|
||||
}
|
||||
this.popularTagsRoot = null;
|
||||
this._popularTagStrip = null;
|
||||
this._popularTagsSortedList = [];
|
||||
}
|
||||
|
||||
setPlaybackHandler(handler) {
|
||||
@@ -330,228 +313,21 @@ export class VideoListView {
|
||||
}
|
||||
|
||||
setTagPreferenceStateResolver(resolver) {
|
||||
this.tagPreferenceStateResolver =
|
||||
typeof resolver === "function" ? resolver : null;
|
||||
if (this.popularTagHelper) {
|
||||
this.popularTagHelper.setTagStateResolver(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
setPopularTagsContainer(container) {
|
||||
this._teardownPopularTagResizeObserver();
|
||||
if (this.popularTagsRoot && this.popularTagsRoot !== container) {
|
||||
this.popularTagsRoot.textContent = "";
|
||||
this.popularTagsRoot.hidden = true;
|
||||
}
|
||||
|
||||
this.popularTagsRoot = container || null;
|
||||
this._popularTagStrip = null;
|
||||
|
||||
if (this.popularTagsRoot) {
|
||||
this.popularTagsRoot.textContent = "";
|
||||
this.popularTagsRoot.hidden = true;
|
||||
if (this._popularTagsSortedList.length) {
|
||||
this.renderPopularTagStrip();
|
||||
this._ensurePopularTagResizeObserver();
|
||||
}
|
||||
if (this.popularTagHelper) {
|
||||
this.popularTagHelper.mount(container || null);
|
||||
}
|
||||
}
|
||||
|
||||
updatePopularTags(videos) {
|
||||
const root = this.popularTagsRoot;
|
||||
if (!root) {
|
||||
return;
|
||||
if (this.popularTagHelper) {
|
||||
this.popularTagHelper.update(videos);
|
||||
}
|
||||
|
||||
if (!Array.isArray(videos) || videos.length === 0) {
|
||||
this._popularTagsSortedList = [];
|
||||
this.renderPopularTagStrip();
|
||||
this._teardownPopularTagResizeObserver();
|
||||
return;
|
||||
}
|
||||
|
||||
const counts = new Map();
|
||||
const displayNames = new Map();
|
||||
|
||||
videos.forEach((video) => {
|
||||
const tags = collectVideoTags(video);
|
||||
tags.forEach((tag) => {
|
||||
if (typeof tag !== "string" || !tag) {
|
||||
return;
|
||||
}
|
||||
const lower = tag.toLowerCase();
|
||||
counts.set(lower, (counts.get(lower) || 0) + 1);
|
||||
if (!displayNames.has(lower)) {
|
||||
displayNames.set(lower, tag);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (!counts.size) {
|
||||
this._popularTagsSortedList = [];
|
||||
this.renderPopularTagStrip();
|
||||
this._teardownPopularTagResizeObserver();
|
||||
return;
|
||||
}
|
||||
|
||||
const tagEntries = Array.from(counts.entries()).map(([lower, count]) => ({
|
||||
count,
|
||||
tag: displayNames.get(lower) || lower,
|
||||
}));
|
||||
|
||||
tagEntries.sort((a, b) => {
|
||||
if (b.count !== a.count) {
|
||||
return b.count - a.count;
|
||||
}
|
||||
const lowerA = a.tag.toLowerCase();
|
||||
const lowerB = b.tag.toLowerCase();
|
||||
if (lowerA === lowerB) {
|
||||
return a.tag.localeCompare(b.tag);
|
||||
}
|
||||
return lowerA.localeCompare(lowerB);
|
||||
});
|
||||
|
||||
this._popularTagsSortedList = tagEntries.map((entry) => entry.tag);
|
||||
this.renderPopularTagStrip();
|
||||
if (this._popularTagsSortedList.length) {
|
||||
this._ensurePopularTagResizeObserver();
|
||||
} else {
|
||||
this._teardownPopularTagResizeObserver();
|
||||
}
|
||||
}
|
||||
|
||||
renderPopularTagStrip() {
|
||||
const root = this.popularTagsRoot;
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tags = Array.isArray(this._popularTagsSortedList)
|
||||
? [...this._popularTagsSortedList]
|
||||
: [];
|
||||
|
||||
this._isApplyingPopularTagTrim = true;
|
||||
|
||||
try {
|
||||
root.textContent = "";
|
||||
this._popularTagStrip = null;
|
||||
|
||||
if (!tags.length) {
|
||||
root.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const doc = this.document || root.ownerDocument || null;
|
||||
if (!doc) {
|
||||
root.hidden = true;
|
||||
this._teardownPopularTagResizeObserver();
|
||||
return;
|
||||
}
|
||||
|
||||
const { root: strip } = renderTagPillStrip({
|
||||
document: doc,
|
||||
tags,
|
||||
onTagActivate: (tag, detail = {}) =>
|
||||
this.handlePopularTagActivate(tag, detail),
|
||||
getTagState: (tag) => this.resolveTagPreferenceState(tag),
|
||||
});
|
||||
|
||||
root.appendChild(strip);
|
||||
this._popularTagStrip = strip;
|
||||
trimTagPillStripToFit({ strip, container: root });
|
||||
root.hidden = strip.childElementCount === 0;
|
||||
} finally {
|
||||
this._isApplyingPopularTagTrim = false;
|
||||
}
|
||||
}
|
||||
|
||||
_ensurePopularTagResizeObserver() {
|
||||
const root = this.popularTagsRoot;
|
||||
if (!root || this._popularTagResizeObserver || this._popularTagResizeHandler) {
|
||||
return;
|
||||
}
|
||||
|
||||
const resizeObserverCtor =
|
||||
(this.window && this.window.ResizeObserver) ||
|
||||
(typeof globalThis !== "undefined" ? globalThis.ResizeObserver : null);
|
||||
|
||||
if (typeof resizeObserverCtor === "function") {
|
||||
this._popularTagResizeObserver = new resizeObserverCtor(() => {
|
||||
this._handlePopularTagResize();
|
||||
});
|
||||
this._popularTagResizeObserver.observe(root);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.window) {
|
||||
return;
|
||||
}
|
||||
|
||||
const schedule = (callback) => {
|
||||
if (this._popularTagResizeScheduled) {
|
||||
return;
|
||||
}
|
||||
this._popularTagResizeScheduled = true;
|
||||
|
||||
if (typeof this.window.requestAnimationFrame === "function") {
|
||||
const frameId = this.window.requestAnimationFrame(() => {
|
||||
this._popularTagResizeScheduled = false;
|
||||
this._popularTagResizeCancel = null;
|
||||
callback();
|
||||
});
|
||||
this._popularTagResizeCancel = () => {
|
||||
this.window.cancelAnimationFrame(frameId);
|
||||
this._popularTagResizeCancel = null;
|
||||
this._popularTagResizeScheduled = false;
|
||||
};
|
||||
} else {
|
||||
const timeoutId = this.window.setTimeout(() => {
|
||||
this._popularTagResizeScheduled = false;
|
||||
this._popularTagResizeCancel = null;
|
||||
callback();
|
||||
}, 50);
|
||||
this._popularTagResizeCancel = () => {
|
||||
this.window.clearTimeout(timeoutId);
|
||||
this._popularTagResizeCancel = null;
|
||||
this._popularTagResizeScheduled = false;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const handler = () => {
|
||||
schedule(() => {
|
||||
if (!this.popularTagsRoot) {
|
||||
return;
|
||||
}
|
||||
this._handlePopularTagResize();
|
||||
});
|
||||
};
|
||||
|
||||
this.window.addEventListener("resize", handler);
|
||||
this._popularTagResizeHandler = handler;
|
||||
}
|
||||
|
||||
_teardownPopularTagResizeObserver() {
|
||||
if (this._popularTagResizeObserver) {
|
||||
try {
|
||||
this._popularTagResizeObserver.disconnect();
|
||||
} catch (error) {
|
||||
// Ignore disconnect errors.
|
||||
}
|
||||
}
|
||||
this._popularTagResizeObserver = null;
|
||||
|
||||
if (this._popularTagResizeHandler && this.window) {
|
||||
this.window.removeEventListener("resize", this._popularTagResizeHandler);
|
||||
}
|
||||
this._popularTagResizeHandler = null;
|
||||
|
||||
if (typeof this._popularTagResizeCancel === "function") {
|
||||
try {
|
||||
this._popularTagResizeCancel();
|
||||
} catch (error) {
|
||||
// Ignore cancellation errors.
|
||||
}
|
||||
}
|
||||
this._popularTagResizeCancel = null;
|
||||
this._popularTagResizeScheduled = false;
|
||||
}
|
||||
|
||||
render(videos, metadata = null) {
|
||||
@@ -1500,34 +1276,10 @@ export class VideoListView {
|
||||
this.emitSelected(detail);
|
||||
}
|
||||
|
||||
resolveTagPreferenceState(tag) {
|
||||
const resolver = this.tagPreferenceStateResolver;
|
||||
if (typeof resolver !== "function") {
|
||||
return "neutral";
|
||||
}
|
||||
|
||||
try {
|
||||
return resolver(tag);
|
||||
} catch (error) {
|
||||
userLogger.warn(
|
||||
"[VideoListView] Failed to resolve tag preference state:",
|
||||
error,
|
||||
);
|
||||
return "neutral";
|
||||
}
|
||||
}
|
||||
|
||||
refreshTagPreferenceStates() {
|
||||
if (!this._popularTagStrip) {
|
||||
return;
|
||||
if (this.popularTagHelper) {
|
||||
this.popularTagHelper.refreshTagStates();
|
||||
}
|
||||
|
||||
const buttons = this._popularTagStrip.querySelectorAll("button[data-tag]");
|
||||
buttons.forEach((button) => {
|
||||
const tag = button.dataset.tag || "";
|
||||
const state = this.resolveTagPreferenceState(tag);
|
||||
applyTagPreferenceState(button, state);
|
||||
});
|
||||
}
|
||||
|
||||
handlePopularTagActivate(tag, { event = null, button = null } = {}) {
|
||||
|
||||
Reference in new issue
Block a user