mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 09:09:36 +02:00
Editor Redesign Cleanup: main layout, toolbar, and rail (#31031)
* feat: integrate main layout, toolbar, and rail from redesign into main ide-react folder * feat: remove additional files no longer used after ide redesign GitOrigin-RevId: 8fd77f63cb9c67be91995a9dde13b0fe2376d80f
This commit is contained in:
committed by
Copybot
parent
c790449196
commit
fc8d564320
@@ -1294,7 +1294,6 @@
|
||||
"pdf_only_hide_editor": "",
|
||||
"pdf_preview": "",
|
||||
"pdf_preview_error": "",
|
||||
"pdf_preview_logs": "",
|
||||
"pdf_rendering_error": "",
|
||||
"pdf_unavailable_for_download": "",
|
||||
"pdf_viewer": "",
|
||||
@@ -1379,7 +1378,6 @@
|
||||
"project_figure_modal": "",
|
||||
"project_files": "",
|
||||
"project_files_history": "",
|
||||
"project_files_outline": "",
|
||||
"project_flagged_too_many_compiles": "",
|
||||
"project_has_too_many_files_limit": "",
|
||||
"project_history_labels": "",
|
||||
@@ -2020,10 +2018,8 @@
|
||||
"toolbar_undo": "",
|
||||
"toolbar_undo_redo_actions": "",
|
||||
"tools": "",
|
||||
"tooltip_hide_filetree": "",
|
||||
"tooltip_hide_panel": "",
|
||||
"tooltip_hide_pdf": "",
|
||||
"tooltip_show_filetree": "",
|
||||
"tooltip_show_panel": "",
|
||||
"tooltip_show_pdf": "",
|
||||
"total_due_in_x_days": "",
|
||||
|
||||
@@ -29,7 +29,7 @@ import { useIdeContext } from '@/shared/context/ide-context'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { User } from '../../../../../types/user'
|
||||
import { useRailContext } from '@/features/ide-redesign/contexts/rail-context'
|
||||
import { useRailContext } from '@/features/ide-react/context/rail-context'
|
||||
import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
|
||||
|
||||
const PAGE_SIZE = 50
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
import React, { useState, useCallback } from 'react'
|
||||
import ToolbarHeader from './toolbar-header'
|
||||
import { useEditorContext } from '../../../shared/context/editor-context'
|
||||
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
|
||||
import { useChatContext } from '../../chat/context/chat-context'
|
||||
import { useLayoutContext } from '../../../shared/context/layout-context'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
import * as eventTracking from '../../../infrastructure/event-tracking'
|
||||
import { Doc } from '../../../../../types/doc'
|
||||
import { OnlineUser } from '@/features/ide-react/context/online-users-context'
|
||||
|
||||
function isOpentoString(open: boolean) {
|
||||
return open ? 'open' : 'close'
|
||||
}
|
||||
|
||||
const EditorNavigationToolbarRoot = React.memo(
|
||||
function EditorNavigationToolbarRoot({
|
||||
onlineUsersArray,
|
||||
openDoc,
|
||||
openShareProjectModal,
|
||||
}: {
|
||||
onlineUsersArray: OnlineUser[]
|
||||
openDoc: (
|
||||
doc: Doc,
|
||||
{ gotoLine }: { gotoLine: number }
|
||||
) => Promise<Doc | undefined>
|
||||
openShareProjectModal: () => void
|
||||
}) {
|
||||
const {
|
||||
name: projectName,
|
||||
features: { trackChangesVisible },
|
||||
} = useProjectContext()
|
||||
|
||||
const { cobranding, isRestrictedTokenMember, renameProject } =
|
||||
useEditorContext()
|
||||
|
||||
const { permissionsLevel } = useIdeReactContext()
|
||||
|
||||
const {
|
||||
chatIsOpen,
|
||||
setChatIsOpen,
|
||||
reviewPanelOpen,
|
||||
setReviewPanelOpen,
|
||||
view,
|
||||
setView,
|
||||
setLeftMenuShown,
|
||||
} = useLayoutContext()
|
||||
|
||||
const { markMessagesAsRead, unreadMessageCount } = useChatContext()
|
||||
|
||||
const toggleChatOpen = useCallback(() => {
|
||||
if (!chatIsOpen) {
|
||||
markMessagesAsRead()
|
||||
}
|
||||
eventTracking.sendMB('navigation-clicked-chat', {
|
||||
action: isOpentoString(!chatIsOpen),
|
||||
})
|
||||
setChatIsOpen(!chatIsOpen)
|
||||
}, [chatIsOpen, setChatIsOpen, markMessagesAsRead])
|
||||
|
||||
const toggleReviewPanelOpen = useCallback(
|
||||
(event: any) => {
|
||||
event.preventDefault()
|
||||
eventTracking.sendMB('navigation-clicked-review', {
|
||||
action: isOpentoString(!reviewPanelOpen),
|
||||
})
|
||||
setReviewPanelOpen(value => !value)
|
||||
},
|
||||
[reviewPanelOpen, setReviewPanelOpen]
|
||||
)
|
||||
|
||||
const [shouldReopenChat, setShouldReopenChat] = useState(chatIsOpen)
|
||||
const toggleHistoryOpen = useCallback(() => {
|
||||
const action = view === 'history' ? 'close' : 'open'
|
||||
eventTracking.sendMB('navigation-clicked-history', { action })
|
||||
|
||||
if (chatIsOpen && action === 'open') {
|
||||
setShouldReopenChat(true)
|
||||
toggleChatOpen()
|
||||
}
|
||||
if (shouldReopenChat && action === 'close') {
|
||||
setShouldReopenChat(false)
|
||||
toggleChatOpen()
|
||||
}
|
||||
setView(view === 'history' ? 'editor' : 'history')
|
||||
}, [view, chatIsOpen, shouldReopenChat, setView, toggleChatOpen])
|
||||
|
||||
const openShareModal = useCallback(() => {
|
||||
eventTracking.sendMB('navigation-clicked-share')
|
||||
openShareProjectModal()
|
||||
}, [openShareProjectModal])
|
||||
|
||||
const onShowLeftMenuClick = useCallback(() => {
|
||||
eventTracking.sendMB('navigation-clicked-menu')
|
||||
setLeftMenuShown(value => !value)
|
||||
}, [setLeftMenuShown])
|
||||
|
||||
const goToUser = useCallback(
|
||||
async (user: OnlineUser) => {
|
||||
if (user.doc && typeof user.row === 'number') {
|
||||
return await openDoc(user.doc, { gotoLine: user.row + 1 })
|
||||
}
|
||||
},
|
||||
[openDoc]
|
||||
)
|
||||
|
||||
return (
|
||||
<ToolbarHeader
|
||||
cobranding={cobranding}
|
||||
onShowLeftMenuClick={onShowLeftMenuClick}
|
||||
chatIsOpen={chatIsOpen}
|
||||
unreadMessageCount={unreadMessageCount}
|
||||
toggleChatOpen={toggleChatOpen}
|
||||
reviewPanelOpen={reviewPanelOpen}
|
||||
toggleReviewPanelOpen={toggleReviewPanelOpen}
|
||||
historyIsOpen={view === 'history'}
|
||||
toggleHistoryOpen={toggleHistoryOpen}
|
||||
onlineUsers={onlineUsersArray}
|
||||
goToUser={goToUser}
|
||||
isRestrictedTokenMember={isRestrictedTokenMember}
|
||||
hasPublishPermissions={
|
||||
permissionsLevel === 'owner' || permissionsLevel === 'readAndWrite'
|
||||
}
|
||||
chatVisible={!isRestrictedTokenMember}
|
||||
projectName={projectName}
|
||||
renameProject={renameProject}
|
||||
hasRenamePermissions={permissionsLevel === 'owner'}
|
||||
openShareModal={openShareModal}
|
||||
trackChangesVisible={trackChangesVisible}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
export default EditorNavigationToolbarRoot
|
||||
@@ -1,123 +0,0 @@
|
||||
import React, { FC, useState } from 'react'
|
||||
import { Panel, PanelGroup } from 'react-resizable-panels'
|
||||
import NoSelectionPane from '@/features/ide-react/components/editor/no-selection-pane'
|
||||
import FileView from '@/features/file-view/components/file-view'
|
||||
import MultipleSelectionPane from '@/features/ide-react/components/editor/multiple-selection-pane'
|
||||
import { HorizontalResizeHandle } from '@/features/ide-react/components/resize/horizontal-resize-handle'
|
||||
import { HorizontalToggler } from '@/features/ide-react/components/resize/horizontal-toggler'
|
||||
import { DefaultSynctexControl } from '@/features/pdf-preview/components/detach-synctex-control'
|
||||
import PdfPreview from '@/features/pdf-preview/components/pdf-preview'
|
||||
import { usePdfPane } from '@/features/ide-react/hooks/use-pdf-pane'
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import classNames from 'classnames'
|
||||
import { fileViewFile } from '@/features/ide-react/util/file-view'
|
||||
import { useFileTreeOpenContext } from '@/features/ide-react/context/file-tree-open-context'
|
||||
import { EditorPane } from '@/features/ide-react/components/editor/editor-pane'
|
||||
|
||||
export const EditorAndPdf: FC = () => {
|
||||
const [resizing, setResizing] = useState(false)
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
const {
|
||||
togglePdfPane,
|
||||
handlePdfPaneExpand,
|
||||
handlePdfPaneCollapse,
|
||||
setPdfIsOpen,
|
||||
pdfIsOpen,
|
||||
pdfPanelRef,
|
||||
} = usePdfPane()
|
||||
|
||||
const { view, pdfLayout } = useLayoutContext()
|
||||
|
||||
const { selectedEntityCount, openEntity } = useFileTreeOpenContext()
|
||||
|
||||
const editorIsOpen =
|
||||
view === 'editor' || view === 'file' || pdfLayout === 'sideBySide'
|
||||
|
||||
return (
|
||||
<PanelGroup
|
||||
autoSaveId="ide-editor-pdf-layout"
|
||||
direction="horizontal"
|
||||
className={classNames({
|
||||
'ide-panel-group-resizing': resizing,
|
||||
hidden: view === 'history',
|
||||
})}
|
||||
>
|
||||
{/* ide */}
|
||||
<Panel
|
||||
id="panel-ide"
|
||||
order={1}
|
||||
defaultSize={50}
|
||||
minSize={5}
|
||||
className={classNames('ide-react-panel', {
|
||||
'ide-panel-group-resizing': resizing,
|
||||
hidden: !editorIsOpen,
|
||||
})}
|
||||
tagName="section"
|
||||
aria-label={t('editor')}
|
||||
>
|
||||
{selectedEntityCount === 0 && <NoSelectionPane />}
|
||||
{selectedEntityCount === 1 && openEntity?.type === 'fileRef' && (
|
||||
<FileView
|
||||
file={fileViewFile(openEntity.entity)}
|
||||
key={openEntity.entity._id}
|
||||
/>
|
||||
)}
|
||||
{selectedEntityCount > 1 && (
|
||||
<MultipleSelectionPane selectedEntityCount={selectedEntityCount} />
|
||||
)}
|
||||
<EditorPane />
|
||||
</Panel>
|
||||
|
||||
<HorizontalResizeHandle
|
||||
resizable={pdfLayout === 'sideBySide'}
|
||||
onDoubleClick={togglePdfPane}
|
||||
onDragging={setResizing}
|
||||
className={classNames({
|
||||
hidden: !editorIsOpen,
|
||||
})}
|
||||
hitAreaMargins={{ coarse: 0, fine: 0 }}
|
||||
>
|
||||
<HorizontalToggler
|
||||
id="editor-pdf"
|
||||
togglerType="east"
|
||||
isOpen={pdfIsOpen}
|
||||
setIsOpen={setPdfIsOpen}
|
||||
tooltipWhenOpen={t('tooltip_hide_pdf')}
|
||||
tooltipWhenClosed={t('tooltip_show_pdf')}
|
||||
/>
|
||||
|
||||
{pdfLayout === 'sideBySide' && (
|
||||
<div className="synctex-controls">
|
||||
<DefaultSynctexControl />
|
||||
</div>
|
||||
)}
|
||||
</HorizontalResizeHandle>
|
||||
|
||||
{/* pdf */}
|
||||
<Panel
|
||||
ref={pdfPanelRef}
|
||||
id="panel-pdf"
|
||||
order={2}
|
||||
defaultSize={50}
|
||||
minSize={5}
|
||||
collapsible
|
||||
onCollapse={handlePdfPaneCollapse}
|
||||
onExpand={handlePdfPaneExpand}
|
||||
className="ide-react-panel"
|
||||
tagName="section"
|
||||
aria-label={t('pdf_preview_logs')}
|
||||
>
|
||||
<PdfPreview />
|
||||
{/* ensure that "sync to code" is available in PDF only layout */}
|
||||
{pdfLayout === 'flat' && view === 'pdf' && (
|
||||
<div className="synctex-controls" hidden>
|
||||
<DefaultSynctexControl />
|
||||
</div>
|
||||
)}
|
||||
</Panel>
|
||||
</PanelGroup>
|
||||
)
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import { useState, useCallback } from 'react'
|
||||
import { useOnlineUsersContext } from '@/features/ide-react/context/online-users-context'
|
||||
import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
|
||||
import EditorNavigationToolbarRoot from '@/features/editor-navigation-toolbar/components/editor-navigation-toolbar-root'
|
||||
import ShareProjectModal from '@/features/share-project-modal/components/share-project-modal'
|
||||
import EditorOverLimitModal from '@/features/share-project-modal/components/editor-over-limit-modal'
|
||||
import ViewOnlyAccessModal from '@/features/share-project-modal/components/view-only-access-modal'
|
||||
import { useEditorAnalytics } from '@/shared/hooks/use-editor-analytics'
|
||||
|
||||
function EditorNavigationToolbar() {
|
||||
const [showShareModal, setShowShareModal] = useState(false)
|
||||
const { onlineUsersArray } = useOnlineUsersContext()
|
||||
const { openDoc } = useEditorManagerContext()
|
||||
const { sendEventOnce } = useEditorAnalytics()
|
||||
|
||||
const handleOpenShareModal = useCallback(() => {
|
||||
sendEventOnce('ide-open-share-modal-once')
|
||||
setShowShareModal(true)
|
||||
}, [sendEventOnce])
|
||||
|
||||
const handleHideShareModal = useCallback(() => {
|
||||
setShowShareModal(false)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<EditorNavigationToolbarRoot
|
||||
onlineUsersArray={onlineUsersArray}
|
||||
openDoc={openDoc}
|
||||
openShareProjectModal={handleOpenShareModal}
|
||||
/>
|
||||
<EditorOverLimitModal />
|
||||
<ViewOnlyAccessModal />
|
||||
<ShareProjectModal
|
||||
show={showShareModal}
|
||||
handleOpen={handleOpenShareModal}
|
||||
handleHide={handleHideShareModal}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default EditorNavigationToolbar
|
||||
@@ -1,60 +0,0 @@
|
||||
import { Panel, PanelGroup } from 'react-resizable-panels'
|
||||
import { VerticalResizeHandle } from '@/features/ide-react/components/resize/vertical-resize-handle'
|
||||
import { FileTree } from '@/features/ide-react/components/file-tree'
|
||||
import classNames from 'classnames'
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import { OutlineContainer } from '@/features/outline/components/outline-container'
|
||||
import { useOutlinePane } from '@/features/ide-react/hooks/use-outline-pane'
|
||||
import React, { ElementType } from 'react'
|
||||
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
|
||||
import { t } from 'i18next'
|
||||
|
||||
const editorSidebarComponents = importOverleafModules(
|
||||
'editorSidebarComponents'
|
||||
) as { import: { default: ElementType }; path: string }[]
|
||||
|
||||
export default function EditorSidebar() {
|
||||
const { view } = useLayoutContext()
|
||||
|
||||
const { outlineEnabled, outlinePanelRef } = useOutlinePane()
|
||||
|
||||
return (
|
||||
<nav
|
||||
className={classNames('ide-react-editor-sidebar', {
|
||||
hidden: view === 'history',
|
||||
})}
|
||||
aria-label={t('project_files_outline')}
|
||||
>
|
||||
{editorSidebarComponents.map(
|
||||
({ import: { default: Component }, path }) => (
|
||||
<Component key={path} />
|
||||
)
|
||||
)}
|
||||
<PanelGroup autoSaveId="ide-editor-sidebar-layout" direction="vertical">
|
||||
<Panel
|
||||
defaultSize={50}
|
||||
minSize={25}
|
||||
className="ide-react-file-tree-panel"
|
||||
id="panel-file-tree"
|
||||
order={1}
|
||||
>
|
||||
<FileTree />
|
||||
</Panel>
|
||||
|
||||
<VerticalResizeHandle disabled={!outlineEnabled} />
|
||||
|
||||
<Panel
|
||||
defaultSize={50}
|
||||
maxSize={75}
|
||||
id="panel-outline"
|
||||
order={2}
|
||||
collapsible
|
||||
ref={outlinePanelRef}
|
||||
style={{ minHeight: 32 }} // keep the header visible
|
||||
>
|
||||
<OutlineContainer />
|
||||
</Panel>
|
||||
</PanelGroup>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
import { Panel, PanelGroup } from 'react-resizable-panels'
|
||||
import React, { FC, lazy, Suspense } from 'react'
|
||||
import SourceEditor from '@/features/source-editor/components/source-editor'
|
||||
import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
|
||||
import { useEditorOpenDocContext } from '@/features/ide-react/context/editor-open-doc-context'
|
||||
import classNames from 'classnames'
|
||||
import { EditorLoadingPane } from '@/features/ide-react/components/editor/editor-loading-pane'
|
||||
import { FullSizeLoadingSpinner } from '@/shared/components/loading-spinner'
|
||||
import { VerticalResizeHandle } from '@/features/ide-react/components/resize/vertical-resize-handle'
|
||||
import { useFileTreeOpenContext } from '@/features/ide-react/context/file-tree-open-context'
|
||||
import { useEditorPropertiesContext } from '@/features/ide-react/context/editor-properties-context'
|
||||
|
||||
const SymbolPalettePane = lazy(
|
||||
() => import('@/features/ide-react/components/editor/symbol-palette-pane')
|
||||
)
|
||||
|
||||
export const EditorPane: FC = () => {
|
||||
const { showSymbolPalette } = useEditorPropertiesContext()
|
||||
const { selectedEntityCount, openEntity } = useFileTreeOpenContext()
|
||||
const { isLoading } = useEditorManagerContext()
|
||||
const { currentDocumentId } = useEditorOpenDocContext()
|
||||
|
||||
if (!currentDocumentId) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames('ide-react-editor-content', 'full-size', {
|
||||
hidden: openEntity?.type !== 'doc' || selectedEntityCount !== 1,
|
||||
})}
|
||||
>
|
||||
<PanelGroup autoSaveId="ide-editor-layout" direction="vertical">
|
||||
<Panel
|
||||
id="panel-source-editor"
|
||||
order={1}
|
||||
className="ide-react-editor-panel"
|
||||
>
|
||||
<SourceEditor />
|
||||
{isLoading && <EditorLoadingPane />}
|
||||
</Panel>
|
||||
|
||||
{showSymbolPalette && (
|
||||
<>
|
||||
<VerticalResizeHandle id="editor-symbol-palette" />
|
||||
<Panel
|
||||
id="panel-symbol-palette"
|
||||
order={2}
|
||||
defaultSize={25}
|
||||
minSize={10}
|
||||
maxSize={50}
|
||||
>
|
||||
<Suspense fallback={<FullSizeLoadingSpinner delay={500} />}>
|
||||
<SymbolPalettePane />
|
||||
</Suspense>
|
||||
</Panel>
|
||||
</>
|
||||
)}
|
||||
</PanelGroup>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import NoSelectionPane from '@/features/ide-react/components/editor/no-selection-pane'
|
||||
import { Editor } from './editor'
|
||||
import { Editor } from '@/features/ide-redesign/components/editor'
|
||||
import { useFileTreeOpenContext } from '@/features/ide-react/context/file-tree-open-context'
|
||||
import FileView from '@/features/file-view/components/file-view'
|
||||
import { fileViewFile } from '@/features/ide-react/util/file-view'
|
||||
@@ -1,7 +1,4 @@
|
||||
import { lazy, Suspense } from 'react'
|
||||
import { Alerts } from '@/features/ide-react/components/alerts/alerts'
|
||||
import { MainLayout } from '@/features/ide-react/components/layout/main-layout'
|
||||
import EditorLeftMenu from '@/features/editor-left-menu/components/editor-left-menu'
|
||||
import { useLayoutEventTracking } from '@/features/ide-react/hooks/use-layout-event-tracking'
|
||||
import useSocketListeners from '@/features/ide-react/hooks/use-socket-listeners'
|
||||
import { useEditingSessionHeartbeat } from '@/features/ide-react/hooks/use-editing-session-heartbeat'
|
||||
@@ -10,21 +7,13 @@ import { useHasLintingError } from '@/features/ide-react/hooks/use-has-linting-e
|
||||
import { Modals } from '@/features/ide-react/components/modals/modals'
|
||||
import { GlobalAlertsProvider } from '@/features/ide-react/context/global-alerts-context'
|
||||
import { GlobalToasts } from '../global-toasts'
|
||||
import {
|
||||
canUseNewEditor,
|
||||
useIsNewEditorEnabled,
|
||||
} from '@/features/ide-redesign/utils/new-editor-utils'
|
||||
import EditorSurvey from '../editor-survey'
|
||||
import { useFeatureFlag } from '@/shared/context/split-test-context'
|
||||
import { useStatusFavicon } from '@/features/ide-react/hooks/use-status-favicon'
|
||||
import useThemedPage from '@/shared/hooks/use-themed-page'
|
||||
|
||||
const MainLayoutNew = lazy(
|
||||
() => import('@/features/ide-redesign/components/main-layout')
|
||||
)
|
||||
const SettingsModalNew = lazy(
|
||||
() => import('@/features/ide-redesign/components/settings/settings-modal')
|
||||
)
|
||||
import MainLayout from '@/features/ide-react/components/layout/main-layout'
|
||||
import SettingsModalNew from '@/features/ide-redesign/components/settings/settings-modal'
|
||||
|
||||
export default function IdePage() {
|
||||
useLayoutEventTracking() // sent event when the layout changes
|
||||
@@ -35,26 +24,15 @@ export default function IdePage() {
|
||||
useStatusFavicon() // update the favicon based on the compile status
|
||||
useThemedPage() // set the page theme based on user settings
|
||||
|
||||
const newEditor = useIsNewEditorEnabled()
|
||||
const canAccessNewEditor = canUseNewEditor()
|
||||
const editorSurveyFlag = useFeatureFlag('editor-popup-ux-survey')
|
||||
const showEditorSurvey = editorSurveyFlag && !canAccessNewEditor
|
||||
const showEditorSurvey = editorSurveyFlag
|
||||
|
||||
return (
|
||||
<GlobalAlertsProvider>
|
||||
<Alerts />
|
||||
<Modals />
|
||||
{newEditor ? (
|
||||
<Suspense fallback={null}>
|
||||
<SettingsModalNew />
|
||||
<MainLayoutNew />
|
||||
</Suspense>
|
||||
) : (
|
||||
<>
|
||||
<EditorLeftMenu />
|
||||
<MainLayout />
|
||||
</>
|
||||
)}
|
||||
<SettingsModalNew />
|
||||
<MainLayout />
|
||||
<GlobalToasts />
|
||||
{showEditorSurvey && <EditorSurvey />}
|
||||
</GlobalAlertsProvider>
|
||||
|
||||
@@ -1,134 +1,136 @@
|
||||
import { Panel, PanelGroup } from 'react-resizable-panels'
|
||||
import { ElementType, FC } from 'react'
|
||||
import { HorizontalResizeHandle } from '../resize/horizontal-resize-handle'
|
||||
import classNames from 'classnames'
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import EditorNavigationToolbar from '@/features/ide-react/components/editor-navigation-toolbar'
|
||||
import ChatPane from '@/features/chat/components/chat-pane'
|
||||
import { HorizontalResizeHandle } from '@/features/ide-react/components/resize/horizontal-resize-handle'
|
||||
import PdfPreview from '@/features/pdf-preview/components/pdf-preview'
|
||||
import { RailLayout } from '../rail/rail'
|
||||
import { Toolbar } from '../toolbar/toolbar'
|
||||
import { HorizontalToggler } from '@/features/ide-react/components/resize/horizontal-toggler'
|
||||
import { HistorySidebar } from '@/features/ide-react/components/history-sidebar'
|
||||
import EditorSidebar from '@/features/ide-react/components/editor-sidebar'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useSidebarPane } from '@/features/ide-react/hooks/use-sidebar-pane'
|
||||
import { useChatPane } from '@/features/ide-react/hooks/use-chat-pane'
|
||||
import { EditorAndPdf } from '@/features/ide-react/components/editor-and-pdf'
|
||||
import { usePdfPane } from '@/features/ide-react/hooks/use-pdf-pane'
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import { ElementType, useState } from 'react'
|
||||
import EditorPanel from '../editor/editor-panel'
|
||||
import { useRailContext } from '../../context/rail-context'
|
||||
import HistoryContainer from '@/features/ide-react/components/history-container'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { useEditorContext } from '@/shared/context/editor-context'
|
||||
import { DefaultSynctexControl } from '@/features/pdf-preview/components/detach-synctex-control'
|
||||
import importOverleafModules from '../../../../../macros/import-overleaf-module.macro'
|
||||
|
||||
const mainEditorLayoutPanels: Array<{
|
||||
import: { default: ElementType }
|
||||
path: string
|
||||
}> = importOverleafModules('mainEditorLayoutPanels')
|
||||
|
||||
const mainEditorLayoutModalsModules: Array<{
|
||||
import: { default: ElementType }
|
||||
path: string
|
||||
}> = importOverleafModules('mainEditorLayoutModals')
|
||||
|
||||
export const MainLayout: FC = () => {
|
||||
const { view } = useLayoutContext()
|
||||
const { isRestrictedTokenMember } = useEditorContext()
|
||||
|
||||
export default function MainLayout() {
|
||||
const [resizing, setResizing] = useState(false)
|
||||
const { resizing: railResizing } = useRailContext()
|
||||
const {
|
||||
isOpen: sidebarIsOpen,
|
||||
setIsOpen: setSidebarIsOpen,
|
||||
panelRef: sidebarPanelRef,
|
||||
togglePane: toggleSidebar,
|
||||
handlePaneExpand: handleSidebarExpand,
|
||||
handlePaneCollapse: handleSidebarCollapse,
|
||||
resizing: sidebarResizing,
|
||||
setResizing: setSidebarResizing,
|
||||
} = useSidebarPane()
|
||||
togglePdfPane,
|
||||
handlePdfPaneExpand,
|
||||
handlePdfPaneCollapse,
|
||||
setPdfIsOpen: setIsPdfOpen,
|
||||
pdfIsOpen: isPdfOpen,
|
||||
pdfPanelRef,
|
||||
} = usePdfPane()
|
||||
const { view, pdfLayout } = useLayoutContext()
|
||||
|
||||
const {
|
||||
isOpen: chatIsOpen,
|
||||
panelRef: chatPanelRef,
|
||||
togglePane: toggleChat,
|
||||
resizing: chatResizing,
|
||||
setResizing: setChatResizing,
|
||||
handlePaneCollapse: handleChatCollapse,
|
||||
handlePaneExpand: handleChatExpand,
|
||||
} = useChatPane()
|
||||
|
||||
const chatEnabled =
|
||||
getMeta('ol-capabilities')?.includes('chat') && !isRestrictedTokenMember
|
||||
const editorIsOpen =
|
||||
view === 'editor' || view === 'file' || pdfLayout === 'sideBySide'
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="ide-react-main">
|
||||
<EditorNavigationToolbar />
|
||||
<div className="ide-react-body">
|
||||
<div className="ide-redesign-main">
|
||||
<Toolbar />
|
||||
<div className="ide-redesign-body">
|
||||
<PanelGroup
|
||||
autoSaveId="ide-outer-layout"
|
||||
autoSaveId="ide-redesign-outer-layout"
|
||||
direction="horizontal"
|
||||
className={classNames({
|
||||
'ide-panel-group-resizing': sidebarResizing || chatResizing,
|
||||
className={classNames('ide-redesign-inner', {
|
||||
'ide-panel-group-resizing': resizing || railResizing,
|
||||
})}
|
||||
>
|
||||
{/* sidebar */}
|
||||
<Panel
|
||||
ref={sidebarPanelRef}
|
||||
id="panel-sidebar"
|
||||
order={1}
|
||||
defaultSize={15}
|
||||
minSize={5}
|
||||
maxSize={80}
|
||||
collapsible
|
||||
onCollapse={handleSidebarCollapse}
|
||||
onExpand={handleSidebarExpand}
|
||||
>
|
||||
<EditorSidebar />
|
||||
{view === 'history' && <HistorySidebar />}
|
||||
</Panel>
|
||||
|
||||
<HorizontalResizeHandle
|
||||
onDoubleClick={toggleSidebar}
|
||||
resizable={sidebarIsOpen}
|
||||
onDragging={setSidebarResizing}
|
||||
hitAreaMargins={{ coarse: 0, fine: 0 }}
|
||||
>
|
||||
<HorizontalToggler
|
||||
id="panel-sidebar"
|
||||
togglerType="west"
|
||||
isOpen={sidebarIsOpen}
|
||||
setIsOpen={setSidebarIsOpen}
|
||||
tooltipWhenOpen={t('tooltip_hide_filetree')}
|
||||
tooltipWhenClosed={t('tooltip_show_filetree')}
|
||||
/>
|
||||
</HorizontalResizeHandle>
|
||||
|
||||
<Panel id="panel-outer-main" order={2}>
|
||||
<PanelGroup autoSaveId="ide-inner-layout" direction="horizontal">
|
||||
<Panel className="ide-react-panel" id="panel-main" order={1}>
|
||||
<HistoryContainer />
|
||||
<EditorAndPdf />
|
||||
<RailLayout />
|
||||
<Panel id="ide-redesign-editor-and-pdf-panel" order={2}>
|
||||
<HistoryContainer />
|
||||
<PanelGroup
|
||||
autoSaveId="ide-redesign-editor-and-pdf-panel-group"
|
||||
direction="horizontal"
|
||||
className={classNames({
|
||||
hidden: view === 'history',
|
||||
})}
|
||||
>
|
||||
<Panel
|
||||
id="ide-redesign-editor-panel"
|
||||
order={1}
|
||||
className={classNames({
|
||||
hidden: !editorIsOpen || view === 'history',
|
||||
})}
|
||||
minSize={5}
|
||||
defaultSize={50}
|
||||
tagName="section"
|
||||
aria-label={t('editor')}
|
||||
>
|
||||
<div className="ide-redesign-editor-container">
|
||||
<EditorPanel />
|
||||
</div>
|
||||
</Panel>
|
||||
<HorizontalResizeHandle
|
||||
resizable={pdfLayout === 'sideBySide'}
|
||||
onDragging={setResizing}
|
||||
onDoubleClick={togglePdfPane}
|
||||
hitAreaMargins={{ coarse: 0, fine: 0 }}
|
||||
className={classNames({
|
||||
hidden: !editorIsOpen,
|
||||
})}
|
||||
>
|
||||
<HorizontalToggler
|
||||
id="ide-redesign-pdf-panel"
|
||||
togglerType="east"
|
||||
isOpen={isPdfOpen}
|
||||
setIsOpen={setIsPdfOpen}
|
||||
tooltipWhenOpen={t('tooltip_hide_pdf')}
|
||||
tooltipWhenClosed={t('tooltip_show_pdf')}
|
||||
/>
|
||||
{pdfLayout === 'sideBySide' && (
|
||||
<div className="synctex-controls">
|
||||
<DefaultSynctexControl />
|
||||
</div>
|
||||
)}
|
||||
</HorizontalResizeHandle>
|
||||
<Panel
|
||||
collapsible
|
||||
className={classNames('ide-redesign-pdf-container', {
|
||||
hidden: view === 'history',
|
||||
})}
|
||||
id="ide-redesign-pdf-panel"
|
||||
order={2}
|
||||
defaultSize={50}
|
||||
minSize={5}
|
||||
ref={pdfPanelRef}
|
||||
onExpand={handlePdfPaneExpand}
|
||||
onCollapse={handlePdfPaneCollapse}
|
||||
tagName="section"
|
||||
aria-label={t('pdf_preview')}
|
||||
>
|
||||
<PdfPreview />
|
||||
{pdfLayout === 'flat' && view === 'pdf' && (
|
||||
<div className="synctex-controls" hidden>
|
||||
<DefaultSynctexControl />
|
||||
</div>
|
||||
)}
|
||||
</Panel>
|
||||
|
||||
{chatEnabled && (
|
||||
<>
|
||||
<HorizontalResizeHandle
|
||||
onDoubleClick={toggleChat}
|
||||
resizable={chatIsOpen}
|
||||
onDragging={setChatResizing}
|
||||
hitAreaMargins={{ coarse: 0, fine: 0 }}
|
||||
/>
|
||||
|
||||
{/* chat */}
|
||||
<Panel
|
||||
ref={chatPanelRef}
|
||||
id="panel-chat"
|
||||
order={2}
|
||||
defaultSize={20}
|
||||
minSize={5}
|
||||
maxSize={30}
|
||||
collapsible
|
||||
onCollapse={handleChatCollapse}
|
||||
onExpand={handleChatExpand}
|
||||
>
|
||||
<ChatPane />
|
||||
</Panel>
|
||||
</>
|
||||
)}
|
||||
</PanelGroup>
|
||||
</Panel>
|
||||
{mainEditorLayoutPanels.map(
|
||||
({ import: { default: Component }, path }, i) => {
|
||||
return <Component key={path} order={i + 3} />
|
||||
}
|
||||
)}
|
||||
</PanelGroup>
|
||||
</div>
|
||||
{mainEditorLayoutModalsModules.map(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import getMeta from '@/utils/meta'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useRailContext } from '../../contexts/rail-context'
|
||||
import { useRailContext } from '@/features/ide-react/context/rail-context'
|
||||
import { useCallback } from 'react'
|
||||
import {
|
||||
DropdownDivider,
|
||||
@@ -1,8 +1,11 @@
|
||||
import { FC } from 'react'
|
||||
import { RailModalKey, useRailContext } from '../../contexts/rail-context'
|
||||
import { RailHelpContactUsModal } from '../help/contact-us'
|
||||
import { RailHelpShowHotkeysModal } from '../help/keyboard-shortcuts'
|
||||
import DictionarySettingsModal from '../settings/editor-settings/dictionary-settings-modal'
|
||||
import {
|
||||
RailModalKey,
|
||||
useRailContext,
|
||||
} from '@/features/ide-react/context/rail-context'
|
||||
import { RailHelpContactUsModal } from '@/features/ide-redesign/components/help/contact-us'
|
||||
import { RailHelpShowHotkeysModal } from '@/features/ide-redesign/components/help/keyboard-shortcuts'
|
||||
import DictionarySettingsModal from '@/features/ide-redesign/components/settings/editor-settings/dictionary-settings-modal'
|
||||
|
||||
const RAIL_MODALS: {
|
||||
key: RailModalKey
|
||||
@@ -1,8 +1,8 @@
|
||||
import { DropdownMenu } from '@/shared/components/dropdown/dropdown-menu'
|
||||
import { RailTabKey } from '../../contexts/rail-context'
|
||||
import { RailElement } from '../../utils/rail-types'
|
||||
import { RailTabKey } from '@/features/ide-react/context/rail-context'
|
||||
import { RailElement } from '@/features/ide-react/util/rail-types'
|
||||
import RailTab from './rail-tab'
|
||||
import { shouldIncludeElement } from '../../utils/rail-utils'
|
||||
import { shouldIncludeElement } from '@/features/ide-react/util/rail-utils'
|
||||
|
||||
export default function RailOverflowDropdown({
|
||||
tabs,
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useRailContext } from '../../contexts/rail-context'
|
||||
import { useRailContext } from '@/features/ide-react/context/rail-context'
|
||||
import OLIconButton from '@/shared/components/ol/ol-icon-button'
|
||||
import React, { useCallback } from 'react'
|
||||
import OLTooltip from '@/shared/components/ol/ol-tooltip'
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Panel } from 'react-resizable-panels'
|
||||
import { useRailContext } from '../../contexts/rail-context'
|
||||
import { useRailContext } from '@/features/ide-react/context/rail-context'
|
||||
import classNames from 'classnames'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import usePreviousValue from '@/shared/hooks/use-previous-value'
|
||||
import { HistorySidebar } from '@/features/ide-react/components/history-sidebar'
|
||||
import { Tab } from 'react-bootstrap'
|
||||
import { RailElement } from '../../utils/rail-types'
|
||||
import { shouldIncludeElement } from '../../utils/rail-utils'
|
||||
import { RailElement } from '@/features/ide-react/util/rail-types'
|
||||
import { shouldIncludeElement } from '@/features/ide-react/util/rail-utils'
|
||||
|
||||
export default function RailPanel({
|
||||
isReviewPanelOpen,
|
||||
@@ -1,7 +1,7 @@
|
||||
import { HorizontalResizeHandle } from '@/features/ide-react/components/resize/horizontal-resize-handle'
|
||||
import { HorizontalToggler } from '@/features/ide-react/components/resize/horizontal-toggler'
|
||||
import classNames from 'classnames'
|
||||
import { useRailContext } from '../../contexts/rail-context'
|
||||
import { useRailContext } from '@/features/ide-react/context/rail-context'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export default function RailResizeHandle({
|
||||
@@ -3,7 +3,7 @@ import MaterialIcon from '@/shared/components/material-icon'
|
||||
import classNames from 'classnames'
|
||||
import { ComponentProps, forwardRef, ReactElement } from 'react'
|
||||
import { NavLink } from 'react-bootstrap'
|
||||
import { RailElement } from '../../utils/rail-types'
|
||||
import { RailElement } from '@/features/ide-react/util/rail-types'
|
||||
|
||||
const RailTab = forwardRef<
|
||||
HTMLAnchorElement,
|
||||
@@ -2,35 +2,41 @@ import { FC, RefObject, useCallback, useEffect, useMemo, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Nav, TabContainer } from 'react-bootstrap'
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import { RailTabKey, useRailContext } from '../../contexts/rail-context'
|
||||
import FileTreeOutlinePanel from '../file-tree/file-tree-outline-panel'
|
||||
import { ChatIndicator, ChatPane } from '../chat/chat'
|
||||
import {
|
||||
RailTabKey,
|
||||
useRailContext,
|
||||
} from '@/features/ide-react/context/rail-context'
|
||||
import FileTreeOutlinePanel from '@/features/ide-redesign/components/file-tree/file-tree-outline-panel'
|
||||
import {
|
||||
ChatIndicator,
|
||||
ChatPane,
|
||||
} from '@/features/ide-redesign/components/chat/chat'
|
||||
import getMeta from '@/utils/meta'
|
||||
import classNames from 'classnames'
|
||||
import IntegrationsPanel from '../integrations-panel/integrations-panel'
|
||||
import IntegrationsPanel from '@/features/ide-redesign/components/integrations-panel/integrations-panel'
|
||||
import { useChatContext } from '@/features/chat/context/chat-context'
|
||||
import { useEditorAnalytics } from '@/shared/hooks/use-editor-analytics'
|
||||
import {
|
||||
FullProjectSearchPanel,
|
||||
hasFullProjectSearch,
|
||||
} from '../full-project-search-panel'
|
||||
} from '@/features/ide-redesign/components/full-project-search-panel'
|
||||
import { sendSearchEvent } from '@/features/event-tracking/search-events'
|
||||
import { useProjectContext } from '@/shared/context/project-context'
|
||||
import { useCommandProvider } from '@/features/ide-react/hooks/use-command-provider'
|
||||
import RailHelpDropdown from './rail-help-dropdown'
|
||||
import RailTab from './rail-tab'
|
||||
import RailActionElement, { RailAction } from './rail-action-element'
|
||||
import { RailElement } from '../../utils/rail-types'
|
||||
import { RailElement } from '@/features/ide-react/util/rail-types'
|
||||
import RailPanel from './rail-panel'
|
||||
import RailResizeHandle from './rail-resize-handle'
|
||||
import RailModals from './rail-modals'
|
||||
import RailOverflowDropdown from './rail-overflow-dropdown'
|
||||
import useRailOverflow from '../../hooks/use-rail-overflow'
|
||||
import EditorTourRailTooltip from '../editor-tour/editor-tour-rail-tooltip'
|
||||
import useRailOverflow from '@/features/ide-redesign/hooks/use-rail-overflow'
|
||||
import EditorTourRailTooltip from '@/features/ide-redesign/components/editor-tour/editor-tour-rail-tooltip'
|
||||
import importOverleafModules from '../../../../../macros/import-overleaf-module.macro'
|
||||
import EditorTourThemeTooltip from '../editor-tour/editor-tour-theme-tooltip'
|
||||
import EditorTourGotQuestionsTooltip from '../editor-tour/editor-tour-got-questions'
|
||||
import { shouldIncludeElement } from '../../utils/rail-utils'
|
||||
import EditorTourThemeTooltip from '@/features/ide-redesign/components/editor-tour/editor-tour-theme-tooltip'
|
||||
import EditorTourGotQuestionsTooltip from '@/features/ide-redesign/components/editor-tour/editor-tour-got-questions'
|
||||
import { shouldIncludeElement } from '@/features/ide-react/util/rail-utils'
|
||||
import { useEditorContext } from '@/shared/context/editor-context'
|
||||
import useEventListener from '@/shared/hooks/use-event-listener'
|
||||
|
||||
@@ -16,7 +16,7 @@ import CommandDropdown, {
|
||||
MenuSectionStructure,
|
||||
MenuStructure,
|
||||
} from './command-dropdown'
|
||||
import { useRailContext } from '../../contexts/rail-context'
|
||||
import { useRailContext } from '../../context/rail-context'
|
||||
import WordCountModal from '@/features/word-count-modal/components/word-count-modal'
|
||||
import { isSplitTestEnabled } from '@/utils/splitTestUtils'
|
||||
import { useDetachCompileContext as useCompileContext } from '@/shared/context/detach-compile-context'
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
useOnlineUsersContext,
|
||||
} from '@/features/ide-react/context/online-users-context'
|
||||
import { useCallback } from 'react'
|
||||
import { OnlineUsersWidget } from '../online-users/online-users-widget'
|
||||
import { OnlineUsersWidget } from '@/features/ide-redesign/components/online-users/online-users-widget'
|
||||
|
||||
export const OnlineUsers = () => {
|
||||
const { openDoc } = useEditorManagerContext()
|
||||
@@ -20,7 +20,7 @@ import { OnlineUsersProvider } from '@/features/ide-react/context/online-users-c
|
||||
import { OutlineProvider } from '@/features/ide-react/context/outline-context'
|
||||
import { PermissionsProvider } from '@/features/ide-react/context/permissions-context'
|
||||
import { ProjectProvider } from '@/shared/context/project-context'
|
||||
import { RailProvider } from '@/features/ide-redesign/contexts/rail-context'
|
||||
import { RailProvider } from '@/features/ide-react/context/rail-context'
|
||||
import { ProjectSettingsProvider } from '@/features/editor-left-menu/context/project-settings-context'
|
||||
import { ReferencesProvider } from '@/features/ide-react/context/references-context'
|
||||
import { SnapshotProvider } from '@/features/ide-react/context/snapshot-context'
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import useCollapsiblePanel from '@/features/ide-react/hooks/use-collapsible-panel'
|
||||
import useDebounce from '@/shared/hooks/use-debounce'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { ImperativePanelHandle } from 'react-resizable-panels'
|
||||
|
||||
export const useChatPane = () => {
|
||||
const { chatIsOpen: isOpen, setChatIsOpen: setIsOpen } = useLayoutContext()
|
||||
const [resizing, setResizing] = useState(false)
|
||||
const panelRef = useRef<ImperativePanelHandle>(null)
|
||||
|
||||
// Keep track of a debounced local state variable for panel openness and
|
||||
// only update the external openness state when the debounced value changes.
|
||||
// This prevents successive calls to onCollapse and onExpand from
|
||||
// react-resizable-panels updating the openness state multiple times in quick
|
||||
// succession, which causes confusing behaviour that is different in React 17
|
||||
// and 18. Collapsing the chat pane on initialization is necessary because
|
||||
// react-resizable-panels does not provide a way to specify both that a panel
|
||||
// should be collapsed and a default size for the panel when expanded.
|
||||
const [localIsOpen, setLocalIsOpen] = useState(isOpen)
|
||||
const debouncedLocalIsOpen = useDebounce(localIsOpen, 100)
|
||||
|
||||
useCollapsiblePanel(isOpen, panelRef)
|
||||
|
||||
const togglePane = useCallback(() => {
|
||||
setIsOpen(value => !value)
|
||||
}, [setIsOpen])
|
||||
|
||||
const handlePaneExpand = useCallback(() => {
|
||||
setLocalIsOpen(true)
|
||||
}, [])
|
||||
|
||||
const handlePaneCollapse = useCallback(() => {
|
||||
setLocalIsOpen(false)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
setIsOpen(debouncedLocalIsOpen)
|
||||
}, [debouncedLocalIsOpen, setIsOpen])
|
||||
|
||||
return {
|
||||
isOpen,
|
||||
panelRef,
|
||||
resizing,
|
||||
setResizing,
|
||||
togglePane,
|
||||
handlePaneExpand,
|
||||
handlePaneCollapse,
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
import {
|
||||
RailTabKey,
|
||||
useRailContext,
|
||||
} from '@/features/ide-redesign/contexts/rail-context'
|
||||
} from '@/features/ide-react/context/rail-context'
|
||||
|
||||
function createEditingSessionHeartbeatData(
|
||||
editorType: EditorType,
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import { useCallback, useRef, useState } from 'react'
|
||||
import useCollapsiblePanel from '@/features/ide-react/hooks/use-collapsible-panel'
|
||||
import { ImperativePanelHandle } from 'react-resizable-panels'
|
||||
|
||||
export const useSidebarPane = () => {
|
||||
const [isOpen, setIsOpen] = useState(true)
|
||||
const [resizing, setResizing] = useState(false)
|
||||
const panelRef = useRef<ImperativePanelHandle>(null)
|
||||
useCollapsiblePanel(isOpen, panelRef)
|
||||
|
||||
const togglePane = useCallback(() => {
|
||||
setIsOpen(value => !value)
|
||||
}, [])
|
||||
|
||||
const handlePaneExpand = useCallback(() => {
|
||||
setIsOpen(true)
|
||||
}, [])
|
||||
|
||||
const handlePaneCollapse = useCallback(() => {
|
||||
setIsOpen(false)
|
||||
}, [])
|
||||
|
||||
return {
|
||||
isOpen,
|
||||
setIsOpen,
|
||||
panelRef,
|
||||
togglePane,
|
||||
handlePaneExpand,
|
||||
handlePaneCollapse,
|
||||
resizing,
|
||||
setResizing,
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { AvailableUnfilledIcon } from '@/shared/components/material-icon'
|
||||
import { RailTabKey } from '../contexts/rail-context'
|
||||
import { RailTabKey } from '../context/rail-context'
|
||||
import { FC, ReactElement } from 'react'
|
||||
import RailTab from '@/features/ide-redesign/components/rail/rail-tab'
|
||||
import RailTab from '@/features/ide-react/components/rail/rail-tab'
|
||||
|
||||
export type CustomRailTabIcon = FC<{ open: boolean; title: string }>
|
||||
|
||||
@@ -9,8 +9,8 @@ import { useUserContext } from '@/shared/context/user-context'
|
||||
import { lazy, Suspense, useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import classNames from 'classnames'
|
||||
import { RailIndicator } from '../rail/rail-indicator'
|
||||
import RailPanelHeader from '../rail/rail-panel-header'
|
||||
import { RailIndicator } from '@/features/ide-react/components/rail/rail-indicator'
|
||||
import RailPanelHeader from '@/features/ide-react/components/rail/rail-panel-header'
|
||||
|
||||
const MessageList = lazy(() => import('../../../chat/components/message-list'))
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import React from 'react'
|
||||
import { useCommandProvider } from '@/features/ide-react/hooks/use-command-provider'
|
||||
import { usePermissionsContext } from '@/features/ide-react/context/permissions-context'
|
||||
import FileTreeActionButton from './file-tree-action-button'
|
||||
import { useRailContext } from '../../contexts/rail-context'
|
||||
import { useRailContext } from '../../../ide-react/context/rail-context'
|
||||
|
||||
export default function FileTreeActionButtons({
|
||||
fileTreeExpanded,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FC, JSXElementConstructor, useCallback } from 'react'
|
||||
import importOverleafModules from '../../../../../macros/import-overleaf-module.macro'
|
||||
import { useRailContext } from '../../contexts/rail-context'
|
||||
import { useRailContext } from '../../../ide-react/context/rail-context'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
const [contactUsModalModules] = importOverleafModules('contactUsModal')
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FC } from 'react'
|
||||
import { useProjectContext } from '@/shared/context/project-context'
|
||||
import HotkeysModal from '@/features/hotkeys-modal/components/hotkeys-modal'
|
||||
import { isMac } from '@/shared/utils/os'
|
||||
import { useRailContext } from '../../contexts/rail-context'
|
||||
import { useRailContext } from '../../../ide-react/context/rail-context'
|
||||
|
||||
export const RailHelpShowHotkeysModal: FC<{ show: boolean }> = ({ show }) => {
|
||||
const { features } = useProjectContext()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ElementType } from 'react'
|
||||
import importOverleafModules from '../../../../../macros/import-overleaf-module.macro'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import RailPanelHeader from '../rail/rail-panel-header'
|
||||
import RailPanelHeader from '@/features/ide-react/components/rail/rail-panel-header'
|
||||
|
||||
const integrationPanelComponents = importOverleafModules(
|
||||
'integrationPanelComponents'
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
import { Panel, PanelGroup } from 'react-resizable-panels'
|
||||
import classNames from 'classnames'
|
||||
import { HorizontalResizeHandle } from '@/features/ide-react/components/resize/horizontal-resize-handle'
|
||||
import PdfPreview from '@/features/pdf-preview/components/pdf-preview'
|
||||
import { RailLayout } from './rail/rail'
|
||||
import { Toolbar } from './toolbar/toolbar'
|
||||
import { HorizontalToggler } from '@/features/ide-react/components/resize/horizontal-toggler'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { usePdfPane } from '@/features/ide-react/hooks/use-pdf-pane'
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import { ElementType, useState } from 'react'
|
||||
import EditorPanel from './editor-panel'
|
||||
import { useRailContext } from '../contexts/rail-context'
|
||||
import HistoryContainer from '@/features/ide-react/components/history-container'
|
||||
import { DefaultSynctexControl } from '@/features/pdf-preview/components/detach-synctex-control'
|
||||
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
|
||||
|
||||
const mainEditorLayoutPanels: Array<{
|
||||
import: { default: ElementType }
|
||||
path: string
|
||||
}> = importOverleafModules('mainEditorLayoutPanels')
|
||||
|
||||
const mainEditorLayoutModalsModules: Array<{
|
||||
import: { default: ElementType }
|
||||
path: string
|
||||
}> = importOverleafModules('mainEditorLayoutModals')
|
||||
|
||||
export default function MainLayout() {
|
||||
const [resizing, setResizing] = useState(false)
|
||||
const { resizing: railResizing } = useRailContext()
|
||||
const {
|
||||
togglePdfPane,
|
||||
handlePdfPaneExpand,
|
||||
handlePdfPaneCollapse,
|
||||
setPdfIsOpen: setIsPdfOpen,
|
||||
pdfIsOpen: isPdfOpen,
|
||||
pdfPanelRef,
|
||||
} = usePdfPane()
|
||||
const { view, pdfLayout } = useLayoutContext()
|
||||
|
||||
const editorIsOpen =
|
||||
view === 'editor' || view === 'file' || pdfLayout === 'sideBySide'
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="ide-redesign-main">
|
||||
<Toolbar />
|
||||
<div className="ide-redesign-body">
|
||||
<PanelGroup
|
||||
autoSaveId="ide-redesign-outer-layout"
|
||||
direction="horizontal"
|
||||
className={classNames('ide-redesign-inner', {
|
||||
'ide-panel-group-resizing': resizing || railResizing,
|
||||
})}
|
||||
>
|
||||
<RailLayout />
|
||||
<Panel id="ide-redesign-editor-and-pdf-panel" order={2}>
|
||||
<HistoryContainer />
|
||||
<PanelGroup
|
||||
autoSaveId="ide-redesign-editor-and-pdf-panel-group"
|
||||
direction="horizontal"
|
||||
className={classNames({
|
||||
hidden: view === 'history',
|
||||
})}
|
||||
>
|
||||
<Panel
|
||||
id="ide-redesign-editor-panel"
|
||||
order={1}
|
||||
className={classNames({
|
||||
hidden: !editorIsOpen || view === 'history',
|
||||
})}
|
||||
minSize={5}
|
||||
defaultSize={50}
|
||||
tagName="section"
|
||||
aria-label={t('editor')}
|
||||
>
|
||||
<div className="ide-redesign-editor-container">
|
||||
<EditorPanel />
|
||||
</div>
|
||||
</Panel>
|
||||
<HorizontalResizeHandle
|
||||
resizable={pdfLayout === 'sideBySide'}
|
||||
onDragging={setResizing}
|
||||
onDoubleClick={togglePdfPane}
|
||||
hitAreaMargins={{ coarse: 0, fine: 0 }}
|
||||
className={classNames({
|
||||
hidden: !editorIsOpen,
|
||||
})}
|
||||
>
|
||||
<HorizontalToggler
|
||||
id="ide-redesign-pdf-panel"
|
||||
togglerType="east"
|
||||
isOpen={isPdfOpen}
|
||||
setIsOpen={setIsPdfOpen}
|
||||
tooltipWhenOpen={t('tooltip_hide_pdf')}
|
||||
tooltipWhenClosed={t('tooltip_show_pdf')}
|
||||
/>
|
||||
{pdfLayout === 'sideBySide' && (
|
||||
<div className="synctex-controls">
|
||||
<DefaultSynctexControl />
|
||||
</div>
|
||||
)}
|
||||
</HorizontalResizeHandle>
|
||||
<Panel
|
||||
collapsible
|
||||
className={classNames('ide-redesign-pdf-container', {
|
||||
hidden: view === 'history',
|
||||
})}
|
||||
id="ide-redesign-pdf-panel"
|
||||
order={2}
|
||||
defaultSize={50}
|
||||
minSize={5}
|
||||
ref={pdfPanelRef}
|
||||
onExpand={handlePdfPaneExpand}
|
||||
onCollapse={handlePdfPaneCollapse}
|
||||
tagName="section"
|
||||
aria-label={t('pdf_preview')}
|
||||
>
|
||||
<PdfPreview />
|
||||
{pdfLayout === 'flat' && view === 'pdf' && (
|
||||
<div className="synctex-controls" hidden>
|
||||
<DefaultSynctexControl />
|
||||
</div>
|
||||
)}
|
||||
</Panel>
|
||||
</PanelGroup>
|
||||
</Panel>
|
||||
{mainEditorLayoutPanels.map(
|
||||
({ import: { default: Component }, path }, i) => {
|
||||
return <Component key={path} order={i + 3} />
|
||||
}
|
||||
)}
|
||||
</PanelGroup>
|
||||
</div>
|
||||
{mainEditorLayoutModalsModules.map(
|
||||
({ import: { default: Component }, path }) => (
|
||||
<Component key={path} />
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import { useCallback } from 'react'
|
||||
import ButtonSetting from '../button-setting'
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import { useRailContext } from '@/features/ide-redesign/contexts/rail-context'
|
||||
import { useRailContext } from '@/features/ide-react/context/rail-context'
|
||||
|
||||
export default function DictionarySetting() {
|
||||
const { t } = useTranslation()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import DictionaryModal from '@/features/dictionary/components/dictionary-modal'
|
||||
import { useRailContext } from '@/features/ide-redesign/contexts/rail-context'
|
||||
import { useRailContext } from '@/features/ide-react/context/rail-context'
|
||||
import { useCallback } from 'react'
|
||||
|
||||
export default function DictionarySettingsModal({ show }: { show: boolean }) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useState } from 'react'
|
||||
import { RailElement } from '../utils/rail-types'
|
||||
import { RailElement } from '../../ide-react/util/rail-types'
|
||||
import { useResizeObserver } from '@/shared/hooks/use-resize-observer'
|
||||
|
||||
const useRailOverflow = (railTabs: RailElement[]) => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ReviewPanelResolvedThreadsButton } from './review-panel-resolved-thread
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { PanelHeading } from '@/shared/components/panel-heading'
|
||||
import useReviewPanelLayout from '../hooks/use-review-panel-layout'
|
||||
import RailPanelHeader from '@/features/ide-redesign/components/rail/rail-panel-header'
|
||||
import RailPanelHeader from '@/features/ide-react/components/rail/rail-panel-header'
|
||||
import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
|
||||
|
||||
const ReviewPanelHeader: FC = () => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import { useRangesContext } from '../context/ranges-context'
|
||||
import { useThreadsContext } from '@/features/review-panel/context/threads-context'
|
||||
import { hasActiveRange } from '@/features/review-panel/utils/has-active-range'
|
||||
import { useRailContext } from '@/features/ide-redesign/contexts/rail-context'
|
||||
import { useRailContext } from '@/features/ide-react/context/rail-context'
|
||||
import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
|
||||
import { useCallback } from 'react'
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useCodeMirrorViewContext } from './codemirror-context'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
|
||||
import { useRailContext } from '@/features/ide-redesign/contexts/rail-context'
|
||||
import { useRailContext } from '@/features/ide-react/context/rail-context'
|
||||
|
||||
export const FullProjectSearchButton = ({ query }: { query: SearchQuery }) => {
|
||||
const view = useCodeMirrorViewContext()
|
||||
|
||||
@@ -20,7 +20,7 @@ import useScopeEventEmitter from '@/shared/hooks/use-scope-event-emitter'
|
||||
import useEventListener from '@/shared/hooks/use-event-listener'
|
||||
import { isMac } from '@/shared/utils/os'
|
||||
import { sendSearchEvent } from '@/features/event-tracking/search-events'
|
||||
import { useRailContext } from '@/features/ide-redesign/contexts/rail-context'
|
||||
import { useRailContext } from '@/features/ide-react/context/rail-context'
|
||||
import usePersistedState from '@/shared/hooks/use-persisted-state'
|
||||
import { repositionAllTooltips } from '@/features/source-editor/extensions/tooltips-reposition'
|
||||
import { useEditorAnalytics } from '@/shared/hooks/use-editor-analytics'
|
||||
|
||||
@@ -141,12 +141,6 @@ $editor-toggler-bg-dark-color: color.adjust(
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
// Ensure an element with class "full-size", such as the binary file view, stays within the bounds of the panel
|
||||
.ide-react-panel {
|
||||
position: relative;
|
||||
container-type: size;
|
||||
}
|
||||
|
||||
.ide-panel-group-resizing {
|
||||
background-color: var(--white);
|
||||
|
||||
|
||||
@@ -1683,7 +1683,6 @@
|
||||
"pdf_only_hide_editor": "PDF only <0>(hide editor)</0>",
|
||||
"pdf_preview": "PDF preview",
|
||||
"pdf_preview_error": "There was a problem displaying the compilation results for this project.",
|
||||
"pdf_preview_logs": "PDF preview and logs",
|
||||
"pdf_rendering_error": "PDF Rendering Error",
|
||||
"pdf_unavailable_for_download": "PDF unavailable for download",
|
||||
"pdf_viewer": "PDF Viewer",
|
||||
@@ -1794,7 +1793,6 @@
|
||||
"project_figure_modal": "Project",
|
||||
"project_files": "Project files",
|
||||
"project_files_history": "Project files history",
|
||||
"project_files_outline": "Project files and outline",
|
||||
"project_flagged_too_many_compiles": "This project has been flagged for compiling too often. The limit will be lifted shortly.",
|
||||
"project_has_too_many_files": "This project has reached the 2000 file limit",
|
||||
"project_has_too_many_files_limit": "This project has reached the __limit__ file limit",
|
||||
@@ -2546,10 +2544,8 @@
|
||||
"toolbar_undo": "Undo",
|
||||
"toolbar_undo_redo_actions": "Undo/Redo actions",
|
||||
"tools": "Tools",
|
||||
"tooltip_hide_filetree": "Click to hide the file tree",
|
||||
"tooltip_hide_panel": "Click to hide the panel",
|
||||
"tooltip_hide_pdf": "Click to hide the PDF",
|
||||
"tooltip_show_filetree": "Click to show the file tree",
|
||||
"tooltip_show_panel": "Click to show the panel",
|
||||
"tooltip_show_pdf": "Click to show the PDF",
|
||||
"top_pick": "Top pick",
|
||||
|
||||
@@ -36,7 +36,7 @@ import { useFileTreePathContext } from '@/features/file-tree/contexts/file-tree-
|
||||
import { FullProjectSearchResults } from './full-project-search-results'
|
||||
import { signalWithTimeout } from '@/utils/abort-signal'
|
||||
import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
|
||||
import RailPanelHeader from '@/features/ide-redesign/components/rail/rail-panel-header'
|
||||
import RailPanelHeader from '@/features/ide-react/components/rail/rail-panel-header'
|
||||
import { useActiveOverallTheme } from '@/shared/hooks/use-active-overall-theme'
|
||||
|
||||
const FullProjectSearchUI: FC = () => {
|
||||
|
||||
@@ -63,7 +63,7 @@ describe('<FileViewHeader/>', function () {
|
||||
},
|
||||
created: new Date(2021, 1, 17, 3, 24).toISOString(),
|
||||
}
|
||||
// FIXME: This should be tested through the <EditorAndPdf /> component instead
|
||||
// FIXME: This should be tested through the <EditorPanel /> component instead
|
||||
const fileShown = fileViewFile(fileFromServer)
|
||||
renderWithEditorContext(<FileViewHeader file={fileShown} />)
|
||||
screen.getByText('Imported from', { exact: false })
|
||||
|
||||
@@ -3,7 +3,7 @@ import { expect } from 'chai'
|
||||
import { SettingsModalProvider } from '@/features/ide-redesign/contexts/settings-modal-context'
|
||||
import { EditorProviders } from '../../../helpers/editor-providers'
|
||||
import DictionarySetting from '@/features/ide-redesign/components/settings/editor-settings/dictionary-setting'
|
||||
import RailModals from '@/features/ide-redesign/components/rail/rail-modals'
|
||||
import RailModals from '@/features/ide-react/components/rail/rail-modals'
|
||||
|
||||
describe('<DictionarySetting />', function () {
|
||||
it('open dictionary modal', function () {
|
||||
|
||||
Reference in New Issue
Block a user