diff --git a/lib/hooks/disconnected-bar.js b/lib/hooks/disconnected-bar.js index 4c54f26ec..153a0cd15 100644 --- a/lib/hooks/disconnected-bar.js +++ b/lib/hooks/disconnected-bar.js @@ -1,69 +1,117 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { connectionSelector } from '../selectors/keyserver-selectors.js'; import { updateDisconnectedBarActionType, type ConnectionStatus, } from '../types/socket-types.js'; import { useSelector, useDispatch } from '../utils/redux-utils.js'; import { ashoatKeyserverID } from '../utils/validation-utils.js'; function useDisconnectedBarVisibilityHandler(networkConnected: boolean): void { const dispatch = useDispatch(); const connection = useSelector(connectionSelector(ashoatKeyserverID)); invariant(connection, 'keyserver missing from keyserverStore'); const disconnected = connection.showDisconnectedBar; const setDisconnected = React.useCallback( (newDisconnected: boolean) => { if (newDisconnected === disconnected) { return; } dispatch({ type: updateDisconnectedBarActionType, payload: { visible: newDisconnected, keyserverID: ashoatKeyserverID }, }); }, [disconnected, dispatch], ); const networkActiveRef = React.useRef(true); React.useEffect(() => { networkActiveRef.current = networkConnected; if (!networkConnected) { setDisconnected(true); } }, [setDisconnected, networkConnected]); const prevConnectionStatusRef = React.useRef(); const connectionStatus = connection.status; const someRequestIsLate = connection.lateResponses.length !== 0; React.useEffect(() => { const prevConnectionStatus = prevConnectionStatusRef.current; prevConnectionStatusRef.current = connectionStatus; if ( connectionStatus === 'connected' && prevConnectionStatus !== 'connected' ) { // Sometimes NetInfo misses the network coming back online for some // reason. But if the socket reconnects, the network must be up networkActiveRef.current = true; setDisconnected(false); } else if (!networkActiveRef.current || someRequestIsLate) { setDisconnected(true); } else if ( connectionStatus === 'reconnecting' || connectionStatus === 'forcedDisconnecting' ) { setDisconnected(true); } else if (connectionStatus === 'connected') { setDisconnected(false); } }, [connectionStatus, someRequestIsLate, setDisconnected]); } -export { useDisconnectedBarVisibilityHandler }; +function useShouldShowDisconnectedBar(): { + +disconnected: boolean, + +shouldShowDisconnectedBar: boolean, +} { + const connection = useSelector(connectionSelector(ashoatKeyserverID)); + invariant(connection, 'keyserver missing from keyserverStore'); + const disconnected = connection.showDisconnectedBar; + const socketConnected = connection.status === 'connected'; + + const shouldShowDisconnectedBar = disconnected || !socketConnected; + return { disconnected, shouldShowDisconnectedBar }; +} + +type DisconnectedBarCause = 'connecting' | 'disconnected'; + +function useDisconnectedBar( + changeShowing: boolean => void, +): DisconnectedBarCause { + const { disconnected, shouldShowDisconnectedBar } = + useShouldShowDisconnectedBar(); + + const prevShowDisconnectedBar = React.useRef(); + React.useEffect(() => { + const wasShowing = prevShowDisconnectedBar.current; + if (shouldShowDisconnectedBar && wasShowing === false) { + changeShowing(true); + } else if (!shouldShowDisconnectedBar && wasShowing) { + changeShowing(false); + } + prevShowDisconnectedBar.current = shouldShowDisconnectedBar; + }, [shouldShowDisconnectedBar, changeShowing]); + + const [barCause, setBarCause] = + React.useState('connecting'); + React.useEffect(() => { + if (shouldShowDisconnectedBar && disconnected) { + setBarCause('disconnected'); + } else if (shouldShowDisconnectedBar) { + setBarCause('connecting'); + } + }, [shouldShowDisconnectedBar, disconnected]); + return barCause; +} + +export { + useDisconnectedBarVisibilityHandler, + useShouldShowDisconnectedBar, + useDisconnectedBar, +};