import { memo, ReactNode, useCallback, forwardRef } from 'react' import { Dropdown as BS3Dropdown, MenuItem, MenuItemProps, } from 'react-bootstrap' import { Spinner } from 'react-bootstrap-5' import { Dropdown, DropdownItem, DropdownMenu, DropdownToggle, DropdownToggleCustom, } from '@/features/ui/components/bootstrap-5/dropdown-menu' import { Trans, useTranslation } from 'react-i18next' import Tooltip from '../../../shared/components/tooltip' import Icon from '../../../shared/components/icon' import IconChecked from '../../../shared/components/icon-checked' import ControlledDropdown from '../../../shared/components/controlled-dropdown' import { IdeLayout, IdeView, useLayoutContext, } from '../../../shared/context/layout-context' import * as eventTracking from '../../../infrastructure/event-tracking' import useEventListener from '../../../shared/hooks/use-event-listener' import { DetachRole } from '@/shared/context/detach-context' import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' import MaterialIcon from '@/shared/components/material-icon' import OLTooltip from '@/features/ui/components/ol/ol-tooltip' function IconPlaceholder() { return } function IconRefresh() { return } function IconLayout() { return } function IconSplit() { return } function IconDetach() { return } function IconEditorOnly() { return } function IconPdfOnly() { return } const isActiveDropdownItem = ({ iconFor, pdfLayout, view, detachRole, }: { iconFor: string pdfLayout: IdeLayout view: IdeView | null detachRole?: DetachRole }) => { if (detachRole === 'detacher' || view === 'history') { return false } if ( iconFor === 'editorOnly' && pdfLayout === 'flat' && (view === 'editor' || view === 'file') ) { return true } else if (iconFor === 'pdfOnly' && pdfLayout === 'flat' && view === 'pdf') { return true } else if (iconFor === 'sideBySide' && pdfLayout === 'sideBySide') { return true } return false } function IconCheckmark(props: Parameters[0]) { return isActiveDropdownItem(props) ? : } function LayoutMenuItem({ checkmark, icon, text, ...props }: { checkmark: ReactNode icon: ReactNode text: string | ReactNode } & MenuItemProps) { return (
{checkmark}
{icon}
{text}
) } function EnhancedDropdownItem({ active, ...props }: React.ComponentProps) { return ( ) } const LayoutDropdownToggleButton = forwardRef< HTMLButtonElement, { onClick: (e: React.MouseEvent) => void } >(({ onClick, ...props }, ref) => { const handleClick = (e: React.MouseEvent) => { eventTracking.sendMB('navigation-clicked-layout') onClick(e) } return }) LayoutDropdownToggleButton.displayName = 'LayoutDropdownToggleButton' function BS3DetachDisabled() { const { t } = useTranslation() return ( } icon={} text={t('pdf_in_separate_tab')} /> ) } function BS5DetachDisabled() { const { t } = useTranslation() return ( {t('pdf_in_separate_tab')} ) } function LayoutDropdownButton() { const { reattach, detach, detachIsLinked, detachRole, changeLayout, view, pdfLayout, } = useLayoutContext() const handleDetach = useCallback(() => { detach() eventTracking.sendMB('project-layout-detach') }, [detach]) const handleReattach = useCallback(() => { if (detachRole !== 'detacher') { return } reattach() eventTracking.sendMB('project-layout-reattach') }, [detachRole, reattach]) // reattach when the PDF pane opens useEventListener('ui:pdf-open', handleReattach) const handleChangeLayout = useCallback( (newLayout: IdeLayout, newView?: IdeView) => { handleReattach() changeLayout(newLayout, newView) eventTracking.sendMB('project-layout-change', { layout: newLayout, view: newView, }) }, [changeLayout, handleReattach] ) return ( ) } type LayoutDropdownButtonUiProps = { processing: boolean handleChangeLayout: (newLayout: IdeLayout, newView?: IdeView) => void handleDetach: () => void detachIsLinked: boolean detachRole: DetachRole pdfLayout: IdeLayout view: IdeView | null detachable: boolean } export const LayoutDropdownButtonUi = ({ processing, handleChangeLayout, handleDetach, detachIsLinked, detachRole, view, pdfLayout, detachable, }: LayoutDropdownButtonUiProps) => { const { t } = useTranslation() return ( <> {processing && (
{t('layout_processing')}
)} { eventTracking.sendMB('navigation-clicked-layout') }} className="toolbar-item layout-dropdown" pullRight > {/* bsStyle is required for Dropdown.Toggle, but we will override style */} {processing ? : } {t('layout')} handleChangeLayout('sideBySide')} checkmark={ } icon={} text={t('editor_and_pdf')} /> handleChangeLayout('flat', 'editor')} checkmark={ } icon={} text={ , ]} /> } /> handleChangeLayout('flat', 'pdf')} checkmark={ } icon={} text={ , ]} /> } /> {detachable ? ( handleDetach()} checkmark={ detachRole === 'detacher' ? ( detachIsLinked ? ( ) : ( ) ) : ( ) } icon={} text={t('pdf_in_separate_tab')} /> ) : ( )} } bs5={ {processing ? ( handleChangeLayout('sideBySide')} active={isActiveDropdownItem({ iconFor: 'sideBySide', pdfLayout, view, detachRole, })} leadingIcon="dock_to_right" > {t('editor_and_pdf')} handleChangeLayout('flat', 'editor')} active={isActiveDropdownItem({ iconFor: 'editorOnly', pdfLayout, view, detachRole, })} leadingIcon="code" >
, ]} />
handleChangeLayout('flat', 'pdf')} active={isActiveDropdownItem({ iconFor: 'pdfOnly', pdfLayout, view, detachRole, })} leadingIcon="picture_as_pdf" >
, ]} />
{detachable ? ( handleDetach()} active={detachRole === 'detacher' && detachIsLinked} trailingIcon={ detachRole === 'detacher' ? ( detachIsLinked ? ( 'check' ) : ( ) ) : null } leadingIcon="select_window" > {t('pdf_in_separate_tab')} ) : ( )}
} /> ) } export default memo(LayoutDropdownButton)