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`
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;
}
}