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/lib/src/useSystemBar.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
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 (
|
|
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
|
-
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
|
|
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
|
-
|
|
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
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
156
|
+
type: "unknown",
|
|
157
|
+
isConnected: false,
|
|
158
|
+
isAirplaneMode: false,
|
|
159
|
+
ssid: null,
|
|
160
|
+
cellularGeneration: null,
|
|
170
161
|
});
|
|
171
162
|
(0, react_1.useEffect)(() => {
|
|
172
|
-
|
|
173
|
-
SystemBar.getAppCastInfo()
|
|
163
|
+
SystemBar.getNetworkInfo()
|
|
174
164
|
.then(setInfo)
|
|
175
165
|
.catch(() => { });
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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.
|
|
222
|
+
exports.useFontScale = useFontScale;
|
package/package.json
CHANGED
package/src/SystemBar.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
// ─────────────────────────────────────────────
|
|
2
2
|
// rn-system-bar · SystemBar.ts
|
|
3
|
-
//
|
|
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
|
-
|
|
11
|
-
|
|
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
|
|
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);
|
|
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
|
|
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
|
|
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
|
|
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
|
-
//
|
|
244
|
-
// Reads DisplayManager — detects any externally mirrored display.
|
|
219
|
+
// NETWORK
|
|
245
220
|
// ═══════════════════════════════════════════════
|
|
246
221
|
|
|
247
222
|
/**
|
|
248
|
-
* One-shot snapshot of
|
|
249
|
-
* Works on both Android (DisplayManager) and iOS (UIScreen.screens).
|
|
223
|
+
* One-shot snapshot of the current network state.
|
|
250
224
|
*/
|
|
251
|
-
export const
|
|
252
|
-
|
|
253
|
-
|
|
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
|
|
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
|
|
272
|
-
callback: (info:
|
|
234
|
+
export const onNetworkChange = (
|
|
235
|
+
callback: (info: NetworkInfo) => void,
|
|
273
236
|
): (() => void) => {
|
|
274
237
|
checkNative();
|
|
275
238
|
const { DeviceEventEmitter } = require("react-native");
|
|
276
|
-
Native.
|
|
239
|
+
Native.startNetworkListener();
|
|
277
240
|
const sub = DeviceEventEmitter.addListener(
|
|
278
|
-
"
|
|
241
|
+
"SystemBar_NetworkChange",
|
|
279
242
|
callback,
|
|
280
243
|
);
|
|
281
244
|
return () => {
|
|
282
245
|
sub.remove();
|
|
283
|
-
Native.
|
|
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
|
-
//
|
|
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
|
-
*
|
|
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
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
Native.startAppCastScan();
|
|
257
|
+
export const getBatteryInfo = (): Promise<BatteryInfo> => {
|
|
258
|
+
checkNative("getBatteryInfo");
|
|
259
|
+
return Native.getBatteryInfo();
|
|
312
260
|
};
|
|
313
261
|
|
|
314
262
|
/**
|
|
315
|
-
*
|
|
263
|
+
* Subscribe to battery level / state changes.
|
|
264
|
+
* @returns unsubscribe function
|
|
316
265
|
*/
|
|
317
|
-
export const
|
|
318
|
-
|
|
266
|
+
export const onBatteryChange = (
|
|
267
|
+
callback: (info: BatteryInfo) => void,
|
|
268
|
+
): (() => void) => {
|
|
319
269
|
checkNative();
|
|
320
|
-
|
|
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
|
-
|
|
325
|
-
|
|
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
|
-
*
|
|
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
|
|
338
|
-
if (!androidOnly("disconnectAppCast")) return;
|
|
292
|
+
export const haptic = (pattern: HapticPattern = "medium"): void => {
|
|
339
293
|
checkNative();
|
|
340
|
-
Native.
|
|
294
|
+
Native.haptic(pattern);
|
|
341
295
|
};
|
|
342
296
|
|
|
297
|
+
// ═══════════════════════════════════════════════
|
|
298
|
+
// SYSTEM SCREENCAST (external display / HDMI / Miracast / AirPlay)
|
|
299
|
+
// ═══════════════════════════════════════════════
|
|
300
|
+
|
|
343
301
|
/**
|
|
344
|
-
*
|
|
302
|
+
* One-shot snapshot of system-level external display state.
|
|
345
303
|
*/
|
|
346
|
-
export const
|
|
347
|
-
if (!
|
|
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
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
|
373
|
-
callback: (info:
|
|
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
|
-
"
|
|
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;
|