mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-29 12:01:32 +02:00
[cm6] Improve "vertical overflow" handling (#12405)
* Avoid setting style on the editor view whenever overflowPaddingState changes * Round values in recalculateScreenPositions * Refactor ignoreGeometryChangesUntil slightly * Restore the original value GitOrigin-RevId: 75c57be21dd16a748c0d9b14058386849a80b831
This commit is contained in:
@@ -63,8 +63,8 @@ export const createChangeManager = (
|
||||
)
|
||||
|
||||
if (coords) {
|
||||
const y = coords.top - contentRect.top - editorPaddingTop
|
||||
const height = coords.bottom - coords.top
|
||||
const y = Math.round(coords.top - contentRect.top - editorPaddingTop)
|
||||
const height = Math.round(coords.bottom - coords.top)
|
||||
|
||||
entry.screenPos = { y, height, editorPaddingTop }
|
||||
}
|
||||
@@ -442,8 +442,7 @@ export const createChangeManager = (
|
||||
window.removeEventListener('review-panel:event', reviewPanelEventListener)
|
||||
}
|
||||
|
||||
let lastUpdatedTopPaddingAt = 0
|
||||
const PADDING_GEOMETRY_CHANGE_INTERVAL = 50
|
||||
let ignoreGeometryChangesUntil = 0
|
||||
|
||||
return {
|
||||
initialize() {
|
||||
@@ -452,8 +451,18 @@ export const createChangeManager = (
|
||||
},
|
||||
handleUpdate(update: ViewUpdate) {
|
||||
if (updateSetsVerticalOverflow(update)) {
|
||||
lastUpdatedTopPaddingAt = Date.now()
|
||||
ignoreGeometryChangesUntil = Date.now() + 50 // ignore changes for 50ms
|
||||
} else if (
|
||||
(update.geometryChanged || update.viewportChanged) &&
|
||||
Date.now() < ignoreGeometryChangesUntil
|
||||
) {
|
||||
// Ignore a change to the editor geometry that occurs immediately after
|
||||
// an update to the vertical padding because otherwise it triggers
|
||||
// another update to the padding and so on ad infinitum. This is not an
|
||||
// ideal way to handle this but I couldn't see another way.
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
update.docChanged ||
|
||||
update.focusChanged ||
|
||||
@@ -461,17 +470,6 @@ export const createChangeManager = (
|
||||
update.selectionSet ||
|
||||
update.geometryChanged
|
||||
) {
|
||||
// Ignore a change to the editor geometry that occurs immediately after
|
||||
// an update to the vertical padding because otherwise it triggers
|
||||
// another update to the padding and so on ad infinitum. This is not an
|
||||
// ideal way to handle this but I couldn't see another way.
|
||||
if (
|
||||
update.geometryChanged &&
|
||||
Date.now() - lastUpdatedTopPaddingAt <
|
||||
PADDING_GEOMETRY_CHANGE_INTERVAL
|
||||
) {
|
||||
return
|
||||
}
|
||||
dispatchFocusChangedEvent(update.state)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
Extension,
|
||||
Facet,
|
||||
StateEffect,
|
||||
StateField,
|
||||
TransactionSpec,
|
||||
@@ -10,6 +11,8 @@ export function verticalOverflow(): Extension {
|
||||
return [
|
||||
overflowPaddingState,
|
||||
minimumBottomPaddingState,
|
||||
bottomPadding,
|
||||
topPadding,
|
||||
contentAttributes,
|
||||
bottomPaddingPlugin,
|
||||
topPaddingPlugin,
|
||||
@@ -132,19 +135,36 @@ const bottomPaddingPlugin = ViewPlugin.define(view => {
|
||||
}
|
||||
})
|
||||
|
||||
// Set a style attribute on the contentDOM containing the calculated top and bottom padding.
|
||||
// This value will be concatenated with style values from any other extensions.
|
||||
const contentAttributes = EditorView.contentAttributes.compute(
|
||||
const topPaddingFacet = Facet.define<number>()
|
||||
const topPadding = topPaddingFacet.compute([overflowPaddingState], state => {
|
||||
return state.field(overflowPaddingState).top
|
||||
})
|
||||
|
||||
const bottomPaddingFacet = Facet.define<number>({
|
||||
combine(values) {
|
||||
return [Math.max(...values)]
|
||||
},
|
||||
})
|
||||
const bottomPadding = bottomPaddingFacet.computeN(
|
||||
[overflowPaddingState, minimumBottomPaddingState],
|
||||
state => {
|
||||
const overflowPadding = state.field(overflowPaddingState)
|
||||
const minimumBottomPadding = state.field(minimumBottomPaddingState)
|
||||
return [
|
||||
state.field(minimumBottomPaddingState),
|
||||
state.field(overflowPaddingState).bottom,
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const bottomPadding = Math.max(minimumBottomPadding, overflowPadding.bottom)
|
||||
|
||||
return {
|
||||
style: `padding-top: ${overflowPadding.top}px; padding-bottom: ${bottomPadding}px;`,
|
||||
}
|
||||
// Set a style attribute on the contentDOM containing the calculated top and bottom padding.
|
||||
// This value will be concatenated with style values from any other extensions.
|
||||
// TODO: use elements instead?
|
||||
const contentAttributes = EditorView.contentAttributes.compute(
|
||||
[topPaddingFacet, bottomPaddingFacet],
|
||||
state => {
|
||||
const [top] = state.facet(topPaddingFacet)
|
||||
const [bottom] = state.facet(bottomPaddingFacet)
|
||||
const style = `padding-top: ${top}px; padding-bottom: ${bottom}px;`
|
||||
return { style }
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user