mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
Merge pull request #32884 from overleaf/em-editor-switch-by-filetype
[web] Split editor mode preference by file type GitOrigin-RevId: 2574623c9c1c88cc66de72c19cffb4428a632e96
This commit is contained in:
@@ -6,18 +6,21 @@ import {
|
||||
SetStateAction,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react'
|
||||
import customLocalStorage from '@/infrastructure/local-storage'
|
||||
import usePersistedState from '@/shared/hooks/use-persisted-state'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { useUnstableStoreSync } from '@/shared/hooks/use-unstable-store-sync'
|
||||
import { sendMB } from '@/infrastructure/event-tracking'
|
||||
import { useEditorOpenDocContext } from '@/features/ide-react/context/editor-open-doc-context'
|
||||
import { getVisualEditorStorageKey } from '@/features/source-editor/utils/visual-editor'
|
||||
|
||||
// Context value type
|
||||
export type EditorPropertiesContextValue = {
|
||||
showVisual: boolean
|
||||
setShowVisual: Dispatch<SetStateAction<boolean>>
|
||||
showVisualForFile: (filename: string) => boolean
|
||||
showSymbolPalette: boolean
|
||||
setShowSymbolPalette: Dispatch<SetStateAction<boolean>>
|
||||
toggleSymbolPalette: () => void
|
||||
@@ -35,31 +38,58 @@ export const EditorPropertiesContext = createContext<
|
||||
EditorPropertiesContextValue | undefined
|
||||
>(undefined)
|
||||
|
||||
function showVisualFallbackValue() {
|
||||
function migrateTexVisualMode(): boolean {
|
||||
const projectId = getMeta('ol-project_id')
|
||||
const editorModeKey = `editor.mode.${projectId}`
|
||||
const editorModeVal = customLocalStorage.getItem(editorModeKey)
|
||||
|
||||
if (editorModeVal) {
|
||||
// clean up the old key
|
||||
customLocalStorage.removeItem(editorModeKey)
|
||||
return editorModeVal === 'rich-text'
|
||||
}
|
||||
|
||||
return editorModeVal === 'rich-text'
|
||||
return false
|
||||
}
|
||||
|
||||
export function showVisualForFile(filename: string): boolean {
|
||||
const key = getVisualEditorStorageKey(filename)
|
||||
const stored = customLocalStorage.getItem(key)
|
||||
if (stored !== null) {
|
||||
return stored === 'visual'
|
||||
}
|
||||
if (key === 'editor.lastUsedMode') {
|
||||
return migrateTexVisualMode()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export const EditorPropertiesProvider: FC<PropsWithChildren> = ({
|
||||
children,
|
||||
}) => {
|
||||
const [showVisual, setShowVisual] = usePersistedState(
|
||||
`editor.lastUsedMode`,
|
||||
showVisualFallbackValue(),
|
||||
{
|
||||
converter: {
|
||||
toPersisted: showVisual => (showVisual ? 'visual' : 'code'),
|
||||
fromPersisted: mode => mode === 'visual',
|
||||
},
|
||||
}
|
||||
const { openDocName } = useEditorOpenDocContext()
|
||||
|
||||
const [showVisual, setShowVisualState] = useState(() =>
|
||||
openDocName != null ? showVisualForFile(openDocName) : false
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
setShowVisualState(
|
||||
openDocName != null ? showVisualForFile(openDocName) : false
|
||||
)
|
||||
}, [openDocName])
|
||||
|
||||
const setShowVisual: Dispatch<SetStateAction<boolean>> = useCallback(
|
||||
value => {
|
||||
setShowVisualState(prev => {
|
||||
const actual = typeof value === 'function' ? value(prev) : value
|
||||
if (openDocName != null) {
|
||||
const key = getVisualEditorStorageKey(openDocName)
|
||||
customLocalStorage.setItem(key, actual ? 'visual' : 'code')
|
||||
}
|
||||
return actual
|
||||
})
|
||||
},
|
||||
[openDocName]
|
||||
)
|
||||
|
||||
// Sync the showVisual state with the exposed store
|
||||
@@ -83,6 +113,7 @@ export const EditorPropertiesProvider: FC<PropsWithChildren> = ({
|
||||
const value = {
|
||||
showVisual,
|
||||
setShowVisual,
|
||||
showVisualForFile,
|
||||
showSymbolPalette,
|
||||
setShowSymbolPalette,
|
||||
toggleSymbolPalette,
|
||||
|
||||
@@ -49,7 +49,7 @@ export const FileTreeOpenProvider: FC<React.PropsWithChildren> = ({
|
||||
const { eventEmitter, projectJoined } = useIdeReactContext()
|
||||
const { openDocWithId, openInitialDoc } = useEditorManagerContext()
|
||||
const { currentDocumentId } = useEditorOpenDocContext()
|
||||
const { showVisual } = useEditorPropertiesContext()
|
||||
const { showVisualForFile } = useEditorPropertiesContext()
|
||||
const { setOpenFile } = useLayoutContext()
|
||||
const [openEntity, setOpenEntity] = useState<
|
||||
FileTreeDocumentFindResult | FileTreeFileRefFindResult | null
|
||||
@@ -93,7 +93,8 @@ export const FileTreeOpenProvider: FC<React.PropsWithChildren> = ({
|
||||
|
||||
setOpenEntity(selected)
|
||||
const editorMode =
|
||||
isVisualEditorAvailable(selected.entity.name) && showVisual
|
||||
isVisualEditorAvailable(selected.entity.name) &&
|
||||
showVisualForFile(selected.entity.name)
|
||||
? 'visual'
|
||||
: 'code'
|
||||
|
||||
@@ -127,7 +128,7 @@ export const FileTreeOpenProvider: FC<React.PropsWithChildren> = ({
|
||||
window.dispatchEvent(new CustomEvent('file-view:file-opened'))
|
||||
}
|
||||
},
|
||||
[fileTreeReady, openDocWithId, projectOwner, setOpenFile, showVisual]
|
||||
[fileTreeReady, openDocWithId, projectOwner, setOpenFile, showVisualForFile]
|
||||
)
|
||||
|
||||
const handleFileTreeDelete = useCallback(
|
||||
|
||||
@@ -103,9 +103,9 @@ export const ReactContextRoot: FC<
|
||||
<Providers.UserProvider>
|
||||
<Providers.SnapshotProvider>
|
||||
<Providers.DetachProvider>
|
||||
<Providers.EditorPropertiesProvider>
|
||||
<Providers.EditorOpenDocProvider>
|
||||
<Providers.EditorViewProvider>
|
||||
<Providers.EditorOpenDocProvider>
|
||||
<Providers.EditorPropertiesProvider>
|
||||
<Providers.EditorProvider>
|
||||
<Providers.TutorialProvider>
|
||||
<Providers.FileTreeDataProvider>
|
||||
@@ -151,9 +151,9 @@ export const ReactContextRoot: FC<
|
||||
</Providers.FileTreeDataProvider>
|
||||
</Providers.TutorialProvider>
|
||||
</Providers.EditorProvider>
|
||||
</Providers.EditorOpenDocProvider>
|
||||
</Providers.EditorPropertiesProvider>
|
||||
</Providers.EditorViewProvider>
|
||||
</Providers.EditorPropertiesProvider>
|
||||
</Providers.EditorOpenDocProvider>
|
||||
</Providers.DetachProvider>
|
||||
</Providers.SnapshotProvider>
|
||||
</Providers.UserProvider>
|
||||
|
||||
@@ -27,3 +27,13 @@ export function getVisualEditorComponent(filename: string) {
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export function getVisualEditorStorageKey(filename: string): string {
|
||||
for (const provider of visualEditorProviders) {
|
||||
if (provider.import.isVisualEditorAvailable(filename)) {
|
||||
const id = provider.import.id
|
||||
return id != null ? `editor.lastUsedMode.${id}` : 'editor.lastUsedMode'
|
||||
}
|
||||
}
|
||||
return 'editor.lastUsedMode'
|
||||
}
|
||||
|
||||
@@ -92,6 +92,7 @@ const VisualEditorPropertiesProvider: FC<React.PropsWithChildren> = ({
|
||||
const value = {
|
||||
showVisual,
|
||||
setShowVisual,
|
||||
showVisualForFile: () => showVisual,
|
||||
showSymbolPalette: true,
|
||||
setShowSymbolPalette: () => undefined,
|
||||
toggleSymbolPalette: () => undefined,
|
||||
|
||||
@@ -636,6 +636,7 @@ export function makeEditorPropertiesProvider(
|
||||
const value = {
|
||||
showVisual,
|
||||
setShowVisual,
|
||||
showVisualForFile: () => showVisual,
|
||||
showSymbolPalette,
|
||||
setShowSymbolPalette,
|
||||
toggleSymbolPalette,
|
||||
|
||||
Reference in New Issue
Block a user