60 lines
1.7 KiB
TypeScript
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);
|