rn-system-bar 3.2.3 → 3.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +180 -650
- package/android/src/main/java/com/systembar/SystemBarModule.kt +0 -222
- package/index.ts +3 -2
- package/ios/SystemBarModule.m +1 -8
- package/ios/SystemBarModule.swift +55 -68
- package/lib/index.d.ts +2 -2
- package/lib/index.js +4 -2
- package/lib/src/SystemBar.d.ts +33 -64
- package/lib/src/SystemBar.js +95 -131
- package/lib/src/types.d.ts +43 -43
- package/lib/src/useSystemBar.d.ts +25 -24
- package/lib/src/useSystemBar.js +101 -69
- package/package.json +1 -1
- package/src/SystemBar.ts +111 -128
- package/src/types.ts +68 -51
- package/src/useSystemBar.ts +106 -135
package/src/types.ts
CHANGED
|
@@ -14,20 +14,17 @@ export type StatusBarStyle = "light" | "dark";
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Navigation bar color value.
|
|
17
|
-
*
|
|
18
|
-
* -
|
|
19
|
-
* - `"
|
|
20
|
-
* transparent color; content draws behind bar)
|
|
21
|
-
* - `"translucent"` → semi-transparent (FLAG_TRANSLUCENT_NAVIGATION)
|
|
17
|
+
* - Any hex string → solid colour e.g. "#1a1a2e"
|
|
18
|
+
* - `"transparent"` → fully transparent
|
|
19
|
+
* - `"translucent"` → semi-transparent
|
|
22
20
|
*/
|
|
23
21
|
export type NavigationBarColorValue = string | "transparent" | "translucent";
|
|
24
22
|
|
|
25
23
|
/**
|
|
26
24
|
* Status bar background color value.
|
|
27
|
-
*
|
|
28
|
-
* -
|
|
29
|
-
* - `"
|
|
30
|
-
* - `"translucent"` → semi-transparent
|
|
25
|
+
* - Any hex string → solid colour
|
|
26
|
+
* - `"transparent"` → fully transparent
|
|
27
|
+
* - `"translucent"` → semi-transparent
|
|
31
28
|
*/
|
|
32
29
|
export type StatusBarColorValue = string | "transparent" | "translucent";
|
|
33
30
|
|
|
@@ -35,19 +32,11 @@ export type StatusBarColorValue = string | "transparent" | "translucent";
|
|
|
35
32
|
// Theme
|
|
36
33
|
// ─────────────────────────────────────────────
|
|
37
34
|
|
|
38
|
-
/**
|
|
39
|
-
* "system" → follow the OS Appearance (dark/light).
|
|
40
|
-
* "dark" → force dark.
|
|
41
|
-
* "light" → force light.
|
|
42
|
-
*/
|
|
43
35
|
export type ThemeMode = "system" | "dark" | "light";
|
|
44
36
|
|
|
45
37
|
export interface ThemeState {
|
|
46
|
-
/** Resolved dark-mode flag. Always a concrete boolean. */
|
|
47
38
|
isDark: boolean;
|
|
48
|
-
/** Currently active override ("system" = following OS). */
|
|
49
39
|
mode: ThemeMode;
|
|
50
|
-
/** Set the override mode. Pass "system" to revert to OS. */
|
|
51
40
|
setMode: (mode: ThemeMode) => void;
|
|
52
41
|
}
|
|
53
42
|
|
|
@@ -66,7 +55,7 @@ export type VolumeStream =
|
|
|
66
55
|
| "system";
|
|
67
56
|
|
|
68
57
|
// ─────────────────────────────────────────────
|
|
69
|
-
// System screencast (external display / HDMI)
|
|
58
|
+
// System screencast (external display / HDMI / AirPlay)
|
|
70
59
|
// ─────────────────────────────────────────────
|
|
71
60
|
|
|
72
61
|
export interface ScreencastDisplay {
|
|
@@ -75,49 +64,77 @@ export interface ScreencastDisplay {
|
|
|
75
64
|
isValid: boolean;
|
|
76
65
|
}
|
|
77
66
|
|
|
78
|
-
/** Result of getSystemScreencastInfo() — physical/HDMI/Miracast external display. */
|
|
79
67
|
export interface SystemScreencastInfo {
|
|
80
68
|
isCasting: boolean;
|
|
81
69
|
displayName: string | null;
|
|
82
70
|
displays: ScreencastDisplay[];
|
|
83
71
|
}
|
|
84
72
|
|
|
73
|
+
/** @deprecated Use SystemScreencastInfo */
|
|
74
|
+
export interface ScreencastInfo extends SystemScreencastInfo {}
|
|
75
|
+
|
|
85
76
|
// ─────────────────────────────────────────────
|
|
86
|
-
//
|
|
77
|
+
// Network
|
|
87
78
|
// ─────────────────────────────────────────────
|
|
88
79
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
name: string;
|
|
103
|
-
/** Device description / model string (may be null). */
|
|
104
|
-
description: string | null;
|
|
105
|
-
/** Signal strength 0–100, or null if unavailable. */
|
|
106
|
-
signalStrength: number | null;
|
|
107
|
-
/** Whether a pairing/PIN step is required. */
|
|
108
|
-
requiresPairing: boolean;
|
|
80
|
+
export type NetworkType = "wifi" | "cellular" | "none" | "unknown";
|
|
81
|
+
|
|
82
|
+
export interface NetworkInfo {
|
|
83
|
+
/** Connection medium. */
|
|
84
|
+
type: NetworkType;
|
|
85
|
+
/** True when the device has an active internet connection. */
|
|
86
|
+
isConnected: boolean;
|
|
87
|
+
/** True when airplane mode is on (Android only; always false on iOS). */
|
|
88
|
+
isAirplaneMode: boolean;
|
|
89
|
+
/** Wi-Fi SSID — Android only, requires location permission; null on iOS. */
|
|
90
|
+
ssid: string | null;
|
|
91
|
+
/** Cellular generation e.g. "4g" | "5g" — Android only; null on iOS. */
|
|
92
|
+
cellularGeneration: string | null;
|
|
109
93
|
}
|
|
110
94
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
|
|
95
|
+
// ─────────────────────────────────────────────
|
|
96
|
+
// Battery
|
|
97
|
+
// ─────────────────────────────────────────────
|
|
98
|
+
|
|
99
|
+
export type BatteryState = "charging" | "discharging" | "full" | "unknown";
|
|
100
|
+
|
|
101
|
+
export interface BatteryInfo {
|
|
102
|
+
/** Battery level 0–100, or -1 if unknown. */
|
|
103
|
+
level: number;
|
|
104
|
+
state: BatteryState;
|
|
105
|
+
isCharging: boolean;
|
|
106
|
+
/** True when level ≤ 20 and not charging. */
|
|
107
|
+
isLow: boolean;
|
|
120
108
|
}
|
|
121
109
|
|
|
122
|
-
|
|
123
|
-
|
|
110
|
+
// ─────────────────────────────────────────────
|
|
111
|
+
// Haptics
|
|
112
|
+
// ─────────────────────────────────────────────
|
|
113
|
+
|
|
114
|
+
export type HapticPattern =
|
|
115
|
+
| "light"
|
|
116
|
+
| "medium"
|
|
117
|
+
| "heavy"
|
|
118
|
+
| "success"
|
|
119
|
+
| "warning"
|
|
120
|
+
| "error"
|
|
121
|
+
| "selection";
|
|
122
|
+
|
|
123
|
+
// ─────────────────────────────────────────────
|
|
124
|
+
// Font Scale
|
|
125
|
+
// ─────────────────────────────────────────────
|
|
126
|
+
|
|
127
|
+
export interface FontScaleInfo {
|
|
128
|
+
/**
|
|
129
|
+
* System font scale multiplier (1.0 = default).
|
|
130
|
+
* Android: from Configuration.fontScale.
|
|
131
|
+
* iOS: derived from UIContentSizeCategory.
|
|
132
|
+
*/
|
|
133
|
+
fontScale: number;
|
|
134
|
+
/**
|
|
135
|
+
* Screen pixel density.
|
|
136
|
+
* Android: DisplayMetrics.density.
|
|
137
|
+
* iOS: UIScreen.main.scale.
|
|
138
|
+
*/
|
|
139
|
+
density: number;
|
|
140
|
+
}
|
package/src/useSystemBar.ts
CHANGED
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
// rn-system-bar · useSystemBar.ts
|
|
3
3
|
// ─────────────────────────────────────────────
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { useEffect, useState } from "react";
|
|
6
6
|
import * as SystemBar from "./SystemBar";
|
|
7
7
|
import type {
|
|
8
|
-
|
|
8
|
+
BatteryInfo,
|
|
9
|
+
FontScaleInfo,
|
|
9
10
|
NavigationBarBehavior,
|
|
10
11
|
NavigationBarButtonStyle,
|
|
11
12
|
NavigationBarColorValue,
|
|
12
13
|
NavigationBarStyle,
|
|
13
14
|
NavigationBarVisibility,
|
|
15
|
+
NetworkInfo,
|
|
14
16
|
Orientation,
|
|
15
17
|
ScreencastInfo,
|
|
16
18
|
StatusBarColorValue,
|
|
@@ -37,7 +39,6 @@ export interface SystemBarConfig {
|
|
|
37
39
|
statusBarColor?: StatusBarColorValue;
|
|
38
40
|
statusBarStyle?: StatusBarStyle;
|
|
39
41
|
statusBarVisible?: boolean;
|
|
40
|
-
statusBarAnimated?: boolean;
|
|
41
42
|
|
|
42
43
|
// Screen
|
|
43
44
|
keepScreenOn?: boolean;
|
|
@@ -61,75 +62,46 @@ export interface SystemBarConfig {
|
|
|
61
62
|
// ─────────────────────────────────────────────
|
|
62
63
|
|
|
63
64
|
export const useSystemBar = (config: SystemBarConfig): void => {
|
|
64
|
-
const configRef = useRef("");
|
|
65
65
|
const configStr = JSON.stringify(config);
|
|
66
66
|
|
|
67
67
|
useEffect(() => {
|
|
68
|
-
if (
|
|
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
|
-
if (config.orientation !== undefined)
|
|
95
|
-
SystemBar.setOrientation(config.orientation);
|
|
96
|
-
if (config.secureScreen !== undefined)
|
|
97
|
-
SystemBar.setSecureScreen(config.secureScreen);
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
apply().catch(() => {
|
|
101
|
-
if (__DEV__)
|
|
102
|
-
console.warn(
|
|
103
|
-
"[rn-system-bar] useSystemBar: one or more settings failed.",
|
|
104
|
-
);
|
|
105
|
-
});
|
|
68
|
+
if (config.navigationBarColor !== undefined)
|
|
69
|
+
SystemBar.setNavigationBarColor(config.navigationBarColor);
|
|
70
|
+
if (config.navigationBarVisibility !== undefined)
|
|
71
|
+
SystemBar.setNavigationBarVisibility(config.navigationBarVisibility);
|
|
72
|
+
if (config.navigationBarButtonStyle !== undefined)
|
|
73
|
+
SystemBar.setNavigationBarButtonStyle(config.navigationBarButtonStyle);
|
|
74
|
+
if (config.navigationBarStyle !== undefined)
|
|
75
|
+
SystemBar.setNavigationBarStyle(config.navigationBarStyle);
|
|
76
|
+
if (config.navigationBarBehavior !== undefined)
|
|
77
|
+
SystemBar.setNavigationBarBehavior(config.navigationBarBehavior);
|
|
78
|
+
if (config.statusBarColor !== undefined)
|
|
79
|
+
SystemBar.setStatusBarColor(config.statusBarColor);
|
|
80
|
+
if (config.statusBarStyle !== undefined)
|
|
81
|
+
SystemBar.setStatusBarStyle(config.statusBarStyle);
|
|
82
|
+
if (config.statusBarVisible !== undefined)
|
|
83
|
+
SystemBar.setStatusBarVisibility(config.statusBarVisible);
|
|
84
|
+
if (config.keepScreenOn !== undefined)
|
|
85
|
+
SystemBar.keepScreenOn(config.keepScreenOn);
|
|
86
|
+
if (config.immersiveMode !== undefined)
|
|
87
|
+
SystemBar.immersiveMode(config.immersiveMode);
|
|
88
|
+
if (config.brightness !== undefined)
|
|
89
|
+
SystemBar.setBrightness(config.brightness);
|
|
90
|
+
if (config.orientation !== undefined)
|
|
91
|
+
SystemBar.setOrientation(config.orientation);
|
|
92
|
+
if (config.secureScreen !== undefined)
|
|
93
|
+
SystemBar.setSecureScreen(config.secureScreen);
|
|
106
94
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
107
95
|
}, [configStr]);
|
|
108
96
|
};
|
|
109
97
|
|
|
110
98
|
// ─────────────────────────────────────────────
|
|
111
99
|
// ThemedSystemBarConfig + useThemeSystemBar
|
|
112
|
-
//
|
|
113
|
-
// Combines useTheme() + useSystemBar() — nav/status bars
|
|
114
|
-
// automatically update whenever the theme changes (OS or manual).
|
|
115
|
-
//
|
|
116
|
-
// @example
|
|
117
|
-
// const { isDark, mode, setMode } = useThemeSystemBar({
|
|
118
|
-
// dark: { navigationBarColor: "#000000", statusBarStyle: "light" },
|
|
119
|
-
// light: { navigationBarColor: "#ffffff", statusBarStyle: "dark" },
|
|
120
|
-
// base: { keepScreenOn: true },
|
|
121
|
-
// });
|
|
122
100
|
// ─────────────────────────────────────────────
|
|
123
101
|
|
|
124
102
|
export interface ThemedSystemBarConfig {
|
|
125
|
-
/** Config applied when the resolved theme is DARK. */
|
|
126
103
|
dark?: SystemBarConfig;
|
|
127
|
-
/** Config applied when the resolved theme is LIGHT. */
|
|
128
104
|
light?: SystemBarConfig;
|
|
129
|
-
/**
|
|
130
|
-
* Static config merged under both themes.
|
|
131
|
-
* Theme-specific (dark/light) values always win.
|
|
132
|
-
*/
|
|
133
105
|
base?: SystemBarConfig;
|
|
134
106
|
}
|
|
135
107
|
|
|
@@ -157,12 +129,6 @@ export type { ThemeMode, ThemeState };
|
|
|
157
129
|
|
|
158
130
|
// ─────────────────────────────────────────────
|
|
159
131
|
// useSystemScreencast
|
|
160
|
-
// Tracks OS-level external display state.
|
|
161
|
-
// Android: DisplayManager (HDMI / Miracast / Presentation display).
|
|
162
|
-
// iOS: UIScreen.screens (AirPlay mirror).
|
|
163
|
-
//
|
|
164
|
-
// @example
|
|
165
|
-
// const { isCasting, displayName, displays } = useSystemScreencast();
|
|
166
132
|
// ─────────────────────────────────────────────
|
|
167
133
|
|
|
168
134
|
export const useSystemScreencast = (): SystemScreencastInfo => {
|
|
@@ -183,9 +149,8 @@ export const useSystemScreencast = (): SystemScreencastInfo => {
|
|
|
183
149
|
return info;
|
|
184
150
|
};
|
|
185
151
|
|
|
186
|
-
/** @deprecated
|
|
187
|
-
|
|
188
|
-
export const useScreencast = () => {
|
|
152
|
+
/** @deprecated Use useSystemScreencast() */
|
|
153
|
+
export const useScreencast = (): ScreencastInfo => {
|
|
189
154
|
const [info, setInfo] = useState<ScreencastInfo>({
|
|
190
155
|
isCasting: false,
|
|
191
156
|
displayName: null,
|
|
@@ -193,7 +158,6 @@ export const useScreencast = () => {
|
|
|
193
158
|
});
|
|
194
159
|
|
|
195
160
|
useEffect(() => {
|
|
196
|
-
// Guard: if method doesn't exist on native module, bail silently
|
|
197
161
|
SystemBar.getScreencastInfo()
|
|
198
162
|
.then(setInfo)
|
|
199
163
|
.catch(() => {
|
|
@@ -202,13 +166,10 @@ export const useScreencast = () => {
|
|
|
202
166
|
"[rn-system-bar] getSystemScreencastInfo not available. Rebuild native.",
|
|
203
167
|
);
|
|
204
168
|
});
|
|
205
|
-
|
|
206
169
|
let unsub: (() => void) | undefined;
|
|
207
170
|
try {
|
|
208
171
|
unsub = SystemBar.onScreencastChange(setInfo);
|
|
209
|
-
} catch {
|
|
210
|
-
// native listener not available
|
|
211
|
-
}
|
|
172
|
+
} catch {}
|
|
212
173
|
return () => unsub?.();
|
|
213
174
|
}, []);
|
|
214
175
|
|
|
@@ -216,79 +177,89 @@ export const useScreencast = () => {
|
|
|
216
177
|
};
|
|
217
178
|
|
|
218
179
|
// ─────────────────────────────────────────────
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
// In-app device discovery + casting via Android MediaRouter.
|
|
222
|
-
// Mirrors ONLY this app's screen — NOT the whole system.
|
|
223
|
-
// iOS always returns idle (AirPlay is system-managed, no public API).
|
|
224
|
-
//
|
|
225
|
-
// Flow:
|
|
226
|
-
// 1. Mount the component — calls getAppCastInfo() for initial state
|
|
227
|
-
// 2. call scan() → state = "scanning", devices populate
|
|
228
|
-
// 3. call connect(device.id) → state = "connecting" → "connected"
|
|
229
|
-
// 4. call disconnect() → state = "disconnecting" → "idle"
|
|
230
|
-
// 5. Unmount → scan auto-stopped (battery safe)
|
|
231
|
-
//
|
|
232
|
-
// @example
|
|
233
|
-
// const { state, devices, connectedDevice, error,
|
|
234
|
-
// scan, stopScan, connect, disconnect } = useAppCast();
|
|
235
|
-
//
|
|
236
|
-
// <Button title="Find TVs" onPress={scan} />
|
|
237
|
-
// {devices.map(d => (
|
|
238
|
-
// <Button key={d.id} title={`Cast to ${d.name}`}
|
|
239
|
-
// onPress={() => connect(d.id)} />
|
|
240
|
-
// ))}
|
|
241
|
-
// {connectedDevice && (
|
|
242
|
-
// <Button title="Stop casting" onPress={disconnect} />
|
|
243
|
-
// )}
|
|
180
|
+
// useNetwork
|
|
244
181
|
// ─────────────────────────────────────────────
|
|
245
182
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
export const useAppCast = (): UseAppCastReturn => {
|
|
262
|
-
const [info, setInfo] = useState<AppCastInfo>({
|
|
263
|
-
state: "idle",
|
|
264
|
-
devices: [],
|
|
265
|
-
connectedDevice: null,
|
|
266
|
-
error: null,
|
|
183
|
+
/**
|
|
184
|
+
* Subscribe to network state. Fires immediately with the current snapshot,
|
|
185
|
+
* then on every connectivity change.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* const { isConnected, type } = useNetwork();
|
|
189
|
+
*/
|
|
190
|
+
export const useNetwork = (): NetworkInfo => {
|
|
191
|
+
const [info, setInfo] = useState<NetworkInfo>({
|
|
192
|
+
type: "unknown",
|
|
193
|
+
isConnected: false,
|
|
194
|
+
isAirplaneMode: false,
|
|
195
|
+
ssid: null,
|
|
196
|
+
cellularGeneration: null,
|
|
267
197
|
});
|
|
268
198
|
|
|
269
199
|
useEffect(() => {
|
|
270
|
-
|
|
271
|
-
SystemBar.getAppCastInfo()
|
|
200
|
+
SystemBar.getNetworkInfo()
|
|
272
201
|
.then(setInfo)
|
|
273
202
|
.catch(() => {});
|
|
203
|
+
const unsub = SystemBar.onNetworkChange(setInfo);
|
|
204
|
+
return () => unsub();
|
|
205
|
+
}, []);
|
|
274
206
|
|
|
275
|
-
|
|
276
|
-
|
|
207
|
+
return info;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
// ─────────────────────────────────────────────
|
|
211
|
+
// useBattery
|
|
212
|
+
// ─────────────────────────────────────────────
|
|
277
213
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
214
|
+
/**
|
|
215
|
+
* Subscribe to battery state. Fires immediately with the current snapshot,
|
|
216
|
+
* then on every level / state change.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* const { level, isCharging, isLow } = useBattery();
|
|
220
|
+
*/
|
|
221
|
+
export const useBattery = (): BatteryInfo => {
|
|
222
|
+
const [info, setInfo] = useState<BatteryInfo>({
|
|
223
|
+
level: -1,
|
|
224
|
+
state: "unknown",
|
|
225
|
+
isCharging: false,
|
|
226
|
+
isLow: false,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
useEffect(() => {
|
|
230
|
+
SystemBar.getBatteryInfo()
|
|
231
|
+
.then(setInfo)
|
|
232
|
+
.catch(() => {});
|
|
233
|
+
const unsub = SystemBar.onBatteryChange(setInfo);
|
|
234
|
+
return () => unsub();
|
|
283
235
|
}, []);
|
|
284
236
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
237
|
+
return info;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
// ─────────────────────────────────────────────
|
|
241
|
+
// useFontScale
|
|
242
|
+
// ─────────────────────────────────────────────
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Subscribe to system font scale changes (accessibility text size).
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* const { fontScale, density } = useFontScale();
|
|
249
|
+
*/
|
|
250
|
+
export const useFontScale = (): FontScaleInfo => {
|
|
251
|
+
const [info, setInfo] = useState<FontScaleInfo>({
|
|
252
|
+
fontScale: 1,
|
|
253
|
+
density: 1,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
useEffect(() => {
|
|
257
|
+
SystemBar.getFontScaleInfo()
|
|
258
|
+
.then(setInfo)
|
|
259
|
+
.catch(() => {});
|
|
260
|
+
const unsub = SystemBar.onFontScaleChange(setInfo);
|
|
261
|
+
return () => unsub();
|
|
262
|
+
}, []);
|
|
292
263
|
|
|
293
|
-
return
|
|
264
|
+
return info;
|
|
294
265
|
};
|