rn-system-bar 3.2.3 → 3.2.5

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.
@@ -36,7 +36,7 @@ var __importStar = (this && this.__importStar) || (function () {
36
36
  };
37
37
  })();
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.useAppCast = exports.useScreencast = exports.useSystemScreencast = exports.useTheme = exports.useThemeSystemBar = exports.useSystemBar = void 0;
39
+ exports.useFontScale = exports.useBattery = exports.useNetwork = exports.useScreencast = exports.useSystemScreencast = exports.useTheme = exports.useThemeSystemBar = exports.useSystemBar = void 0;
40
40
  const react_1 = require("react");
41
41
  const SystemBar = __importStar(require("./SystemBar"));
42
42
  const useTheme_1 = require("./useTheme");
@@ -53,44 +53,34 @@ const useTheme_1 = require("./useTheme");
53
53
  // });
54
54
  // ─────────────────────────────────────────────
55
55
  const useSystemBar = (config) => {
56
- const configRef = (0, react_1.useRef)("");
57
56
  const configStr = JSON.stringify(config);
58
57
  (0, react_1.useEffect)(() => {
59
- if (configRef.current === configStr)
60
- return;
61
- configRef.current = configStr;
62
- const apply = async () => {
63
- if (config.navigationBarColor !== undefined)
64
- SystemBar.setNavigationBarColor(config.navigationBarColor);
65
- if (config.navigationBarVisibility !== undefined)
66
- SystemBar.setNavigationBarVisibility(config.navigationBarVisibility);
67
- if (config.navigationBarButtonStyle !== undefined)
68
- SystemBar.setNavigationBarButtonStyle(config.navigationBarButtonStyle);
69
- if (config.navigationBarStyle !== undefined)
70
- SystemBar.setNavigationBarStyle(config.navigationBarStyle);
71
- if (config.navigationBarBehavior !== undefined)
72
- SystemBar.setNavigationBarBehavior(config.navigationBarBehavior);
73
- if (config.statusBarColor !== undefined)
74
- SystemBar.setStatusBarColor(config.statusBarColor);
75
- if (config.statusBarStyle !== undefined)
76
- SystemBar.setStatusBarStyle(config.statusBarStyle);
77
- if (config.statusBarVisible !== undefined)
78
- SystemBar.setStatusBarVisibility(config.statusBarVisible);
79
- if (config.keepScreenOn !== undefined)
80
- SystemBar.keepScreenOn(config.keepScreenOn);
81
- if (config.immersiveMode !== undefined)
82
- SystemBar.immersiveMode(config.immersiveMode);
83
- if (config.brightness !== undefined)
84
- SystemBar.setBrightness(config.brightness);
85
- if (config.orientation !== undefined)
86
- SystemBar.setOrientation(config.orientation);
87
- if (config.secureScreen !== undefined)
88
- SystemBar.setSecureScreen(config.secureScreen);
89
- };
90
- apply().catch(() => {
91
- if (__DEV__)
92
- console.warn("[rn-system-bar] useSystemBar: one or more settings failed.");
93
- });
58
+ if (config.navigationBarColor !== undefined)
59
+ SystemBar.setNavigationBarColor(config.navigationBarColor);
60
+ if (config.navigationBarVisibility !== undefined)
61
+ SystemBar.setNavigationBarVisibility(config.navigationBarVisibility);
62
+ if (config.navigationBarButtonStyle !== undefined)
63
+ SystemBar.setNavigationBarButtonStyle(config.navigationBarButtonStyle);
64
+ if (config.navigationBarStyle !== undefined)
65
+ SystemBar.setNavigationBarStyle(config.navigationBarStyle);
66
+ if (config.navigationBarBehavior !== undefined)
67
+ SystemBar.setNavigationBarBehavior(config.navigationBarBehavior);
68
+ if (config.statusBarColor !== undefined)
69
+ SystemBar.setStatusBarColor(config.statusBarColor);
70
+ if (config.statusBarStyle !== undefined)
71
+ SystemBar.setStatusBarStyle(config.statusBarStyle);
72
+ if (config.statusBarVisible !== undefined)
73
+ SystemBar.setStatusBarVisibility(config.statusBarVisible);
74
+ if (config.keepScreenOn !== undefined)
75
+ SystemBar.keepScreenOn(config.keepScreenOn);
76
+ if (config.immersiveMode !== undefined)
77
+ SystemBar.immersiveMode(config.immersiveMode);
78
+ if (config.brightness !== undefined)
79
+ SystemBar.setBrightness(config.brightness);
80
+ if (config.orientation !== undefined)
81
+ SystemBar.setOrientation(config.orientation);
82
+ if (config.secureScreen !== undefined)
83
+ SystemBar.setSecureScreen(config.secureScreen);
94
84
  // eslint-disable-next-line react-hooks/exhaustive-deps
95
85
  }, [configStr]);
96
86
  };
@@ -110,12 +100,6 @@ var useTheme_2 = require("./useTheme");
110
100
  Object.defineProperty(exports, "useTheme", { enumerable: true, get: function () { return useTheme_2.useTheme; } });
111
101
  // ─────────────────────────────────────────────
112
102
  // useSystemScreencast
113
- // Tracks OS-level external display state.
114
- // Android: DisplayManager (HDMI / Miracast / Presentation display).
115
- // iOS: UIScreen.screens (AirPlay mirror).
116
- //
117
- // @example
118
- // const { isCasting, displayName, displays } = useSystemScreencast();
119
103
  // ─────────────────────────────────────────────
120
104
  const useSystemScreencast = () => {
121
105
  const [info, setInfo] = (0, react_1.useState)({
@@ -133,8 +117,7 @@ const useSystemScreencast = () => {
133
117
  return info;
134
118
  };
135
119
  exports.useSystemScreencast = useSystemScreencast;
136
- /** @deprecated Renamed to useSystemScreencast() */
137
- // useSystemBar.ts — useScreencast
120
+ /** @deprecated Use useSystemScreencast() */
138
121
  const useScreencast = () => {
139
122
  const [info, setInfo] = (0, react_1.useState)({
140
123
  isCasting: false,
@@ -142,7 +125,6 @@ const useScreencast = () => {
142
125
  displays: [],
143
126
  });
144
127
  (0, react_1.useEffect)(() => {
145
- // Guard: if method doesn't exist on native module, bail silently
146
128
  SystemBar.getScreencastInfo()
147
129
  .then(setInfo)
148
130
  .catch(() => {
@@ -153,38 +135,88 @@ const useScreencast = () => {
153
135
  try {
154
136
  unsub = SystemBar.onScreencastChange(setInfo);
155
137
  }
156
- catch (_a) {
157
- // native listener not available
158
- }
138
+ catch (_a) { }
159
139
  return () => unsub === null || unsub === void 0 ? void 0 : unsub();
160
140
  }, []);
161
141
  return info;
162
142
  };
163
143
  exports.useScreencast = useScreencast;
164
- const useAppCast = () => {
144
+ // ─────────────────────────────────────────────
145
+ // useNetwork
146
+ // ─────────────────────────────────────────────
147
+ /**
148
+ * Subscribe to network state. Fires immediately with the current snapshot,
149
+ * then on every connectivity change.
150
+ *
151
+ * @example
152
+ * const { isConnected, type } = useNetwork();
153
+ */
154
+ const useNetwork = () => {
165
155
  const [info, setInfo] = (0, react_1.useState)({
166
- state: "idle",
167
- devices: [],
168
- connectedDevice: null,
169
- error: null,
156
+ type: "unknown",
157
+ isConnected: false,
158
+ isAirplaneMode: false,
159
+ ssid: null,
160
+ cellularGeneration: null,
170
161
  });
171
162
  (0, react_1.useEffect)(() => {
172
- // Sync initial state
173
- SystemBar.getAppCastInfo()
163
+ SystemBar.getNetworkInfo()
174
164
  .then(setInfo)
175
165
  .catch(() => { });
176
- // Subscribe to all cast events (device found/lost, state changes, errors)
177
- const unsub = SystemBar.onAppCastChange(setInfo);
178
- return () => {
179
- unsub();
180
- // Auto-stop scan on unmount — avoids background battery drain
181
- SystemBar.stopAppCastScan();
182
- };
166
+ const unsub = SystemBar.onNetworkChange(setInfo);
167
+ return () => unsub();
183
168
  }, []);
184
- const scan = (0, react_1.useCallback)(() => SystemBar.startAppCastScan(), []);
185
- const stopScan = (0, react_1.useCallback)(() => SystemBar.stopAppCastScan(), []);
186
- const connect = (0, react_1.useCallback)((id, pin) => SystemBar.connectAppCast(id, pin), []);
187
- const disconnect = (0, react_1.useCallback)(() => SystemBar.disconnectAppCast(), []);
188
- return Object.assign(Object.assign({}, info), { scan, stopScan, connect, disconnect });
169
+ return info;
170
+ };
171
+ exports.useNetwork = useNetwork;
172
+ // ─────────────────────────────────────────────
173
+ // useBattery
174
+ // ─────────────────────────────────────────────
175
+ /**
176
+ * Subscribe to battery state. Fires immediately with the current snapshot,
177
+ * then on every level / state change.
178
+ *
179
+ * @example
180
+ * const { level, isCharging, isLow } = useBattery();
181
+ */
182
+ const useBattery = () => {
183
+ const [info, setInfo] = (0, react_1.useState)({
184
+ level: -1,
185
+ state: "unknown",
186
+ isCharging: false,
187
+ isLow: false,
188
+ });
189
+ (0, react_1.useEffect)(() => {
190
+ SystemBar.getBatteryInfo()
191
+ .then(setInfo)
192
+ .catch(() => { });
193
+ const unsub = SystemBar.onBatteryChange(setInfo);
194
+ return () => unsub();
195
+ }, []);
196
+ return info;
197
+ };
198
+ exports.useBattery = useBattery;
199
+ // ─────────────────────────────────────────────
200
+ // useFontScale
201
+ // ─────────────────────────────────────────────
202
+ /**
203
+ * Subscribe to system font scale changes (accessibility text size).
204
+ *
205
+ * @example
206
+ * const { fontScale, density } = useFontScale();
207
+ */
208
+ const useFontScale = () => {
209
+ const [info, setInfo] = (0, react_1.useState)({
210
+ fontScale: 1,
211
+ density: 1,
212
+ });
213
+ (0, react_1.useEffect)(() => {
214
+ SystemBar.getFontScaleInfo()
215
+ .then(setInfo)
216
+ .catch(() => { });
217
+ const unsub = SystemBar.onFontScaleChange(setInfo);
218
+ return () => unsub();
219
+ }, []);
220
+ return info;
189
221
  };
190
- exports.useAppCast = useAppCast;
222
+ exports.useFontScale = useFontScale;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rn-system-bar",
3
- "version": "3.2.3",
3
+ "version": "3.2.5",
4
4
  "description": "Control Android & iOS system bars, brightness, volume, orientation and screen flags from React Native.",
5
5
  "main": "lib/index.js",
6
6
  "react-native": "lib/index.js",
package/src/SystemBar.ts CHANGED
@@ -1,19 +1,20 @@
1
1
  // ─────────────────────────────────────────────
2
2
  // rn-system-bar · SystemBar.ts
3
- // Zero expo-navigation-bar dependency.
4
- // All APIs → native Kotlin / iOS Swift.
3
+ // All APIs → native Kotlin (Android) / Swift (iOS)
5
4
  // ─────────────────────────────────────────────
6
5
 
7
6
  import { NativeModules, Platform } from "react-native";
8
7
 
9
8
  import type {
10
- AppCastInfo,
11
- AppCastState,
9
+ BatteryInfo,
10
+ FontScaleInfo,
11
+ HapticPattern,
12
12
  NavigationBarBehavior,
13
13
  NavigationBarButtonStyle,
14
14
  NavigationBarColorValue,
15
15
  NavigationBarStyle,
16
16
  NavigationBarVisibility,
17
+ NetworkInfo,
17
18
  Orientation,
18
19
  StatusBarColorValue,
19
20
  StatusBarStyle,
@@ -46,33 +47,15 @@ const checkNative = (method?: string) => {
46
47
  };
47
48
 
48
49
  // ═══════════════════════════════════════════════
49
- // NAVIGATION BAR (Android — 100% native)
50
+ // NAVIGATION BAR (Android only)
50
51
  // ═══════════════════════════════════════════════
51
52
 
52
- /**
53
- * Set the navigation bar background colour.
54
- *
55
- * @param color
56
- * - Any hex string → solid colour e.g. `"#1a1a2e"`
57
- * - `"transparent"` → fully transparent (content draws behind bar)
58
- * - `"translucent"` → semi-transparent (system scrim over content)
59
- *
60
- * @example
61
- * setNavigationBarColor("#000000"); // solid black
62
- * setNavigationBarColor("transparent"); // glass / edge-to-edge
63
- * setNavigationBarColor("translucent"); // frosted glass
64
- */
65
53
  export const setNavigationBarColor = (color: NavigationBarColorValue): void => {
66
54
  if (!androidOnly("setNavigationBarColor")) return;
67
55
  checkNative();
68
- Native.setNavigationBarColor(color); // Kotlin handles the special values
56
+ Native.setNavigationBarColor(color);
69
57
  };
70
58
 
71
- /**
72
- * Hide or show the navigation bar.
73
- *
74
- * @param mode `"visible"` | `"hidden"`
75
- */
76
59
  export const setNavigationBarVisibility = (
77
60
  mode: NavigationBarVisibility,
78
61
  ): void => {
@@ -104,17 +87,9 @@ export const setNavigationBarBehavior = (
104
87
  };
105
88
 
106
89
  // ═══════════════════════════════════════════════
107
- // STATUS BAR (native — no RN StatusBar)
90
+ // STATUS BAR
108
91
  // ═══════════════════════════════════════════════
109
92
 
110
- /**
111
- * Set the status bar background colour (Android only).
112
- *
113
- * @param color
114
- * - Any hex string → solid colour
115
- * - `"transparent"` → fully transparent
116
- * - `"translucent"` → semi-transparent
117
- */
118
93
  export const setStatusBarColor = (color: StatusBarColorValue): void => {
119
94
  if (!androidOnly("setStatusBarColor")) return;
120
95
  checkNative();
@@ -146,7 +121,8 @@ export const getBrightness = (): Promise<number> => {
146
121
  };
147
122
 
148
123
  /**
149
- * Subscribe to system brightness changes (polls every 500 ms on Android).
124
+ * Subscribe to system brightness changes.
125
+ * Android: polls every 500 ms. iOS: UIScreen brightness.
150
126
  * @returns unsubscribe function
151
127
  */
152
128
  export const onBrightnessChange = (
@@ -189,7 +165,7 @@ export const setVolumeHUDVisible = (visible: boolean): void => {
189
165
  };
190
166
 
191
167
  /**
192
- * Subscribe to system volume changes (hardware buttons, other apps).
168
+ * Subscribe to system volume changes.
193
169
  * @returns unsubscribe function
194
170
  */
195
171
  export const onVolumeChange = (
@@ -240,155 +216,162 @@ export const setOrientation = (mode: Orientation): void => {
240
216
  };
241
217
 
242
218
  // ═══════════════════════════════════════════════
243
- // SYSTEM SCREENCAST (external display / HDMI / Miracast)
244
- // Reads DisplayManager — detects any externally mirrored display.
219
+ // NETWORK
245
220
  // ═══════════════════════════════════════════════
246
221
 
247
222
  /**
248
- * One-shot snapshot of system-level external display state.
249
- * Works on both Android (DisplayManager) and iOS (UIScreen.screens).
223
+ * One-shot snapshot of the current network state.
250
224
  */
251
- export const getSystemScreencastInfo = (): Promise<SystemScreencastInfo> => {
252
- if (!Native || typeof Native.getSystemScreencastInfo !== "function") {
253
- if (__DEV__)
254
- console.warn(
255
- "[rn-system-bar] getSystemScreencastInfo not available on this build.",
256
- );
257
- return Promise.resolve({
258
- isCasting: false,
259
- displayName: null,
260
- displays: [],
261
- });
262
- }
263
- return Native.getSystemScreencastInfo();
225
+ export const getNetworkInfo = (): Promise<NetworkInfo> => {
226
+ checkNative("getNetworkInfo");
227
+ return Native.getNetworkInfo();
264
228
  };
265
229
 
266
230
  /**
267
- * Subscribe to system external-display changes.
268
- * Fires when an HDMI / Miracast / AirPlay display connects or disconnects.
231
+ * Subscribe to network changes (connectivity, type).
269
232
  * @returns unsubscribe function
270
233
  */
271
- export const onSystemScreencastChange = (
272
- callback: (info: SystemScreencastInfo) => void,
234
+ export const onNetworkChange = (
235
+ callback: (info: NetworkInfo) => void,
273
236
  ): (() => void) => {
274
237
  checkNative();
275
238
  const { DeviceEventEmitter } = require("react-native");
276
- Native.startSystemScreencastListener();
239
+ Native.startNetworkListener();
277
240
  const sub = DeviceEventEmitter.addListener(
278
- "SystemBar_SystemScreencastChange",
241
+ "SystemBar_NetworkChange",
279
242
  callback,
280
243
  );
281
244
  return () => {
282
245
  sub.remove();
283
- Native.stopSystemScreencastListener();
246
+ Native.stopNetworkListener();
284
247
  };
285
248
  };
286
249
 
287
- // ─────────────────────────────────────────────
288
- // Legacy aliases (backward compat)
289
- // ─────────────────────────────────────────────
290
- /** @deprecated Use getSystemScreencastInfo() */
291
- export const getScreencastInfo = getSystemScreencastInfo;
292
- /** @deprecated Use onSystemScreencastChange() */
293
- export const onScreencastChange = onSystemScreencastChange;
294
-
295
250
  // ═══════════════════════════════════════════════
296
- // APP-ONLY CAST (MediaRouter — Chromecast / TV)
297
- // Mirrors only this app's screen — NOT the whole system.
298
- // Flow: startAppCastScan() → onAppCastChange (devices arrive)
299
- // → connectAppCast(deviceId) → onAppCastChange (state = "connected")
300
- // → disconnectAppCast()
251
+ // BATTERY
301
252
  // ═══════════════════════════════════════════════
302
253
 
303
254
  /**
304
- * Start scanning for nearby castable devices (Chromecast, TV, etc.).
305
- * Listen for results via `onAppCastChange`.
306
- * Android: uses MediaRouter. iOS: no-op (AirPlay is system-only).
255
+ * One-shot snapshot of the current battery state.
307
256
  */
308
- export const startAppCastScan = (): void => {
309
- if (!androidOnly("startAppCastScan")) return;
310
- checkNative();
311
- Native.startAppCastScan();
257
+ export const getBatteryInfo = (): Promise<BatteryInfo> => {
258
+ checkNative("getBatteryInfo");
259
+ return Native.getBatteryInfo();
312
260
  };
313
261
 
314
262
  /**
315
- * Stop the device discovery scan.
263
+ * Subscribe to battery level / state changes.
264
+ * @returns unsubscribe function
316
265
  */
317
- export const stopAppCastScan = (): void => {
318
- if (!androidOnly("stopAppCastScan")) return;
266
+ export const onBatteryChange = (
267
+ callback: (info: BatteryInfo) => void,
268
+ ): (() => void) => {
319
269
  checkNative();
320
- Native.stopAppCastScan();
270
+ const { DeviceEventEmitter } = require("react-native");
271
+ Native.startBatteryListener();
272
+ const sub = DeviceEventEmitter.addListener(
273
+ "SystemBar_BatteryChange",
274
+ callback,
275
+ );
276
+ return () => {
277
+ sub.remove();
278
+ Native.stopBatteryListener();
279
+ };
321
280
  };
322
281
 
323
- /**
324
- * Connect to a discovered device and begin casting this app's screen.
325
- * @param deviceId The `id` field from `AppCastDevice` (MediaRouter route ID).
326
- * @param pairingPin Optional PIN string if `requiresPairing` is true.
327
- */
328
- export const connectAppCast = (deviceId: string, pairingPin?: string): void => {
329
- if (!androidOnly("connectAppCast")) return;
330
- checkNative();
331
- Native.connectAppCast(deviceId, pairingPin ?? null);
332
- };
282
+ // ═══════════════════════════════════════════════
283
+ // HAPTICS
284
+ // ═══════════════════════════════════════════════
333
285
 
334
286
  /**
335
- * Disconnect the active in-app cast session.
287
+ * Trigger a haptic feedback pattern.
288
+ * iOS: UIFeedbackGenerator. Android: Vibrator.
289
+ *
290
+ * @param pattern "light" | "medium" | "heavy" | "success" | "warning" | "error" | "selection"
336
291
  */
337
- export const disconnectAppCast = (): void => {
338
- if (!androidOnly("disconnectAppCast")) return;
292
+ export const haptic = (pattern: HapticPattern = "medium"): void => {
339
293
  checkNative();
340
- Native.disconnectAppCast();
294
+ Native.haptic(pattern);
341
295
  };
342
296
 
297
+ // ═══════════════════════════════════════════════
298
+ // SYSTEM SCREENCAST (external display / HDMI / Miracast / AirPlay)
299
+ // ═══════════════════════════════════════════════
300
+
343
301
  /**
344
- * Get the current in-app cast snapshot (state + device list).
302
+ * One-shot snapshot of system-level external display state.
345
303
  */
346
- export const getAppCastInfo = (): Promise<AppCastInfo> => {
347
- if (!isAndroid) {
304
+ export const getSystemScreencastInfo = (): Promise<SystemScreencastInfo> => {
305
+ if (!Native || typeof Native.getSystemScreencastInfo !== "function") {
306
+ if (__DEV__)
307
+ console.warn(
308
+ "[rn-system-bar] getSystemScreencastInfo not available on this build.",
309
+ );
348
310
  return Promise.resolve({
349
- state: "idle" as AppCastState,
350
- devices: [],
351
- connectedDevice: null,
352
- error: null,
311
+ isCasting: false,
312
+ displayName: null,
313
+ displays: [],
353
314
  });
354
315
  }
316
+ return Native.getSystemScreencastInfo();
317
+ };
318
+
319
+ /**
320
+ * Subscribe to external-display connect / disconnect events.
321
+ * @returns unsubscribe function
322
+ */
323
+ export const onSystemScreencastChange = (
324
+ callback: (info: SystemScreencastInfo) => void,
325
+ ): (() => void) => {
355
326
  checkNative();
356
- return Native.getAppCastInfo();
327
+ const { DeviceEventEmitter } = require("react-native");
328
+ Native.startSystemScreencastListener();
329
+ const sub = DeviceEventEmitter.addListener(
330
+ "SystemBar_SystemScreencastChange",
331
+ callback,
332
+ );
333
+ return () => {
334
+ sub.remove();
335
+ Native.stopSystemScreencastListener();
336
+ };
357
337
  };
358
338
 
339
+ // ═══════════════════════════════════════════════
340
+ // FONT SCALE
341
+ // ═══════════════════════════════════════════════
342
+
359
343
  /**
360
- * Subscribe to in-app cast state changes.
361
- * Fires on: device discovered/lost, state changes (scanning → connecting → connected),
362
- * pairing requests, errors.
363
- *
364
- * @example
365
- * const unsub = onAppCastChange((info) => {
366
- * if (info.state === "connected") console.log("Casting to", info.connectedDevice?.name);
367
- * if (info.error) console.warn("Cast error:", info.error);
368
- * });
369
- *
344
+ * One-shot snapshot of the system font scale and screen density.
345
+ */
346
+ export const getFontScaleInfo = (): Promise<FontScaleInfo> => {
347
+ checkNative("getFontScaleInfo");
348
+ return Native.getFontScaleInfo();
349
+ };
350
+
351
+ /**
352
+ * Subscribe to font scale / accessibility text size changes.
370
353
  * @returns unsubscribe function
371
354
  */
372
- export const onAppCastChange = (
373
- callback: (info: AppCastInfo) => void,
355
+ export const onFontScaleChange = (
356
+ callback: (info: FontScaleInfo) => void,
374
357
  ): (() => void) => {
375
- if (!isAndroid) {
376
- // iOS: immediately call with idle state, return no-op
377
- callback({
378
- state: "idle",
379
- devices: [],
380
- connectedDevice: null,
381
- error: null,
382
- });
383
- return () => {};
384
- }
385
358
  checkNative();
386
359
  const { DeviceEventEmitter } = require("react-native");
360
+ Native.startFontScaleListener();
387
361
  const sub = DeviceEventEmitter.addListener(
388
- "SystemBar_AppCastChange",
362
+ "SystemBar_FontScaleChange",
389
363
  callback,
390
364
  );
391
365
  return () => {
392
366
  sub.remove();
367
+ Native.stopFontScaleListener();
393
368
  };
394
369
  };
370
+
371
+ // ─────────────────────────────────────────────
372
+ // Legacy aliases (backward compat)
373
+ // ─────────────────────────────────────────────
374
+ /** @deprecated Use getSystemScreencastInfo() */
375
+ export const getScreencastInfo = getSystemScreencastInfo;
376
+ /** @deprecated Use onSystemScreencastChange() */
377
+ export const onScreencastChange = onSystemScreencastChange;