| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823 |
- // Disable prop type checks for test harnesses
- /* eslint-disable react/prop-types */
- import { merge } from 'lodash'
- import { SocketIOMock } from '@/ide/connection/SocketIoShim'
- import { IdeContext } from '@/shared/context/ide-context'
- import React, {
- useCallback,
- useEffect,
- useState,
- useMemo,
- type FC,
- type PropsWithChildren,
- } from 'react'
- import { IdeReactContext } from '@/features/ide-react/context/ide-react-context'
- import { IdeEventEmitter } from '@/features/ide-react/create-ide-event-emitter'
- import { ReactScopeValueStore } from '@/features/ide-react/scope-value-store/react-scope-value-store'
- import { ReactScopeEventEmitter } from '@/features/ide-react/scope-event-emitter/react-scope-event-emitter'
- import { ConnectionContext } from '@/features/ide-react/context/connection-context'
- import {
- EditorOpenDocContext,
- type EditorOpenDocContextState,
- } from '@/features/ide-react/context/editor-open-doc-context'
- import { ProjectContext } from '@/shared/context/project-context'
- import { ReactContextRoot } from '@/features/ide-react/context/react-context-root'
- import useEventListener from '@/shared/hooks/use-event-listener'
- import useDetachLayout from '@/shared/hooks/use-detach-layout'
- import useExposedState from '@/shared/hooks/use-exposed-state'
- import { ProjectSnapshot } from '@/infrastructure/project-snapshot'
- import {
- EditorPropertiesContext,
- EditorPropertiesContextValue,
- } from '@/features/ide-react/context/editor-properties-context'
- import {
- type IdeLayout,
- type IdeView,
- LayoutContext,
- type LayoutContextValue,
- } from '@/shared/context/layout-context'
- import type { Socket } from '@/features/ide-react/connection/types/socket'
- import type { PermissionsLevel } from '@/features/ide-react/types/permissions'
- import type { Folder } from '../../../types/folder'
- import type { SocketDebuggingInfo } from '@/features/ide-react/connection/types/connection-state'
- import type { DocumentContainer } from '@/features/ide-react/editor/document-container'
- import {
- ProjectMetadata,
- ProjectUpdate,
- } from '@/shared/context/types/project-metadata'
- import { UserId } from '../../../types/user'
- import { ProjectCompiler } from '../../../types/project-settings'
- import { ReferencesContext } from '@/features/ide-react/context/references-context'
- import { useEditorAnalytics } from '@/shared/hooks/use-editor-analytics'
- import { defaultSettings } from '@/shared/context/user-settings-context'
- import { UserSettings } from '@ol-types/user-settings'
- import { DetachCompileContext } from '@/shared/context/detach-compile-context'
- import { type CompileContext } from '@/shared/context/local-compile-context'
- import { EditorContext } from '@/shared/context/editor-context'
- import { Cobranding } from '@ol-types/cobranding'
- import { EDITOR_SESSION_ID } from '@/features/pdf-preview/util/metrics'
- // these constants can be imported in tests instead of
- // using magic strings
- export const PROJECT_ID = 'project123'
- export const PROJECT_NAME = 'project-name'
- export const USER_ID = '123abd' as UserId
- export const USER_EMAIL = 'testuser@example.com'
- const defaultUserSettings = {
- ...defaultSettings,
- referencesSearchMode: 'simple',
- } satisfies UserSettings
- export type EditorProvidersProps = {
- user?: {
- id: string
- email: string
- signUpDate?: string
- isProfessionalGroupPlan?: boolean
- }
- projectId?: string
- projectName?: string
- projectOwner?: ProjectMetadata['owner']
- rootDocId?: string
- imageName?: string
- compiler?: ProjectCompiler
- socket?: Socket
- isRestrictedTokenMember?: boolean
- scope?: Record<string, any>
- features?: Record<string, boolean>
- projectFeatures?: Record<string, boolean>
- permissionsLevel?: PermissionsLevel
- children?: React.ReactNode
- rootFolder?: Folder[]
- layoutContext?: Partial<LayoutContextValue>
- userSettings?: Record<string, any>
- providers?: Record<string, React.FC<React.PropsWithChildren<any>>>
- mockCompileOnLoad?: boolean
- }
- export const projectDefaults: ProjectMetadata = {
- _id: PROJECT_ID,
- name: PROJECT_NAME,
- owner: {
- _id: '124abd' as UserId,
- email: 'owner@example.com',
- first_name: 'Test',
- last_name: 'Owner',
- privileges: 'owner',
- signUpDate: new Date('2025-07-07').toISOString(),
- },
- features: {
- referencesSearch: true,
- gitBridge: false,
- },
- rootDocId: '_root_doc_id',
- rootFolder: [
- {
- _id: 'root-folder-id',
- name: 'rootFolder',
- docs: [
- {
- _id: '_root_doc_id',
- name: 'main.tex',
- },
- ],
- folders: [],
- fileRefs: [],
- },
- ],
- imageName: 'texlive-full:2024.1',
- compiler: 'pdflatex' as ProjectCompiler,
- members: [],
- invites: [],
- trackChangesState: {} as Record<UserId | '__guests__', boolean>,
- spellCheckLanguage: 'en',
- }
- /**
- * @typedef {import('@/shared/context/layout-context').LayoutContextValue} LayoutContextValue
- * @type Partial<LayoutContextValue>
- */
- const layoutContextDefault = {
- view: 'editor',
- openFile: null,
- chatIsOpen: true, // false in the application, true in tests
- reviewPanelOpen: false,
- miniReviewPanelVisible: false,
- leftMenuShown: false,
- projectSearchIsOpen: false,
- pdfLayout: 'sideBySide',
- loadingStyleSheet: false,
- } satisfies Partial<LayoutContextValue>
- export function EditorProviders({
- user = {
- id: USER_ID,
- email: USER_EMAIL,
- signUpDate: '2025-10-10T10:10:10Z',
- },
- projectId = projectDefaults._id,
- projectName = projectDefaults.name,
- projectOwner = projectDefaults.owner,
- rootDocId = projectDefaults.rootDocId,
- imageName = projectDefaults.imageName,
- compiler = projectDefaults.compiler,
- socket = new SocketIOMock() as any as Socket,
- isRestrictedTokenMember = false,
- scope: defaultScope = {},
- features = {
- referencesSearch: true,
- gitBridge: false,
- },
- projectFeatures = features,
- permissionsLevel = 'owner',
- children,
- rootFolder = projectDefaults.rootFolder,
- /** @type {Partial<LayoutContext>} */
- layoutContext = layoutContextDefault,
- userSettings = {},
- providers = {},
- mockCompileOnLoad = false,
- }: EditorProvidersProps) {
- window.metaAttributesCache.set(
- 'ol-gitBridgePublicBaseUrl',
- 'https://git.overleaf.test'
- )
- window.metaAttributesCache.set(
- 'ol-isRestrictedTokenMember',
- isRestrictedTokenMember
- )
- window.metaAttributesCache.set(
- 'ol-userSettings',
- merge({}, defaultUserSettings, userSettings)
- )
- window.metaAttributesCache.set('ol-capabilities', [
- 'chat',
- 'dropbox',
- 'link-sharing',
- ])
- const scope = merge(
- {
- user,
- editor: {
- sharejs_doc: {
- doc_id: 'test-doc',
- getSnapshot: () => 'some doc content',
- hasBufferedOps: () => false,
- on: () => {},
- off: () => {},
- leaveAndCleanUpPromise: async () => {},
- } as any as DocumentContainer,
- openDocName: null,
- currentDocumentId: null,
- wantTrackChanges: false,
- },
- permissionsLevel,
- },
- defaultScope
- )
- const project = {
- _id: projectId,
- name: projectName,
- owner: projectOwner,
- features: projectFeatures,
- rootDocId,
- rootFolder,
- imageName,
- compiler,
- members: [],
- invites: [],
- trackChangesState: false,
- spellCheckLanguage: 'en',
- }
- // Add details for useUserContext
- window.metaAttributesCache.set('ol-user', { ...user, features })
- window.metaAttributesCache.set('ol-project_id', projectId)
- const customProviders: Record<string, FC<PropsWithChildren>> = {
- ConnectionProvider: makeConnectionProvider(socket),
- IdeReactProvider: makeIdeReactProvider(scope, socket),
- EditorOpenDocProvider: makeEditorOpenDocProvider({
- currentDocumentId: scope.editor.currentDocumentId,
- openDocName: scope.editor.openDocName,
- currentDocument: scope.editor.sharejs_doc,
- }),
- EditorPropertiesProvider: makeEditorPropertiesProvider({
- wantTrackChanges: scope.editor.wantTrackChanges,
- }),
- LayoutProvider: makeLayoutProvider(layoutContext),
- ProjectProvider: makeProjectProvider(project),
- ReferencesProvider: makeReferencesProvider(),
- ...providers,
- }
- // Only use the mock EditorProvider when explicitly required
- if (providers.EditorProvider) {
- customProviders.EditorProvider = providers.EditorProvider
- }
- // Only override DetachCompileProvider when we need the mock
- if (mockCompileOnLoad) {
- customProviders.DetachCompileProvider =
- makeDetachCompileProvider(mockCompileOnLoad)
- }
- // Otherwise, let ReactContextRoot use the real DetachCompileProvider from production
- return (
- <ReactContextRoot providers={customProviders}>{children}</ReactContextRoot>
- )
- }
- export function makeEditorProvider({
- isProjectOwner = true,
- cobranding = undefined,
- renameProject = () => {},
- isRestrictedTokenMember,
- }: {
- isProjectOwner?: boolean
- cobranding?: Cobranding
- renameProject?: () => void
- isRestrictedTokenMember?: boolean
- } = {}) {
- const EditorProvider: FC<PropsWithChildren> = ({ children }) => {
- const value = {
- isProjectOwner,
- renameProject,
- isPendingEditor: false,
- hasSuggestionsLeft: false,
- premiumSuggestionResetDate: new Date(),
- hasTokensLeft: false,
- tokensLeft: 0,
- setTokensLeft: () => {},
- tokenResetDate: new Date(),
- setTokenResetDate: () => {},
- suggestionsLeft: 0,
- setSuggestionsLeft: () => {},
- setPremiumSuggestionResetDate: () => {},
- writefullInstance: null,
- setWritefullInstance: () => {},
- cobranding,
- isRestrictedTokenMember,
- upgradeTrackChangesModal: { show: false },
- setUpgradeTrackChangesModal: () => {},
- }
- return (
- <EditorContext.Provider value={value}>{children}</EditorContext.Provider>
- )
- }
- return EditorProvider
- }
- const makeReferencesProvider = () => {
- const ReferencesProvider: FC<PropsWithChildren> = ({ children }) => {
- return (
- <ReferencesContext.Provider
- value={{
- referenceKeys: new Set(),
- indexAllReferences: () => Promise.resolve(),
- searchLocalReferences() {
- return Promise.resolve({
- hits: [],
- })
- },
- }}
- >
- {children}
- </ReferencesContext.Provider>
- )
- }
- return ReferencesProvider
- }
- const makeConnectionProvider = (socket: Socket) => {
- const ConnectionProvider: FC<PropsWithChildren> = ({ children }) => {
- const [value] = useState(() => ({
- socket,
- connectionState: {
- readyState: WebSocket.OPEN,
- forceDisconnected: false,
- inactiveDisconnect: false,
- reconnectAt: null,
- forcedDisconnectDelay: 0,
- lastConnectionAttempt: 0,
- error: '' as const,
- },
- isConnected: true,
- isStillReconnecting: false,
- secondsUntilReconnect: () => 0,
- tryReconnectNow: () => {},
- registerUserActivity: () => {},
- disconnect: () => {},
- closeConnection: () => {},
- getSocketDebuggingInfo: () => ({}) as SocketDebuggingInfo,
- }))
- return (
- <ConnectionContext.Provider value={value}>
- {children}
- </ConnectionContext.Provider>
- )
- }
- return ConnectionProvider
- }
- const makeIdeReactProvider = (
- scope: Record<string, unknown>,
- socket: Socket
- ) => {
- const IdeReactProvider: FC<PropsWithChildren> = ({ children }) => {
- const [startedFreeTrial, setStartedFreeTrial] = useState(false)
- const [ideReactContextValue] = useState(() => ({
- projectId: PROJECT_ID,
- eventEmitter: new IdeEventEmitter(),
- startedFreeTrial,
- setStartedFreeTrial,
- reportError: () => {},
- projectJoined: true,
- permissionsLevel: scope.permissionsLevel as PermissionsLevel,
- setPermissionsLevel: () => {},
- setOutOfSync: () => {},
- }))
- const [ideContextValue] = useState(() => {
- const scopeEventEmitter = new ReactScopeEventEmitter(
- new IdeEventEmitter()
- )
- const unstableStore = new ReactScopeValueStore()
- return {
- socket,
- scopeEventEmitter,
- unstableStore,
- }
- })
- useEffect(() => {
- window.overleaf = {
- ...window.overleaf,
- unstable: {
- ...window.overleaf?.unstable,
- store: ideContextValue.unstableStore,
- },
- }
- }, [ideContextValue.unstableStore])
- return (
- <IdeReactContext.Provider value={ideReactContextValue}>
- <IdeContext.Provider value={ideContextValue}>
- {children}
- </IdeContext.Provider>
- </IdeReactContext.Provider>
- )
- }
- return IdeReactProvider
- }
- export function makeEditorOpenDocProvider(
- initialValues: EditorOpenDocContextState
- ) {
- const {
- currentDocumentId: initialCurrentDocumentId,
- openDocName: initialOpenDocName,
- currentDocument: initialCurrentDocument,
- } = initialValues
- const EditorOpenDocProvider: FC<PropsWithChildren> = ({ children }) => {
- const [currentDocumentId, setCurrentDocumentId] = useExposedState(
- initialCurrentDocumentId,
- 'editor.open_doc_id'
- )
- const [openDocName, setOpenDocName] = useExposedState(
- initialOpenDocName,
- 'editor.open_doc_name'
- )
- const [currentDocument, setCurrentDocument] = useState(
- initialCurrentDocument
- )
- const value = {
- currentDocumentId,
- setCurrentDocumentId,
- openDocName,
- setOpenDocName,
- currentDocument,
- setCurrentDocument,
- }
- return (
- <EditorOpenDocContext.Provider value={value}>
- {children}
- </EditorOpenDocContext.Provider>
- )
- }
- return EditorOpenDocProvider
- }
- const makeLayoutProvider = (
- layoutContextOverrides?: Partial<LayoutContextValue>
- ) => {
- const layout = {
- ...layoutContextDefault,
- ...layoutContextOverrides,
- }
- const LayoutProvider: FC<PropsWithChildren> = ({ children }) => {
- const [view, setView] = useState<IdeView | null>(layout.view)
- const [openFile, setOpenFile] = useState(layout.openFile)
- const [chatIsOpen, setChatIsOpen] = useState(layout.chatIsOpen)
- const [reviewPanelOpen, setReviewPanelOpen] = useState(
- layout.reviewPanelOpen
- )
- const [miniReviewPanelVisible, setMiniReviewPanelVisible] = useState(
- layout.miniReviewPanelVisible
- )
- const [leftMenuShown, setLeftMenuShown] = useState(layout.leftMenuShown)
- const [projectSearchIsOpen, setProjectSearchIsOpen] = useState(
- layout.projectSearchIsOpen
- )
- const [pdfLayout, setPdfLayout] = useState(layout.pdfLayout)
- const [loadingStyleSheet, setLoadingStyleSheet] = useState(
- layout.loadingStyleSheet
- )
- const { sendEvent } = useEditorAnalytics()
- useEventListener(
- 'ui.toggle-review-panel',
- useCallback(() => {
- setReviewPanelOpen(open => !open)
- }, [setReviewPanelOpen])
- )
- const changeLayout = useCallback(
- (newLayout: IdeLayout, newView: IdeView = 'editor') => {
- setPdfLayout(newLayout)
- setView(newLayout === 'sideBySide' ? 'editor' : newView)
- },
- [setPdfLayout, setView]
- )
- const restoreView = useCallback(() => {
- setView('editor')
- }, [])
- const {
- reattach,
- detach,
- isLinked: detachIsLinked,
- role: detachRole,
- } = useDetachLayout()
- const handleDetach = useCallback(() => {
- detach()
- sendEvent('project-layout-detach')
- }, [detach, sendEvent])
- const handleReattach = useCallback(() => {
- if (detachRole !== 'detacher') {
- return
- }
- reattach()
- sendEvent('project-layout-reattach')
- }, [detachRole, reattach, sendEvent])
- const handleChangeLayout = useCallback(
- (newLayout: IdeLayout, newView?: IdeView) => {
- handleReattach()
- changeLayout(newLayout, newView)
- sendEvent('project-layout-change', {
- layout: newLayout,
- view: newView,
- })
- },
- [changeLayout, handleReattach, sendEvent]
- )
- const pdfPreviewOpen =
- pdfLayout === 'sideBySide' || view === 'pdf' || detachRole === 'detacher'
- const value = useMemo(
- () => ({
- reattach,
- detach,
- detachIsLinked,
- detachRole,
- changeLayout,
- chatIsOpen,
- leftMenuShown,
- openFile,
- pdfLayout,
- pdfPreviewOpen,
- projectSearchIsOpen,
- setProjectSearchIsOpen,
- reviewPanelOpen,
- miniReviewPanelVisible,
- loadingStyleSheet,
- setChatIsOpen,
- setLeftMenuShown,
- setOpenFile,
- setPdfLayout,
- setReviewPanelOpen,
- setMiniReviewPanelVisible,
- setLoadingStyleSheet,
- setView,
- view,
- restoreView,
- handleChangeLayout,
- handleDetach,
- }),
- [
- reattach,
- detach,
- detachIsLinked,
- detachRole,
- changeLayout,
- chatIsOpen,
- leftMenuShown,
- openFile,
- pdfLayout,
- pdfPreviewOpen,
- projectSearchIsOpen,
- setProjectSearchIsOpen,
- reviewPanelOpen,
- miniReviewPanelVisible,
- loadingStyleSheet,
- setChatIsOpen,
- setLeftMenuShown,
- setOpenFile,
- setPdfLayout,
- setReviewPanelOpen,
- setMiniReviewPanelVisible,
- setLoadingStyleSheet,
- setView,
- view,
- restoreView,
- handleChangeLayout,
- handleDetach,
- ]
- )
- return (
- <LayoutContext.Provider value={value}>{children}</LayoutContext.Provider>
- )
- }
- return LayoutProvider
- }
- export function makeEditorPropertiesProvider(
- initialValues: Partial<
- Pick<
- EditorPropertiesContextValue,
- 'showVisual' | 'showSymbolPalette' | 'wantTrackChanges'
- >
- >
- ) {
- const EditorPropertiesProvider: FC<PropsWithChildren> = ({ children }) => {
- const {
- showVisual: initialShowVisual,
- showSymbolPalette: initialShowSymbolPalette,
- wantTrackChanges: initialWantTrackChanges,
- } = initialValues
- const [showVisual, setShowVisual] = useState(initialShowVisual || false)
- const [showSymbolPalette, setShowSymbolPalette] = useState(
- initialShowSymbolPalette || false
- )
- function toggleSymbolPalette() {
- setShowSymbolPalette(show => !show)
- }
- const [opening, setOpening] = useState(true)
- const [trackChanges, setTrackChanges] = useState(false)
- const [wantTrackChanges, setWantTrackChanges] = useState(
- initialWantTrackChanges || false
- )
- const [errorState, setErrorState] = useState(false)
- const value = {
- showVisual,
- setShowVisual,
- showVisualForFile: () => showVisual,
- showSymbolPalette,
- setShowSymbolPalette,
- toggleSymbolPalette,
- opening,
- setOpening,
- trackChanges,
- setTrackChanges,
- wantTrackChanges,
- setWantTrackChanges,
- errorState,
- setErrorState,
- }
- return (
- <EditorPropertiesContext.Provider value={value}>
- {children}
- </EditorPropertiesContext.Provider>
- )
- }
- return EditorPropertiesProvider
- }
- export function makeProjectProvider(initialProject: ProjectMetadata) {
- const ProjectProvider: FC<PropsWithChildren> = ({ children }) => {
- const [project, setProject] = useState(initialProject)
- const updateProject = useCallback((projectUpdateData: ProjectUpdate) => {
- setProject(projectData =>
- Object.assign({}, projectData, projectUpdateData)
- )
- }, [])
- const value = {
- projectId: project._id,
- project,
- joinProject: () => {},
- updateProject,
- joinedOnce: true,
- projectSnapshot: new ProjectSnapshot(project._id),
- tags: [],
- features: project.features,
- name: project.name,
- }
- return (
- <ProjectContext.Provider value={value}>
- {children}
- </ProjectContext.Provider>
- )
- }
- return ProjectProvider
- }
- const BASE_COMPILE_CONTEXT_MOCK = {
- animateCompileDropdownArrow: false,
- clearCache: () => {},
- clearingCache: false,
- clsiServerId: undefined,
- codeCheckFailed: false,
- deliveryLatencies: {},
- editedSinceCompileStarted: false,
- fileList: undefined,
- hasChanges: false,
- hasShortCompileTimeout: false,
- highlights: undefined,
- isProjectOwner: true,
- lastCompileOptions: {},
- logEntryAnnotations: undefined,
- logEntries: undefined,
- outputFilesArchive: undefined,
- pdfViewer: 'pdfjs',
- position: undefined,
- rawLog: undefined,
- recompileFromScratch: () => {},
- setAnimateCompileDropdownArrow: () => {},
- setHasLintingError: () => {},
- setHighlights: () => {},
- setPosition: () => {},
- setShowCompileTimeWarning: () => {},
- setShowLogs: () => {},
- toggleLogs: () => {},
- setStopOnValidationError: () => {},
- showLogs: false,
- showCompileTimeWarning: false,
- stopCompile: () => {},
- stopOnValidationError: true,
- stoppedOnFirstError: false,
- uncompiled: false,
- validationIssues: undefined,
- firstRenderDone: () => {},
- setChangedAt: () => {},
- cleanupCompileResult: undefined,
- syncToEntry: () => {},
- recordAction: () => {},
- darkModePdf: false,
- setDarkModePdf: () => {},
- activeOverallTheme: 'light',
- } as const
- const makeDetachCompileProvider = (mockCompileOnLoad: boolean = false) => {
- const DetachCompileProvider: FC<PropsWithChildren> = ({ children }) => {
- const [pdfUrl, setPdfUrl] = useState<string | undefined>()
- const [pdfDownloadUrl, setPdfDownloadUrl] = useState<string | undefined>()
- const [pdfFile, setPdfFile] = useState<any>()
- const [compiling, setCompiling] = useState(false)
- const [error, setError] = useState<string | undefined>()
- const [autoCompile, setAutoCompile] = useState(true)
- const [draft, setDraft] = useState(false)
- const [stopOnFirstError, setStopOnFirstError] = useState(false)
- const startCompile = useCallback(async () => {
- setCompiling(true)
- try {
- const response = await fetch('/project/123abc/compile', {
- method: 'POST',
- })
- const data = await response.json()
- const pdfFileData = data.outputFiles?.find(
- (file: any) => file.type === 'pdf'
- )
- if (data.status === 'success' && pdfFileData) {
- const newPdfUrl = `${data.pdfDownloadDomain || ''}${pdfFileData.url}`
- const params = [
- data.compileGroup && `compileGroup=${data.compileGroup}`,
- data.clsiServerId && `clsiserverid=${data.clsiServerId}`,
- `editorId=${EDITOR_SESSION_ID}`,
- 'popupDownload=true',
- ]
- .filter(Boolean)
- .join('&')
- const newPdfDownloadUrl = `/download/project/123abc/build/${pdfFileData.build}/output/${pdfFileData.path}?${params}`
- setPdfUrl(newPdfUrl)
- setPdfDownloadUrl(newPdfDownloadUrl)
- setPdfFile({ pdfUrl: newPdfUrl, pdfDownloadUrl: newPdfDownloadUrl })
- }
- } catch (err) {
- setError('Compile failed')
- } finally {
- setCompiling(false)
- }
- }, [])
- useEffect(() => {
- if (mockCompileOnLoad) {
- startCompile()
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [startCompile])
- const value = {
- ...BASE_COMPILE_CONTEXT_MOCK,
- autoCompile,
- compiling,
- draft,
- error,
- pdfDownloadUrl,
- pdfFile,
- pdfUrl,
- setAutoCompile,
- setCompiling,
- setDraft,
- setError,
- setStopOnFirstError,
- startCompile,
- stopOnFirstError,
- } as CompileContext
- return (
- <DetachCompileContext.Provider value={value}>
- {children}
- </DetachCompileContext.Provider>
- )
- }
- return DetachCompileProvider
- }
|