-
Notifications
You must be signed in to change notification settings - Fork 94
/
index.ts
130 lines (117 loc) · 3.71 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import {useEffect, useState} from 'react';
import {isBrowser} from '../util/const.js';
import {off, on} from '../util/misc.js';
import {type InitialState} from '../util/resolve-hook-state.js';
export type NetworkInformation = {
readonly downlink: number;
readonly downlinkMax: number;
readonly effectiveType: 'slow-2g' | '2g' | '3g' | '4g';
readonly rtt: number;
readonly saveData: boolean;
readonly type:
| 'bluetooth'
| 'cellular'
| 'ethernet'
| 'none'
| 'wifi'
| 'wimax'
| 'other'
| 'unknown';
} & EventTarget;
export type UseNetworkState = {
/**
* @desc Whether browser connected to the network or not.
*/
online: boolean | undefined;
/**
* @desc Previous value of `online` property. Helps to identify if browser
* just connected or lost connection.
*/
previous: boolean | undefined;
/**
* @desc The {Date} object pointing to the moment when state change occurred.
*/
since: Date | undefined;
/**
* @desc Effective bandwidth estimate in megabits per second, rounded to the
* nearest multiple of 25 kilobits per seconds.
*/
downlink: NetworkInformation['downlink'] | undefined;
/**
* @desc Maximum downlink speed, in megabits per second (Mbps), for the
* underlying connection technology
*/
downlinkMax: NetworkInformation['downlinkMax'] | undefined;
/**
* @desc Effective type of the connection meaning one of 'slow-2g', '2g', '3g', or '4g'.
* This value is determined using a combination of recently observed round-trip time
* and downlink values.
*/
effectiveType: NetworkInformation['effectiveType'] | undefined;
/**
* @desc Estimated effective round-trip time of the current connection, rounded
* to the nearest multiple of 25 milliseconds
*/
rtt: NetworkInformation['rtt'] | undefined;
/**
* @desc {true} if the user has set a reduced data usage option on the user agent.
*/
saveData: NetworkInformation['saveData'] | undefined;
/**
* @desc The type of connection a device is using to communicate with the network.
* It will be one of the following values:
* - bluetooth
* - cellular
* - ethernet
* - none
* - wifi
* - wimax
* - other
* - unknown
*/
type: NetworkInformation['type'] | undefined;
};
type NavigatorWithConnection = Navigator &
Partial<Record<'connection' | 'mozConnection' | 'webkitConnection', NetworkInformation>>;
const navigator = isBrowser ? (globalThis.navigator as NavigatorWithConnection) : undefined;
const conn: NetworkInformation | undefined =
navigator && (navigator.connection ?? navigator.mozConnection ?? navigator.webkitConnection);
function getConnectionState(previousState?: UseNetworkState): UseNetworkState {
const online = navigator?.onLine;
const previousOnline = previousState?.online;
return {
online,
previous: previousOnline,
since: online === previousOnline ? previousState?.since : new Date(),
downlink: conn?.downlink,
downlinkMax: conn?.downlinkMax,
effectiveType: conn?.effectiveType,
rtt: conn?.rtt,
saveData: conn?.saveData,
type: conn?.type,
};
}
/**
* Tracks the state of browser's network connection.
*/
export function useNetworkState(initialState?: InitialState<UseNetworkState>): UseNetworkState {
const [state, setState] = useState(initialState ?? getConnectionState);
useEffect(() => {
const handleStateChange = () => {
setState(getConnectionState);
};
on(globalThis, 'online', handleStateChange, {passive: true});
on(globalThis, 'offline', handleStateChange, {passive: true});
if (conn) {
on(conn, 'change', handleStateChange, {passive: true});
}
return () => {
off(globalThis, 'online', handleStateChange);
off(globalThis, 'offline', handleStateChange);
if (conn) {
off(conn, 'change', handleStateChange);
}
};
}, []);
return state;
}