yt-playlist-features/src/content/ui/lifecycle.ts
2026-04-09 03:00:56 +09:00

60 lines
1.7 KiB
TypeScript

import type { PlaylistData, PlaylistVideo } from "../../types/playlist";
import { injectStyles } from "./styles";
import { renderPlaylistTable, type PlaylistTableHandle } from "./table-renderer";
const CONTAINER_ID = "ytpf-playlist-table";
let currentHandle: PlaylistTableHandle | null = null;
export function mountTable(data: PlaylistData): void {
unmountTable();
injectStyles();
currentHandle = renderPlaylistTable(data);
const el = currentHandle.element;
el.id = CONTAINER_ID;
// Primary: before ytd-playlist-video-list-renderer (sibling)
const videoList = document.querySelector("ytd-playlist-video-list-renderer");
if (videoList?.parentElement) {
videoList.parentElement.insertBefore(el, videoList);
return;
}
// Fallback: end of ytd-section-list-renderer > #contents
const sectionContents = document.querySelector(
"ytd-section-list-renderer > #contents",
);
if (sectionContents) {
sectionContents.appendChild(el);
return;
}
// Last resort: #primary
const primary = document.querySelector(
"ytd-two-column-browse-results-renderer > #primary",
);
if (primary) {
primary.appendChild(el);
return;
}
console.warn("[yt-playlist-features] Could not find anchor to mount table");
}
export function appendToTable(newVideos: PlaylistVideo[]): void {
currentHandle?.appendVideos(newVideos);
}
export function setTableComplete(extractedCount: number): void {
currentHandle?.setComplete(extractedCount);
}
export function unmountTable(): void {
currentHandle = null;
document.getElementById(CONTAINER_ID)?.remove();
}
// Auto-cleanup on SPA navigation
document.addEventListener("yt-navigate-start", unmountTable);