Minimise use of ide context provider (#23308)

GitOrigin-RevId: 468b8d4b33925bdb97bd46d2c4e7acb969f3d82b
This commit is contained in:
Alf Eaton
2025-02-07 09:05:05 +00:00
committed by Copybot
parent 4e51b79fbd
commit be3a208166
19 changed files with 106 additions and 197 deletions
@@ -4,7 +4,7 @@ import useScopeValue from '../../../shared/hooks/use-scope-value'
import type { ProjectSettings } from '../utils/api'
export default function useProjectWideSettingsSocketListener() {
const ide = useIdeContext()
const { socket } = useIdeContext()
const [project, setProject] = useScopeValue<ProjectSettings | undefined>(
'project'
@@ -41,18 +41,18 @@ export default function useProjectWideSettingsSocketListener() {
// data is not available on initial mounting
const dataAvailable = !!project
if (dataAvailable && ide?.socket) {
ide.socket.on('compilerUpdated', setCompiler)
ide.socket.on('imageNameUpdated', setImageName)
ide.socket.on('spellCheckLanguageUpdated', setSpellCheckLanguage)
if (dataAvailable && socket) {
socket.on('compilerUpdated', setCompiler)
socket.on('imageNameUpdated', setImageName)
socket.on('spellCheckLanguageUpdated', setSpellCheckLanguage)
return () => {
ide.socket.removeListener('compilerUpdated', setCompiler)
ide.socket.removeListener('imageNameUpdated', setImageName)
ide.socket.removeListener(
socket.removeListener('compilerUpdated', setCompiler)
socket.removeListener('imageNameUpdated', setImageName)
socket.removeListener(
'spellCheckLanguageUpdated',
setSpellCheckLanguage
)
}
}
}, [ide?.socket, project, setCompiler, setImageName, setSpellCheckLanguage])
}, [socket, project, setCompiler, setImageName, setSpellCheckLanguage])
}
@@ -22,6 +22,7 @@ import { fileCollator } from '@/features/file-tree/util/file-collator'
import { Folder } from '../../../../../types/folder'
import { FileTreeEntity } from '../../../../../types/file-tree-entity'
import { isMac } from '@/shared/utils/os'
import useEventListener from '@/shared/hooks/use-event-listener'
const FileTreeSelectableContext = createContext<
| {
@@ -188,18 +189,22 @@ export const FileTreeSelectableProvider: FC<{
setSelectedEntities,
])
useEffect(() => {
// listen for `editor.openDoc` and selected that doc
function handleOpenDoc(ev: any) {
const found = findInTree(fileTreeData, ev.detail)
if (!found) return
// Synchronize the file tree when openFileWithId or openDocWithId is called on the editor
// manager context from elsewhere. If the file tree does change, it will
// trigger the onSelect handler in this component, which will update the local
// state.
useEventListener(
'entity:opened',
useCallback(
(event: CustomEvent<string>) => {
const found = findInTree(fileTreeData, event.detail)
if (!found) return
dispatch({ type: ACTION_TYPES.SELECT, id: found.entity._id })
}
window.addEventListener('editor.openDoc', handleOpenDoc)
return () => window.removeEventListener('editor.openDoc', handleOpenDoc)
}, [fileTreeData])
dispatch({ type: ACTION_TYPES.SELECT, id: found.entity._id })
},
[fileTreeData]
)
)
const select = useCallback(id => {
dispatch({ type: ACTION_TYPES.SELECT, id })
@@ -1,5 +1,4 @@
import { sendMB } from '../../../../infrastructure/event-tracking'
import { useIdeContext } from '../../../../shared/context/ide-context'
import { useLayoutContext } from '../../../../shared/context/layout-context'
import { restoreFile } from '../../services/api'
import { isFileRemoved } from '../../utils/file-diff'
@@ -10,6 +9,7 @@ import { useFileTreeData } from '@/shared/context/file-tree-data-context'
import { findInTree } from '@/features/file-tree/util/find-in-tree'
import { useCallback, useEffect, useState } from 'react'
import { RestoreFileResponse } from '@/features/history/services/types/restore-file'
import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
type RestorationState =
| 'idle'
@@ -21,8 +21,8 @@ type RestorationState =
export function useRestoreDeletedFile() {
const { projectId } = useHistoryContext()
const ide = useIdeContext()
const { setView } = useLayoutContext()
const { openDocWithId, openFileWithId } = useEditorManagerContext()
const handleError = useErrorHandler()
const { fileTreeData } = useFileTreeData()
const [state, setState] = useState<RestorationState>('idle')
@@ -39,12 +39,10 @@ export function useRestoreDeletedFile() {
const { _id: id } = result.entity
setView('editor')
// Once Angular is gone, these can be replaced with calls to context
// methods
if (restoredFileMetadata.type === 'doc') {
ide.editorManager.openDocWithId(id)
openDocWithId(id)
} else {
ide.binaryFilesManager.openFileWithId(id)
openFileWithId(id)
}
}
}
@@ -52,8 +50,8 @@ export function useRestoreDeletedFile() {
state,
fileTreeData,
restoredFileMetadata,
ide.editorManager,
ide.binaryFilesManager,
openDocWithId,
openFileWithId,
setView,
])
@@ -1,4 +1,3 @@
import { useIdeContext } from '../../../../shared/context/ide-context'
import { useLayoutContext } from '../../../../shared/context/layout-context'
import { restoreFileToVersion } from '../../services/api'
import { isFileRemoved } from '../../utils/file-diff'
@@ -9,6 +8,7 @@ import { useFileTreeData } from '@/shared/context/file-tree-data-context'
import { findInTree } from '@/features/file-tree/util/find-in-tree'
import { useCallback, useEffect, useState } from 'react'
import { RestoreFileResponse } from '../../services/types/restore-file'
import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
const RESTORE_FILE_TIMEOUT = 3000
@@ -22,8 +22,8 @@ type RestoreState =
export function useRestoreSelectedFile() {
const { projectId } = useHistoryContext()
const ide = useIdeContext()
const { setView } = useLayoutContext()
const { openDocWithId, openFileWithId } = useEditorManagerContext()
const handleError = useErrorHandler()
const { fileTreeData } = useFileTreeData()
const [state, setState] = useState<RestoreState>('idle')
@@ -40,12 +40,10 @@ export function useRestoreSelectedFile() {
const { _id: id } = result.entity
setView('editor')
// Once Angular is gone, these can be replaced with calls to context
// methods
if (restoredFileMetadata.type === 'doc') {
ide.editorManager.openDocWithId(id)
openDocWithId(id)
} else {
ide.binaryFilesManager.openFileWithId(id)
openFileWithId(id)
}
}
}
@@ -53,8 +51,8 @@ export function useRestoreSelectedFile() {
state,
fileTreeData,
restoredFileMetadata,
ide.editorManager,
ide.binaryFilesManager,
openDocWithId,
openFileWithId,
setView,
])
@@ -4,7 +4,6 @@ import { MainLayout } from '@/features/ide-react/components/layout/main-layout'
import EditorLeftMenu from '@/features/editor-left-menu/components/editor-left-menu'
import { useLayoutEventTracking } from '@/features/ide-react/hooks/use-layout-event-tracking'
import useSocketListeners from '@/features/ide-react/hooks/use-socket-listeners'
import { useOpenFile } from '@/features/ide-react/hooks/use-open-file'
import { useEditingSessionHeartbeat } from '@/features/ide-react/hooks/use-editing-session-heartbeat'
import { useRegisterUserActivity } from '@/features/ide-react/hooks/use-register-user-activity'
import { useHasLintingError } from '@/features/ide-react/hooks/use-has-linting-error'
@@ -26,7 +25,6 @@ export default function IdePage() {
useEditingSessionHeartbeat() // send a batched event when user is active
useRegisterUserActivity() // record activity and ensure connection when user is active
useHasLintingError() // pass editor:lint hasLintingError to the compiler
useOpenFile() // create ide.binaryFilesManager (TODO: move to the history file restore component)
const newEditor = useFeatureFlag('editor-redesign')
@@ -21,7 +21,10 @@ import { useLayoutContext } from '@/shared/context/layout-context'
import { GotoLineOptions } from '@/features/ide-react/types/goto-line-options'
import { Doc } from '../../../../../types/doc'
import { useFileTreeData } from '@/shared/context/file-tree-data-context'
import { findDocEntityById } from '@/features/ide-react/util/find-doc-entity-by-id'
import {
findDocEntityById,
findFileRefEntityById,
} from '@/features/ide-react/util/find-doc-entity-by-id'
import useScopeEventEmitter from '@/shared/hooks/use-scope-event-emitter'
import { useModalsContext } from '@/features/ide-react/context/modals-context'
import { useTranslation } from 'react-i18next'
@@ -32,6 +35,9 @@ import { DocId } from '../../../../../types/project-settings'
import { Update } from '@/features/history/services/types/update'
import { useDebugDiffTracker } from '../hooks/use-debug-diff-tracker'
import { useEditorContext } from '@/shared/context/editor-context'
import useScopeValueSetterOnly from '@/shared/hooks/use-scope-value-setter-only'
import { BinaryFile } from '@/features/file-view/types/binary-file'
import { convertFileRefToBinaryFile } from '@/features/ide-react/util/file-view'
export interface GotoOffsetOptions {
gotoOffset: number
@@ -57,6 +63,7 @@ export type EditorManager = {
openDocWithId: (docId: string, options?: OpenDocOptions) => void
openDoc: (document: Doc, options?: OpenDocOptions) => void
openDocs: OpenDocuments
openFileWithId: (fileId: string) => void
openInitialDoc: (docId: string) => void
jumpToLine: (options: GotoLineOptions) => void
wantTrackChanges: boolean
@@ -94,7 +101,7 @@ export const EditorManagerContext = createContext<EditorManager | undefined>(
export const EditorManagerProvider: FC = ({ children }) => {
const { t } = useTranslation()
const ide = useIdeContext()
const { scopeStore } = useIdeContext()
const { projectId } = useIdeReactContext()
const { reportError, eventEmitter } = useIdeReactContext()
const { setOutOfSync } = useEditorContext()
@@ -203,14 +210,14 @@ export const EditorManagerProvider: FC = ({ children }) => {
// implementation in EditorManager interacts with Angular scope to update
// the layout. Once Angular is gone, this can become a context method.
useEffect(() => {
ide.scopeStore.set('editor.toggleSymbolPalette', () => {
scopeStore.set('editor.toggleSymbolPalette', () => {
setShowSymbolPalette(show => {
const newValue = !show
sendMB(newValue ? 'symbol-palette-show' : 'symbol-palette-hide')
return newValue
})
})
}, [ide.scopeStore, setShowSymbolPalette])
}, [scopeStore, setShowSymbolPalette])
const getEditorType = useCallback((): EditorType | null => {
if (!currentDocument) {
@@ -443,6 +450,11 @@ export const EditorManagerProvider: FC = ({ children }) => {
detail: { isNewDoc, docId: doc._id },
})
)
window.dispatchEvent(
new CustomEvent('entity:opened', {
detail: doc._id,
})
)
if (hasGotoLine(options)) {
window.setTimeout(() => jumpToLine(options))
@@ -527,6 +539,24 @@ export const EditorManagerProvider: FC = ({ children }) => {
[fileTreeData, openDoc]
)
const [, setOpenFile] = useScopeValueSetterOnly<BinaryFile | null>('openFile')
const openFileWithId = useCallback(
(fileRefId: string) => {
const fileRef = findFileRefEntityById(fileTreeData, fileRefId)
if (!fileRef) {
return
}
setOpenFile(convertFileRefToBinaryFile(fileRef))
window.dispatchEvent(
new CustomEvent('entity:opened', {
detail: fileRef._id,
})
)
},
[fileTreeData, setOpenFile]
)
const openInitialDoc = useCallback(
(fallbackDocId: string) => {
const docId =
@@ -655,7 +685,7 @@ export const EditorManagerProvider: FC = ({ children }) => {
}
}, [currentDocument, syncTrackChangesState, wantTrackChanges])
const editorManager = useMemo(
const value = useMemo(
() => ({
getEditorType,
showSymbolPalette,
@@ -668,6 +698,7 @@ export const EditorManagerProvider: FC = ({ children }) => {
openDocWithId,
openDoc,
openDocs,
openFileWithId,
openInitialDoc,
jumpToLine,
wantTrackChanges,
@@ -686,6 +717,7 @@ export const EditorManagerProvider: FC = ({ children }) => {
openDocWithId,
openDoc,
openDocs,
openFileWithId,
openInitialDoc,
jumpToLine,
wantTrackChanges,
@@ -694,12 +726,8 @@ export const EditorManagerProvider: FC = ({ children }) => {
]
)
// Expose editorManager via ide object because some React code relies on it,
// for now
ide.editorManager = editorManager
return (
<EditorManagerContext.Provider value={editorManager}>
<EditorManagerContext.Provider value={value}>
{children}
</EditorManagerContext.Provider>
)
@@ -11,8 +11,7 @@ import {
import { useProjectContext } from '@/shared/context/project-context'
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
import { useSelectFileTreeEntity } from '@/features/ide-react/hooks/use-select-file-tree-entity'
import useScopeValue from '@/shared/hooks/use-scope-value'
import useScopeValueSetterOnly from '@/shared/hooks/use-scope-value-setter-only'
import { BinaryFile } from '@/features/file-view/types/binary-file'
import {
FileTreeDocumentFindResult,
@@ -23,7 +22,6 @@ import { debugConsole } from '@/utils/debugging'
import { convertFileRefToBinaryFile } from '@/features/ide-react/util/file-view'
import { sendMB } from '@/infrastructure/event-tracking'
import { FileRef } from '../../../../../types/file-ref'
import useEventListener from '@/shared/hooks/use-event-listener'
const FileTreeOpenContext = createContext<
| {
@@ -41,8 +39,7 @@ export const FileTreeOpenProvider: FC = ({ children }) => {
const { eventEmitter, projectJoined } = useIdeReactContext()
const { openDocWithId, currentDocumentId, openInitialDoc } =
useEditorManagerContext()
const { selectEntity } = useSelectFileTreeEntity()
const [, setOpenFile] = useScopeValue<BinaryFile | null>('openFile')
const [, setOpenFile] = useScopeValueSetterOnly<BinaryFile | null>('openFile')
const [openEntity, setOpenEntity] = useState<
FileTreeDocumentFindResult | FileTreeFileRefFindResult | null
>(null)
@@ -111,20 +108,6 @@ export const FileTreeOpenProvider: FC = ({ children }) => {
[eventEmitter, currentDocumentId, openDocWithId, rootDocId]
)
// Synchronize the file tree when openDoc or openDocWithId is called on the editor
// manager context from elsewhere. If the file tree does change, it will
// trigger the onSelect handler in this component, which will update the local
// state.
useEventListener(
'doc:after-opened',
useCallback(
(event: CustomEvent<{ docId: string }>) => {
selectEntity(event.detail.docId)
},
[selectEntity]
)
)
// Open a document once the file tree and project are ready
const initialOpenDoneRef = useRef(false)
useEffect(() => {
@@ -1,24 +0,0 @@
import { useIdeContext } from '@/shared/context/ide-context'
import { useFileTreeData } from '@/shared/context/file-tree-data-context'
import { useCallback } from 'react'
import { findInTree } from '@/features/file-tree/util/find-in-tree'
export function useOpenFile() {
const ide = useIdeContext()
const { fileTreeData } = useFileTreeData()
const openFileWithId = useCallback(
(id: string) => {
const result = findInTree(fileTreeData, id)
if (result?.type === 'fileRef') {
window.dispatchEvent(new CustomEvent('editor.openDoc', { detail: id }))
}
},
[fileTreeData]
)
// Expose BinaryFilesManager via ide object solely for the benefit of the file
// restore feature in history. This can be removed once Angular is gone.
ide.binaryFilesManager = { openFileWithId }
}
@@ -1,25 +0,0 @@
import { useFileTreeData } from '@/shared/context/file-tree-data-context'
import { useCallback } from 'react'
import { findInTree } from '@/features/file-tree/util/find-in-tree'
export function useSelectFileTreeEntity() {
const { fileTreeData, selectedEntities } = useFileTreeData()
const selectEntity = useCallback(
id => {
if (
selectedEntities.length === 1 &&
selectedEntities[0].entity._id === id
) {
return
}
const entityToSelect = findInTree(fileTreeData, id)
if (entityToSelect) {
window.dispatchEvent(new CustomEvent('editor.openDoc', { detail: id }))
}
},
[fileTreeData, selectedEntities]
)
return { selectEntity }
}
@@ -1,6 +1,7 @@
import { findInTree } from '@/features/file-tree/util/find-in-tree'
import { Folder } from '../../../../../types/folder'
import { Doc } from '../../../../../types/doc'
import { FileRef } from '../../../../../types/file-ref'
export function findDocEntityById(fileTreeData: Folder, docId: string) {
const item = findInTree(fileTreeData, docId)
@@ -9,3 +10,11 @@ export function findDocEntityById(fileTreeData: Folder, docId: string) {
}
return item.entity as Doc
}
export function findFileRefEntityById(fileTreeData: Folder, docId: string) {
const item = findInTree(fileTreeData, docId)
if (!item || item.type !== 'fileRef') {
return null
}
return item.entity as FileRef
}
@@ -1,7 +1,6 @@
import classNames from 'classnames'
import { memo, useCallback, useEffect, useState, useRef } from 'react'
import PropTypes from 'prop-types'
import { useIdeContext } from '../../../shared/context/ide-context'
import { useProjectContext } from '../../../shared/context/project-context'
import { getJSON } from '../../../infrastructure/fetch-json'
import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context'
@@ -25,6 +24,7 @@ import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/boots
import MaterialIcon from '@/shared/components/material-icon'
import { Spinner } from 'react-bootstrap-5'
import { bsVersion } from '@/features/utils/bootstrap-5'
import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
function GoToCodeButton({
position,
@@ -170,8 +170,6 @@ function GoToPdfButton({
}
function PdfSynctexControls() {
const ide = useIdeContext()
const { _id: projectId, rootDocId } = useProjectContext()
const { detachRole } = useLayoutContext()
@@ -187,10 +185,11 @@ function PdfSynctexControls() {
const { selectedEntities } = useFileTreeData()
const { findEntityByPath, dirname, pathInFolder } = useFileTreePathContext()
const { getCurrentDocumentId, openDocWithId } = useEditorManagerContext()
const [cursorPosition, setCursorPosition] = useState(() => {
const position = localStorage.getItem(
`doc.position.${ide.editorManager.getCurrentDocumentId()}`
`doc.position.${getCurrentDocumentId()}`
)
return position ? position.cursorPosition : null
})
@@ -203,7 +202,7 @@ function PdfSynctexControls() {
const listener = event => setCursorPosition(event.detail)
window.addEventListener('cursor:editor:update', listener)
return () => window.removeEventListener('cursor:editor:update', listener)
}, [ide])
}, [])
const [syncToPdfInFlight, setSyncToPdfInFlight] = useState(false)
const [syncToCodeInFlight, setSyncToCodeInFlight] = useDetachState(
@@ -216,7 +215,7 @@ function PdfSynctexControls() {
const [, setSynctexError] = useScopeValue('sync_tex_error')
const getCurrentFilePath = useCallback(() => {
const docId = ide.editorManager.getCurrentDocumentId()
const docId = getCurrentDocumentId()
let path = pathInFolder(docId)
// If the root file is folder/main.tex, then synctex sees the path as folder/./main.tex
@@ -227,7 +226,7 @@ function PdfSynctexControls() {
}
return path
}, [dirname, ide.editorManager, pathInFolder, rootDocId])
}, [dirname, getCurrentDocumentId, pathInFolder, rootDocId])
const goToCodeLine = useCallback(
(file, line) => {
@@ -238,7 +237,7 @@ function PdfSynctexControls() {
return
}
ide.editorManager.openDocWithId(doc._id, {
openDocWithId(doc._id, {
gotoLine: line,
})
} else {
@@ -251,7 +250,7 @@ function PdfSynctexControls() {
}, 4000)
}
},
[findEntityByPath, ide.editorManager, isMounted, setSynctexError]
[findEntityByPath, openDocWithId, isMounted, setSynctexError]
)
const goToPdfLocation = useCallback(
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types'
import { useTranslation } from 'react-i18next'
import { useIdeContext } from '../../../shared/context/ide-context'
import { useProjectContext } from '../../../shared/context/project-context'
import { useProjectContext } from '@/shared/context/project-context'
import { useLocalCompileContext } from '@/shared/context/local-compile-context'
import { useWordCount } from '../hooks/use-word-count'
import {
OLModalBody,
@@ -20,7 +20,7 @@ import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/boots
// NOTE: this component is only mounted when the modal is open
export default function WordCountModalContent({ handleHide }) {
const { _id: projectId } = useProjectContext()
const { clsiServerId } = useIdeContext()
const { clsiServerId } = useLocalCompileContext()
const { t } = useTranslation()
const { data, error, loading } = useWordCount(projectId, clsiServerId)
@@ -60,7 +60,7 @@ export const EditorContext = createContext<
>(undefined)
export const EditorProvider: FC = ({ children }) => {
const ide = useIdeContext()
const { socket } = useIdeContext()
const { id: userId, featureUsage } = useUserContext()
const { role } = useDetachContext()
const { showGenericMessageModal } = useModalsContext()
@@ -127,12 +127,11 @@ export const EditorProvider: FC = ({ children }) => {
)
useEffect(() => {
if (ide?.socket) {
ide.socket.on('projectNameUpdated', setProjectName)
return () =>
ide.socket.removeListener('projectNameUpdated', setProjectName)
if (socket) {
socket.on('projectNameUpdated', setProjectName)
return () => socket.removeListener('projectNameUpdated', setProjectName)
}
}, [ide?.socket, setProjectName])
}, [socket, setProjectName])
const renameProject = useCallback(
(newName: string) => {
@@ -1,10 +1,11 @@
import { createContext, FC, useContext, useEffect, useMemo } from 'react'
import { ScopeValueStore } from '../../../../types/ide/scope-value-store'
import { ScopeEventEmitter } from '../../../../types/ide/scope-event-emitter'
import { Socket } from '@/features/ide-react/connection/types/socket'
export type Ide = {
[key: string]: any // TODO: define the rest of the `ide` and `$scope` properties
$scope: Record<string, any>
socket: Socket
}
type IdeContextValue = Ide & {
@@ -28,7 +28,6 @@ import {
handleLogFiles,
handleOutputFiles,
} from '../../features/pdf-preview/util/output-files'
import { useIdeContext } from './ide-context'
import { useProjectContext } from './project-context'
import { useEditorContext } from './editor-context'
import { buildFileList } from '../../features/pdf-preview/util/file-list'
@@ -112,8 +111,6 @@ export const LocalCompileContext = createContext<CompileContext | undefined>(
)
export const LocalCompileProvider: FC = ({ children }) => {
const ide = useIdeContext()
const { hasPremiumCompile, isProjectOwner } = useEditorContext()
const { openDocWithId, openDocs } = useEditorManagerContext()
@@ -530,7 +527,6 @@ export const LocalCompileProvider: FC = ({ children }) => {
}
}, [
data,
ide,
alphaProgram,
labsProgram,
features,
@@ -53,9 +53,5 @@ export const getMockIde = () => {
settings: { syntaxValidation: false, pdfViewer: 'pdfjs' },
hasLintingError: false,
},
editorManager: {
openDoc: () => {},
getCurrentDocumentId: () => {},
},
}
}
@@ -101,12 +101,6 @@ const initialize = () => {
socket: new SocketIOShim.SocketShimNoop(
new SocketIOMock()
) as unknown as Socket,
editorManager: {
getCurrentDocumentId: () => 'foo',
openDoc: (id: string, options: unknown) => {
console.log('open doc', id, options)
},
},
}
// window.metaAttributesCache is reset in preview.tsx
@@ -175,50 +175,6 @@ describe('<FileTreeRoot/>', function () {
])
})
it('listen to editor.openDoc', function () {
const rootFolder = [
{
_id: 'root-folder-id',
name: 'rootFolder',
docs: [
{ _id: '456def', name: 'main.tex' },
{ _id: '789ghi', name: 'other.tex' },
],
folders: [],
fileRefs: [],
},
]
cy.mount(
<EditorProviders
rootFolder={rootFolder as any}
projectId="123abc"
rootDocId="456def"
features={{} as any}
permissionsLevel="readOnly"
>
<FileTreeRoot
refProviders={{}}
setRefProviderEnabled={cy.stub()}
setStartedFreeTrial={cy.stub()}
onSelect={cy.stub()}
onInit={cy.stub()}
isConnected
/>
</EditorProviders>
)
cy.findByRole('treeitem', { name: 'main.tex', selected: true })
// entities not found should be ignored
cy.document().trigger('editor.openDoc', { detail: 'not-an-id' })
cy.findByRole('treeitem', { name: 'main.tex', selected: true })
cy.document().trigger('editor.openDoc', { detail: '789ghi' })
cy.findByRole('treeitem', { name: 'main.tex', selected: false })
cy.findByRole('treeitem', { name: 'other.tex', selected: true })
})
it('only shows a menu button when a single item is selected', function () {
const rootFolder = [
{
+2 -4
View File
@@ -1,6 +1,7 @@
import 'recurly__recurly-js'
import { ScopeValueStore } from './ide/scope-value-store'
import { MetaAttributesCache } from '@/utils/meta'
import { Socket } from '@/features/ide-react/connection/types/socket'
declare global {
// eslint-disable-next-line no-unused-vars
@@ -12,10 +13,7 @@ declare global {
logEntryAnnotations: Record<string, unknown>
}
}
socket: {
on: (event: string, listener: any) => void
removeListener: (event: string, listener: any) => void
}
socket: Socket
}
MathJax: Record<string, any>
crypto: {