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

GitOrigin-RevId: ef98f5d20e99bfc03c91cbf4027d277e738ab176
This commit is contained in:
Alf Eaton 2022-04-08 10:07:13 +01:00 committed by Copybot
parent 5cb46643da
commit aca889a3e0
4 changed files with 30 additions and 16 deletions

View file

@ -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}

View file

@ -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)

View file

@ -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)
})
})
})

View file

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