mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-31 12:51:35 +02:00
[web] Move UI scope to React states (#26403)
* Move `ui.view` to setState
* Move `openFile` to setState
* Move `ui.leftMenuShown` to setState
* Move `ui.miniReviewPanelVisible` to setState
* Move `ui.pdfLayout` to setState
* Move `ui.chatOpen` to setState
* Move `ui.reviewPanelOpen` to setState
* Cleanup: remove layout-context-adapter and imports
* Replace `ui` scope by mocked `LayoutProvider` in tests
* Update test
* Remove unnecessary `scopeStore.set('ui.chatOpen' ...`
GitOrigin-RevId: 81578bfdc958239eac492905f714a6074c81d0f5
This commit is contained in:
@@ -36,8 +36,6 @@ 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 {
|
||||
@@ -97,7 +95,7 @@ export const EditorManagerProvider: FC<React.PropsWithChildren> = ({
|
||||
const { reportError, eventEmitter, projectId } = useIdeReactContext()
|
||||
const { setOutOfSync } = useEditorContext()
|
||||
const { socket, closeConnection, connectionState } = useConnectionContext()
|
||||
const { view, setView } = useLayoutContext()
|
||||
const { view, setView, setOpenFile } = useLayoutContext()
|
||||
const { showGenericMessageModal, genericModalVisible, showOutOfSyncModal } =
|
||||
useModalsContext()
|
||||
const { id: userId } = useUserContext()
|
||||
@@ -521,8 +519,6 @@ export const EditorManagerProvider: FC<React.PropsWithChildren> = ({
|
||||
[fileTreeData, openDoc]
|
||||
)
|
||||
|
||||
const [, setOpenFile] = useScopeValueSetterOnly<BinaryFile | null>('openFile')
|
||||
|
||||
const openFileWithId = useCallback(
|
||||
(fileRefId: string) => {
|
||||
const fileRef = findFileRefEntityById(fileTreeData, fileRefId)
|
||||
|
||||
@@ -11,8 +11,6 @@ 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 useScopeValueSetterOnly from '@/shared/hooks/use-scope-value-setter-only'
|
||||
import { BinaryFile } from '@/features/file-view/types/binary-file'
|
||||
import {
|
||||
FileTreeDocumentFindResult,
|
||||
FileTreeFileRefFindResult,
|
||||
@@ -22,6 +20,7 @@ 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 { useLayoutContext } from '@/shared/context/layout-context'
|
||||
|
||||
const FileTreeOpenContext = createContext<
|
||||
| {
|
||||
@@ -43,7 +42,7 @@ export const FileTreeOpenProvider: FC<React.PropsWithChildren> = ({
|
||||
const { eventEmitter, projectJoined } = useIdeReactContext()
|
||||
const { openDocWithId, currentDocumentId, openInitialDoc } =
|
||||
useEditorManagerContext()
|
||||
const [, setOpenFile] = useScopeValueSetterOnly<BinaryFile | null>('openFile')
|
||||
const { setOpenFile } = useLayoutContext()
|
||||
const [openEntity, setOpenEntity] = useState<
|
||||
FileTreeDocumentFindResult | FileTreeFileRefFindResult | null
|
||||
>(null)
|
||||
|
||||
@@ -8,7 +8,6 @@ import React, {
|
||||
useCallback,
|
||||
} from 'react'
|
||||
import { ReactScopeValueStore } from '@/features/ide-react/scope-value-store/react-scope-value-store'
|
||||
import populateLayoutScope from '@/features/ide-react/scope-adapters/layout-context-adapter'
|
||||
import { IdeProvider } from '@/shared/context/ide-context'
|
||||
import {
|
||||
createIdeEventEmitter,
|
||||
@@ -67,7 +66,6 @@ export function createReactScopeValueStore(projectId: string) {
|
||||
// necessary values in the store, but this is simpler for now
|
||||
populateIdeReactScope(scopeStore)
|
||||
populateEditorScope(scopeStore, projectId)
|
||||
populateLayoutScope(scopeStore)
|
||||
populateProjectScope(scopeStore)
|
||||
populatePdfScope(scopeStore)
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import { ReactScopeValueStore } from '../scope-value-store/react-scope-value-store'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
const reviewPanelStorageKey = `ui.reviewPanelOpen.${getMeta('ol-project_id')}`
|
||||
|
||||
export default function populateLayoutScope(store: ReactScopeValueStore) {
|
||||
store.set('ui.view', 'editor')
|
||||
store.set('openFile', null)
|
||||
store.persisted('ui.chatOpen', false, 'ui.chatOpen')
|
||||
store.persisted('ui.reviewPanelOpen', false, reviewPanelStorageKey)
|
||||
store.set('ui.leftMenuShown', false)
|
||||
store.set('ui.miniReviewPanelVisible', false)
|
||||
store.set('ui.pdfLayout', 'sideBySide')
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
FC,
|
||||
useState,
|
||||
} from 'react'
|
||||
import useScopeValue from '../hooks/use-scope-value'
|
||||
import useDetachLayout from '../hooks/use-detach-layout'
|
||||
import localStorage from '../../infrastructure/local-storage'
|
||||
import getMeta from '../../utils/meta'
|
||||
@@ -21,6 +20,7 @@ import useEventListener from '@/shared/hooks/use-event-listener'
|
||||
import { isMac } from '@/shared/utils/os'
|
||||
import { sendSearchEvent } from '@/features/event-tracking/search-events'
|
||||
import { useRailContext } from '@/features/ide-redesign/contexts/rail-context'
|
||||
import usePersistedState from '@/shared/hooks/use-persisted-state'
|
||||
|
||||
export type IdeLayout = 'sideBySide' | 'flat'
|
||||
export type IdeView = 'editor' | 'file' | 'pdf' | 'history'
|
||||
@@ -55,6 +55,8 @@ export type LayoutContextValue = {
|
||||
pdfPreviewOpen: boolean
|
||||
projectSearchIsOpen: boolean
|
||||
setProjectSearchIsOpen: Dispatch<SetStateAction<boolean>>
|
||||
openFile: BinaryFile | null
|
||||
setOpenFile: Dispatch<SetStateAction<BinaryFile | null>>
|
||||
}
|
||||
|
||||
const debugPdfDetach = getMeta('ol-debugPdfDetach')
|
||||
@@ -70,10 +72,12 @@ function setLayoutInLocalStorage(pdfLayout: IdeLayout) {
|
||||
)
|
||||
}
|
||||
|
||||
const reviewPanelStorageKey = `ui.reviewPanelOpen.${getMeta('ol-project_id')}`
|
||||
|
||||
export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
|
||||
// what to show in the "flat" view (editor or pdf)
|
||||
const [view, _setView] = useScopeValue<IdeView | null>('ui.view')
|
||||
const [openFile] = useScopeValue<BinaryFile | null>('openFile')
|
||||
const [view, _setView] = useState<IdeView | null>('editor')
|
||||
const [openFile, setOpenFile] = useState<BinaryFile | null>(null)
|
||||
const historyToggleEmitter = useScopeEventEmitter('history:toggle', true)
|
||||
const { isOpen: railIsOpen, setIsOpen: setRailIsOpen } = useRailContext()
|
||||
const [prevRailIsOpen, setPrevRailIsOpen] = useState(railIsOpen)
|
||||
@@ -118,19 +122,23 @@ export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
|
||||
)
|
||||
|
||||
// whether the chat pane is open
|
||||
const [chatIsOpen, setChatIsOpen] = useScopeValue<boolean>('ui.chatOpen')
|
||||
const [chatIsOpen, setChatIsOpen] = usePersistedState<boolean>(
|
||||
'ui.chatOpen',
|
||||
false
|
||||
)
|
||||
|
||||
// whether the review pane is open
|
||||
const [reviewPanelOpen, setReviewPanelOpen] =
|
||||
useScopeValue<boolean>('ui.reviewPanelOpen')
|
||||
const [reviewPanelOpen, setReviewPanelOpen] = usePersistedState<boolean>(
|
||||
reviewPanelStorageKey,
|
||||
false
|
||||
)
|
||||
|
||||
// whether the review pane is collapsed
|
||||
const [miniReviewPanelVisible, setMiniReviewPanelVisible] =
|
||||
useScopeValue<boolean>('ui.miniReviewPanelVisible')
|
||||
useState<boolean>(false)
|
||||
|
||||
// whether the menu pane is open
|
||||
const [leftMenuShown, setLeftMenuShown] =
|
||||
useScopeValue<boolean>('ui.leftMenuShown')
|
||||
const [leftMenuShown, setLeftMenuShown] = useState<boolean>(false)
|
||||
|
||||
// whether the project search is open
|
||||
const [projectSearchIsOpen, setProjectSearchIsOpen] = useState(false)
|
||||
@@ -173,7 +181,7 @@ export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
|
||||
)
|
||||
|
||||
// whether to display the editor and preview side-by-side or full-width ("flat")
|
||||
const [pdfLayout, setPdfLayout] = useScopeValue<IdeLayout>('ui.pdfLayout')
|
||||
const [pdfLayout, setPdfLayout] = useState<IdeLayout>('sideBySide')
|
||||
|
||||
// whether stylesheet on theme is loading
|
||||
const [loadingStyleSheet, setLoadingStyleSheet] = useState(false)
|
||||
@@ -238,6 +246,7 @@ export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
|
||||
changeLayout,
|
||||
chatIsOpen,
|
||||
leftMenuShown,
|
||||
openFile,
|
||||
pdfLayout,
|
||||
pdfPreviewOpen,
|
||||
projectSearchIsOpen,
|
||||
@@ -247,6 +256,7 @@ export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
|
||||
loadingStyleSheet,
|
||||
setChatIsOpen,
|
||||
setLeftMenuShown,
|
||||
setOpenFile,
|
||||
setPdfLayout,
|
||||
setReviewPanelOpen,
|
||||
setMiniReviewPanelVisible,
|
||||
@@ -262,6 +272,7 @@ export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
|
||||
changeLayout,
|
||||
chatIsOpen,
|
||||
leftMenuShown,
|
||||
openFile,
|
||||
pdfLayout,
|
||||
pdfPreviewOpen,
|
||||
projectSearchIsOpen,
|
||||
@@ -271,6 +282,7 @@ export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
|
||||
loadingStyleSheet,
|
||||
setChatIsOpen,
|
||||
setLeftMenuShown,
|
||||
setOpenFile,
|
||||
setPdfLayout,
|
||||
setReviewPanelOpen,
|
||||
setMiniReviewPanelVisible,
|
||||
|
||||
@@ -59,10 +59,6 @@ const project: Project = {
|
||||
const initialScope = {
|
||||
user,
|
||||
project,
|
||||
ui: {
|
||||
chatOpen: true,
|
||||
pdfLayout: 'flat',
|
||||
},
|
||||
settings: {
|
||||
pdfViewer: 'js',
|
||||
syntaxValidation: true,
|
||||
|
||||
@@ -56,14 +56,10 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('render full menu', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders scope={scope} layoutContext={{ leftMenuShown: true }}>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -110,14 +106,12 @@ describe('<EditorLeftMenu />', function () {
|
||||
|
||||
describe('download menu', function () {
|
||||
it('have a correct source & pdf download url', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
|
||||
const scope = mockScope()
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -142,14 +136,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
},
|
||||
})
|
||||
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -184,14 +177,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
},
|
||||
}).as('wordCount')
|
||||
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -217,9 +209,6 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
project: {
|
||||
members: [],
|
||||
owner: {
|
||||
@@ -234,7 +223,10 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -245,9 +237,6 @@ describe('<EditorLeftMenu />', function () {
|
||||
|
||||
it('shows git modal correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
project: {
|
||||
owner: {
|
||||
_id: '123',
|
||||
@@ -259,7 +248,10 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -271,9 +263,6 @@ describe('<EditorLeftMenu />', function () {
|
||||
|
||||
it('shows git modal paywall correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
project: {
|
||||
owner: {
|
||||
_id: '123',
|
||||
@@ -285,7 +274,10 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -304,14 +296,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
enabled: false,
|
||||
}).as('project-status')
|
||||
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -335,14 +326,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
|
||||
describe('settings menu', function () {
|
||||
it('shows compiler menu correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -369,14 +359,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('shows texlive version menu correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -410,14 +399,14 @@ describe('<EditorLeftMenu />', function () {
|
||||
folders: [],
|
||||
}
|
||||
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope} rootFolder={[rootFolder as any]}>
|
||||
<EditorProviders
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
scope={scope}
|
||||
rootFolder={[rootFolder as any]}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -451,14 +440,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
|
||||
window.metaAttributesCache.set('ol-languages', languages)
|
||||
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -475,14 +463,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('shows dictionary modal correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -493,14 +480,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('shows auto-complete menu correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -517,14 +503,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('shows auto-close brackets menu correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -541,14 +526,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('shows code check menu correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -579,14 +563,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
legacyEditorThemes
|
||||
)
|
||||
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -619,14 +602,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('shows overall theme menu correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -643,14 +625,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('shows keybindings menu correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -667,14 +648,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('shows font size menu correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -713,14 +693,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('shows font family menu correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -741,14 +720,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('shows line height menu correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -765,14 +743,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('shows pdf viewer menu correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -791,14 +768,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
|
||||
describe('help menu', function () {
|
||||
it('shows hotkeys modal correctly', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -808,14 +784,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('shows correct url for documentation', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -828,14 +803,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
})
|
||||
|
||||
it('shows correct contact us modal', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
layoutContext={{ leftMenuShown: true }}
|
||||
>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -848,16 +822,13 @@ describe('<EditorLeftMenu />', function () {
|
||||
|
||||
describe('for anonymous users', function () {
|
||||
it('render minimal menu', function () {
|
||||
const scope = mockScope({
|
||||
ui: {
|
||||
leftMenuShown: true,
|
||||
},
|
||||
})
|
||||
const scope = mockScope()
|
||||
|
||||
window.metaAttributesCache.set('ol-anonymous', true)
|
||||
Object.assign(getMeta('ol-ExposedSettings'), { ieeeBrandId: 123 })
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders scope={scope} layoutContext={{ leftMenuShown: true }}>
|
||||
<EditorLeftMenu />
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
@@ -47,10 +47,5 @@ export const mockScope = (scope?: Scope) => ({
|
||||
},
|
||||
},
|
||||
hasLintingError: false,
|
||||
ui: {
|
||||
view: 'editor',
|
||||
pdfLayout: 'sideBySide',
|
||||
leftMenuShown: false,
|
||||
},
|
||||
...scope,
|
||||
})
|
||||
|
||||
@@ -17,8 +17,4 @@ export const mockScope = () => ({
|
||||
}),
|
||||
},
|
||||
hasLintingError: false,
|
||||
ui: {
|
||||
view: 'editor',
|
||||
pdfLayout: 'sideBySide',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -9,9 +9,11 @@ import * as eventTracking from '@/infrastructure/event-tracking'
|
||||
describe('<LayoutDropdownButton />', function () {
|
||||
let openStub
|
||||
let sendMBSpy
|
||||
const defaultUi = {
|
||||
|
||||
const defaultLayout = {
|
||||
pdfLayout: 'flat',
|
||||
view: 'pdf',
|
||||
chatIsOpen: false,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
@@ -27,7 +29,9 @@ describe('<LayoutDropdownButton />', function () {
|
||||
|
||||
it('should mark current layout option as selected', async function () {
|
||||
// Selected is aria-label, visually we show a checkmark
|
||||
renderWithEditorContext(<LayoutDropdownButton />, { ui: defaultUi })
|
||||
renderWithEditorContext(<LayoutDropdownButton />, {
|
||||
layoutContext: defaultLayout,
|
||||
})
|
||||
|
||||
screen.getByRole('button', { name: 'Layout' }).click()
|
||||
|
||||
@@ -69,7 +73,7 @@ describe('<LayoutDropdownButton />', function () {
|
||||
it('should not select any option in history view', async function () {
|
||||
// Selected is aria-label, visually we show a checkmark
|
||||
renderWithEditorContext(<LayoutDropdownButton />, {
|
||||
ui: { ...defaultUi, view: 'history' },
|
||||
layoutContext: { ...defaultLayout, view: 'history' },
|
||||
})
|
||||
|
||||
screen.getByRole('button', { name: 'Layout' }).click()
|
||||
@@ -112,9 +116,10 @@ describe('<LayoutDropdownButton />', function () {
|
||||
it('should treat file and editor views the same way', async function () {
|
||||
// Selected is aria-label, visually we show a checkmark
|
||||
renderWithEditorContext(<LayoutDropdownButton />, {
|
||||
ui: {
|
||||
layoutContext: {
|
||||
pdfLayout: 'flat',
|
||||
view: 'file',
|
||||
chatIsOpen: false,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -161,7 +166,7 @@ describe('<LayoutDropdownButton />', function () {
|
||||
window.BroadcastChannel = originalBroadcastChannel || true // ensure that window.BroadcastChannel is truthy
|
||||
|
||||
renderWithEditorContext(<LayoutDropdownButton />, {
|
||||
ui: { ...defaultUi, view: 'editor' },
|
||||
layoutContext: { ...defaultLayout, view: 'editor' },
|
||||
})
|
||||
|
||||
screen.getByRole('button', { name: 'Layout' }).click()
|
||||
@@ -192,7 +197,7 @@ describe('<LayoutDropdownButton />', function () {
|
||||
beforeEach(async function () {
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detacher')
|
||||
renderWithEditorContext(<LayoutDropdownButton />, {
|
||||
ui: { ...defaultUi, view: 'editor' },
|
||||
layoutContext: { ...defaultLayout, view: 'editor' },
|
||||
})
|
||||
|
||||
screen.getByRole('button', { name: 'Layout' }).click()
|
||||
|
||||
@@ -93,6 +93,8 @@ const createInitialValue = () =>
|
||||
pdfPreviewOpen: false,
|
||||
projectSearchIsOpen: true,
|
||||
setProjectSearchIsOpen: cy.stub(),
|
||||
openFile: null,
|
||||
setOpenFile: cy.stub(),
|
||||
}) satisfies LayoutContextValue
|
||||
|
||||
const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
|
||||
|
||||
@@ -14,11 +14,10 @@ import { withTestContainerErrorBoundary } from '../../../helpers/error-boundary'
|
||||
|
||||
const TestContainerWithoutErrorBoundary: FC<{
|
||||
component: React.ReactNode
|
||||
scope: Record<string, unknown>
|
||||
props: Record<string, unknown>
|
||||
}> = ({ component, scope, props }) => {
|
||||
}> = ({ component, props }) => {
|
||||
return (
|
||||
<EditorProviders scope={scope} {...props}>
|
||||
<EditorProviders {...props}>
|
||||
<HistoryProvider>
|
||||
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<div className="history-react">{component}</div>
|
||||
@@ -34,17 +33,12 @@ const TestContainer = withTestContainerErrorBoundary(
|
||||
|
||||
const mountWithEditorProviders = (
|
||||
component: React.ReactNode,
|
||||
scope: Record<string, unknown> = {},
|
||||
props: Record<string, unknown> = {}
|
||||
) => {
|
||||
cy.mount(<TestContainer component={component} scope={scope} props={props} />)
|
||||
cy.mount(<TestContainer component={component} props={props} />)
|
||||
}
|
||||
|
||||
describe('change list (Bootstrap 5)', function () {
|
||||
const scope = {
|
||||
ui: { view: 'history', pdfLayout: 'sideBySide', chatOpen: true },
|
||||
}
|
||||
|
||||
const waitForData = () => {
|
||||
cy.wait('@updates')
|
||||
cy.wait('@labels')
|
||||
@@ -101,7 +95,8 @@ describe('change list (Bootstrap 5)', function () {
|
||||
|
||||
describe('tags', function () {
|
||||
it('renders tags', function () {
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
mountWithEditorProviders(<ChangeList />, {
|
||||
layoutContext: { view: 'history' },
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
@@ -173,13 +168,18 @@ describe('change list (Bootstrap 5)', function () {
|
||||
})
|
||||
|
||||
it('deletes tag', function () {
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
})
|
||||
mountWithEditorProviders(
|
||||
<ChangeList />,
|
||||
|
||||
{
|
||||
layoutContext: { view: 'history' },
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
}
|
||||
)
|
||||
waitForData()
|
||||
|
||||
cy.findByLabelText(/all history/i).click({ force: true })
|
||||
@@ -235,7 +235,8 @@ describe('change list (Bootstrap 5)', function () {
|
||||
})
|
||||
|
||||
it('verifies that selecting the same list item will not trigger a new diff', function () {
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
mountWithEditorProviders(<ChangeList />, {
|
||||
layoutContext: { view: 'history' },
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
@@ -257,13 +258,18 @@ describe('change list (Bootstrap 5)', function () {
|
||||
|
||||
describe('all history', function () {
|
||||
beforeEach(function () {
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
})
|
||||
mountWithEditorProviders(
|
||||
<ChangeList />,
|
||||
|
||||
{
|
||||
layoutContext: { view: 'history' },
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
}
|
||||
)
|
||||
waitForData()
|
||||
})
|
||||
|
||||
@@ -318,13 +324,18 @@ describe('change list (Bootstrap 5)', function () {
|
||||
|
||||
describe('labels only', function () {
|
||||
beforeEach(function () {
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
})
|
||||
mountWithEditorProviders(
|
||||
<ChangeList />,
|
||||
|
||||
{
|
||||
layoutContext: { view: 'history' },
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
}
|
||||
)
|
||||
waitForData()
|
||||
cy.findByLabelText(/labels/i).click({ force: true })
|
||||
})
|
||||
@@ -399,13 +410,18 @@ describe('change list (Bootstrap 5)', function () {
|
||||
|
||||
describe('compare mode', function () {
|
||||
beforeEach(function () {
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
})
|
||||
mountWithEditorProviders(
|
||||
<ChangeList />,
|
||||
|
||||
{
|
||||
layoutContext: { view: 'history' },
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
}
|
||||
)
|
||||
waitForData()
|
||||
})
|
||||
|
||||
@@ -435,13 +451,18 @@ describe('change list (Bootstrap 5)', function () {
|
||||
|
||||
describe('dropdown', function () {
|
||||
beforeEach(function () {
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
})
|
||||
mountWithEditorProviders(
|
||||
<ChangeList />,
|
||||
|
||||
{
|
||||
layoutContext: { view: 'history' },
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
}
|
||||
)
|
||||
waitForData()
|
||||
})
|
||||
|
||||
@@ -610,21 +631,18 @@ describe('change list (Bootstrap 5)', function () {
|
||||
})
|
||||
|
||||
it('shows non-owner paywall', function () {
|
||||
const scope = {
|
||||
ui: {
|
||||
view: 'history',
|
||||
pdfLayout: 'sideBySide',
|
||||
chatOpen: true,
|
||||
},
|
||||
}
|
||||
mountWithEditorProviders(
|
||||
<ChangeList />,
|
||||
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: false,
|
||||
},
|
||||
})
|
||||
{
|
||||
layoutContext: { view: 'history' },
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: false,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
waitForData()
|
||||
|
||||
@@ -634,15 +652,8 @@ describe('change list (Bootstrap 5)', function () {
|
||||
})
|
||||
|
||||
it('shows owner paywall', function () {
|
||||
const scope = {
|
||||
ui: {
|
||||
view: 'history',
|
||||
pdfLayout: 'sideBySide',
|
||||
chatOpen: true,
|
||||
},
|
||||
}
|
||||
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
mountWithEditorProviders(<ChangeList />, {
|
||||
layoutContext: { view: 'history' },
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
@@ -662,15 +673,8 @@ describe('change list (Bootstrap 5)', function () {
|
||||
})
|
||||
|
||||
it('shows all labels in free tier', function () {
|
||||
const scope = {
|
||||
ui: {
|
||||
view: 'history',
|
||||
pdfLayout: 'sideBySide',
|
||||
chatOpen: true,
|
||||
},
|
||||
}
|
||||
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
mountWithEditorProviders(<ChangeList />, {
|
||||
layoutContext: { view: 'history' },
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
|
||||
@@ -5,14 +5,15 @@ import { Diff } from '../../../../../frontend/js/features/history/services/types
|
||||
import { EditorProviders } from '../../../helpers/editor-providers'
|
||||
import { FC } from 'react'
|
||||
import { withTestContainerErrorBoundary } from '../../../helpers/error-boundary'
|
||||
import { LayoutContextValue } from '@/shared/context/layout-context'
|
||||
|
||||
const TestContainerWithoutErrorBoundary: FC<{
|
||||
scope: Record<string, unknown>
|
||||
layoutContext: LayoutContextValue
|
||||
diff: Diff
|
||||
selection: HistoryContextValue['selection']
|
||||
}> = ({ scope, diff, selection }) => {
|
||||
}> = ({ diff, selection, layoutContext }) => {
|
||||
return (
|
||||
<EditorProviders scope={scope}>
|
||||
<EditorProviders layoutContext={layoutContext}>
|
||||
<HistoryProvider>
|
||||
<div className="history-react">
|
||||
<Toolbar diff={diff} selection={selection} />
|
||||
@@ -27,10 +28,6 @@ const TestContainer = withTestContainerErrorBoundary(
|
||||
)
|
||||
|
||||
describe('history toolbar', function () {
|
||||
const editorProvidersScope = {
|
||||
ui: { view: 'history', pdfLayout: 'sideBySide', chatOpen: true },
|
||||
}
|
||||
|
||||
const diff: Diff = {
|
||||
binary: false,
|
||||
docDiff: {
|
||||
@@ -81,7 +78,7 @@ describe('history toolbar', function () {
|
||||
|
||||
cy.mount(
|
||||
<TestContainer
|
||||
scope={editorProvidersScope}
|
||||
layoutContext={{ view: 'history' }}
|
||||
diff={diff}
|
||||
selection={selection}
|
||||
/>
|
||||
@@ -129,7 +126,7 @@ describe('history toolbar', function () {
|
||||
|
||||
cy.mount(
|
||||
<TestContainer
|
||||
scope={editorProvidersScope}
|
||||
layoutContext={{ view: 'history' }}
|
||||
diff={diff}
|
||||
selection={selection}
|
||||
/>
|
||||
|
||||
@@ -4,7 +4,9 @@ import SwitchToEditorButton from '@/features/pdf-preview/components/switch-to-ed
|
||||
describe('<SwitchToEditorButton />', function () {
|
||||
it('shows button in full screen pdf layout', function () {
|
||||
cy.mount(
|
||||
<EditorProviders ui={{ view: 'pdf', pdfLayout: 'flat', chatOpen: false }}>
|
||||
<EditorProviders
|
||||
layoutContext={{ view: 'pdf', pdfLayout: 'flat', chatIsOpen: false }}
|
||||
>
|
||||
<SwitchToEditorButton />
|
||||
</EditorProviders>
|
||||
)
|
||||
@@ -15,7 +17,11 @@ describe('<SwitchToEditorButton />', function () {
|
||||
it('does not show button in split screen layout', function () {
|
||||
cy.mount(
|
||||
<EditorProviders
|
||||
ui={{ view: 'pdf', pdfLayout: 'sideBySide', chatOpen: false }}
|
||||
layoutContext={{
|
||||
view: 'pdf',
|
||||
pdfLayout: 'sideBySide',
|
||||
chatIsOpen: false,
|
||||
}}
|
||||
>
|
||||
<SwitchToEditorButton />
|
||||
</EditorProviders>
|
||||
@@ -28,7 +34,13 @@ describe('<SwitchToEditorButton />', function () {
|
||||
window.metaAttributesCache.set('ol-detachRole', 'detacher')
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders ui={{ view: 'pdf', pdfLayout: 'flat', chatOpen: false }}>
|
||||
<EditorProviders
|
||||
layoutContext={{
|
||||
view: 'pdf',
|
||||
pdfLayout: 'flat',
|
||||
chatIsOpen: false,
|
||||
}}
|
||||
>
|
||||
<SwitchToEditorButton />
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@ describe('<SwitchToPDFButton />', function () {
|
||||
it('shows button in full screen editor layout', function () {
|
||||
cy.mount(
|
||||
<EditorProviders
|
||||
ui={{ view: 'editor', pdfLayout: 'flat', chatOpen: false }}
|
||||
layoutContext={{ view: 'editor', pdfLayout: 'flat', chatIsOpen: false }}
|
||||
>
|
||||
<SwitchToPDFButton />
|
||||
</EditorProviders>
|
||||
@@ -17,7 +17,11 @@ describe('<SwitchToPDFButton />', function () {
|
||||
it('does not show button in split screen layout', function () {
|
||||
cy.mount(
|
||||
<EditorProviders
|
||||
ui={{ view: 'editor', pdfLayout: 'sideBySide', chatOpen: false }}
|
||||
layoutContext={{
|
||||
view: 'editor',
|
||||
pdfLayout: 'sideBySide',
|
||||
chatIsOpen: false,
|
||||
}}
|
||||
>
|
||||
<SwitchToPDFButton />
|
||||
</EditorProviders>
|
||||
@@ -31,7 +35,7 @@ describe('<SwitchToPDFButton />', function () {
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders
|
||||
ui={{ view: 'editor', pdfLayout: 'flat', chatOpen: false }}
|
||||
layoutContext={{ view: 'editor', pdfLayout: 'flat', chatIsOpen: false }}
|
||||
>
|
||||
<SwitchToPDFButton />
|
||||
</EditorProviders>
|
||||
|
||||
@@ -81,9 +81,6 @@ export const mockScope = (
|
||||
write: true,
|
||||
...permissions,
|
||||
},
|
||||
ui: {
|
||||
reviewPanelOpen: false,
|
||||
},
|
||||
toggleReviewPanel: cy.stub(),
|
||||
toggleTrackChangesForEveryone: cy.stub(),
|
||||
refreshResolvedCommentsDropdown: cy.stub(() => sleep(1000)),
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { merge } from 'lodash'
|
||||
import { SocketIOMock } from '@/ide/connection/SocketIoShim'
|
||||
import { IdeContext } from '@/shared/context/ide-context'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import {
|
||||
createReactScopeValueStore,
|
||||
IdeReactContext,
|
||||
@@ -12,6 +12,9 @@ import { IdeEventEmitter } from '@/features/ide-react/create-ide-event-emitter'
|
||||
import { ReactScopeEventEmitter } from '@/features/ide-react/scope-event-emitter/react-scope-event-emitter'
|
||||
import { ConnectionContext } from '@/features/ide-react/context/connection-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 { LayoutContext } from '@/shared/context/layout-context'
|
||||
|
||||
// these constants can be imported in tests instead of
|
||||
// using magic strings
|
||||
@@ -35,6 +38,22 @@ const defaultUserSettings = {
|
||||
mathPreview: true,
|
||||
}
|
||||
|
||||
/**
|
||||
* @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,
|
||||
}
|
||||
|
||||
export function EditorProviders({
|
||||
user = { id: USER_ID, email: USER_EMAIL },
|
||||
projectId = PROJECT_ID,
|
||||
@@ -68,7 +87,8 @@ export function EditorProviders({
|
||||
fileRefs: [],
|
||||
},
|
||||
],
|
||||
ui = { view: 'editor', pdfLayout: 'sideBySide', chatOpen: true },
|
||||
/** @type {Partial<LayoutContext>} */
|
||||
layoutContext = layoutContextDefault,
|
||||
userSettings = {},
|
||||
providers = {},
|
||||
}) {
|
||||
@@ -110,7 +130,6 @@ export function EditorProviders({
|
||||
imageName,
|
||||
compiler,
|
||||
},
|
||||
ui,
|
||||
permissionsLevel,
|
||||
},
|
||||
defaultScope
|
||||
@@ -125,6 +144,7 @@ export function EditorProviders({
|
||||
providers={{
|
||||
ConnectionProvider: makeConnectionProvider(socket),
|
||||
IdeReactProvider: makeIdeReactProvider(scope, socket),
|
||||
LayoutProvider: makeLayoutProvider(layoutContext),
|
||||
...providers,
|
||||
}}
|
||||
>
|
||||
@@ -183,7 +203,6 @@ const makeIdeReactProvider = (scope, socket) => {
|
||||
scopeStore.set(key, value)
|
||||
}
|
||||
scopeStore.set('editor.sharejs_doc', scope.editor.sharejs_doc)
|
||||
scopeStore.set('ui.chatOpen', scope.ui.chatOpen)
|
||||
const scopeEventEmitter = new ReactScopeEventEmitter(
|
||||
new IdeEventEmitter()
|
||||
)
|
||||
@@ -215,3 +234,110 @@ const makeIdeReactProvider = (scope, socket) => {
|
||||
}
|
||||
return IdeReactProvider
|
||||
}
|
||||
|
||||
const makeLayoutProvider = layoutContextOverrides => {
|
||||
const layout = {
|
||||
...layoutContextDefault,
|
||||
...layoutContextOverrides,
|
||||
}
|
||||
const LayoutProvider = ({ children }) => {
|
||||
const [view, setView] = useState(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
|
||||
)
|
||||
|
||||
useEventListener(
|
||||
'ui.toggle-review-panel',
|
||||
useCallback(() => {
|
||||
setReviewPanelOpen(open => !open)
|
||||
}, [setReviewPanelOpen])
|
||||
)
|
||||
const changeLayout = useCallback(
|
||||
(newLayout, newView = 'editor') => {
|
||||
setPdfLayout(newLayout)
|
||||
setView(newLayout === 'sideBySide' ? 'editor' : newView)
|
||||
},
|
||||
[setPdfLayout, setView]
|
||||
)
|
||||
const {
|
||||
reattach,
|
||||
detach,
|
||||
isLinked: detachIsLinked,
|
||||
role: detachRole,
|
||||
} = useDetachLayout()
|
||||
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,
|
||||
}),
|
||||
[
|
||||
reattach,
|
||||
detach,
|
||||
detachIsLinked,
|
||||
detachRole,
|
||||
changeLayout,
|
||||
chatIsOpen,
|
||||
leftMenuShown,
|
||||
openFile,
|
||||
pdfLayout,
|
||||
pdfPreviewOpen,
|
||||
projectSearchIsOpen,
|
||||
setProjectSearchIsOpen,
|
||||
reviewPanelOpen,
|
||||
miniReviewPanelVisible,
|
||||
loadingStyleSheet,
|
||||
setChatIsOpen,
|
||||
setLeftMenuShown,
|
||||
setOpenFile,
|
||||
setPdfLayout,
|
||||
setReviewPanelOpen,
|
||||
setMiniReviewPanelVisible,
|
||||
setLoadingStyleSheet,
|
||||
setView,
|
||||
view,
|
||||
]
|
||||
)
|
||||
|
||||
return (
|
||||
<LayoutContext.Provider value={value}>{children}</LayoutContext.Provider>
|
||||
)
|
||||
}
|
||||
return LayoutProvider
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user