import { Popover, Transition } from '@headlessui/react' import { ActionButton, ActionButtonProps } from './ActionButton' import { type IndexLoaderData } from 'lib/types' import { PATHS } from 'lib/paths' import { isDesktop } from '../lib/isDesktop' import { Link, useLocation, useNavigate } from 'react-router-dom' import { Fragment, useMemo, useContext } from 'react' import { Logo } from './Logo' import { APP_NAME } from 'lib/constants' import { useCommandsContext } from 'hooks/useCommandsContext' import { CustomIcon } from './CustomIcon' import { useLspContext } from './LspProvider' import { engineCommandManager, kclManager } from 'lib/singletons' import { MachineManagerContext } from 'components/MachineManagerProvider' import usePlatform from 'hooks/usePlatform' import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath' import Tooltip from './Tooltip' const ProjectSidebarMenu = ({ project, file, enableMenu = false, }: { enableMenu?: boolean project?: IndexLoaderData['project'] file?: IndexLoaderData['file'] }) => { // Make room for traffic lights on desktop left side. // TODO: make sure this doesn't look like shit on Linux or Windows const trafficLightsOffset = isDesktop() && window.electron.os.isMac ? 'ml-20' : '' return (
{enableMenu ? ( ) : ( {project?.name ? project.name : APP_NAME} )}
) } function AppLogoLink({ project, file, }: { project?: IndexLoaderData['project'] file?: IndexLoaderData['file'] }) { const { onProjectClose } = useLspContext() const wrapperClassName = "relative h-full grid place-content-center group p-1.5 before:block before:content-[''] before:absolute before:inset-0 before:bottom-2.5 before:z-[-1] before:bg-primary before:rounded-b-sm" const logoClassName = 'w-auto h-4 text-chalkboard-10' return isDesktop() ? ( { onProjectClose(file || null, project?.path || null, false) kclManager.switchedFiles = true }} to={PATHS.HOME} className={wrapperClassName + ' hover:before:brightness-110'} > {APP_NAME} ) : (
{APP_NAME}
) } function ProjectMenuPopover({ project, file, }: { project?: IndexLoaderData['project'] file?: IndexLoaderData['file'] }) { const platform = usePlatform() const location = useLocation() const navigate = useNavigate() const filePath = useAbsoluteFilePath() const machineManager = useContext(MachineManagerContext) const { commandBarState, commandBarSend } = useCommandsContext() const { onProjectClose } = useLspContext() const exportCommandInfo = { name: 'Export', groupId: 'modeling' } const makeCommandInfo = { name: 'Make', groupId: 'modeling' } const findCommand = (obj: { name: string; groupId: string }) => Boolean( commandBarState.context.commands.find( (c) => c.name === obj.name && c.groupId === obj.groupId ) ) const machineCount = machineManager.machines.length // We filter this memoized list so that no orphan "break" elements are rendered. const projectMenuItems = useMemo<(ActionButtonProps | 'break')[]>( () => [ { id: 'settings', Element: 'button', children: ( <> Project settings {`${platform === 'macos' ? '⌘' : 'Ctrl'}${ isDesktop() ? '' : '⬆' },`} ), onClick: () => { const targetPath = location.pathname.includes(PATHS.FILE) ? filePath + PATHS.SETTINGS_PROJECT : PATHS.HOME + PATHS.SETTINGS_PROJECT navigate(targetPath) }, }, 'break', { id: 'export', Element: 'button', children: ( <> Export current part {!findCommand(exportCommandInfo) && ( Awaiting engine connection )} ), disabled: !findCommand(exportCommandInfo), onClick: () => commandBarSend({ type: 'Find and select command', data: exportCommandInfo, }), }, 'break', { id: 'make', Element: 'button', className: !isDesktop() ? 'hidden' : '', children: ( <> Make current part {!findCommand(makeCommandInfo) && ( Awaiting engine connection )} ), disabled: !findCommand(makeCommandInfo) || machineCount === 0, onClick: () => { commandBarSend({ type: 'Find and select command', data: makeCommandInfo, }) }, }, 'break', { id: 'go-home', Element: 'button', children: 'Go to Home', className: !isDesktop() ? 'hidden' : '', onClick: () => { onProjectClose(file || null, project?.path || null, true) kclManager.switchedFiles = true }, }, ].filter( (props) => props === 'break' || (typeof props !== 'string' && !props.className?.includes('hidden')) ) as (ActionButtonProps | 'break')[], [ platform, findCommand, commandBarSend, engineCommandManager, onProjectClose, isDesktop, ] ) return (
{isDesktop() && file?.name ? file.name.slice( file.name.lastIndexOf(window.electron.path.sep) + 1 ) : APP_NAME} {isDesktop() && project?.name && ( {project.name} )}
{({ close }) => (
    {projectMenuItems.map((props, index) => { if (props === 'break') { return index !== projectMenuItems.length - 1 ? (

  • ) : null } const { id, className, children, ...rest } = props return (
  • { close() }} > {children}
  • ) })}
)}
) } export default ProjectSidebarMenu