ソースを参照

Store the scroll position of the PDF per root doc (#20376)

GitOrigin-RevId: 561c38b7258df40f0e738fdc2575e23d9d15102a
Alf Eaton 1 年間 前
コミット
7daebe2f42

+ 10 - 5
services/web/frontend/js/shared/context/local-compile-context.tsx

@@ -7,6 +7,8 @@ import {
   useMemo,
   useRef,
   useState,
+  Dispatch,
+  SetStateAction,
 } from 'react'
 import useScopeValue from '../hooks/use-scope-value'
 import useScopeValueSetterOnly from '../hooks/use-scope-value-setter-only'
@@ -37,6 +39,10 @@ import { useFileTreePathContext } from '@/features/file-tree/contexts/file-tree-
 import { useUserSettingsContext } from '@/shared/context/user-settings-context'
 import { useFeatureFlag } from '@/shared/context/split-test-context'
 import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
+import {
+  PdfScrollPosition,
+  usePdfScrollPosition,
+} from '@/shared/hooks/use-pdf-scroll-position'
 
 type PdfFile = Record<string, any>
 
@@ -61,14 +67,14 @@ export type CompileContext = {
   pdfFile?: PdfFile
   pdfUrl?: string
   pdfViewer?: string
-  position?: Record<string, any>
+  position?: PdfScrollPosition
   rawLog?: string
   setAutoCompile: (value: boolean) => void
   setDraft: (value: any) => void
   setError: (value: any) => void
   setHasLintingError: (value: any) => void // only for storybook
   setHighlights: (value: any) => void
-  setPosition: (value: any) => void
+  setPosition: Dispatch<SetStateAction<PdfScrollPosition>>
   setShowCompileTimeWarning: (value: any) => void
   setShowLogs: (value: boolean) => void
   toggleLogs: () => void
@@ -171,7 +177,7 @@ export const LocalCompileProvider: FC = ({ children }) => {
   // the rootDocId used in the most recent compile request, which may not be the
   // same as the project rootDocId. This is used to calculate correct paths when
   // parsing the compile logs
-  const lastCompileRootDocId = data?.rootDocId
+  const lastCompileRootDocId = data ? (data.rootDocId ?? rootDocId) : null
 
   // callback to be invoked for PdfJsMetrics
   const [firstRenderDone, setFirstRenderDone] = useState(() => () => {})
@@ -216,8 +222,7 @@ export const LocalCompileProvider: FC = ({ children }) => {
   // areas to highlight on the PDF, from synctex
   const [highlights, setHighlights] = useState()
 
-  // scroll position of the PDF
-  const [position, setPosition] = usePersistedState(`pdf.position.${projectId}`)
+  const [position, setPosition] = usePdfScrollPosition(lastCompileRootDocId)
 
   // whether autocompile is switched on
   const [autoCompile, setAutoCompile] = usePersistedState(

+ 56 - 0
services/web/frontend/js/shared/hooks/use-pdf-scroll-position.ts

@@ -0,0 +1,56 @@
+import { Dispatch, SetStateAction, useEffect, useRef, useState } from 'react'
+import customLocalStorage from '@/infrastructure/local-storage'
+import { debugConsole } from '@/utils/debugging'
+
+export type PdfScrollPosition = Record<string, any> | undefined
+
+export const usePdfScrollPosition = (
+  lastCompileRootDocId: string | null | undefined
+): [PdfScrollPosition, Dispatch<SetStateAction<PdfScrollPosition>>] => {
+  // scroll position of the PDF
+  const [position, setPosition] = useState<PdfScrollPosition>()
+
+  const lastCompileRootDocIdRef = useRef<string | null | undefined>(
+    lastCompileRootDocId
+  )
+  useEffect(() => {
+    lastCompileRootDocIdRef.current = lastCompileRootDocId
+  }, [lastCompileRootDocId])
+
+  const initialScrollPositionRef = useRef<PdfScrollPosition | null>(null)
+
+  // load the stored PDF scroll position when the compiled root doc changes
+  useEffect(() => {
+    if (lastCompileRootDocId) {
+      const position = customLocalStorage.getItem(
+        `pdf.position.${lastCompileRootDocId}`
+      )
+      if (position) {
+        debugConsole.log('loaded position for', lastCompileRootDocId, position)
+        initialScrollPositionRef.current = position
+        setPosition(position)
+      }
+    }
+  }, [lastCompileRootDocId])
+
+  // store the current root doc's PDF scroll position when it changes
+  useEffect(() => {
+    if (
+      lastCompileRootDocIdRef.current &&
+      position &&
+      position !== initialScrollPositionRef.current
+    ) {
+      debugConsole.log(
+        'storing position for',
+        lastCompileRootDocIdRef.current,
+        position
+      )
+      customLocalStorage.setItem(
+        `pdf.position.${lastCompileRootDocIdRef.current}`,
+        position
+      )
+    }
+  }, [position])
+
+  return [position, setPosition]
+}