/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format */ import {NativeEventSubscription} from 'react-native'; import NativeInterface from './nativeInterface'; import InternetReachability from './internetReachability'; import * as Types from './types'; import * as PrivateTypes from './privateTypes'; export default class State { private _nativeEventSubscription: NativeEventSubscription | null = null; private _subscriptions = new Set(); private _latestState: Types.NetInfoState | null = null; private _internetReachability: InternetReachability; constructor(configuration: Types.NetInfoConfiguration) { // Add the listener to the internet connectivity events this._internetReachability = new InternetReachability( configuration, this._handleInternetReachabilityUpdate, ); // Add the subscription to the native events this._nativeEventSubscription = NativeInterface.eventEmitter.addListener( PrivateTypes.DEVICE_CONNECTIVITY_EVENT, this._handleNativeStateUpdate, ); // Fetch the current state from the native module this._fetchCurrentState(); } private _handleNativeStateUpdate = ( state: PrivateTypes.NetInfoNativeModuleState, ): void => { // Update the internet reachability module this._internetReachability.update(state); // Convert the state from native to JS shape const convertedState = this._convertState(state); // Update the listeners this._latestState = convertedState; this._subscriptions.forEach((handler): void => handler(convertedState)); }; private _handleInternetReachabilityUpdate = ( isInternetReachable: boolean | null | undefined, ): void => { if (!this._latestState) { return; } const nextState = { ...this._latestState, isInternetReachable, } as Types.NetInfoState; this._latestState = nextState; this._subscriptions.forEach((handler): void => handler(nextState)); }; private _fetchCurrentState = async ( requestedInterface?: string, ): Promise => { const state = await NativeInterface.getCurrentState(requestedInterface); // Update the internet reachability module this._internetReachability.update(state); // Convert and store the new state const convertedState = this._convertState(state); if (!requestedInterface) { this._latestState = convertedState; } return convertedState; }; private _convertState = ( input: PrivateTypes.NetInfoNativeModuleState, ): Types.NetInfoState => { if (typeof input.isInternetReachable === 'boolean') { return input as Types.NetInfoState; } else { return { ...input, isInternetReachable: this._internetReachability.currentState(), } as Types.NetInfoState; } }; public latest = ( requestedInterface?: string, ): Promise => { if (requestedInterface) { return this._fetchCurrentState(requestedInterface); } else if (this._latestState) { return Promise.resolve(this._latestState); } else { return this._fetchCurrentState(); } }; public add = (handler: Types.NetInfoChangeHandler): void => { // Add the subscription handler to our set this._subscriptions.add(handler); // Send it the latest data we have if (this._latestState) { handler(this._latestState); } else { this.latest().then(handler); } }; public remove = (handler: Types.NetInfoChangeHandler): void => { this._subscriptions.delete(handler); }; public tearDown = (): void => { if (this._internetReachability) { this._internetReachability.tearDown(); } if (this._nativeEventSubscription) { this._nativeEventSubscription.remove(); } this._subscriptions.clear(); }; }