import { html, render } from "/js/lib/lit-html.js"; import { effect } from "/js/signals.js"; import { linkToLogin } from "/js/navigation.js"; import { sidebarTemplate } from "/js/templates/sidebar.template.js"; import { footerTemplate } from "/js/templates/footer.template.js"; import { PLUGIN_PREVIEW_QUERY_PARAM } from "/js/plugins/pluginService.js"; import { Layout } from "/js/router.js"; import "/js/components/animated-sidebar.js"; import "/js/components/trending-pane.js"; import "/js/components/sidebar-search.js"; import "/js/components/pinned-feeds-pane.js"; import "/js/components/app-icon.js"; function exitPluginPreview() { const url = new URL(window.location.href); url.searchParams.delete(PLUGIN_PREVIEW_QUERY_PARAM); window.location.assign(url.toString()); } function pluginPreviewBannerTemplate({ plugins }) { if (plugins.length === 0) return null; const links = []; plugins.forEach((plugin, index) => { if (index > 0) links.push(", "); links.push( html`${plugin.name}`, ); }); return html`
Preview mode
You are currently previewing community ${links.length === 1 ? "plugin" : "plugins"}: ${links}. Sign in to install.
`; } export function mainLayoutTemplate({ isAuthenticated = true, currentUser, activeNavItem, isNavItemPage = false, numNotifications = 0, numChatNotifications = 0, onClickActiveNavItem, children, onClickComposeButton, pluginService, previewingPlugins = [], onLongPressProfile = null, groupChatLinkService, liveStatusService, dataLayer, }) { return html`
groupChatLinkService.handleAction( e.detail.actionType, e.detail.preview, )} @live-avatar:click=${(e) => liveStatusService.handleAvatarClick(e.detail.did)} >
${sidebarTemplate({ isAuthenticated, currentUser, activeNavItem, isNavItemPage, numNotifications, numChatNotifications, onClickActiveItem: onClickActiveNavItem, onClickComposeButton, pluginSidebarItems: pluginService.getSidebarItems(), onLongPressProfile, })}
${children}
${activeNavItem === "search" ? html`` : html``} ${isAuthenticated ? html`` : ""}
${pluginPreviewBannerTemplate({ plugins: previewingPlugins })} ${footerTemplate({ isAuthenticated, currentUser, activeNavItem, isNavItemPage, numNotifications, numChatNotifications, onClickActiveItem: onClickActiveNavItem, onLongPressProfile, })}
`; } export class MainLayout extends Layout { #container = null; #disposeEffect = null; constructor(context, router) { super(); this.context = context; this.router = router; const pagesEl = document.createElement("div"); pagesEl.id = "pages"; this.slot = pagesEl; } mount(container) { if (this.#container) { throw new Error("MainLayout is already mounted"); } const { isAuthenticated, dataLayer, notificationService, chatNotificationService, postComposerService, accountSwitcherService, pluginService, groupChatLinkService, liveStatusService, profileHoverCardService, auth, } = this.context; const { router, slot } = this; container.id = "main-layout"; this.#container = container; profileHoverCardService?.install(container); const onLongPressProfile = accountSwitcherService && auth.supportsMultipleAccounts() ? () => accountSwitcherService.openAccountSwitcherDialog() : null; // The active page may claim the click by cancelling the event const onClickActiveNavItem = () => { const event = new CustomEvent("active-nav-click", { cancelable: true }); this.dispatchEvent(event); if (!event.defaultPrevented) { window.scrollTo({ top: -1, behavior: "smooth" }); } }; this.#disposeEffect = effect(() => { const currentRoute = router.$currentRoute.get(); const layoutOptions = currentRoute?.options?.layoutOptions ?? {}; const currentUser = dataLayer.derived.$currentUser.get(); const activeNavItem = typeof layoutOptions.activeNavItem === "function" ? layoutOptions.activeNavItem(currentRoute.params) : (layoutOptions.activeNavItem ?? null); // True when this route is the nav item's own page, rather than somewhere // deeper in its section const isNavItemPage = typeof layoutOptions.isNavItemPage === "function" ? layoutOptions.isNavItemPage(currentRoute.params) : (layoutOptions.isNavItemPage ?? false); const previewingPlugins = pluginService.getPreviewPlugins(); render( mainLayoutTemplate({ isAuthenticated, currentUser, activeNavItem, isNavItemPage, numNotifications: notificationService?.$numNotifications.get() ?? null, numChatNotifications: chatNotificationService?.$numNotifications.get() ?? null, onClickActiveNavItem, children: slot, onClickComposeButton: () => postComposerService.composePost({ currentUser }), pluginService, previewingPlugins, onLongPressProfile, groupChatLinkService, liveStatusService, dataLayer, }), container, ); }); } openSidebar() { this.#container?.querySelector("animated-sidebar")?.open(); } dispose() { this.context.profileHoverCardService?.dispose(); this.#disposeEffect?.(); this.#disposeEffect = null; this.#container?.replaceChildren(); this.#container = null; } }