Browse Source

Merge pull request #25999 from overleaf/dp-eq-preview-fix

Move rendering of equation preview math into codemirror extension to fix zoomed in issue

GitOrigin-RevId: 66bf9120191da236d88213d16b457c0a676f38ac
David 1 year ago
parent
commit
ba53ea3306

+ 42 - 53
services/web/frontend/js/features/source-editor/components/math-preview-tooltip.tsx

@@ -13,7 +13,7 @@ import OLModal, {
 } from '@/features/ui/components/ol/ol-modal'
 import MaterialIcon from '@/shared/components/material-icon'
 import useEventListener from '@/shared/hooks/use-event-listener'
-import { FC, useCallback, useLayoutEffect, useRef, useState } from 'react'
+import { FC, useCallback, useState } from 'react'
 import { Trans, useTranslation } from 'react-i18next'
 import {
   useCodeMirrorStateContext,
@@ -35,9 +35,9 @@ const MathPreviewTooltipContainer: FC = () => {
     return null
   }
 
-  const { tooltip, mathContent } = mathPreviewState
+  const { tooltip } = mathPreviewState
 
-  if (!tooltip || !mathContent) {
+  if (!tooltip) {
     return null
   }
 
@@ -47,15 +47,16 @@ const MathPreviewTooltipContainer: FC = () => {
     return null
   }
 
-  return ReactDOM.createPortal(
-    <MathPreviewTooltip mathContent={mathContent} />,
-    tooltipView.dom
-  )
+  const inner = tooltipView.dom.querySelector('#ol-cm-math-tooltip')
+
+  if (!inner) {
+    return null
+  }
+
+  return ReactDOM.createPortal(<MathPreviewTooltipMenu />, inner)
 }
 
-const MathPreviewTooltip: FC<{ mathContent: HTMLDivElement }> = ({
-  mathContent,
-}) => {
+const MathPreviewTooltipMenu: FC = () => {
   const { t } = useTranslation()
 
   const newEditor = useIsNewEditorEnabled()
@@ -69,8 +70,6 @@ const MathPreviewTooltip: FC<{ mathContent: HTMLDivElement }> = ({
     window.dispatchEvent(new Event('editor:hideMathTooltip'))
   }, [])
 
-  const mathRef = useRef<HTMLSpanElement>(null)
-
   const keyDownListener = useCallback(
     (event: KeyboardEvent) => {
       if (event.key === 'Escape') {
@@ -82,50 +81,40 @@ const MathPreviewTooltip: FC<{ mathContent: HTMLDivElement }> = ({
 
   useEventListener('keydown', keyDownListener)
 
-  useLayoutEffect(() => {
-    if (mathRef.current) {
-      mathRef.current.replaceChildren(mathContent)
-    }
-  }, [mathContent])
-
   return (
     <>
-      <div className="ol-cm-math-tooltip">
-        <span ref={mathRef} />
-
-        <Dropdown align="end">
-          <DropdownToggle
-            id="some-id"
-            className="math-tooltip-options-toggle"
-            variant="secondary"
-            size="sm"
+      <Dropdown align="end">
+        <DropdownToggle
+          id="some-id"
+          className="math-tooltip-options-toggle"
+          variant="secondary"
+          size="sm"
+        >
+          <MaterialIcon
+            type="more_vert"
+            accessibilityLabel={t('more_options')}
+          />
+        </DropdownToggle>
+        <DropdownMenu flip={false}>
+          <OLDropdownMenuItem
+            onClick={onHide}
+            description={t('temporarily_hides_the_preview')}
+            trailingIcon={
+              <span className="math-tooltip-options-keyboard-shortcut">
+                Esc
+              </span>
+            }
           >
-            <MaterialIcon
-              type="more_vert"
-              accessibilityLabel={t('more_options')}
-            />
-          </DropdownToggle>
-          <DropdownMenu flip={false}>
-            <OLDropdownMenuItem
-              onClick={onHide}
-              description={t('temporarily_hides_the_preview')}
-              trailingIcon={
-                <span className="math-tooltip-options-keyboard-shortcut">
-                  Esc
-                </span>
-              }
-            >
-              {t('hide')}
-            </OLDropdownMenuItem>
-            <OLDropdownMenuItem
-              onClick={openDisableModal}
-              description={t('permanently_disables_the_preview')}
-            >
-              {t('disable')}
-            </OLDropdownMenuItem>
-          </DropdownMenu>
-        </Dropdown>
-      </div>
+            {t('hide')}
+          </OLDropdownMenuItem>
+          <OLDropdownMenuItem
+            onClick={openDisableModal}
+            description={t('permanently_disables_the_preview')}
+          >
+            {t('disable')}
+          </OLDropdownMenuItem>
+        </DropdownMenu>
+      </Dropdown>
 
       {showDisableModal && (
         <OLModal show onHide={closeDisableModal}>

+ 8 - 5
services/web/frontend/js/features/source-editor/extensions/math-preview.ts

@@ -44,7 +44,6 @@ export const setMathPreview = (enabled: boolean): TransactionSpec => ({
 
 export const mathPreviewStateField = StateField.define<{
   tooltip: Tooltip | null
-  mathContent: HTMLDivElement | null
   hide: boolean
 }>({
   create: buildInitialState,
@@ -52,7 +51,7 @@ export const mathPreviewStateField = StateField.define<{
   update(state, tr) {
     for (const effect of tr.effects) {
       if (effect.is(hideTooltipEffect)) {
-        return { tooltip: null, hide: true, mathContent: null }
+        return { tooltip: null, hide: true }
       }
     }
 
@@ -61,19 +60,18 @@ export const mathPreviewStateField = StateField.define<{
 
       if (mathContainer) {
         if (state.hide) {
-          return { tooltip: null, hide: true, mathContent: null }
+          return { tooltip: null, hide: true }
         } else {
           const mathContent = buildTooltipContent(tr.state, mathContainer)
 
           return {
             tooltip: buildTooltip(mathContainer, mathContent),
-            mathContent,
             hide: false,
           }
         }
       }
 
-      return { tooltip: null, hide: false, mathContent: null }
+      return { tooltip: null, hide: false }
     }
 
     return state
@@ -159,6 +157,11 @@ function buildTooltip(
     create() {
       const dom = document.createElement('div')
       dom.classList.add('ol-cm-math-tooltip-container')
+      const innerElt = document.createElement('div')
+      innerElt.classList.add('ol-cm-math-tooltip')
+      innerElt.id = 'ol-cm-math-tooltip'
+      innerElt.appendChild(mathContent)
+      dom.appendChild(innerElt)
 
       return { dom, overlap: true, offset: { x: 0, y: 8 } }
     },