Skip to content

Commit 8a4703c

Browse files
chrisbobbegnprice
authored andcommitted
offline notice [nfc]: Move update-redux logic here
From AppEventHandlers, which is kind of cluttered.
1 parent 59176bd commit 8a4703c

File tree

2 files changed

+64
-65
lines changed

2 files changed

+64
-65
lines changed

src/boot/AppEventHandlers.js

Lines changed: 1 addition & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import React, { PureComponent } from 'react';
44
import type { Node, ComponentType } from 'react';
55
import { AppState, View } from 'react-native';
6-
import NetInfo from '@react-native-community/netinfo';
76
import * as ScreenOrientation from 'expo-screen-orientation';
87

98
import type { GlobalDispatch, Orientation as OrientationT } from '../types';
@@ -12,7 +11,7 @@ import { connectGlobal } from '../react-redux';
1211
import { handleInitialNotification } from '../notification/notifOpen';
1312
import NotificationListener from '../notification/NotificationListener';
1413
import { ShareReceivedListener, handleInitialShare } from '../sharing';
15-
import { appOnline, appOrientation } from '../actions';
14+
import { appOrientation } from '../actions';
1615
import PresenceHeartbeat from '../presence/PresenceHeartbeat';
1716

1817
const styles = createStyleSheet({
@@ -50,9 +49,6 @@ const orientationLookup: OrientationLookup = {
5049
};
5150

5251
class AppEventHandlersInner extends PureComponent<Props> {
53-
/** NetInfo disconnection callback. */
54-
netInfoDisconnectCallback: (() => void) | null = null;
55-
5652
handleOrientationChange = (event: ScreenOrientation.OrientationChangeEvent) => {
5753
const { dispatch } = this.props;
5854

@@ -61,54 +57,6 @@ class AppEventHandlersInner extends PureComponent<Props> {
6157
dispatch(appOrientation(orientationLookup[orientation]));
6258
};
6359

64-
handleConnectivityChange = netInfoState => {
65-
const { dispatch } = this.props;
66-
67-
dispatch(
68-
appOnline(
69-
// From reading code at @react-native-community/net-info v6.0.0 (the
70-
// docs and types don't really give these answers):
71-
//
72-
// This will be `null` on both platforms while the first known value
73-
// of `true` or `false` is being shipped across the asynchronous RN
74-
// bridge.
75-
//
76-
// On Android, it shouldn't otherwise be `null`. The value is set to the
77-
// result of an Android function that only returns a boolean:
78-
// https://developer.android.com/reference/android/net/NetworkInfo#isConnected()
79-
//
80-
// On iOS, this can also be `null` while the app asynchronously
81-
// evaluates whether a network change should cause this to go from
82-
// `false` to `true`. Read on for details (gathered from
83-
// src/internal/internetReachability.ts in the library).
84-
//
85-
// 1. A request loop is started. A HEAD request is made to
86-
// https://clients3.google.com/generate_204, with a timeout of
87-
// 15s (`reachabilityRequestTimeout`), to see if the Internet is
88-
// reachable.
89-
// - If the `fetch` succeeds and a 204 is received, this will be
90-
// made `true`. We'll then sleep for 60s before making the
91-
// request again.
92-
// - If the `fetch` succeeds and a 204 is not received, or if the
93-
// fetch fails, or if the timeout expires, this will be made
94-
// `false`. We'll then sleep for only 5s before making the
95-
// request again.
96-
// 2. The request loop is interrupted if we get a
97-
// 'netInfo.networkStatusDidChange' event from the library's
98-
// native code, signaling a change in the network state. If that
99-
// change would make `netInfoState.type` become or remain
100-
// something good (i.e., not 'none' or 'unknown'), and this
101-
// (`.isInternetReachable`) is currently `false`, then this will
102-
// be made `null`, and the request loop described above will
103-
// start again.
104-
//
105-
// (Several of those parameters are configurable -- timeout durations,
106-
// URL, etc.)
107-
netInfoState.isInternetReachable,
108-
),
109-
);
110-
};
111-
11260
notificationListener = new NotificationListener(this.props.dispatch);
11361
shareListener = new ShareReceivedListener();
11462

@@ -121,13 +69,6 @@ class AppEventHandlersInner extends PureComponent<Props> {
12169
dispatch(handleInitialNotification());
12270
handleInitialShare();
12371

124-
NetInfo.configure({
125-
// This is the default, as of 6.0.0, but `OfflineNoticeProvider`
126-
// depends on this value being stable.
127-
reachabilityRequestTimeout: 15 * 1000,
128-
});
129-
this.netInfoDisconnectCallback = NetInfo.addEventListener(this.handleConnectivityChange);
130-
13172
AppState.addEventListener('memoryWarning', this.handleMemoryWarning);
13273

13374
// The listener doesn't seem to fire in RN's "Debug with Chrome" mode.
@@ -138,10 +79,6 @@ class AppEventHandlersInner extends PureComponent<Props> {
13879
}
13980

14081
componentWillUnmount() {
141-
if (this.netInfoDisconnectCallback) {
142-
this.netInfoDisconnectCallback();
143-
this.netInfoDisconnectCallback = null;
144-
}
14582
AppState.removeEventListener('memoryWarning', this.handleMemoryWarning);
14683
ScreenOrientation.removeOrientationChangeListeners();
14784
this.notificationListener.stop();

src/boot/OfflineNoticeProvider.js

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type { ViewProps } from 'react-native/Libraries/Components/View/ViewPropT
88
import type { DimensionValue } from 'react-native/Libraries/StyleSheet/StyleSheetTypes';
99

1010
import * as logging from '../utils/logging';
11-
import { useGlobalSelector } from '../react-redux';
11+
import { useDispatch, useGlobalSelector } from '../react-redux';
1212
import { getGlobalSession, getGlobalSettings } from '../directSelectors';
1313
import { useHasStayedTrueForMs, usePrevious } from '../reactUtils';
1414
import type { JSONableDict } from '../utils/jsonable';
@@ -18,6 +18,66 @@ import type { ViewStylePropWithout } from '../reactNativeUtils';
1818
import ZulipStatusBar from '../common/ZulipStatusBar';
1919
import type { ThemeName } from '../reduxTypes';
2020
import { TranslationContext } from './TranslationProvider';
21+
import { appOnline } from '../session/sessionActions';
22+
23+
function useUpdateSessionOnConnectivityChange() {
24+
const dispatch = useDispatch();
25+
26+
useEffect(() => {
27+
NetInfo.configure({
28+
// This is the default, as of 6.0.0, but
29+
// `useShouldShowUncertaintyNotice` depends on this value being
30+
// stable.
31+
reachabilityRequestTimeout: 15 * 1000,
32+
});
33+
34+
return NetInfo.addEventListener(netInfoState => {
35+
dispatch(
36+
appOnline(
37+
// From reading code at @react-native-community/net-info v6.0.0 (the
38+
// docs and types don't really give these answers):
39+
//
40+
// This will be `null` on both platforms while the first known value
41+
// of `true` or `false` is being shipped across the asynchronous RN
42+
// bridge.
43+
//
44+
// On Android, it shouldn't otherwise be `null`. The value is set to the
45+
// result of an Android function that only returns a boolean:
46+
// https://developer.android.com/reference/android/net/NetworkInfo#isConnected()
47+
//
48+
// On iOS, this can also be `null` while the app asynchronously
49+
// evaluates whether a network change should cause this to go from
50+
// `false` to `true`. Read on for details (gathered from
51+
// src/internal/internetReachability.ts in the library).
52+
//
53+
// 1. A request loop is started. A HEAD request is made to
54+
// https://clients3.google.com/generate_204, with a timeout of
55+
// 15s (`reachabilityRequestTimeout`), to see if the Internet is
56+
// reachable.
57+
// - If the `fetch` succeeds and a 204 is received, this will be
58+
// made `true`. We'll then sleep for 60s before making the
59+
// request again.
60+
// - If the `fetch` succeeds and a 204 is not received, or if the
61+
// fetch fails, or if the timeout expires, this will be made
62+
// `false`. We'll then sleep for only 5s before making the
63+
// request again.
64+
// 2. The request loop is interrupted if we get a
65+
// 'netInfo.networkStatusDidChange' event from the library's
66+
// native code, signaling a change in the network state. If that
67+
// change would make `netInfoState.type` become or remain
68+
// something good (i.e., not 'none' or 'unknown'), and this
69+
// (`.isInternetReachable`) is currently `false`, then this will
70+
// be made `null`, and the request loop described above will
71+
// start again.
72+
//
73+
// (Several of those parameters are configurable -- timeout durations,
74+
// URL, etc.)
75+
netInfoState.isInternetReachable,
76+
),
77+
);
78+
});
79+
}, [dispatch]);
80+
}
2181

2282
function useShouldShowUncertaintyNotice(): boolean {
2383
const isOnline = useGlobalSelector(state => getGlobalSession(state).isOnline);
@@ -92,6 +152,8 @@ export function OfflineNoticeProvider(props: ProviderProps): Node {
92152
const isOnline = useGlobalSelector(state => getGlobalSession(state).isOnline);
93153
const shouldShowUncertaintyNotice = useShouldShowUncertaintyNotice();
94154

155+
useUpdateSessionOnConnectivityChange();
156+
95157
// Use local UI state for isNoticeVisible instead of computing directly as
96158
// a `const`, so we can apply LayoutAnimation.configureNext to just the
97159
// visibility state change, instead of, e.g., all layout changes

0 commit comments

Comments
 (0)