// js/viewManager.js import { initChannelProfileView } from "./channelProfile.js"; import { subscriptions } from "./subscriptions.js"; import { getApplication } from "./applicationContext.js"; import { ASSET_VERSION } from "../config/asset-version.js"; import { applyDesignSystemAttributes } from "./designSystem.js"; const TRACKING_SCRIPT_PATTERN = /(?:^|\/)tracking\.js(?:$|\?)/; const withAssetVersion = (url) => { if (typeof url !== "string" || url.length === 0) { return url; } const separator = url.includes("?") ? "&" : "?"; return `${url}${separator}v=${encodeURIComponent(ASSET_VERSION)}`; }; /** * Load a partial view by URL into the #viewContainer. */ export async function loadView(viewUrl) { try { const app = getApplication(); if (app && typeof app.prepareForViewLoad === "function") { app.prepareForViewLoad(); } const res = await fetch(withAssetVersion(viewUrl), { cache: "no-store" }); if (!res.ok) { throw new Error(`Failed to load view: ${res.status}`); } const text = await res.text(); // Use a DOMParser to extract the body contents const parser = new DOMParser(); const doc = parser.parseFromString(text, "text/html"); const container = document.getElementById("viewContainer"); container.innerHTML = doc.body.innerHTML; applyDesignSystemAttributes(container); // Copy and execute any inline scripts const scriptTags = doc.querySelectorAll("script"); scriptTags.forEach((oldScript) => { const src = oldScript.getAttribute("src") || ""; if (src && TRACKING_SCRIPT_PATTERN.test(src)) { return; } const newScript = document.createElement("script"); Array.from(oldScript.attributes).forEach((attr) => { newScript.setAttribute(attr.name, attr.value); }); newScript.textContent = oldScript.textContent; container.appendChild(newScript); }); } catch (err) { console.error("View loading error:", err); const fallbackMarkup = `

Failed to load content.

`; const fallbackContainer = document.getElementById("viewContainer"); if (fallbackContainer) { fallbackContainer.innerHTML = fallbackMarkup; applyDesignSystemAttributes(fallbackContainer); } } } /** * Registry of view-specific initialization functions. */ export const viewInitRegistry = { "most-recent-videos": () => { const app = getApplication(); if (app && typeof app.loadVideos === "function") { if (typeof app.mountVideoListView === "function") { app.mountVideoListView(); } app.loadVideos(); } // Force profile updates after the new view is in place. const refreshApp = getApplication(); if (refreshApp && typeof refreshApp.forceRefreshAllProfiles === "function") { refreshApp.forceRefreshAllProfiles(); } }, explore: () => { console.log("Explore view loaded."); }, history: async () => { try { const module = await import("./historyView.js"); if (typeof module.initHistoryView === "function") { await module.initHistoryView(); } } catch (error) { console.error("Failed to initialize history view:", error); } }, /** * Subscriptions view: * - If user is logged in, calls subscriptions.showSubscriptionVideos * which loads subs if needed and renders the video grid in #subscriptionsVideoList */ subscriptions: async () => { console.log("Subscriptions view loaded."); const app = getApplication(); if (!app?.pubkey) { const container = document.getElementById("subscriptionsVideoList"); if (container) { container.innerHTML = "

Please log in to see your subscriptions.

"; } return; } // If user is logged in, let the SubscriptionsManager do everything: await subscriptions.showSubscriptionVideos( app.pubkey, "subscriptionsVideoList" ); }, "channel-profile": () => { // Call the initialization function from channelProfile.js initChannelProfileView(); }, };