overleaf-cep/services/web/frontend/js/features/outline/hooks/use-nested-outline.ts
David d7ad742ba3 Merge pull request #23747 from overleaf/dp-breadcrumbs
Add file breadcrumbs to new editor

GitOrigin-RevId: 54bde446ad632976503a2c4aff915c862bad710e
2025-03-11 09:05:08 +00:00

70 lines
1.7 KiB
TypeScript

import { useEffect, useRef, useState } from 'react'
import {
FlatOutlineState,
PartialFlatOutline,
useOutlineContext,
} from '@/features/ide-react/context/outline-context'
import {
nestOutline,
Outline,
} from '@/features/source-editor/utils/tree-operations/outline'
import { debugConsole } from '@/utils/debugging'
const outlineChanged = (
a: PartialFlatOutline | undefined,
b: PartialFlatOutline
): boolean => {
if (!a) {
return true
}
if (a.length !== b.length) {
return true
}
for (let i = 0; i < a.length; i++) {
const aItem = a[i]
const bItem = b[i]
if (
aItem.level !== bItem.level ||
aItem.line !== bItem.line ||
aItem.title !== bItem.title
) {
return true
}
}
return false
}
export default function useNestedOutline() {
const { flatOutline } = useOutlineContext()
const [nestedOutline, setNestedOutline] = useState<{
items: Outline[]
partial: boolean
}>(() => ({ items: [], partial: false }))
const prevFlatOutlineRef = useRef<FlatOutlineState>(undefined)
// when the flat outline changes, calculate the nested outline
// TODO: only calculate when outlineExpanded is true
useEffect(() => {
const prevFlatOutline = prevFlatOutlineRef.current
prevFlatOutlineRef.current = flatOutline
if (flatOutline) {
if (outlineChanged(prevFlatOutline?.items, flatOutline.items)) {
debugConsole.log('Rebuilding changed outline')
setNestedOutline({
items: nestOutline(flatOutline.items),
partial: flatOutline.partial,
})
}
} else {
setNestedOutline({ items: [], partial: false })
}
}, [flatOutline])
return nestedOutline
}