diff --git a/services/web/frontend/js/shared/context/local-compile-context.tsx b/services/web/frontend/js/shared/context/local-compile-context.tsx index b09fe07f86..ef12cbec00 100644 --- a/services/web/frontend/js/shared/context/local-compile-context.tsx +++ b/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 @@ -61,14 +67,14 @@ export type CompileContext = { pdfFile?: PdfFile pdfUrl?: string pdfViewer?: string - position?: Record + 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> 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( diff --git a/services/web/frontend/js/shared/hooks/use-pdf-scroll-position.ts b/services/web/frontend/js/shared/hooks/use-pdf-scroll-position.ts new file mode 100644 index 0000000000..69ec3893e0 --- /dev/null +++ b/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 | undefined + +export const usePdfScrollPosition = ( + lastCompileRootDocId: string | null | undefined +): [PdfScrollPosition, Dispatch>] => { + // scroll position of the PDF + const [position, setPosition] = useState() + + const lastCompileRootDocIdRef = useRef( + lastCompileRootDocId + ) + useEffect(() => { + lastCompileRootDocIdRef.current = lastCompileRootDocId + }, [lastCompileRootDocId]) + + const initialScrollPositionRef = useRef(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] +}