Merge pull request #27384 from overleaf/dp-drag-file-tree-outline

Allow file tree and outline to be expandable and collapsible by dragging

GitOrigin-RevId: e25f0d263b1446537cdb42ef52fe1c486e855773
This commit is contained in:
David
2025-08-05 13:58:41 +01:00
committed by Copybot
parent 203e2e914b
commit 075e18c7c8
5 changed files with 79 additions and 14 deletions

View File

@@ -32,6 +32,8 @@ const FileTreeOpenContext = createContext<
handleFileTreeDelete: (entity: FileTreeFindResult) => void
fileTreeExpanded: boolean
toggleFileTreeExpanded: () => void
expandFileTree: () => void
collapseFileTree: () => void
}
| undefined
>(undefined)
@@ -59,6 +61,14 @@ export const FileTreeOpenProvider: FC<React.PropsWithChildren> = ({
setFileTreeExpanded(prev => !prev)
}, [])
const expandFileTree = useCallback(() => {
setFileTreeExpanded(true)
}, [])
const collapseFileTree = useCallback(() => {
setFileTreeExpanded(false)
}, [])
const handleFileTreeInit = useCallback(() => {
setFileTreeReady(true)
}, [])
@@ -144,6 +154,8 @@ export const FileTreeOpenProvider: FC<React.PropsWithChildren> = ({
handleFileTreeDelete,
fileTreeExpanded,
toggleFileTreeExpanded,
expandFileTree,
collapseFileTree,
}
}, [
handleFileTreeDelete,
@@ -153,6 +165,8 @@ export const FileTreeOpenProvider: FC<React.PropsWithChildren> = ({
selectedEntityCount,
fileTreeExpanded,
toggleFileTreeExpanded,
expandFileTree,
collapseFileTree,
])
return (

View File

@@ -38,6 +38,8 @@ const OutlineContext = createContext<
canShowOutline: boolean
outlineExpanded: boolean
toggleOutlineExpanded: () => void
expandOutline: () => void
collapseOutline: () => void
}
| undefined
>(undefined)
@@ -133,15 +135,29 @@ export const OutlineProvider: FC<React.PropsWithChildren> = ({ children }) => {
const canShowOutline = isTexFile && !binaryFileOpened
const toggleOutlineExpanded = useCallback(() => {
const expandOutline = useCallback(() => {
if (canShowOutline) {
localStorage.setItem(storageKey, !outlineExpanded)
eventTracking.sendMB(
outlineExpanded ? 'outline-collapse' : 'outline-expand'
)
setOutlineExpanded(!outlineExpanded)
localStorage.setItem(storageKey, true)
eventTracking.sendMB('outline-expand')
setOutlineExpanded(true)
}
}, [canShowOutline, outlineExpanded, storageKey])
}, [canShowOutline, storageKey])
const collapseOutline = useCallback(() => {
if (canShowOutline) {
localStorage.setItem(storageKey, false)
eventTracking.sendMB('outline-collapse')
setOutlineExpanded(false)
}
}, [canShowOutline, storageKey])
const toggleOutlineExpanded = useCallback(() => {
if (outlineExpanded) {
collapseOutline()
} else {
expandOutline()
}
}, [collapseOutline, expandOutline, outlineExpanded])
const value = useMemo(
() => ({
@@ -152,6 +168,8 @@ export const OutlineProvider: FC<React.PropsWithChildren> = ({ children }) => {
canShowOutline,
outlineExpanded,
toggleOutlineExpanded,
expandOutline,
collapseOutline,
}),
[
flatOutline,
@@ -160,6 +178,8 @@ export const OutlineProvider: FC<React.PropsWithChildren> = ({ children }) => {
canShowOutline,
outlineExpanded,
toggleOutlineExpanded,
expandOutline,
collapseOutline,
]
)

View File

@@ -4,11 +4,18 @@ import { useRef } from 'react'
import { ImperativePanelHandle } from 'react-resizable-panels'
export const useOutlinePane = () => {
const { canShowOutline, outlineExpanded } = useOutlineContext()
const { canShowOutline, outlineExpanded, expandOutline, collapseOutline } =
useOutlineContext()
const outlinePanelRef = useRef<ImperativePanelHandle>(null)
const outlineEnabled = canShowOutline && outlineExpanded
useCollapsiblePanel(outlineEnabled, outlinePanelRef)
return { outlineEnabled, outlinePanelRef }
return {
outlineEnabled,
canShowOutline,
outlinePanelRef,
expandOutline,
collapseOutline,
}
}

View File

@@ -7,8 +7,14 @@ import useCollapsibleFileTree from '../../hooks/use-collapsible-file-tree'
import classNames from 'classnames'
function FileTreeOutlinePanel() {
const { outlineEnabled, outlinePanelRef } = useOutlinePane()
const { fileTreeExpanded, fileTreePanelRef } = useCollapsibleFileTree()
const { canShowOutline, outlinePanelRef, expandOutline, collapseOutline } =
useOutlinePane()
const {
fileTreeExpanded,
fileTreePanelRef,
expandFileTree,
collapseFileTree,
} = useCollapsibleFileTree()
return (
<PanelGroup
@@ -25,12 +31,15 @@ function FileTreeOutlinePanel() {
order={1}
collapsible
ref={fileTreePanelRef}
onExpand={expandFileTree}
onCollapse={collapseFileTree}
minSize={10}
>
<FileTree />
</Panel>
<VerticalResizeHandle
hitAreaMargins={{ coarse: 0, fine: 0 }}
disabled={!outlineEnabled || !fileTreeExpanded}
disabled={!canShowOutline}
/>
<Panel
className="file-outline-panel"
@@ -39,6 +48,9 @@ function FileTreeOutlinePanel() {
order={2}
collapsible
ref={outlinePanelRef}
onExpand={expandOutline}
onCollapse={collapseOutline}
minSize={10}
>
<OutlineContainer />
</Panel>

View File

@@ -4,9 +4,21 @@ import useCollapsiblePanel from '@/features/ide-react/hooks/use-collapsible-pane
import { useFileTreeOpenContext } from '@/features/ide-react/context/file-tree-open-context'
export default function useCollapsibleFileTree() {
const { fileTreeExpanded, toggleFileTreeExpanded } = useFileTreeOpenContext()
const {
fileTreeExpanded,
toggleFileTreeExpanded,
expandFileTree,
collapseFileTree,
} = useFileTreeOpenContext()
const fileTreePanelRef = useRef<ImperativePanelHandle>(null)
useCollapsiblePanel(fileTreeExpanded, fileTreePanelRef)
return { fileTreeExpanded, fileTreePanelRef, toggleFileTreeExpanded }
return {
fileTreeExpanded,
fileTreePanelRef,
toggleFileTreeExpanded,
expandFileTree,
collapseFileTree,
}
}