-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
/
Copy pathuseBattery.ts
83 lines (70 loc) Β· 2.46 KB
/
useBattery.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
import { useEffect, useState } from 'react';
import { isNavigator, off, on } from './misc/util';
import isDeepEqual from './misc/isDeepEqual';
export interface BatteryState {
charging: boolean;
chargingTime: number;
dischargingTime: number;
level: number;
}
interface BatteryManager extends Readonly<BatteryState>, EventTarget {
onchargingchange: () => void;
onchargingtimechange: () => void;
ondischargingtimechange: () => void;
onlevelchange: () => void;
}
interface NavigatorWithPossibleBattery extends Navigator {
getBattery?: () => Promise<BatteryManager>;
}
type UseBatteryState =
| { isSupported: false } // Battery API is not supported
| { isSupported: true; fetched: false } // battery API supported but not fetched yet
| (BatteryState & { isSupported: true; fetched: true }); // battery API supported and fetched
const nav: NavigatorWithPossibleBattery | undefined = isNavigator ? navigator : undefined;
const isBatteryApiSupported = nav && typeof nav.getBattery === 'function';
function useBatteryMock(): UseBatteryState {
return { isSupported: false };
}
function useBattery(): UseBatteryState {
const [state, setState] = useState<UseBatteryState>({ isSupported: true, fetched: false });
useEffect(() => {
let isMounted = true;
let battery: BatteryManager | null = null;
const handleChange = () => {
if (!isMounted || !battery) {
return;
}
const newState: UseBatteryState = {
isSupported: true,
fetched: true,
level: battery.level,
charging: battery.charging,
dischargingTime: battery.dischargingTime,
chargingTime: battery.chargingTime,
};
!isDeepEqual(state, newState) && setState(newState);
};
nav!.getBattery!().then((bat: BatteryManager) => {
if (!isMounted) {
return;
}
battery = bat;
on(battery, 'chargingchange', handleChange);
on(battery, 'chargingtimechange', handleChange);
on(battery, 'dischargingtimechange', handleChange);
on(battery, 'levelchange', handleChange);
handleChange();
});
return () => {
isMounted = false;
if (battery) {
off(battery, 'chargingchange', handleChange);
off(battery, 'chargingtimechange', handleChange);
off(battery, 'dischargingtimechange', handleChange);
off(battery, 'levelchange', handleChange);
}
};
}, []);
return state;
}
export default isBatteryApiSupported ? useBattery : useBatteryMock;