1import React from 'react';
2import { ScrollView, Platform } from 'react-native';
3import NetInfo, { ConnectionInfo } from '@react-native-community/netinfo';
4
5import Colors from '../constants/Colors';
6import HeadingText from '../components/HeadingText';
7import MonoText from '../components/MonoText';
8
9interface ConnectionEvent {
10  time: Date;
11  key: number;
12}
13
14interface ConnectedChangeEvent extends ConnectionEvent {
15  isConnected: boolean;
16}
17
18interface ConnectionChangeEvent extends ConnectionEvent {
19  connectionInfo: ConnectionInfo;
20}
21
22interface Subscription {
23  remove: () => void;
24}
25
26interface State {
27  connectionInfo?: ConnectionInfo;
28  isConnectionExpensive?: boolean;
29  isConnectedChangeEvents: ConnectedChangeEvent[];
30  connectionChangeEvents: ConnectionChangeEvent[];
31}
32
33export default class NetInfoScreen extends React.Component<{}, State> {
34  static navigationOptions = {
35    title: 'NetInfo',
36  };
37
38  readonly state: State = {
39    isConnectedChangeEvents: [],
40    connectionChangeEvents: [],
41  };
42
43  _eventCounter: number = 0;
44  _subscription?: Subscription;
45  _isConnectedSubscription?: Subscription;
46
47  componentDidMount() {
48    this._eventCounter = 0;
49
50    NetInfo.getConnectionInfo()
51      .then(connectionInfo => this.setState({ connectionInfo }))
52      .catch(console.warn);
53    this._ensureIsConnectionExpensiveIsUpToDate();
54    this._subscription = NetInfo.addEventListener(
55      'connectionChange',
56      this._handleConnectionChange
57    ) as unknown as Subscription;
58    this._isConnectedSubscription = NetInfo.isConnected.addEventListener(
59      'connectionChange',
60      this._handleIsConnectedChange
61    ) as unknown as Subscription;
62  }
63
64  componentWillUnmount() {
65    if (this._subscription) {
66      this._subscription.remove();
67    }
68
69    if (this._isConnectedSubscription) {
70      this._isConnectedSubscription.remove();
71    }
72  }
73
74  _handleConnectionChange = (connectionInfo: ConnectionInfo) => {
75    this._ensureIsConnectionExpensiveIsUpToDate();
76    this.setState(({ connectionChangeEvents }) => ({
77      connectionInfo,
78      connectionChangeEvents: [
79        { connectionInfo, time: new Date(), key: this._eventCounter++ },
80        ...connectionChangeEvents,
81      ],
82    }));
83  }
84
85  _ensureIsConnectionExpensiveIsUpToDate = () =>
86    Platform.OS === 'android' &&
87    NetInfo.isConnectionExpensive()
88      .then(isConnectionExpensive => this.setState({ isConnectionExpensive }))
89      .catch(console.warn)
90
91  _handleIsConnectedChange = (isConnected: boolean) =>
92    this.setState(({ isConnectedChangeEvents }) => ({
93      isConnectedChangeEvents: [
94        { isConnected, time: new Date(), key: this._eventCounter++ },
95        ...isConnectedChangeEvents,
96      ],
97    }))
98
99  _maybeRenderIsConnectionExpensive = () =>
100    Platform.OS === 'android' ? (
101      <>
102        <HeadingText>NetInfo.isConnectionExpensive()</HeadingText>
103        <MonoText>{JSON.stringify(this.state.isConnectionExpensive, null, 2)}</MonoText>
104      </>
105    ) : null
106
107  _renderEvents = (events: ConnectionEvent[]) =>
108    events.map(event => <MonoText key={event.key}>{JSON.stringify(event, null, 2)}</MonoText>)
109
110  render() {
111    return (
112      <ScrollView
113        style={{ flex: 1, backgroundColor: Colors.greyBackground }}
114        contentContainerStyle={{ padding: 10 }}
115      >
116        <HeadingText>NetInfo.getConnectionInfo()</HeadingText>
117        <MonoText>{JSON.stringify(this.state.connectionInfo, null, 2)}</MonoText>
118        {this._maybeRenderIsConnectionExpensive()}
119        <HeadingText>NetInfo.addEventListener</HeadingText>
120        {this._renderEvents(this.state.connectionChangeEvents)}
121        <HeadingText>NetInfo.isConnected.addEventListener</HeadingText>
122        {this._renderEvents(this.state.isConnectedChangeEvents)}
123      </ScrollView>
124    );
125  }
126}
127