Merge pull request #13492 from overleaf/td-review-panel-sync-height

Add hook for synchronizing review panel height with editor content height

GitOrigin-RevId: ef0a96ef4e77e7858b28f6f65254a4b0c1e778ea
This commit is contained in:
ilkin-overleaf
2023-06-19 17:08:13 +03:00
committed by Copybot
parent 423f2604db
commit 15db0ce4e3
6 changed files with 65 additions and 1 deletions

View File

@@ -1,6 +1,11 @@
import Container from './container'
import useCodeMirrorContentHeight from '../../hooks/use-codemirror-content-height'
function CurrentFileContainer() {
const contentHeight = useCodeMirrorContentHeight()
console.log('Review panel got content height', contentHeight)
return (
<Container>
<div

View File

@@ -0,0 +1,15 @@
import { EditorView } from '@codemirror/view'
/**
* An extension that triggers a custom DOM event whenever the editor geometry
* changes. This is used to synchronize the editor content and review panel
* height in "Current file" mode.
*/
export const geometryChangeEvent = (reactReviewPanel: boolean) =>
reactReviewPanel
? EditorView.updateListener.of(update => {
if (update.geometryChanged) {
window.dispatchEvent(new CustomEvent('editor:geometry-change'))
}
})
: []

View File

@@ -45,6 +45,7 @@ import { keymaps } from './keymaps'
import { shortcuts } from './shortcuts'
import { effectListeners } from './effect-listeners'
import { highlightSpecialChars } from './highlight-special-chars'
import { geometryChangeEvent } from './geometry-change-event'
const moduleExtensions: Array<() => Extension> = importOverleafModules(
'sourceEditorExtensions'
@@ -130,4 +131,5 @@ export const createExtensions = (options: Record<string, any>): Extension[] => [
moduleExtensions.map(extension => extension()),
thirdPartyExtensions(),
effectListeners(),
geometryChangeEvent(options.reactReviewPanel),
]

View File

@@ -0,0 +1,12 @@
import { EditorView } from '@codemirror/view'
import useCodeMirrorMeasurement from './use-codemirror-measurement'
// view.contentHeight, which is measured for us by CodeMirror and is what the
// gutters use, is sometimes a pixel or so short of the full height of the
// editor content, which leaves a small gap at the bottom, so use the DOM
// scrollHeight property instead.
const measureContentHeight = (view: EditorView) => view.contentDOM.scrollHeight
export default function useCodeMirrorContentHeight() {
return useCodeMirrorMeasurement('content-height', measureContentHeight)
}

View File

@@ -0,0 +1,27 @@
import { useCallback, useState } from 'react'
import { useCodeMirrorViewContext } from '../components/codemirror-editor'
import { EditorView } from '@codemirror/view'
import useEventListener from '../../../shared/hooks/use-event-listener'
export default function useCodeMirrorMeasurement(
key: string,
measure: (view: EditorView) => number
) {
const view = useCodeMirrorViewContext()
const [measurement, setMeasurement] = useState(measure(view))
useEventListener(
'editor:geometry-change',
useCallback(() => {
view.requestMeasure({
key,
read: () => measure(view),
write(value) {
setMeasurement(value)
},
})
}, [view, measure, key])
)
return measurement
}

View File

@@ -47,6 +47,7 @@ import { EditorView } from '@codemirror/view'
import { CurrentDoc } from '../../../../../types/current-doc'
import { useErrorHandler } from 'react-error-boundary'
import { setVisual } from '../extensions/visual/visual'
import getMeta from '../../../utils/meta'
function useCodeMirrorScope(view: EditorView) {
const ide = useIdeContext()
@@ -86,6 +87,7 @@ function useCodeMirrorScope(view: EditorView) {
)
const [visual] = useScopeValue<boolean>('editor.showVisual')
const reactReviewPanel: boolean = getMeta('ol-isReviewPanelReact')
// build the translation phrases
const phrases = usePhrases()
@@ -266,6 +268,7 @@ function useCodeMirrorScope(view: EditorView) {
visual: visualRef.current,
changeManager: createChangeManager(view, currentDoc),
handleError,
reactReviewPanel,
}),
})
view.setState(state)
@@ -295,7 +298,7 @@ function useCodeMirrorScope(view: EditorView) {
}
// IMPORTANT: This effect must not depend on anything variable apart from currentDoc,
// as the editor state is recreated when the effect runs.
}, [view, currentDoc, handleError])
}, [view, currentDoc, handleError, reactReviewPanel])
useEffect(() => {
visualRef.current.visual = visual