import React , { useEffect , useState , useCallback , useMemo } from 'react' ; import { DeltaBackend } from '../delta-remote' ; import { onDCEvent } from '../ipc' ; import { getLogger } from '../../shared/logger' ; import { useTranslationFunction } from '../contexts' ; import { useKeyBindingAction , KeybindAction } from '../keybindings' ; import { C } from 'deltachat-node/dist/constants' ; import { debounce } from 'debounce' ; import { debounceWithInit } from './chat/ChatListHelpers' ; const log = getLogger ( 'renderer/components/ConnectivityToast' ) ; enum Connectivity { NOT_CONNECTED , CONNECTING , WORKING , CONNECTED } export default function ConnectivityToast ( ) { const [ networkState , setNetworkState ] = useState ( [ Connectivity . CONNECTED , '' ] ) ; const [ tryConnectCooldown , setTryConnectCooldown ] = useState ( true ) ; const maybeNetwork = useMemo ( ( ) => debounce ( ( ) => DeltaBackend . call ( 'context.maybeNetwork' ) , 140 , true ) , [ ] ) ; const onBrowserOffline = ( ) => { log . debug ( "Browser knows we're offline" ) ; setNetworkState ( ( ) => [ Connectivity . NOT_CONNECTED , "Browser knows we're offline" , ] ) ; } ; const tryMaybeNetworkIfOfflineAfterXms = useCallback ( ( ms ) => { setTimeout ( ( ) => { setNetworkState ( ( [ connectivity , error ] ) => { if ( connectivity === Connectivity . NOT_CONNECTED ) { log . debug ( `We are still not online after ${ ms }  milli seconds, try maybeNetwork again` ) ; maybeNetwork ( ) ; } else if ( ms < 30000 ) { tryMaybeNetworkIfOfflineAfterXms ( 2 * ms ) ; } else { log . debug ( `We tried reconnecting with waiting for more then 30 seconds, now stop` ) ; } return [ connectivity , error ] ; } ) ; } , ms ) ; } , [ maybeNetwork ] ) ; const onBrowserOnline = useCallback ( ( ) => { log . debug ( "Browser thinks we're back online, telling rust core" ) ; setNetworkState ( ( ) => [ Connectivity . CONNECTED , "Browser thinks we're online" , ] ) ; maybeNetwork ( ) ; tryMaybeNetworkIfOfflineAfterXms ( 150 ) ; } , [ tryMaybeNetworkIfOfflineAfterXms , maybeNetwork ] ) ; const onConnectivityChanged = useMemo ( ( ) => debounceWithInit ( async ( _data1 , _data2 ) => { const connectivity = await DeltaBackend . call ( 'context.getConnectivity' ) ; if ( connectivity >= C . DC_CONNECTIVITY_CONNECTED ) { log . debug ( "Core thinks we're back online and connected" ) ; setNetworkState ( ( ) => [ Connectivity . CONNECTED , "Core thinks we're connected" , ] ) ; } else if ( connectivity >= C . DC_CONNECTIVITY_WORKING ) { log . debug ( "Core thinks we're back online and connected" ) ; setNetworkState ( ( ) => [ Connectivity . WORKING , "Core thinks we're connected and working" , ] ) ; } else if ( connectivity >= C . DC_CONNECTIVITY_CONNECTING ) { log . debug ( "Core thinks we're back online and connected" ) ; setNetworkState ( ( ) => [ Connectivity . CONNECTING , "Core thinks we're connecting" , ] ) ; } else if ( connectivity >= C . DC_CONNECTIVITY_NOT_CONNECTED ) { log . debug ( "Core thinks we're not connected" ) ; setNetworkState ( ( ) => [ Connectivity . NOT_CONNECTED , "Core thinks we're not connected" , ] ) ; } } , 300 ) , [ ] ) ; useKeyBindingAction ( KeybindAction . Debug_MaybeNetwork , maybeNetwork ) ; useEffect ( ( ) => { if ( navigator . onLine === false ) onBrowserOffline ( ) ; window . addEventListener ( 'online' , onBrowserOnline ) ; window . addEventListener ( 'offline' , onBrowserOffline ) ; window . addEventListener ( 'focus' , maybeNetwork ) ; const removeOnConnectivityChanged = onDCEvent ( 'DC_EVENT_CONNECTIVITY_CHANGED' , onConnectivityChanged ) ; return ( ) => { window . removeEventListener ( 'online' , onBrowserOnline ) ; window . removeEventListener ( 'offline' , onBrowserOffline ) ; window . removeEventListener ( 'focus' , maybeNetwork ) ; removeOnConnectivityChanged ( ) ; } ; } , [ onBrowserOnline , maybeNetwork , onConnectivityChanged ] ) ; const onTryReconnectClick = ( ) => { setTryConnectCooldown ( false ) ; setTimeout ( ( ) => setTryConnectCooldown ( true ) , 15000 ) ; setTimeout ( ( ) => maybeNetwork ( ) , 100 ) ; } ; const tx = useTranslationFunction ( ) ; return ( < > { networkState [ 0 ] === Connectivity . NOT_CONNECTED && ( < div className = 'ConnectivityToast' > < a title = { networkState [ 1 ] } > { tx ( 'connectivity_not_connected' ) } < /a> < div className = { tryConnectCooldown ? '' : 'disabled' } onClick = { onTryReconnectClick } > { tx ( 'try_connect_now' ) } < /div> < /div>)} { networkState [ 0 ] === Connectivity . CONNECTING && ( < div className = 'ConnectivityToast' > { tx ( 'connectivity_connecting' ) } < /div>)} { networkState [ 0 ] === Connectivity . WORKING && ( < div className = 'ConnectivityToast' > { tx ( 'connectivity_updating' ) } < /div>)} < />); }