From b2e74464a2de913fa52205779dd5e5416c5543ae Mon Sep 17 00:00:00 2001 From: Jimmy Domagala-Tang Date: Tue, 22 Aug 2023 09:33:19 -0400 Subject: [PATCH] Merge pull request #14207 from overleaf/jdt-editor-events editor events GitOrigin-RevId: 8d74576d4f8117ecca47402afcc9cee229dd0dca --- .../components/actions-copy-project.tsx | 8 +++- .../components/actions-word-count.tsx | 10 +++- .../components/download-pdf.tsx | 17 ++++++- .../components/download-source.tsx | 9 ++++ .../components/help-contact-us.tsx | 9 +++- .../components/help-show-hotkeys.tsx | 10 +++- .../components/back-to-projects-button.tsx | 9 +++- .../editor-navigation-toolbar-root.js | 24 ++++++++-- .../components/layout-dropdown-button.js | 3 ++ .../file-tree-modal-create-file-mode.js | 2 + .../modes/file-tree-create-new-doc.js | 2 + .../modes/file-tree-import-from-project.js | 2 + .../modes/file-tree-import-from-url.js | 3 +- .../modes/file-tree-upload-doc.js | 2 + .../file-tree-item-menu-items.js | 15 +++++- .../file-tree/components/file-tree-toolbar.js | 15 +++++- .../components/hotkeys-modal-bottom-text.js | 2 + .../components/pdf-compile-button.js | 46 ++++++++++++++++--- .../components/pdf-hybrid-download-button.tsx | 5 +- .../components/pdf-hybrid-logs-button.tsx | 7 ++- .../pdf-preview/components/pdf-js-viewer.js | 6 +++ .../components/pdf-synctex-controls.js | 16 ++++++- 22 files changed, 194 insertions(+), 28 deletions(-) diff --git a/services/web/frontend/js/features/editor-left-menu/components/actions-copy-project.tsx b/services/web/frontend/js/features/editor-left-menu/components/actions-copy-project.tsx index 6030b0ad1b..b6c4ac8b18 100644 --- a/services/web/frontend/js/features/editor-left-menu/components/actions-copy-project.tsx +++ b/services/web/frontend/js/features/editor-left-menu/components/actions-copy-project.tsx @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next' import EditorCloneProjectModalWrapper from '../../clone-project-modal/components/editor-clone-project-modal-wrapper' import LeftMenuButton from './left-menu-button' import { useLocation } from '../../../shared/hooks/use-location' +import * as eventTracking from '../../../infrastructure/event-tracking' type ProjectCopyResponse = { project_id: string @@ -20,10 +21,15 @@ export default function ActionsCopyProject() { [location] ) + const handleShowModal = useCallback(() => { + eventTracking.sendMB('left-menu-copy') + setShowModal(true) + }, []) + return ( <> setShowModal(true)} + onClick={handleShowModal} icon={{ type: 'copy', fw: true, diff --git a/services/web/frontend/js/features/editor-left-menu/components/actions-word-count.tsx b/services/web/frontend/js/features/editor-left-menu/components/actions-word-count.tsx index de95bd49e5..6d503b781d 100644 --- a/services/web/frontend/js/features/editor-left-menu/components/actions-word-count.tsx +++ b/services/web/frontend/js/features/editor-left-menu/components/actions-word-count.tsx @@ -1,20 +1,26 @@ -import { useState } from 'react' +import { useState, useCallback } from 'react' import { useTranslation } from 'react-i18next' import Tooltip from '../../../shared/components/tooltip' import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context' import WordCountModal from '../../word-count-modal/components/word-count-modal' import LeftMenuButton from './left-menu-button' +import * as eventTracking from '../../../infrastructure/event-tracking' export default function ActionsWordCount() { const [showModal, setShowModal] = useState(false) const { pdfUrl } = useCompileContext() const { t } = useTranslation() + const handleShowModal = useCallback(() => { + eventTracking.sendMB('left-menu-count') + setShowModal(true) + }, []) + return ( <> {pdfUrl ? ( setShowModal(true)} + onClick={handleShowModal} icon={{ type: 'eye', fw: true, diff --git a/services/web/frontend/js/features/editor-left-menu/components/download-pdf.tsx b/services/web/frontend/js/features/editor-left-menu/components/download-pdf.tsx index 2feb281d29..b0b3bc106e 100644 --- a/services/web/frontend/js/features/editor-left-menu/components/download-pdf.tsx +++ b/services/web/frontend/js/features/editor-left-menu/components/download-pdf.tsx @@ -1,15 +1,30 @@ import { useTranslation } from 'react-i18next' import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context' +import { useProjectContext } from '../../../shared/context/project-context' import Icon from '../../../shared/components/icon' import Tooltip from '../../../shared/components/tooltip' +import * as eventTracking from '../../../infrastructure/event-tracking' export default function DownloadPDF() { const { t } = useTranslation() const { pdfDownloadUrl, pdfUrl } = useCompileContext() + const { _id: projectId } = useProjectContext() + + function sendDownloadEvent() { + eventTracking.sendMB('download-pdf-button-click', { + projectId, + location: 'left-menu', + }) + } if (pdfUrl) { return ( - +
PDF diff --git a/services/web/frontend/js/features/editor-left-menu/components/download-source.tsx b/services/web/frontend/js/features/editor-left-menu/components/download-source.tsx index fe1c7ccafb..e3a8e715d4 100644 --- a/services/web/frontend/js/features/editor-left-menu/components/download-source.tsx +++ b/services/web/frontend/js/features/editor-left-menu/components/download-source.tsx @@ -1,16 +1,25 @@ import { useTranslation } from 'react-i18next' import { useProjectContext } from '../../../shared/context/project-context' import Icon from '../../../shared/components/icon' +import * as eventTracking from '../../../infrastructure/event-tracking' export default function DownloadSource() { const { t } = useTranslation() const { _id: projectId } = useProjectContext() + function sendDownloadEvent() { + eventTracking.sendMB('download-zip-button-click', { + projectId, + location: 'left-menu', + }) + } + return (

diff --git a/services/web/frontend/js/features/editor-left-menu/components/help-contact-us.tsx b/services/web/frontend/js/features/editor-left-menu/components/help-contact-us.tsx index 9775948a3c..22b6eba4cb 100644 --- a/services/web/frontend/js/features/editor-left-menu/components/help-contact-us.tsx +++ b/services/web/frontend/js/features/editor-left-menu/components/help-contact-us.tsx @@ -1,4 +1,6 @@ import { useTranslation } from 'react-i18next' +import { useCallback } from 'react' +import * as eventTracking from '../../../infrastructure/event-tracking' import { useContactUsModal } from '../../../shared/hooks/use-contact-us-modal' import LeftMenuButton from './left-menu-button' @@ -6,10 +8,15 @@ export default function HelpContactUs() { const { modal, showModal } = useContactUsModal() const { t } = useTranslation() + const showModalWithAnalytics = useCallback(() => { + eventTracking.sendMB('left-menu-contact') + showModal() + }, [showModal]) + return ( <> { + eventTracking.sendMB('left-menu-hotkeys') + setShowModal(true) + }, []) + return ( <> setShowModal(true)} + onClick={showModalWithAnalytics} icon={{ type: 'keyboard-o', fw: true, diff --git a/services/web/frontend/js/features/editor-navigation-toolbar/components/back-to-projects-button.tsx b/services/web/frontend/js/features/editor-navigation-toolbar/components/back-to-projects-button.tsx index 96cf64ab34..3a53c856ba 100644 --- a/services/web/frontend/js/features/editor-navigation-toolbar/components/back-to-projects-button.tsx +++ b/services/web/frontend/js/features/editor-navigation-toolbar/components/back-to-projects-button.tsx @@ -1,6 +1,7 @@ import { useTranslation } from 'react-i18next' import Tooltip from '../../../shared/components/tooltip' import Icon from '../../../shared/components/icon' +import * as eventTracking from '../../../infrastructure/event-tracking' function BackToProjectsButton() { const { t } = useTranslation() @@ -12,7 +13,13 @@ function BackToProjectsButton() { overlayProps={{ placement: 'right' }} >
- + { + eventTracking.sendMB('navigation-clicked-home') + }} + > !value) }, [chatIsOpen, setChatIsOpen, markMessagesAsRead]) const toggleReviewPanelOpen = useCallback( event => { event.preventDefault() + eventTracking.sendMB('navigation-clicked-review', { + action: isOpentoString(!reviewPanelOpen), + }) setReviewPanelOpen(value => !value) }, - [setReviewPanelOpen] + [reviewPanelOpen, setReviewPanelOpen] ) const toggleHistoryOpen = useCallback(() => { + const action = view === 'history' ? 'close' : 'open' + eventTracking.sendMB('navigation-clicked-history', { action }) setView(view === 'history' ? 'editor' : 'history') }, [view, setView]) const openShareModal = useCallback(() => { + eventTracking.sendMB('navigation-clicked-share') openShareProjectModal() }, [openShareProjectModal]) - const onShowLeftMenuClick = useCallback( - () => setLeftMenuShown(value => !value), - [setLeftMenuShown] - ) + const onShowLeftMenuClick = useCallback(() => { + eventTracking.sendMB('navigation-clicked-menu') + setLeftMenuShown(value => !value) + }, [setLeftMenuShown]) const goToUser = useCallback( user => { diff --git a/services/web/frontend/js/features/editor-navigation-toolbar/components/layout-dropdown-button.js b/services/web/frontend/js/features/editor-navigation-toolbar/components/layout-dropdown-button.js index e25614de2d..eaba1dc7b6 100644 --- a/services/web/frontend/js/features/editor-navigation-toolbar/components/layout-dropdown-button.js +++ b/services/web/frontend/js/features/editor-navigation-toolbar/components/layout-dropdown-button.js @@ -149,6 +149,9 @@ function LayoutDropdownButton() { )} { + eventTracking.sendMB('navigation-clicked-layout') + }} className="toolbar-item layout-dropdown" pullRight > diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-mode.js b/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-mode.js index 40912f0158..6fde08ae55 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-mode.js +++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-mode.js @@ -3,12 +3,14 @@ import { Button } from 'react-bootstrap' import PropTypes from 'prop-types' import Icon from '../../../../shared/components/icon' import { useFileTreeActionable } from '../../contexts/file-tree-actionable' +import * as eventTracking from '../../../../infrastructure/event-tracking' export default function FileTreeModalCreateFileMode({ mode, icon, label }) { const { newFileCreateMode, startCreatingFile } = useFileTreeActionable() const handleClick = () => { startCreatingFile(mode) + eventTracking.sendMB('file-modal-click', { method: mode }) } return ( diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-create-new-doc.js b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-create-new-doc.js index c86de20f4f..9e60cb467e 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-create-new-doc.js +++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-create-new-doc.js @@ -3,6 +3,7 @@ import FileTreeCreateNameInput from '../file-tree-create-name-input' import { useFileTreeActionable } from '../../../contexts/file-tree-actionable' import { useFileTreeCreateName } from '../../../contexts/file-tree-create-name' import { useFileTreeCreateForm } from '../../../contexts/file-tree-create-form' +import * as eventTracking from '../../../../../infrastructure/event-tracking' import ErrorMessage from '../error-message' export default function FileTreeCreateNewDoc() { @@ -21,6 +22,7 @@ export default function FileTreeCreateNewDoc() { event.preventDefault() finishCreatingDoc({ name }) + eventTracking.sendMB('new-file-created', { method: 'doc' }) }, [finishCreatingDoc, name] ) diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-project.js b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-project.js index 396f256142..5ac137f4f1 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-project.js +++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-project.js @@ -12,6 +12,7 @@ import { useFileTreeCreateName } from '../../../contexts/file-tree-create-name' import { useFileTreeCreateForm } from '../../../contexts/file-tree-create-form' import { useProjectContext } from '../../../../../shared/context/project-context' import ErrorMessage from '../error-message' +import * as eventTracking from '../../../../../infrastructure/event-tracking' export default function FileTreeImportFromProject() { const { t } = useTranslation() @@ -85,6 +86,7 @@ export default function FileTreeImportFromProject() { // form submission: create a linked file with this name, from this entity or output file const handleSubmit = event => { event.preventDefault() + eventTracking.sendMB('new-file-created', { method: 'project' }) if (isOutputFilesMode) { finishCreatingLinkedFile({ diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-url.js b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-url.js index 752b4d5bfb..13d006aa00 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-url.js +++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-url.js @@ -6,6 +6,7 @@ import { useFileTreeActionable } from '../../../contexts/file-tree-actionable' import { useFileTreeCreateName } from '../../../contexts/file-tree-create-name' import { useFileTreeCreateForm } from '../../../contexts/file-tree-create-form' import ErrorMessage from '../error-message' +import * as eventTracking from '../../../../../infrastructure/event-tracking' export default function FileTreeImportFromUrl() { const { t } = useTranslation() @@ -35,7 +36,7 @@ export default function FileTreeImportFromUrl() { // form submission: create a linked file with this name, from this URL const handleSubmit = event => { event.preventDefault() - + eventTracking.sendMB('new-file-created', { method: 'url' }) finishCreatingLinkedFile({ name, provider: 'url', diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.js b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.js index f9942242f6..e63a571d1d 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.js +++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.js @@ -7,6 +7,7 @@ import XHRUpload from '@uppy/xhr-upload' import { Dashboard, useUppy } from '@uppy/react' import { useFileTreeActionable } from '../../../contexts/file-tree-actionable' import { useProjectContext } from '../../../../../shared/context/project-context' +import * as eventTracking from '../../../../../infrastructure/event-tracking' import '@uppy/core/dist/style.css' import '@uppy/dashboard/dist/style.css' @@ -94,6 +95,7 @@ export default function FileTreeUploadDoc() { }) // broadcast doc metadata after each successful upload .on('upload-success', (file, response) => { + eventTracking.sendMB('new-file-created', { method: 'upload' }) if (response.body.entity_type === 'doc') { window.setTimeout(() => { refreshProjectMetadata(projectId, response.body.entity_id) diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-menu-items.js b/services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-menu-items.js index fe70283890..05608fe488 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-menu-items.js +++ b/services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-menu-items.js @@ -1,4 +1,5 @@ import { useTranslation } from 'react-i18next' +import * as eventTracking from '../../../../infrastructure/event-tracking' import { MenuItem } from 'react-bootstrap' import { useFileTreeActionable } from '../../contexts/file-tree-actionable' @@ -18,6 +19,16 @@ function FileTreeItemMenuItems() { downloadPath, } = useFileTreeActionable() + const createWithAnalytics = () => { + eventTracking.sendMB('new-file-click', { location: 'file-menu' }) + startCreatingDocOrFile() + } + + const uploadWithAnalytics = () => { + eventTracking.sendMB('upload-click', { location: 'file-menu' }) + startUploadingDocOrFile() + } + return ( <> {canRename ? ( @@ -34,9 +45,9 @@ function FileTreeItemMenuItems() { {canCreate ? ( <> - {t('new_file')} + {t('new_file')} {t('new_folder')} - {t('upload')} + {t('upload')} ) : null} diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-toolbar.js b/services/web/frontend/js/features/file-tree/components/file-tree-toolbar.js index d8f9303784..70a873816f 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-toolbar.js +++ b/services/web/frontend/js/features/file-tree/components/file-tree-toolbar.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types' import { useTranslation } from 'react-i18next' +import * as eventTracking from '../../../infrastructure/event-tracking' import { Button } from 'react-bootstrap' import Tooltip from '../../../shared/components/tooltip' @@ -34,6 +35,16 @@ function FileTreeToolbarLeft() { startUploadingDocOrFile, } = useFileTreeActionable() + const createWithAnalytics = () => { + eventTracking.sendMB('new-file-click', { location: 'toolbar' }) + startCreatingDocOrFile() + } + + const uploadWithAnalytics = () => { + eventTracking.sendMB('upload-click', { location: 'toolbar' }) + startUploadingDocOrFile() + } + if (!canCreate) return null return ( @@ -43,7 +54,7 @@ function FileTreeToolbarLeft() { description={t('new_file')} overlayProps={{ placement: 'bottom' }} > - @@ -61,7 +72,7 @@ function FileTreeToolbarLeft() { description={t('upload')} overlayProps={{ placement: 'bottom' }} > - diff --git a/services/web/frontend/js/features/hotkeys-modal/components/hotkeys-modal-bottom-text.js b/services/web/frontend/js/features/hotkeys-modal/components/hotkeys-modal-bottom-text.js index 0111a851f0..db6507e823 100644 --- a/services/web/frontend/js/features/hotkeys-modal/components/hotkeys-modal-bottom-text.js +++ b/services/web/frontend/js/features/hotkeys-modal/components/hotkeys-modal-bottom-text.js @@ -1,4 +1,5 @@ import { Trans } from 'react-i18next' +import * as eventTracking from '../../../infrastructure/event-tracking' export default function HotkeysModalBottomText() { return ( @@ -8,6 +9,7 @@ export default function HotkeysModalBottomText() { components={[ // eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key eventTracking.sendMB('left-menu-hotkeys-template')} href="/articles/overleaf-keyboard-shortcuts/qykqfvmxdnjf" target="_blank" />, diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-compile-button.js b/services/web/frontend/js/features/pdf-preview/components/pdf-compile-button.js index da110a82e8..e5639db8c2 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-compile-button.js +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-compile-button.js @@ -5,9 +5,18 @@ import { useDetachCompileContext as useCompileContext } from '../../../shared/co import { useStopOnFirstError } from '../../../shared/hooks/use-stop-on-first-error' import SplitMenu from '../../../shared/components/split-menu' import Icon from '../../../shared/components/icon' +import * as eventTracking from '../../../infrastructure/event-tracking' const modifierKey = /Mac/i.test(navigator.platform) ? 'Cmd' : 'Ctrl' +function sendEventAndSet(value, setter, settingName) { + eventTracking.sendMB('recompile-setting-changed', { + setting: settingName, + settingVal: value, + }) + setter(value) +} + function PdfCompileButton() { const { animateCompileDropdownArrow, @@ -30,6 +39,13 @@ function PdfCompileButton() { const { t } = useTranslation() + const fromScratchWithEvent = () => { + eventTracking.sendMB('recompile-setting-changed', { + setting: 'from-scratch', + }) + recompileFromScratch() + } + const compileButtonLabel = compiling ? `${t('compiling')}…` : t('recompile') const tooltipElement = ( <> @@ -76,36 +92,52 @@ function PdfCompileButton() { > {t('auto_compile')} - setAutoCompile(true)}> + sendEventAndSet(true, setAutoCompile, 'auto-compile')} + > {t('on')} - setAutoCompile(false)}> + sendEventAndSet(false, setAutoCompile, 'auto-compile')} + > {t('off')} {t('compile_mode')} - setDraft(false)}> + sendEventAndSet(false, setDraft, 'compile-mode')} + > {t('normal')} - setDraft(true)}> + sendEventAndSet(true, setDraft, 'compile-mode')} + > {t('fast')} [draft] Syntax Checks - setStopOnValidationError(true)}> + + sendEventAndSet(true, setStopOnValidationError, 'syntax-check') + } + > {t('stop_on_validation_error')} - setStopOnValidationError(false)}> + + sendEventAndSet(false, setStopOnValidationError, 'syntax-check') + } + > {t('ignore_validation_errors')} @@ -133,7 +165,7 @@ function PdfCompileButton() { recompileFromScratch()} + onSelect={fromScratchWithEvent} disabled={compiling} aria-disabled={compiling} > diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-hybrid-download-button.tsx b/services/web/frontend/js/features/pdf-preview/components/pdf-hybrid-download-button.tsx index bbc8172914..6633b59892 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-hybrid-download-button.tsx +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-hybrid-download-button.tsx @@ -17,7 +17,10 @@ function PdfHybridDownloadButton() { : t('please_compile_pdf_before_download') function handleOnClick() { - eventTracking.sendMB('download-pdf-button-click', { projectId }) + eventTracking.sendMB('download-pdf-button-click', { + projectId, + location: 'pdf-preview', + }) } return ( diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-hybrid-logs-button.tsx b/services/web/frontend/js/features/pdf-preview/components/pdf-hybrid-logs-button.tsx index 325ecd8748..4ef69a28dc 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-hybrid-logs-button.tsx +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-hybrid-logs-button.tsx @@ -4,6 +4,7 @@ import { Button, Label } from 'react-bootstrap' import Tooltip from '../../../shared/components/tooltip' import Icon from '../../../shared/components/icon' import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context' +import * as eventTracking from '../../../infrastructure/event-tracking' function PdfHybridLogsButton() { const { error, logEntries, toggleLogs, showLogs, stoppedOnFirstError } = @@ -12,8 +13,12 @@ function PdfHybridLogsButton() { const { t } = useTranslation() const handleClick = useCallback(() => { + // only send analytics on open + if (!showLogs) { + eventTracking.sendMB('logs-click') + } toggleLogs() - }, [toggleLogs]) + }, [toggleLogs, showLogs]) const errorCount = Number(logEntries?.errors?.length) const warningCount = Number(logEntries?.warnings?.length) diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.js b/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.js index a25a72d8c9..d0465832a5 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.js +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.js @@ -10,6 +10,7 @@ import withErrorBoundary from '../../../infrastructure/error-boundary' import PdfPreviewErrorBoundaryFallback from './pdf-preview-error-boundary-fallback' import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context' import { captureException } from '../../../infrastructure/error-reporter' +import * as eventTracking from '../../../infrastructure/event-tracking' import { getPdfCachingMetrics } from '../util/metrics' function PdfJsViewer({ url, pdfFile }) { @@ -205,6 +206,11 @@ function PdfJsViewer({ url, pdfFile }) { ) if (clickPosition) { + eventTracking.sendMB('jump-to-location', { + direction: 'pdf-location-in-code', + method: 'double-click', + }) + window.dispatchEvent( new CustomEvent('synctex:sync-to-position', { detail: clickPosition, diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-synctex-controls.js b/services/web/frontend/js/features/pdf-preview/components/pdf-synctex-controls.js index 63ab09037e..ae0e6d01f4 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-synctex-controls.js +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-synctex-controls.js @@ -18,6 +18,7 @@ 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' +import * as eventTracking from '../../../infrastructure/event-tracking' function GoToCodeButton({ position, @@ -38,6 +39,14 @@ function GoToCodeButton({ buttonIcon = } + const syncToCodeWithButton = () => { + eventTracking.sendMB('jump-to-location', { + direction: 'pdf-location-in-code', + method: 'arrow', + }) + syncToCode(position, 72) + } + return ( syncToCode(position, 72)} + onClick={syncToCodeWithButton} disabled={syncToCodeInFlight} className={buttonClasses} aria-label={t('go_to_pdf_location_in_code')} @@ -228,6 +237,11 @@ function PdfSynctexControls() { column: cursorPosition.column, }).toString() + eventTracking.sendMB('jump-to-location', { + direction: 'code-location-in-pdf', + method: 'arrow', + }) + goToPdfLocation(params) }, [getCurrentFilePath, goToPdfLocation]