mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
[cm6] Improve performance of the editor toolbar (#13915)
* Memoize figure and math dropdowns * Only build section heading overlay when open * Memoise currentLevel * Remove memo from ToolbarOverflow * Calculate listDepth in the container component * Avoid using document.querySelector GitOrigin-RevId: d5ec8817d35d04e0e2c60c8eecc8678ede69f82a
This commit is contained in:
parent
930cec2189
commit
ff7eec48de
7 changed files with 86 additions and 64 deletions
|
@ -21,6 +21,7 @@ import getMeta from '../../../utils/meta'
|
|||
import { isVisual } from '../extensions/visual/visual'
|
||||
import SplitTestBadge from '../../../shared/components/split-test-badge'
|
||||
import { language } from '@codemirror/language'
|
||||
import { minimumListDepthForSelection } from '../utils/tree-operations/ancestors'
|
||||
|
||||
export const CodeMirrorToolbar = () => {
|
||||
const view = useCodeMirrorViewContext()
|
||||
|
@ -48,6 +49,8 @@ const Toolbar = memo(function Toolbar() {
|
|||
const languageName = state.facet(language)?.name
|
||||
const visual = isVisual(view)
|
||||
|
||||
const listDepth = minimumListDepthForSelection(state)
|
||||
|
||||
const {
|
||||
open: overflowOpen,
|
||||
onToggle: setOverflowOpen,
|
||||
|
@ -108,7 +111,12 @@ const Toolbar = memo(function Toolbar() {
|
|||
return (
|
||||
<div className="ol-cm-toolbar toolbar-editor" ref={elementRef}>
|
||||
{showSourceToolbar && <EditorSwitch />}
|
||||
<ToolbarItems state={state} languageName={languageName} visual={visual} />
|
||||
<ToolbarItems
|
||||
state={state}
|
||||
languageName={languageName}
|
||||
visual={visual}
|
||||
listDepth={listDepth}
|
||||
/>
|
||||
<div
|
||||
className="ol-cm-toolbar-button-group ol-cm-toolbar-stretch"
|
||||
ref={overflowBeforeRef}
|
||||
|
@ -125,6 +133,7 @@ const Toolbar = memo(function Toolbar() {
|
|||
overflowed={overflowedItemsRef.current}
|
||||
languageName={languageName}
|
||||
visual={visual}
|
||||
listDepth={listDepth}
|
||||
/>
|
||||
</ToolbarOverflow>
|
||||
<div className="formatting-buttons-wrapper" />
|
||||
|
|
|
@ -57,7 +57,7 @@ export const ToolbarButtonMenu: FC<{
|
|||
show={open}
|
||||
target={target.current}
|
||||
placement="bottom"
|
||||
container={document.querySelector('.cm-editor')}
|
||||
container={view.dom}
|
||||
containerPadding={0}
|
||||
animation
|
||||
onHide={() => onToggle(false)}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import { ListGroupItem } from 'react-bootstrap'
|
||||
import { ToolbarButtonMenu } from './button-menu'
|
||||
import Icon from '../../../../shared/components/icon'
|
||||
import { useCallback } from 'react'
|
||||
import { memo, useCallback } from 'react'
|
||||
import { FigureModalSource } from '../figure-modal/figure-modal-context'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { emitToolbarEvent } from '../../extensions/toolbar/utils/analytics'
|
||||
import { useCodeMirrorViewContext } from '../codemirror-editor'
|
||||
import { insertFigure } from '../../extensions/toolbar/commands'
|
||||
|
||||
export const InsertFigureDropdown = () => {
|
||||
export const InsertFigureDropdown = memo(function InsertFigureDropdown() {
|
||||
const { t } = useTranslation()
|
||||
const view = useCodeMirrorViewContext()
|
||||
const openFigureModal = useCallback(
|
||||
|
@ -57,4 +57,4 @@ export const InsertFigureDropdown = () => {
|
|||
</ListGroupItem>
|
||||
</ToolbarButtonMenu>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -8,8 +8,9 @@ import {
|
|||
wrapInDisplayMath,
|
||||
wrapInInlineMath,
|
||||
} from '../../extensions/toolbar/commands'
|
||||
import { memo } from 'react'
|
||||
|
||||
export function MathDropdown() {
|
||||
export const MathDropdown = memo(function MathDropdown() {
|
||||
const { t } = useTranslation()
|
||||
const view = useCodeMirrorViewContext()
|
||||
|
||||
|
@ -46,4 +47,4 @@ export function MathDropdown() {
|
|||
</ListGroupItem>
|
||||
</ToolbarButtonMenu>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { FC, LegacyRef, memo } from 'react'
|
||||
import { FC, LegacyRef } from 'react'
|
||||
import { Button, Overlay, Popover } from 'react-bootstrap'
|
||||
import classnames from 'classnames'
|
||||
import Icon from '../../../../shared/components/icon'
|
||||
import { useCodeMirrorViewContext } from '../codemirror-editor'
|
||||
|
||||
export const ToolbarOverflow: FC<{
|
||||
overflowed: boolean
|
||||
|
@ -9,14 +10,16 @@ export const ToolbarOverflow: FC<{
|
|||
overflowOpen: boolean
|
||||
setOverflowOpen: (open: boolean) => void
|
||||
overflowRef?: LegacyRef<Popover>
|
||||
}> = memo(function ToolbarOverflow({
|
||||
}> = ({
|
||||
overflowed,
|
||||
target,
|
||||
overflowOpen,
|
||||
setOverflowOpen,
|
||||
overflowRef,
|
||||
children,
|
||||
}) {
|
||||
}) => {
|
||||
const view = useCodeMirrorViewContext()
|
||||
|
||||
const className = classnames(
|
||||
'ol-cm-toolbar-button',
|
||||
'ol-cm-toolbar-overflow-toggle',
|
||||
|
@ -48,7 +51,7 @@ export const ToolbarOverflow: FC<{
|
|||
show={overflowOpen}
|
||||
target={target}
|
||||
placement="bottom"
|
||||
container={document.querySelector('.cm-editor')}
|
||||
container={view.dom}
|
||||
containerPadding={0}
|
||||
animation
|
||||
onHide={() => setOverflowOpen(false)}
|
||||
|
@ -59,4 +62,4 @@ export const ToolbarOverflow: FC<{
|
|||
</Overlay>
|
||||
</>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
findCurrentSectionHeadingLevel,
|
||||
setSectionHeadingLevel,
|
||||
} from '../../extensions/toolbar/sections'
|
||||
import { useCallback, useRef } from 'react'
|
||||
import { useCallback, useMemo, useRef } from 'react'
|
||||
import { Overlay, Popover } from 'react-bootstrap'
|
||||
import useEventListener from '../../../../shared/hooks/use-event-listener'
|
||||
import useDropdown from '../../../../shared/hooks/use-dropdown'
|
||||
|
@ -42,7 +42,11 @@ export const SectionHeadingDropdown = () => {
|
|||
|
||||
const toggleButtonRef = useRef<HTMLButtonElement | null>(null)
|
||||
|
||||
const currentLevel = findCurrentSectionHeadingLevel(state)
|
||||
const currentLevel = useMemo(
|
||||
() => findCurrentSectionHeadingLevel(state),
|
||||
[state]
|
||||
)
|
||||
|
||||
const currentLabel = currentLevel
|
||||
? levels.get(currentLevel.level) ?? currentLevel.level
|
||||
: '---'
|
||||
|
@ -64,11 +68,12 @@ export const SectionHeadingDropdown = () => {
|
|||
<Icon type="caret-down" fw />
|
||||
</button>
|
||||
|
||||
{overflowOpen && (
|
||||
<Overlay
|
||||
show={overflowOpen}
|
||||
show
|
||||
onHide={() => setOverflowOpen(false)}
|
||||
animation={false}
|
||||
container={document.querySelector('.cm-editor')}
|
||||
container={view.dom}
|
||||
containerPadding={0}
|
||||
placement="bottom"
|
||||
rootClose
|
||||
|
@ -110,6 +115,7 @@ export const SectionHeadingDropdown = () => {
|
|||
</div>
|
||||
</Popover>
|
||||
</Overlay>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,10 +4,7 @@ import { EditorView } from '@codemirror/view'
|
|||
import { useEditorContext } from '../../../../shared/context/editor-context'
|
||||
import useScopeEventEmitter from '../../../../shared/hooks/use-scope-event-emitter'
|
||||
import { useLayoutContext } from '../../../../shared/context/layout-context'
|
||||
import {
|
||||
minimumListDepthForSelection,
|
||||
withinFormattingCommand,
|
||||
} from '../../utils/tree-operations/ancestors'
|
||||
import { withinFormattingCommand } from '../../utils/tree-operations/ancestors'
|
||||
import { ToolbarButton } from './toolbar-button'
|
||||
import { redo, undo } from '@codemirror/commands'
|
||||
import * as commands from '../../extensions/toolbar/commands'
|
||||
|
@ -25,11 +22,17 @@ export const ToolbarItems: FC<{
|
|||
overflowed?: Set<string>
|
||||
languageName?: string
|
||||
visual: boolean
|
||||
}> = memo(function ToolbarItems({ state, overflowed, languageName, visual }) {
|
||||
listDepth: number
|
||||
}> = memo(function ToolbarItems({
|
||||
state,
|
||||
overflowed,
|
||||
languageName,
|
||||
visual,
|
||||
listDepth,
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
const { toggleSymbolPalette, showSymbolPalette } = useEditorContext()
|
||||
const isActive = withinFormattingCommand(state)
|
||||
const listDepth = minimumListDepthForSelection(state)
|
||||
const addCommentEmitter = useScopeEventEmitter('comment:start_adding')
|
||||
const { setReviewPanelOpen } = useLayoutContext()
|
||||
const splitTestVariants = getMeta('ol-splitTestVariants', {})
|
||||
|
|
Loading…
Reference in a new issue