import React from "react" import { Menu, Avatar, Button } from "antd" import { Translation } from "react-i18next" import classnames from "classnames" import config from "config" import { Icons, createIconRender } from "components/Icons" import sidebarItems from "schemas/routes.json" import "./index.less" const onClickHandlers = { settings: (event) => { window.app.openSettings() }, } const getSidebarComponents = () => { const items = {} sidebarItems.forEach((item, index) => { if (!item.reachable) { return } items[item.id] = { ...item, index, content: ( <> {createIconRender(item.icon)} {item.title} ), } }) return items } const generateItems = () => { const components = getSidebarComponents() const itemsMap = [] const pathResolvers = {} Object.keys(components).forEach((key, index) => { const component = components[key] if (typeof component.path !== "undefined") { pathResolvers[component.id] = component.path } itemsMap.push(component) }) return { itemsMap, pathResolvers, } } export default class Sidebar extends React.Component { constructor(props) { super(props) this.controller = window.app["SidebarController"] = { toggleVisibility: this.toggleVisibility, toggleElevation: this.toggleElevation, toggleCollapse: this.toggleCollapse, isVisible: () => this.state.visible, isCollapsed: () => this.state.collapsed, setCustomRender: this.setRender, closeCustomRender: this.closeRender, } this.state = { visible: false, elevated: false, collapsed: window.app.settings.get("collapseOnLooseFocus") ?? false, pathResolvers: null, menus: null, customRenderTitle: null, customRender: null, } // handle sidedrawer open/close window.app.eventBus.on("sidedrawer.hasDrawers", () => { this.toggleElevation(true) }) window.app.eventBus.on("sidedrawer.noDrawers", () => { this.toggleElevation(false) }) } collapseDebounce = null componentDidMount = async () => { await this.loadItems() setTimeout(() => { this.controller.toggleVisibility(true) }, 100) } setRender = (render, options = {}) => { if (!typeof render === "function") { throw new Error("Render is required to be a function") } this.setState({ customRenderTitle:
{ options.icon && createIconRender(options.icon) } { options.title &&

{t => t(options.title)}

}
, customRender: React.createElement(render, { ...options.props ?? {}, close: this.closeRender, }) }) } closeRender = () => { this.setState({ customRenderTitle: null, customRender: null, }) } loadItems = async () => { const generation = generateItems() // update states await this.setState({ menus: generation.itemsMap, pathResolvers: generation.pathResolvers, }) } renderMenuItems(items) { const handleRenderIcon = (icon) => { if (typeof icon === "undefined") { return null } return createIconRender(icon) } return items.map((item) => { if (Array.isArray(item.children)) { return {t => t(item.title)} } {...item.props} > {this.renderMenuItems(item.children)} } return {t => t(item.title ?? item.id)} }) } handleClick = (e) => { if (e.item.props.override_event) { return app.eventBus.emit(e.item.props.override_event, e.item.props.override_event_props) } if (typeof e.key === "undefined") { window.app.eventBus.emit("invalidSidebarKey", e) return false } if (typeof onClickHandlers[e.key] === "function") { return onClickHandlers[e.key](e) } if (typeof this.state.pathResolvers === "object") { if (typeof this.state.pathResolvers[e.key] !== "undefined") { return window.app.setLocation(`/${this.state.pathResolvers[e.key]}`, 150) } } return window.app.setLocation(`/${e.key}`, 150) } toggleCollapse = (to) => { if (!this.state.editMode) { this.setState({ collapsed: to ?? !this.state.collapsed }) } } toggleVisibility = (to) => { this.setState({ visible: to ?? !this.state.visible }) } toggleElevation = (to) => { this.setState({ elevated: to ?? !this.state.elevated }) } onMouseEnter = () => { if (!this.state.visible) return if (window.app.settings.is("collapseOnLooseFocus", false)) return clearTimeout(this.collapseDebounce) this.collapseDebounce = null if (this.state.collapsed) { this.toggleCollapse(false) } } handleMouseLeave = () => { if (!this.state.visible) return if (window.app.settings.is("collapseOnLooseFocus", false)) return if (!this.state.collapsed) { this.collapseDebounce = setTimeout(() => { this.toggleCollapse(true) }, window.app.settings.get("autoCollapseDelay") ?? 500) } } render() { if (!this.state.menus) return null return (
{ this.state.customRender &&
{ this.state.customRenderTitle ?? null }
{this.state.customRender}
} { !this.state.customRender && <>
{this.renderMenuItems(this.state.menus)}
} override_event="app.openSearcher" > {(t) => t("Search")} } override_event="app.openCreator" > {(t) => t("Create")} } override_event="app.openNotifications"> {t => t("Notifications")} }> {t => t("Settings")} { app.userData && } { !app.userData && }> {t => t("Login")} }
}
) } }