瀏覽代碼

Sync cursor position to PDF when double-clicking on a heading in the file outline (#7314)

GitOrigin-RevId: ef98f5d20e99bfc03c91cbf4027d277e738ab176
Alf Eaton 4 年之前
父節點
當前提交
aca889a3e0

+ 3 - 7
services/web/frontend/js/features/outline/components/outline-item.js

@@ -40,12 +40,9 @@ function OutlineItem({ outlineItem, jumpToLine, highlightedLine }) {
     setExpanded(!expanded)
   }
 
-  function handleOutlineItemLinkClick() {
-    jumpToLine(outlineItem.line, false)
-  }
-
-  function handleOutlineItemLinkDoubleClick() {
-    jumpToLine(outlineItem.line, true)
+  function handleOutlineItemLinkClick(event) {
+    const syncToPdf = event.detail === 2 // double-click = sync to PDF
+    jumpToLine(outlineItem.line, syncToPdf)
   }
 
   useEffect(() => {
@@ -87,7 +84,6 @@ function OutlineItem({ outlineItem, jumpToLine, highlightedLine }) {
         <button
           className={itemLinkClasses}
           onClick={handleOutlineItemLinkClick}
-          onDoubleClick={handleOutlineItemLinkDoubleClick}
           ref={titleElementRef}
         >
           {outlineItem.title}

+ 14 - 1
services/web/frontend/js/features/pdf-preview/components/pdf-synctex-controls.js

@@ -1,5 +1,5 @@
 import classNames from 'classnames'
-import { memo, useCallback, useEffect, useState } from 'react'
+import { memo, useCallback, useEffect, useState, useRef } from 'react'
 import PropTypes from 'prop-types'
 import { useIdeContext } from '../../../shared/context/ide-context'
 import { useProjectContext } from '../../../shared/context/project-context'
@@ -16,6 +16,7 @@ import useDetachState from '../../../shared/hooks/use-detach-state'
 import useDetachAction from '../../../shared/hooks/use-detach-action'
 import localStorage from '../../../infrastructure/local-storage'
 import { useFileTreeData } from '../../../shared/context/file-tree-data-context'
+import useScopeEventListener from '../../../shared/hooks/use-scope-event-listener'
 
 function GoToCodeButton({
   position,
@@ -233,6 +234,18 @@ function PdfSynctexControls() {
     [getCurrentFilePath, goToPdfLocation]
   )
 
+  const cursorPositionRef = useRef(cursorPosition)
+
+  useEffect(() => {
+    cursorPositionRef.current = cursorPosition
+  }, [cursorPosition])
+
+  const handleSyncToPdf = useCallback(() => {
+    syncToPdf(cursorPositionRef.current)
+  }, [syncToPdf])
+
+  useScopeEventListener('cursor:editor:syncToPdf', handleSyncToPdf)
+
   const _syncToCode = useCallback(
     (position, visualOffset = 0) => {
       setSyncToCodeInFlight(true)

+ 12 - 8
services/web/test/frontend/features/outline/components/outline-item.test.js

@@ -1,6 +1,6 @@
 import { expect } from 'chai'
 import sinon from 'sinon'
-import { screen, render, fireEvent } from '@testing-library/react'
+import { screen, render, fireEvent, waitFor } from '@testing-library/react'
 
 import OutlineItem from '../../../../../frontend/js/features/outline/components/outline-item'
 
@@ -82,7 +82,7 @@ describe('<OutlineItem />', function () {
     screen.getByRole('treeitem', { name: 'Parent', current: true })
   })
 
-  it('click and double-click jump to location', function () {
+  it('click and double-click jump to location', async function () {
     const outlineItem = {
       title: 'Parent',
       line: 1,
@@ -91,13 +91,17 @@ describe('<OutlineItem />', function () {
 
     const titleButton = screen.getByRole('button', { name: outlineItem.title })
 
-    fireEvent.click(titleButton)
-    expect(jumpToLine).to.be.calledOnce
-    expect(jumpToLine).to.be.calledWith(1, false)
+    fireEvent.click(titleButton, { detail: 1 })
+    await waitFor(() => {
+      expect(jumpToLine).to.be.calledOnce
+      expect(jumpToLine).to.be.calledWith(1, false)
+    })
 
     jumpToLine.reset()
-    fireEvent.doubleClick(titleButton)
-    expect(jumpToLine).to.be.calledOnce
-    expect(jumpToLine).to.be.calledWith(1, true)
+    fireEvent.click(titleButton, { detail: 2 })
+    await waitFor(() => {
+      expect(jumpToLine).to.be.calledOnce
+      expect(jumpToLine).to.be.calledWith(1, true)
+    })
   })
 })

+ 1 - 0
services/web/test/frontend/helpers/editor-providers.js

@@ -79,6 +79,7 @@ export function EditorProviders({
       callback(get($scope, path))
       return () => null
     },
+    $on: sinon.stub(),
     $applyAsync: sinon.stub(),
     toggleHistory: sinon.stub(),
     permissionsLevel,