1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | import {NativeEventSubscription} from 'react-native';
|
11 | import NativeInterface from './nativeInterface';
|
12 | import InternetReachability from './internetReachability';
|
13 | import * as Types from './types';
|
14 | import * as PrivateTypes from './privateTypes';
|
15 |
|
16 | export default class State {
|
17 | private _nativeEventSubscription: NativeEventSubscription | null = null;
|
18 | private _subscriptions = new Set<Types.NetInfoChangeHandler>();
|
19 | private _latestState: Types.NetInfoState | null = null;
|
20 | private _internetReachability: InternetReachability;
|
21 |
|
22 | constructor(configuration: Types.NetInfoConfiguration) {
|
23 |
|
24 | this._internetReachability = new InternetReachability(
|
25 | configuration,
|
26 | this._handleInternetReachabilityUpdate,
|
27 | );
|
28 |
|
29 |
|
30 | this._nativeEventSubscription = NativeInterface.eventEmitter.addListener(
|
31 | PrivateTypes.DEVICE_CONNECTIVITY_EVENT,
|
32 | this._handleNativeStateUpdate,
|
33 | );
|
34 |
|
35 |
|
36 | this._fetchCurrentState();
|
37 | }
|
38 |
|
39 | private _handleNativeStateUpdate = (
|
40 | state: PrivateTypes.NetInfoNativeModuleState,
|
41 | ): void => {
|
42 |
|
43 | this._internetReachability.update(state);
|
44 |
|
45 |
|
46 | const convertedState = this._convertState(state);
|
47 |
|
48 |
|
49 | this._latestState = convertedState;
|
50 | this._subscriptions.forEach((handler): void => handler(convertedState));
|
51 | };
|
52 |
|
53 | private _handleInternetReachabilityUpdate = (
|
54 | isInternetReachable: boolean | null | undefined,
|
55 | ): void => {
|
56 | if (!this._latestState) {
|
57 | return;
|
58 | }
|
59 |
|
60 | const nextState = {
|
61 | ...this._latestState,
|
62 | isInternetReachable,
|
63 | } as Types.NetInfoState;
|
64 | this._latestState = nextState;
|
65 | this._subscriptions.forEach((handler): void => handler(nextState));
|
66 | };
|
67 |
|
68 | private _fetchCurrentState = async (
|
69 | requestedInterface?: string,
|
70 | ): Promise<Types.NetInfoState> => {
|
71 | const state = await NativeInterface.getCurrentState(requestedInterface);
|
72 |
|
73 |
|
74 | this._internetReachability.update(state);
|
75 |
|
76 | const convertedState = this._convertState(state);
|
77 | if (!requestedInterface) {
|
78 | this._latestState = convertedState;
|
79 | }
|
80 |
|
81 | return convertedState;
|
82 | };
|
83 |
|
84 | private _convertState = (
|
85 | input: PrivateTypes.NetInfoNativeModuleState,
|
86 | ): Types.NetInfoState => {
|
87 | if (typeof input.isInternetReachable === 'boolean') {
|
88 | return input as Types.NetInfoState;
|
89 | } else {
|
90 | return {
|
91 | ...input,
|
92 | isInternetReachable: this._internetReachability.currentState(),
|
93 | } as Types.NetInfoState;
|
94 | }
|
95 | };
|
96 |
|
97 | public latest = (
|
98 | requestedInterface?: string,
|
99 | ): Promise<Types.NetInfoState> => {
|
100 | if (requestedInterface) {
|
101 | return this._fetchCurrentState(requestedInterface);
|
102 | } else if (this._latestState) {
|
103 | return Promise.resolve(this._latestState);
|
104 | } else {
|
105 | return this._fetchCurrentState();
|
106 | }
|
107 | };
|
108 |
|
109 | public add = (handler: Types.NetInfoChangeHandler): void => {
|
110 |
|
111 | this._subscriptions.add(handler);
|
112 |
|
113 |
|
114 | if (this._latestState) {
|
115 | handler(this._latestState);
|
116 | } else {
|
117 | this.latest().then(handler);
|
118 | }
|
119 | };
|
120 |
|
121 | public remove = (handler: Types.NetInfoChangeHandler): void => {
|
122 | this._subscriptions.delete(handler);
|
123 | };
|
124 |
|
125 | public tearDown = (): void => {
|
126 | if (this._internetReachability) {
|
127 | this._internetReachability.tearDown();
|
128 | }
|
129 |
|
130 | if (this._nativeEventSubscription) {
|
131 | this._nativeEventSubscription.remove();
|
132 | }
|
133 |
|
134 | this._subscriptions.clear();
|
135 | };
|
136 | }
|