import { FC, ReactElement, useCallback, useMemo } from 'react' import { Nav, NavLink, Tab, TabContainer } from 'react-bootstrap-5' import MaterialIcon, { AvailableUnfilledIcon, } from '@/shared/components/material-icon' import { Panel } from 'react-resizable-panels' import { useLayoutContext } from '@/shared/context/layout-context' import { ErrorIndicator, ErrorPane } from './errors' import { RailModalKey, RailTabKey, useRailContext, } from '../contexts/rail-context' import FileTreeOutlinePanel from './file-tree-outline-panel' import { ChatIndicator, ChatPane } from './chat/chat' import getMeta from '@/utils/meta' import { HorizontalResizeHandle } from '@/features/ide-react/components/resize/horizontal-resize-handle' import { HorizontalToggler } from '@/features/ide-react/components/resize/horizontal-toggler' import { useTranslation } from 'react-i18next' import classNames from 'classnames' import IntegrationsPanel from './integrations-panel/integrations-panel' import OLButton from '@/features/ui/components/ol/ol-button' import { Dropdown, DropdownDivider, DropdownItem, DropdownMenu, DropdownToggle, } from '@/features/ui/components/bootstrap-5/dropdown-menu' import { RailHelpShowHotkeysModal } from './help/keyboard-shortcuts' import { RailHelpContactUsModal } from './help/contact-us' import { HistorySidebar } from '@/features/ide-react/components/history-sidebar' import DictionarySettingsModal from './settings/editor-settings/dictionary-settings-modal' import OLTooltip from '@/features/ui/components/ol/ol-tooltip' type RailElement = { icon: AvailableUnfilledIcon key: RailTabKey component: ReactElement | null indicator?: ReactElement title: string hide?: boolean } type RailActionButton = { key: string icon: AvailableUnfilledIcon title: string action: () => void } type RailDropdown = { key: string icon: AvailableUnfilledIcon title: string dropdown: ReactElement } type RailAction = RailDropdown | RailActionButton const RAIL_MODALS: { key: RailModalKey modalComponentFunction: FC<{ show: boolean }> }[] = [ { key: 'keyboard-shortcuts', modalComponentFunction: RailHelpShowHotkeysModal, }, { key: 'contact-us', modalComponentFunction: RailHelpContactUsModal, }, { key: 'dictionary', modalComponentFunction: DictionarySettingsModal, }, ] export const RailLayout = () => { const { t } = useTranslation() const { activeModal, selectedTab, openTab, isOpen, setIsOpen, panelRef, handlePaneCollapse, handlePaneExpand, togglePane, setResizing, } = useRailContext() const { view, setLeftMenuShown } = useLayoutContext() const isHistoryView = view === 'history' const railTabs: RailElement[] = useMemo( () => [ { key: 'file-tree', icon: 'description', title: t('file_tree'), component: , }, { key: 'integrations', icon: 'integration_instructions', title: t('integrations'), component: , }, { key: 'review-panel', icon: 'rate_review', title: t('review_panel'), component: null, }, { key: 'chat', icon: 'forum', component: , indicator: , title: t('chat'), hide: !getMeta('ol-chatEnabled'), }, { key: 'errors', icon: 'report', title: t('error_log'), component: , indicator: , }, ], [t] ) const railActions: RailAction[] = useMemo( () => [ { key: 'support', icon: 'help', title: t('help'), dropdown: , }, { key: 'settings', icon: 'settings', title: t('settings'), action: () => setLeftMenuShown(true), }, ], [setLeftMenuShown, t] ) const onTabSelect = useCallback( (key: string | null) => { if (key === selectedTab) { togglePane() } else { // HACK: Apparently the onSelect event is triggered with href attributes // from DropdownItems if (!railTabs.some(tab => !tab.hide && tab.key === key)) { // Attempting to open a non-existent tab return } // Change the selected tab and make sure it's open openTab((key ?? 'file-tree') as RailTabKey) } }, [openTab, togglePane, selectedTab, railTabs] ) const isReviewPanelOpen = selectedTab === 'review-panel' return (
{isHistoryView && }
{railTabs .filter(({ hide }) => !hide) .map(({ key, component }) => ( {component} ))}
{RAIL_MODALS.map(({ key, modalComponentFunction: Component }) => ( ))}
) } const RailTab = ({ icon, eventKey, open, indicator, title, }: { icon: AvailableUnfilledIcon eventKey: string open: boolean indicator?: ReactElement title: string }) => { return ( {open ? ( ) : ( )} {indicator} ) } const RailActionElement = ({ action }: { action: RailAction }) => { const icon = ( ) const onActionClick = useCallback(() => { if ('action' in action) { action.action() } }, [action]) if ('dropdown' in action) { return ( {icon} {action.dropdown} ) } else { return ( ) } } export const RailPanelHeader: FC<{ title: string }> = ({ title }) => { const { handlePaneCollapse } = useRailContext() return (

{title}

) } const RailHelpDropdown = () => { const showSupport = getMeta('ol-showSupport') const { t } = useTranslation() const { setActiveModal } = useRailContext() const openKeyboardShortcutsModal = useCallback(() => { setActiveModal('keyboard-shortcuts') }, [setActiveModal]) const openContactUsModal = useCallback(() => { setActiveModal('contact-us') }, [setActiveModal]) return ( {t('keyboard_shortcuts')} {t('documentation')} {showSupport && ( {t('contact_us')} )} {t('give_feedback')} ) }