Ver Fonte

[web] close connection permanently when opening out-of-sync modal (#23148)

* [web] close connection permanently when opening out-of-sync modal

* [web] disable generic forceDisconnected behavior for out-of-sync modal

* [web] hide "disconnected" banner when displaying out of sync modal

GitOrigin-RevId: 133b3e24d94279917298ce7fd5d0a76da2265512
Jakob Ackermann há 1 ano atrás
pai
commit
8df7f6772c

+ 3 - 1
services/web/frontend/js/features/ide-react/components/alerts/alerts.tsx

@@ -27,7 +27,9 @@ export function Alerts() {
 
   return createPortal(
     <>
-      {connectionState.forceDisconnected ? (
+      {connectionState.forceDisconnected &&
+      // hide "disconnected" banner when displaying out of sync modal
+      connectionState.error !== 'out-of-sync' ? (
         <OLNotification
           type="error"
           content={<strong>{t('disconnected')}</strong>}

+ 6 - 2
services/web/frontend/js/features/ide-react/components/modals/force-disconnected.tsx

@@ -15,10 +15,14 @@ function ForceDisconnected() {
   const [show, setShow] = useState(false)
 
   useEffect(() => {
-    if (connectionState.forceDisconnected) {
+    if (
+      connectionState.forceDisconnected &&
+      // out of sync has its own modal
+      connectionState.error !== 'out-of-sync'
+    ) {
       setShow(true)
     }
-  }, [connectionState.forceDisconnected])
+  }, [connectionState.forceDisconnected, connectionState.error])
 
   useEffect(() => {
     if (connectionState.forceDisconnected) {

+ 1 - 1
services/web/frontend/js/features/ide-react/connection/connection-manager.ts

@@ -347,7 +347,7 @@ export class ConnectionManager extends EventTarget {
     return true
   }
 
-  disconnect() {
+  private disconnect() {
     this.changeState({
       ...this.state,
       readyState: WebSocket.CLOSED,

+ 14 - 7
services/web/frontend/js/features/ide-react/context/connection-context.tsx

@@ -8,6 +8,7 @@ import {
   useMemo,
 } from 'react'
 import {
+  ConnectionError,
   ConnectionState,
   SocketDebuggingInfo,
 } from '../connection/types/connection-state'
@@ -27,7 +28,7 @@ type ConnectionContextValue = {
   secondsUntilReconnect: () => number
   tryReconnectNow: () => void
   registerUserActivity: () => void
-  disconnect: () => void
+  closeConnection: (err: ConnectionError) => void
   getSocketDebuggingInfo: () => SocketDebuggingInfo
 }
 
@@ -75,9 +76,10 @@ export const ConnectionProvider: FC = ({ children }) => {
     [connectionManager]
   )
 
-  const disconnect = useCallback(() => {
-    connectionManager.disconnect()
-  }, [connectionManager])
+  const closeConnection = useCallback(
+    (err: ConnectionError) => connectionManager.close(err),
+    [connectionManager]
+  )
 
   const getSocketDebuggingInfo = useCallback(
     () => connectionManager.getSocketDebuggingInfo(),
@@ -87,7 +89,11 @@ export const ConnectionProvider: FC = ({ children }) => {
   // Reload the page on force disconnect. Doing this in React-land means that we
   // can use useLocation(), which provides mockable location methods
   useEffect(() => {
-    if (connectionState.forceDisconnected) {
+    if (
+      connectionState.forceDisconnected &&
+      // keep editor open when out of sync
+      connectionState.error !== 'out-of-sync'
+    ) {
       const timer = window.setTimeout(
         () => location.reload(),
         connectionState.forcedDisconnectDelay * 1000
@@ -99,6 +105,7 @@ export const ConnectionProvider: FC = ({ children }) => {
   }, [
     connectionState.forceDisconnected,
     connectionState.forcedDisconnectDelay,
+    connectionState.error,
     location,
   ])
 
@@ -111,7 +118,7 @@ export const ConnectionProvider: FC = ({ children }) => {
       secondsUntilReconnect,
       tryReconnectNow,
       registerUserActivity,
-      disconnect,
+      closeConnection,
       getSocketDebuggingInfo,
     }),
     [
@@ -122,7 +129,7 @@ export const ConnectionProvider: FC = ({ children }) => {
       registerUserActivity,
       secondsUntilReconnect,
       tryReconnectNow,
-      disconnect,
+      closeConnection,
       getSocketDebuggingInfo,
     ]
   )

+ 3 - 3
services/web/frontend/js/features/ide-react/context/editor-manager-context.tsx

@@ -98,7 +98,7 @@ export const EditorManagerProvider: FC = ({ children }) => {
   const { projectId } = useIdeReactContext()
   const { reportError, eventEmitter, eventLog } = useIdeReactContext()
   const { setOutOfSync } = useEditorContext()
-  const { socket, disconnect, connectionState } = useConnectionContext()
+  const { socket, closeConnection, connectionState } = useConnectionContext()
   const { view, setView } = useLayoutContext()
   const { showGenericMessageModal, genericModalVisible, showOutOfSyncModal } =
     useModalsContext()
@@ -580,7 +580,7 @@ export const EditorManagerProvider: FC = ({ children }) => {
         // Do not re-join after re-connecting.
         document.leaveAndCleanUp()
 
-        disconnect()
+        closeConnection('out-of-sync')
         reportError(error, meta)
 
         // Tell the user about the error state.
@@ -605,7 +605,7 @@ export const EditorManagerProvider: FC = ({ children }) => {
       }
     }
   }, [
-    disconnect,
+    closeConnection,
     docError,
     docTooLongErrorShown,
     eventEmitter,

+ 1 - 1
services/web/frontend/stories/decorators/scope.tsx

@@ -184,7 +184,7 @@ const ConnectionProvider: FC = ({ children }) => {
       secondsUntilReconnect: () => 0,
       tryReconnectNow: () => {},
       registerUserActivity: () => {},
-      disconnect: () => {},
+      closeConnection: () => {},
       getSocketDebuggingInfo: () => ({
         client_id: 'fakeClientId',
         transport: 'fakeTransport',