[web] add a hook for discovering the current root doc (#34027)
GitOrigin-RevId: d1930e6b13ca18dbae927dc15a5c6507351f71c8
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import { isMainFile } from './editor-files'
|
||||
import getMeta from '../../../utils/meta'
|
||||
import { deleteJSON, postJSON } from '../../../infrastructure/fetch-json'
|
||||
import { debounce, DebouncedFunc } from 'lodash'
|
||||
@@ -8,9 +7,9 @@ import { debugConsole } from '@/utils/debugging'
|
||||
import { signalWithTimeout } from '@/utils/abort-signal'
|
||||
import { Dispatch, SetStateAction } from 'react'
|
||||
import { OpenDocuments } from '@/features/ide-react/editor/open-documents'
|
||||
import { DocumentContainer } from '@/features/ide-react/editor/document-container'
|
||||
import { CompileOptions, CompileResponseData } from '@ol-types/compile'
|
||||
import { DeliveryLatencies } from './types'
|
||||
import { RootDocInfo } from '@/shared/hooks/use-root-doc'
|
||||
|
||||
const AUTO_COMPILE_MAX_WAIT = 5000
|
||||
// We add a 2 second debounce to sending user changes to server if they aren't
|
||||
@@ -36,14 +35,12 @@ export default class DocumentCompiler {
|
||||
cleanupCompileResult: () => void
|
||||
signal: AbortSignal
|
||||
openDocs: OpenDocuments
|
||||
projectRootDocId: string | null
|
||||
clsiServerId: string | null
|
||||
currentDoc: DocumentContainer | null
|
||||
error: Error | undefined
|
||||
timer: number
|
||||
defaultOptions: CompileOptions
|
||||
debouncedAutoCompile: DebouncedFunc<() => void>
|
||||
pathInFolder: (docId: string) => string | null
|
||||
getRootDocInfo: () => RootDocInfo
|
||||
|
||||
constructor({
|
||||
compilingRef,
|
||||
@@ -57,6 +54,7 @@ export default class DocumentCompiler {
|
||||
cleanupCompileResult,
|
||||
signal,
|
||||
openDocs,
|
||||
getRootDocInfo,
|
||||
}: {
|
||||
compilingRef: React.MutableRefObject<boolean>
|
||||
projectId: string
|
||||
@@ -69,6 +67,7 @@ export default class DocumentCompiler {
|
||||
cleanupCompileResult: () => void
|
||||
signal: AbortSignal
|
||||
openDocs: OpenDocuments
|
||||
getRootDocInfo: () => RootDocInfo
|
||||
}) {
|
||||
this.compilingRef = compilingRef
|
||||
this.projectId = projectId
|
||||
@@ -81,11 +80,9 @@ export default class DocumentCompiler {
|
||||
this.cleanupCompileResult = cleanupCompileResult
|
||||
this.signal = signal
|
||||
this.openDocs = openDocs
|
||||
this.pathInFolder = () => null
|
||||
this.getRootDocInfo = getRootDocInfo
|
||||
|
||||
this.projectRootDocId = null
|
||||
this.clsiServerId = null
|
||||
this.currentDoc = null
|
||||
this.error = undefined
|
||||
this.timer = 0
|
||||
this.defaultOptions = {
|
||||
@@ -136,9 +133,7 @@ export default class DocumentCompiler {
|
||||
|
||||
const t0 = performance.now()
|
||||
|
||||
const rootDocId = this.getRootDocOverrideId() || this.projectRootDocId
|
||||
const rootResourcePath =
|
||||
(rootDocId && this.pathInFolder(rootDocId)) || 'main.tex'
|
||||
const { rootDocId, rootResourcePath } = this.getRootDocInfo()
|
||||
|
||||
const body = {
|
||||
rootDoc_id: rootDocId,
|
||||
@@ -184,21 +179,6 @@ export default class DocumentCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
// parse the text of the current doc in the editor
|
||||
// if it contains "\documentclass" then use this as the root doc
|
||||
getRootDocOverrideId() {
|
||||
// only override when not in the root doc itself
|
||||
if (this.currentDoc && this.currentDoc.doc_id !== this.projectRootDocId) {
|
||||
const snapshot = this.currentDoc.getSnapshot()
|
||||
|
||||
if (snapshot && isMainFile(snapshot)) {
|
||||
return this.currentDoc.doc_id
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
// build the query parameters added to post-compile requests
|
||||
buildPostCompileParams() {
|
||||
const params = new URLSearchParams()
|
||||
|
||||
@@ -34,6 +34,7 @@ import { useUserContext } from './user-context'
|
||||
import { useFileTreeData } from '@/shared/context/file-tree-data-context'
|
||||
import { useDetachContext } from '@/shared/context/detach-context'
|
||||
import { useFileTreePathContext } from '@/features/file-tree/contexts/file-tree-path'
|
||||
import { useRootDoc } from '@/shared/hooks/use-root-doc'
|
||||
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'
|
||||
@@ -151,7 +152,8 @@ export const LocalCompileProvider: FC<React.PropsWithChildren> = ({
|
||||
const { features, alphaProgram } = useUserContext()
|
||||
|
||||
const { fileTreeData } = useFileTreeData()
|
||||
const { pathInFolder, findEntityByPath } = useFileTreePathContext()
|
||||
const { findEntityByPath } = useFileTreePathContext()
|
||||
const getRootDocInfo = useRootDoc()
|
||||
|
||||
// whether a compile is in progress
|
||||
const [compiling, setCompiling] = useState(false)
|
||||
@@ -332,22 +334,14 @@ export const LocalCompileProvider: FC<React.PropsWithChildren> = ({
|
||||
compilingRef,
|
||||
signal,
|
||||
openDocs,
|
||||
getRootDocInfo,
|
||||
})
|
||||
})
|
||||
|
||||
// keep currentDoc in sync with the compiler
|
||||
// keep the root doc lookup in sync with the compiler
|
||||
useEffect(() => {
|
||||
compiler.currentDoc = currentDocument
|
||||
}, [compiler, currentDocument])
|
||||
|
||||
// keep the project rootDocId in sync with the compiler
|
||||
useEffect(() => {
|
||||
compiler.projectRootDocId = rootDocId || null
|
||||
}, [compiler, rootDocId])
|
||||
// keep pathInFolder in sync with the compiler
|
||||
useEffect(() => {
|
||||
compiler.pathInFolder = pathInFolder
|
||||
}, [compiler, pathInFolder])
|
||||
compiler.getRootDocInfo = getRootDocInfo
|
||||
}, [compiler, getRootDocInfo])
|
||||
|
||||
// keep draft setting in sync with the compiler
|
||||
useEffect(() => {
|
||||
@@ -399,9 +393,8 @@ export const LocalCompileProvider: FC<React.PropsWithChildren> = ({
|
||||
dataFromCache.rootDocId = findEntityByPath(
|
||||
dataFromCache.options?.rootResourcePath || ''
|
||||
)?.entity?._id
|
||||
const rootDocOverride = compiler.getRootDocOverrideId() || rootDocId
|
||||
settingsUpToDate =
|
||||
rootDocOverride === dataFromCache.rootDocId &&
|
||||
getRootDocInfo().rootDocId === dataFromCache.rootDocId &&
|
||||
dataFromCache.options.draft === draft &&
|
||||
// Allow stopOnFirstError to be enabled in the compile from cache and disabled locally.
|
||||
// Compiles that passed with stopOnFirstError=true will also pass with stopOnFirstError=false. The inverse does not hold, and we need to recompile.
|
||||
@@ -428,9 +421,8 @@ export const LocalCompileProvider: FC<React.PropsWithChildren> = ({
|
||||
joinedOnce,
|
||||
currentDocument,
|
||||
compiledOnce,
|
||||
rootDocId,
|
||||
findEntityByPath,
|
||||
compiler,
|
||||
getRootDocInfo,
|
||||
compilerName,
|
||||
imageName,
|
||||
stopOnFirstError,
|
||||
@@ -552,7 +544,7 @@ export const LocalCompileProvider: FC<React.PropsWithChildren> = ({
|
||||
result.logEntries.all
|
||||
) as Record<string, number>
|
||||
|
||||
const rootDocId = data.rootDocId || compiler.projectRootDocId
|
||||
const rootDocId = data.rootDocId
|
||||
|
||||
const previousRuleCounts = previousRuleCountsRef.current
|
||||
previousRuleCountsRef.current = { ruleCounts, rootDocId }
|
||||
@@ -654,7 +646,6 @@ export const LocalCompileProvider: FC<React.PropsWithChildren> = ({
|
||||
setLogEntries,
|
||||
setLogEntryAnnotations,
|
||||
setPdfFile,
|
||||
compiler,
|
||||
])
|
||||
|
||||
// switch to logs if there's an error
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { useCallback } from 'react'
|
||||
import { useProjectContext } from '@/shared/context/project-context'
|
||||
import { useEditorOpenDocContext } from '@/features/ide-react/context/editor-open-doc-context'
|
||||
import { useFileTreePathContext } from '@/features/file-tree/contexts/file-tree-path'
|
||||
import { isMainFile } from '@/features/pdf-preview/util/editor-files'
|
||||
|
||||
export type RootDocInfo = {
|
||||
rootDocId: string | null
|
||||
rootResourcePath: string
|
||||
}
|
||||
|
||||
export function useRootDoc(): () => RootDocInfo {
|
||||
const { project } = useProjectContext()
|
||||
const projectRootDocId = project?.rootDocId ?? null
|
||||
const { currentDocument } = useEditorOpenDocContext()
|
||||
const { pathInFolder } = useFileTreePathContext()
|
||||
|
||||
// Inspecting the document content is too expensive to perform on every update.
|
||||
// Compute the rootDoc on-demand instead.
|
||||
return useCallback((): RootDocInfo => {
|
||||
let rootDocId: string | null = projectRootDocId
|
||||
if (
|
||||
currentDocument &&
|
||||
currentDocument.doc_id !== projectRootDocId &&
|
||||
isMainFile(currentDocument.getSnapshot())
|
||||
) {
|
||||
rootDocId = currentDocument.doc_id
|
||||
}
|
||||
const rootResourcePath =
|
||||
(rootDocId && pathInFolder(rootDocId)) || 'main.tex'
|
||||
return { rootDocId, rootResourcePath }
|
||||
}, [projectRootDocId, currentDocument, pathInFolder])
|
||||
}
|
||||
Reference in New Issue
Block a user