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 (
{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 (
)
}
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')}
)
}