Просмотр исходного кода

Merge pull request #26951 from overleaf/mj-layout-broken

[web] Add restoreView to LayoutContext

GitOrigin-RevId: 3a50c1e215c99236f503285fee1c924df57e07e4
Mathias Jakobsen 1 год назад
Родитель
Сommit
4ab4fbdf51

+ 3 - 3
services/web/frontend/js/features/history/context/hooks/use-restore-deleted-file.ts

@@ -21,7 +21,7 @@ type RestorationState =
 
 export function useRestoreDeletedFile() {
   const { projectId } = useHistoryContext()
-  const { setView } = useLayoutContext()
+  const { restoreView } = useLayoutContext()
   const { openDocWithId, openFileWithId } = useEditorManagerContext()
   const { showBoundary } = useErrorBoundary()
   const { fileTreeData } = useFileTreeData()
@@ -37,7 +37,7 @@ export function useRestoreDeletedFile() {
       if (result) {
         setState('complete')
         const { _id: id } = result.entity
-        setView('editor')
+        restoreView()
 
         if (restoredFileMetadata.type === 'doc') {
           openDocWithId(id)
@@ -52,7 +52,7 @@ export function useRestoreDeletedFile() {
     restoredFileMetadata,
     openDocWithId,
     openFileWithId,
-    setView,
+    restoreView,
   ])
 
   useEffect(() => {

+ 3 - 3
services/web/frontend/js/features/history/context/hooks/use-restore-project.ts

@@ -7,7 +7,7 @@ type RestorationState = 'initial' | 'restoring' | 'restored' | 'error'
 
 export const useRestoreProject = () => {
   const { showBoundary } = useErrorBoundary()
-  const { setView } = useLayoutContext()
+  const { restoreView } = useLayoutContext()
 
   const [restorationState, setRestorationState] =
     useState<RestorationState>('initial')
@@ -18,14 +18,14 @@ export const useRestoreProject = () => {
       restoreProjectToVersion(projectId, version)
         .then(() => {
           setRestorationState('restored')
-          setView('editor')
+          restoreView()
         })
         .catch(err => {
           setRestorationState('error')
           showBoundary(err)
         })
     },
-    [showBoundary, setView]
+    [showBoundary, restoreView]
   )
 
   return {

+ 3 - 3
services/web/frontend/js/features/history/context/hooks/use-restore-selected-file.ts

@@ -22,7 +22,7 @@ type RestoreState =
 
 export function useRestoreSelectedFile() {
   const { projectId } = useHistoryContext()
-  const { setView } = useLayoutContext()
+  const { restoreView } = useLayoutContext()
   const { openDocWithId, openFileWithId } = useEditorManagerContext()
   const { showBoundary } = useErrorBoundary()
   const { fileTreeData } = useFileTreeData()
@@ -38,7 +38,7 @@ export function useRestoreSelectedFile() {
       if (result) {
         setState('complete')
         const { _id: id } = result.entity
-        setView('editor')
+        restoreView()
 
         if (restoredFileMetadata.type === 'doc') {
           openDocWithId(id)
@@ -53,7 +53,7 @@ export function useRestoreSelectedFile() {
     restoredFileMetadata,
     openDocWithId,
     openFileWithId,
-    setView,
+    restoreView,
   ])
 
   useEffect(() => {

+ 7 - 4
services/web/frontend/js/features/ide-redesign/components/toolbar/show-history-button.tsx

@@ -7,15 +7,18 @@ import { useEditorAnalytics } from '@/shared/hooks/use-editor-analytics'
 
 export default function ShowHistoryButton() {
   const { t } = useTranslation()
-  const { view, setView } = useLayoutContext()
+  const { view, setView, restoreView } = useLayoutContext()
   const { sendEvent } = useEditorAnalytics()
 
   const toggleHistoryOpen = useCallback(() => {
     const action = view === 'history' ? 'close' : 'open'
     sendEvent('navigation-clicked-history', { action })
-
-    setView(view === 'history' ? 'editor' : 'history')
-  }, [view, setView, sendEvent])
+    if (view === 'history') {
+      restoreView()
+    } else {
+      setView('history')
+    }
+  }, [view, setView, sendEvent, restoreView])
 
   return (
     <div className="ide-redesign-toolbar-button-container">

+ 3 - 3
services/web/frontend/js/features/ide-redesign/components/toolbar/toolbar.tsx

@@ -20,7 +20,7 @@ const [publishModalModules] = importOverleafModules('publishModal')
 const SubmitProjectButton = publishModalModules?.import.NewPublishToolbarButton
 
 export const Toolbar = () => {
-  const { view, setView } = useLayoutContext()
+  const { view, restoreView } = useLayoutContext()
   const { cobranding } = useEditorContext()
   const { permissionsLevel } = useIdeReactContext()
   const shouldDisplaySubmitButton =
@@ -29,8 +29,8 @@ export const Toolbar = () => {
 
   const handleBackToEditorClick = useCallback(() => {
     eventTracking.sendMB('navigation-clicked-history', { action: 'close' })
-    setView('editor')
-  }, [setView])
+    restoreView()
+  }, [restoreView])
 
   if (view === 'history') {
     return (

+ 2 - 2
services/web/frontend/js/features/pdf-preview/components/switch-to-editor-button.tsx

@@ -4,7 +4,7 @@ import OLButton from '@/features/ui/components/ol/ol-button'
 import { useLayoutContext } from '../../../shared/context/layout-context'
 
 function SwitchToEditorButton() {
-  const { pdfLayout, setView, detachRole } = useLayoutContext()
+  const { pdfLayout, restoreView, detachRole } = useLayoutContext()
 
   const { t } = useTranslation()
 
@@ -17,7 +17,7 @@ function SwitchToEditorButton() {
   }
 
   function handleClick() {
-    setView('editor')
+    restoreView()
     window.setTimeout(() => {
       window.dispatchEvent(new Event('editor:focus'))
     })

+ 19 - 9
services/web/frontend/js/shared/context/layout-context.tsx

@@ -8,6 +8,7 @@ import {
   SetStateAction,
   FC,
   useState,
+  useRef,
 } from 'react'
 import useDetachLayout from '../hooks/use-detach-layout'
 import localStorage from '../../infrastructure/local-storage'
@@ -61,6 +62,7 @@ export type LayoutContextValue = LayoutContextOwnStates & {
   pdfPreviewOpen: boolean
   setProjectSearchIsOpen: Dispatch<SetStateAction<boolean>>
   setOpenFile: Dispatch<SetStateAction<BinaryFile | null>>
+  restoreView: () => void
 }
 
 const debugPdfDetach = getMeta('ol-debugPdfDetach')
@@ -85,6 +87,8 @@ export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
   const historyToggleEmitter = useScopeEventEmitter('history:toggle', true)
   const { isOpen: railIsOpen, setIsOpen: setRailIsOpen } = useRailContext()
   const [prevRailIsOpen, setPrevRailIsOpen] = useState(railIsOpen)
+  // Whether we came from a file or a document when we left the ide
+  const lastIdeView = useRef<IdeView>('editor')
 
   const setView = useCallback(
     (value: IdeView | null) => {
@@ -103,12 +107,8 @@ export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
           setRailIsOpen(prevRailIsOpen)
         }
 
-        if (value === 'editor' && openFile) {
-          // if a file is currently opened, ensure the view is 'file' instead of
-          // 'editor' when the 'editor' view is requested. This is to ensure
-          // that the entity selected in the file tree is the one visible and
-          // that docs don't take precedence over files.
-          return 'file'
+        if (value === 'editor' || value === 'file') {
+          lastIdeView.current = value
         }
 
         return value
@@ -117,7 +117,6 @@ export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
     [
       _setView,
       setRailIsOpen,
-      openFile,
       historyToggleEmitter,
       prevRailIsOpen,
       setPrevRailIsOpen,
@@ -125,6 +124,10 @@ export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
     ]
   )
 
+  const restoreView = useCallback(() => {
+    setView(lastIdeView.current ?? 'editor')
+  }, [setView])
+
   // whether the chat pane is open
   const [chatIsOpen, setChatIsOpen] = usePersistedState<boolean>(
     'ui.chatOpen',
@@ -192,11 +195,16 @@ export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
 
   const changeLayout = useCallback(
     (newLayout: IdeLayout, newView: IdeView = 'editor') => {
+      const targetView = newLayout === 'sideBySide' ? 'editor' : newView
       setPdfLayout(newLayout)
-      setView(newLayout === 'sideBySide' ? 'editor' : newView)
+      if (targetView === 'editor') {
+        restoreView()
+      } else {
+        setView(targetView)
+      }
       setLayoutInLocalStorage(newLayout)
     },
-    [setPdfLayout, setView]
+    [setPdfLayout, setView, restoreView]
   )
 
   // Force codemirror to reposition all tooltips to prevent an issue
@@ -276,6 +284,7 @@ export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
       setLoadingStyleSheet,
       setView,
       view,
+      restoreView,
     }),
     [
       reattach,
@@ -302,6 +311,7 @@ export const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {
       setLoadingStyleSheet,
       setView,
       view,
+      restoreView,
     ]
   )
 

+ 1 - 0
services/web/test/frontend/features/full-project-search/components/full-project-search.spec.tsx

@@ -95,6 +95,7 @@ const createInitialValue = () =>
     setProjectSearchIsOpen: cy.stub(),
     openFile: null,
     setOpenFile: cy.stub(),
+    restoreView: cy.stub(),
   }) satisfies LayoutContextValue
 
 const LayoutProvider: FC<React.PropsWithChildren> = ({ children }) => {

+ 7 - 0
services/web/test/frontend/helpers/editor-providers.tsx

@@ -409,6 +409,11 @@ const makeLayoutProvider = (
       },
       [setPdfLayout, setView]
     )
+
+    const restoreView = useCallback(() => {
+      setView('editor')
+    }, [])
+
     const {
       reattach,
       detach,
@@ -443,6 +448,7 @@ const makeLayoutProvider = (
         setLoadingStyleSheet,
         setView,
         view,
+        restoreView,
       }),
       [
         reattach,
@@ -469,6 +475,7 @@ const makeLayoutProvider = (
         setLoadingStyleSheet,
         setView,
         view,
+        restoreView,
       ]
     )