rn-system-bar 3.1.7 → 3.2.0
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 +655 -125
- package/android/src/main/java/com/systembar/SystemBarModule.kt +288 -13
- package/index.ts +23 -2
- package/ios/SystemBarModule.m +13 -6
- package/ios/SystemBarModule.swift +44 -9
- package/lib/index.d.ts +3 -2
- package/lib/index.js +13 -2
- package/lib/specs/NativeSystemBar.d.ts +9 -0
- package/lib/src/SystemBar.d.ts +83 -5
- package/lib/src/SystemBar.js +172 -13
- package/lib/src/types.d.ts +61 -1
- package/lib/src/useSystemBar.d.ts +34 -3
- package/lib/src/useSystemBar.js +96 -6
- package/lib/src/useTheme.d.ts +24 -0
- package/lib/src/useTheme.js +81 -0
- package/package.json +3 -2
- package/specs/NativeSystemBar.ts +21 -6
- package/src/SystemBar.ts +209 -23
- package/src/types.ts +85 -1
- package/src/useSystemBar.ts +234 -26
- package/src/useTheme.ts +95 -0
package/specs/NativeSystemBar.ts
CHANGED
|
@@ -7,33 +7,48 @@ import type { TurboModule } from "react-native";
|
|
|
7
7
|
import { TurboModuleRegistry } from "react-native";
|
|
8
8
|
|
|
9
9
|
export interface Spec extends TurboModule {
|
|
10
|
-
// Navigation Bar (Android-only)
|
|
10
|
+
// ── Navigation Bar (Android-only) ──────────
|
|
11
|
+
// color: hex string | "transparent" | "translucent"
|
|
11
12
|
setNavigationBarColor(color: string): void;
|
|
12
13
|
setNavigationBarVisibility(mode: string): void;
|
|
13
14
|
setNavigationBarButtonStyle(style: string): void;
|
|
14
15
|
setNavigationBarStyle(style: string): void;
|
|
15
16
|
setNavigationBarBehavior(behavior: string): void;
|
|
16
17
|
|
|
17
|
-
// Status Bar
|
|
18
|
+
// ── Status Bar ─────────────────────────────
|
|
19
|
+
// color: hex string | "transparent" | "translucent"
|
|
18
20
|
setStatusBarColor(color: string): void;
|
|
19
21
|
setStatusBarStyle(style: string): void;
|
|
20
22
|
setStatusBarVisibility(visible: boolean): void;
|
|
21
23
|
|
|
22
|
-
// Brightness
|
|
24
|
+
// ── Brightness ─────────────────────────────
|
|
23
25
|
setBrightness(level: number): void;
|
|
24
26
|
getBrightness(): Promise<number>;
|
|
25
27
|
|
|
26
|
-
// Volume
|
|
28
|
+
// ── Volume ─────────────────────────────────
|
|
27
29
|
setVolume(level: number, stream: string): void;
|
|
28
30
|
getVolume(stream: string): Promise<number>;
|
|
29
31
|
setVolumeHUDVisible(visible: boolean): void;
|
|
30
32
|
|
|
31
|
-
// Screen
|
|
33
|
+
// ── Screen ─────────────────────────────────
|
|
32
34
|
keepScreenOn(enable: boolean): void;
|
|
33
35
|
immersiveMode(enable: boolean): void;
|
|
36
|
+
setSecureScreen(enable: boolean): void;
|
|
34
37
|
|
|
35
|
-
// Orientation
|
|
38
|
+
// ── Orientation ────────────────────────────
|
|
36
39
|
setOrientation(mode: string): void;
|
|
40
|
+
|
|
41
|
+
// ── System Screencast ──────────────────────
|
|
42
|
+
getSystemScreencastInfo(): Promise<Object>;
|
|
43
|
+
startSystemScreencastListener(): void;
|
|
44
|
+
stopSystemScreencastListener(): void;
|
|
45
|
+
|
|
46
|
+
// ── App-only Cast (Android only) ───────────
|
|
47
|
+
startAppCastScan(): void;
|
|
48
|
+
stopAppCastScan(): void;
|
|
49
|
+
connectAppCast(deviceId: string, pairingPin: string | null): void;
|
|
50
|
+
disconnectAppCast(): void;
|
|
51
|
+
getAppCastInfo(): Promise<Object>;
|
|
37
52
|
}
|
|
38
53
|
|
|
39
54
|
export default TurboModuleRegistry.getEnforcing<Spec>("SystemBar");
|
package/src/SystemBar.ts
CHANGED
|
@@ -7,13 +7,17 @@
|
|
|
7
7
|
import { NativeModules, Platform } from "react-native";
|
|
8
8
|
|
|
9
9
|
import type {
|
|
10
|
+
AppCastInfo,
|
|
11
|
+
AppCastState,
|
|
10
12
|
NavigationBarBehavior,
|
|
11
13
|
NavigationBarButtonStyle,
|
|
14
|
+
NavigationBarColorValue,
|
|
12
15
|
NavigationBarStyle,
|
|
13
16
|
NavigationBarVisibility,
|
|
14
17
|
Orientation,
|
|
15
|
-
|
|
18
|
+
StatusBarColorValue,
|
|
16
19
|
StatusBarStyle,
|
|
20
|
+
SystemScreencastInfo,
|
|
17
21
|
VolumeStream,
|
|
18
22
|
} from "./types";
|
|
19
23
|
|
|
@@ -23,33 +27,63 @@ const isAndroid = Platform.OS === "android";
|
|
|
23
27
|
|
|
24
28
|
const androidOnly = (name: string): boolean => {
|
|
25
29
|
if (!isAndroid) {
|
|
26
|
-
if (__DEV__)
|
|
30
|
+
if (__DEV__)
|
|
31
|
+
console.warn(`[rn-system-bar] ${name}() is Android-only, no-op on iOS.`);
|
|
27
32
|
return false;
|
|
28
33
|
}
|
|
29
34
|
return true;
|
|
30
35
|
};
|
|
31
36
|
|
|
32
|
-
const checkNative = () => {
|
|
33
|
-
if (!Native)
|
|
37
|
+
const checkNative = (method?: string) => {
|
|
38
|
+
if (!Native)
|
|
39
|
+
throw new Error(
|
|
40
|
+
"[rn-system-bar] Native module not found. Rebuild your project.",
|
|
41
|
+
);
|
|
42
|
+
if (method && typeof Native[method] !== "function")
|
|
43
|
+
throw new Error(
|
|
44
|
+
`[rn-system-bar] Native.${method} not found. Rebuild your project.`,
|
|
45
|
+
);
|
|
34
46
|
};
|
|
35
47
|
|
|
36
48
|
// ═══════════════════════════════════════════════
|
|
37
49
|
// NAVIGATION BAR (Android — 100% native)
|
|
38
50
|
// ═══════════════════════════════════════════════
|
|
39
51
|
|
|
40
|
-
|
|
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
|
+
export const setNavigationBarColor = (color: NavigationBarColorValue): void => {
|
|
41
66
|
if (!androidOnly("setNavigationBarColor")) return;
|
|
42
67
|
checkNative();
|
|
43
|
-
Native.setNavigationBarColor(color);
|
|
68
|
+
Native.setNavigationBarColor(color); // Kotlin handles the special values
|
|
44
69
|
};
|
|
45
70
|
|
|
46
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Hide or show the navigation bar.
|
|
73
|
+
*
|
|
74
|
+
* @param mode `"visible"` | `"hidden"`
|
|
75
|
+
*/
|
|
76
|
+
export const setNavigationBarVisibility = (
|
|
77
|
+
mode: NavigationBarVisibility,
|
|
78
|
+
): void => {
|
|
47
79
|
if (!androidOnly("setNavigationBarVisibility")) return;
|
|
48
80
|
checkNative();
|
|
49
81
|
Native.setNavigationBarVisibility(mode);
|
|
50
82
|
};
|
|
51
83
|
|
|
52
|
-
export const setNavigationBarButtonStyle = (
|
|
84
|
+
export const setNavigationBarButtonStyle = (
|
|
85
|
+
style: NavigationBarButtonStyle,
|
|
86
|
+
): void => {
|
|
53
87
|
if (!androidOnly("setNavigationBarButtonStyle")) return;
|
|
54
88
|
checkNative();
|
|
55
89
|
Native.setNavigationBarButtonStyle(style);
|
|
@@ -61,7 +95,9 @@ export const setNavigationBarStyle = (style: NavigationBarStyle): void => {
|
|
|
61
95
|
Native.setNavigationBarStyle(style);
|
|
62
96
|
};
|
|
63
97
|
|
|
64
|
-
export const setNavigationBarBehavior = (
|
|
98
|
+
export const setNavigationBarBehavior = (
|
|
99
|
+
behavior: NavigationBarBehavior,
|
|
100
|
+
): void => {
|
|
65
101
|
if (!androidOnly("setNavigationBarBehavior")) return;
|
|
66
102
|
checkNative();
|
|
67
103
|
Native.setNavigationBarBehavior(behavior);
|
|
@@ -71,6 +107,20 @@ export const setNavigationBarBehavior = (behavior: NavigationBarBehavior): void
|
|
|
71
107
|
// STATUS BAR (native — no RN StatusBar)
|
|
72
108
|
// ═══════════════════════════════════════════════
|
|
73
109
|
|
|
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
|
+
export const setStatusBarColor = (color: StatusBarColorValue): void => {
|
|
119
|
+
if (!androidOnly("setStatusBarColor")) return;
|
|
120
|
+
checkNative();
|
|
121
|
+
Native.setStatusBarColor(color);
|
|
122
|
+
};
|
|
123
|
+
|
|
74
124
|
export const setStatusBarStyle = (style: StatusBarStyle): void => {
|
|
75
125
|
checkNative();
|
|
76
126
|
Native.setStatusBarStyle(style);
|
|
@@ -96,18 +146,18 @@ export const getBrightness = (): Promise<number> => {
|
|
|
96
146
|
};
|
|
97
147
|
|
|
98
148
|
/**
|
|
99
|
-
* Subscribe to system brightness changes (polls every
|
|
149
|
+
* Subscribe to system brightness changes (polls every 500 ms on Android).
|
|
100
150
|
* @returns unsubscribe function
|
|
101
151
|
*/
|
|
102
152
|
export const onBrightnessChange = (
|
|
103
|
-
callback: (brightness: number) => void
|
|
153
|
+
callback: (brightness: number) => void,
|
|
104
154
|
): (() => void) => {
|
|
105
155
|
checkNative();
|
|
106
156
|
const { DeviceEventEmitter } = require("react-native");
|
|
107
157
|
Native.startBrightnessListener();
|
|
108
158
|
const sub = DeviceEventEmitter.addListener(
|
|
109
159
|
"SystemBar_BrightnessChange",
|
|
110
|
-
(e: { brightness: number }) => callback(e.brightness)
|
|
160
|
+
(e: { brightness: number }) => callback(e.brightness),
|
|
111
161
|
);
|
|
112
162
|
return () => {
|
|
113
163
|
sub.remove();
|
|
@@ -119,7 +169,10 @@ export const onBrightnessChange = (
|
|
|
119
169
|
// VOLUME
|
|
120
170
|
// ═══════════════════════════════════════════════
|
|
121
171
|
|
|
122
|
-
export const setVolume = (
|
|
172
|
+
export const setVolume = (
|
|
173
|
+
level: number,
|
|
174
|
+
stream: VolumeStream = "music",
|
|
175
|
+
): void => {
|
|
123
176
|
checkNative();
|
|
124
177
|
Native.setVolume(Math.max(0, Math.min(1, level)), stream);
|
|
125
178
|
};
|
|
@@ -140,14 +193,15 @@ export const setVolumeHUDVisible = (visible: boolean): void => {
|
|
|
140
193
|
* @returns unsubscribe function
|
|
141
194
|
*/
|
|
142
195
|
export const onVolumeChange = (
|
|
143
|
-
callback: (volume: number, stream: VolumeStream) => void
|
|
196
|
+
callback: (volume: number, stream: VolumeStream) => void,
|
|
144
197
|
): (() => void) => {
|
|
145
198
|
checkNative();
|
|
146
199
|
const { DeviceEventEmitter } = require("react-native");
|
|
147
200
|
Native.startVolumeListener();
|
|
148
201
|
const sub = DeviceEventEmitter.addListener(
|
|
149
202
|
"SystemBar_VolumeChange",
|
|
150
|
-
(e: { volume: number; stream: VolumeStream }) =>
|
|
203
|
+
(e: { volume: number; stream: VolumeStream }) =>
|
|
204
|
+
callback(e.volume, e.stream),
|
|
151
205
|
);
|
|
152
206
|
return () => {
|
|
153
207
|
sub.remove();
|
|
@@ -186,23 +240,155 @@ export const setOrientation = (mode: Orientation): void => {
|
|
|
186
240
|
};
|
|
187
241
|
|
|
188
242
|
// ═══════════════════════════════════════════════
|
|
189
|
-
// SCREENCAST
|
|
243
|
+
// SYSTEM SCREENCAST (external display / HDMI / Miracast)
|
|
244
|
+
// Reads DisplayManager — detects any externally mirrored display.
|
|
245
|
+
// ═══════════════════════════════════════════════
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* One-shot snapshot of system-level external display state.
|
|
249
|
+
* Works on both Android (DisplayManager) and iOS (UIScreen.screens).
|
|
250
|
+
*/
|
|
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();
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Subscribe to system external-display changes.
|
|
268
|
+
* Fires when an HDMI / Miracast / AirPlay display connects or disconnects.
|
|
269
|
+
* @returns unsubscribe function
|
|
270
|
+
*/
|
|
271
|
+
export const onSystemScreencastChange = (
|
|
272
|
+
callback: (info: SystemScreencastInfo) => void,
|
|
273
|
+
): (() => void) => {
|
|
274
|
+
checkNative();
|
|
275
|
+
const { DeviceEventEmitter } = require("react-native");
|
|
276
|
+
Native.startSystemScreencastListener();
|
|
277
|
+
const sub = DeviceEventEmitter.addListener(
|
|
278
|
+
"SystemBar_SystemScreencastChange",
|
|
279
|
+
callback,
|
|
280
|
+
);
|
|
281
|
+
return () => {
|
|
282
|
+
sub.remove();
|
|
283
|
+
Native.stopSystemScreencastListener();
|
|
284
|
+
};
|
|
285
|
+
};
|
|
286
|
+
|
|
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
|
+
// ═══════════════════════════════════════════════
|
|
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()
|
|
190
301
|
// ═══════════════════════════════════════════════
|
|
191
302
|
|
|
192
|
-
|
|
303
|
+
/**
|
|
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).
|
|
307
|
+
*/
|
|
308
|
+
export const startAppCastScan = (): void => {
|
|
309
|
+
if (!androidOnly("startAppCastScan")) return;
|
|
310
|
+
checkNative();
|
|
311
|
+
Native.startAppCastScan();
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Stop the device discovery scan.
|
|
316
|
+
*/
|
|
317
|
+
export const stopAppCastScan = (): void => {
|
|
318
|
+
if (!androidOnly("stopAppCastScan")) return;
|
|
319
|
+
checkNative();
|
|
320
|
+
Native.stopAppCastScan();
|
|
321
|
+
};
|
|
322
|
+
|
|
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
|
+
};
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Disconnect the active in-app cast session.
|
|
336
|
+
*/
|
|
337
|
+
export const disconnectAppCast = (): void => {
|
|
338
|
+
if (!androidOnly("disconnectAppCast")) return;
|
|
339
|
+
checkNative();
|
|
340
|
+
Native.disconnectAppCast();
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Get the current in-app cast snapshot (state + device list).
|
|
345
|
+
*/
|
|
346
|
+
export const getAppCastInfo = (): Promise<AppCastInfo> => {
|
|
347
|
+
if (!isAndroid) {
|
|
348
|
+
return Promise.resolve({
|
|
349
|
+
state: "idle" as AppCastState,
|
|
350
|
+
devices: [],
|
|
351
|
+
connectedDevice: null,
|
|
352
|
+
error: null,
|
|
353
|
+
});
|
|
354
|
+
}
|
|
193
355
|
checkNative();
|
|
194
|
-
return Native.
|
|
356
|
+
return Native.getAppCastInfo();
|
|
195
357
|
};
|
|
196
358
|
|
|
197
|
-
|
|
198
|
-
|
|
359
|
+
/**
|
|
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
|
+
*
|
|
370
|
+
* @returns unsubscribe function
|
|
371
|
+
*/
|
|
372
|
+
export const onAppCastChange = (
|
|
373
|
+
callback: (info: AppCastInfo) => void,
|
|
199
374
|
): (() => 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
|
+
}
|
|
200
385
|
checkNative();
|
|
201
386
|
const { DeviceEventEmitter } = require("react-native");
|
|
202
|
-
|
|
203
|
-
|
|
387
|
+
const sub = DeviceEventEmitter.addListener(
|
|
388
|
+
"SystemBar_AppCastChange",
|
|
389
|
+
callback,
|
|
390
|
+
);
|
|
204
391
|
return () => {
|
|
205
392
|
sub.remove();
|
|
206
|
-
Native.stopScreencastListener();
|
|
207
393
|
};
|
|
208
394
|
};
|
package/src/types.ts
CHANGED
|
@@ -12,6 +12,45 @@ export type NavigationBarStyle = "auto" | "inverted" | "light" | "dark";
|
|
|
12
12
|
export type NavigationBarVisibility = "visible" | "hidden";
|
|
13
13
|
export type StatusBarStyle = "light" | "dark";
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Navigation bar color value.
|
|
17
|
+
*
|
|
18
|
+
* - Any CSS hex string → solid colour e.g. "#1a1a2e", "#000"
|
|
19
|
+
* - `"transparent"` → fully transparent (FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS +
|
|
20
|
+
* transparent color; content draws behind bar)
|
|
21
|
+
* - `"translucent"` → semi-transparent (FLAG_TRANSLUCENT_NAVIGATION)
|
|
22
|
+
*/
|
|
23
|
+
export type NavigationBarColorValue = string | "transparent" | "translucent";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Status bar background color value.
|
|
27
|
+
*
|
|
28
|
+
* - Any CSS hex string → solid colour
|
|
29
|
+
* - `"transparent"` → fully transparent (draws behind content)
|
|
30
|
+
* - `"translucent"` → semi-transparent
|
|
31
|
+
*/
|
|
32
|
+
export type StatusBarColorValue = string | "transparent" | "translucent";
|
|
33
|
+
|
|
34
|
+
// ─────────────────────────────────────────────
|
|
35
|
+
// Theme
|
|
36
|
+
// ─────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* "system" → follow the OS Appearance (dark/light).
|
|
40
|
+
* "dark" → force dark.
|
|
41
|
+
* "light" → force light.
|
|
42
|
+
*/
|
|
43
|
+
export type ThemeMode = "system" | "dark" | "light";
|
|
44
|
+
|
|
45
|
+
export interface ThemeState {
|
|
46
|
+
/** Resolved dark-mode flag. Always a concrete boolean. */
|
|
47
|
+
isDark: boolean;
|
|
48
|
+
/** Currently active override ("system" = following OS). */
|
|
49
|
+
mode: ThemeMode;
|
|
50
|
+
/** Set the override mode. Pass "system" to revert to OS. */
|
|
51
|
+
setMode: (mode: ThemeMode) => void;
|
|
52
|
+
}
|
|
53
|
+
|
|
15
54
|
export type Orientation =
|
|
16
55
|
| "portrait"
|
|
17
56
|
| "landscape"
|
|
@@ -26,14 +65,59 @@ export type VolumeStream =
|
|
|
26
65
|
| "alarm"
|
|
27
66
|
| "system";
|
|
28
67
|
|
|
68
|
+
// ─────────────────────────────────────────────
|
|
69
|
+
// System screencast (external display / HDMI)
|
|
70
|
+
// ─────────────────────────────────────────────
|
|
71
|
+
|
|
29
72
|
export interface ScreencastDisplay {
|
|
30
73
|
id: number;
|
|
31
74
|
name: string;
|
|
32
75
|
isValid: boolean;
|
|
33
76
|
}
|
|
34
77
|
|
|
35
|
-
|
|
78
|
+
/** Result of getSystemScreencastInfo() — physical/HDMI/Miracast external display. */
|
|
79
|
+
export interface SystemScreencastInfo {
|
|
36
80
|
isCasting: boolean;
|
|
37
81
|
displayName: string | null;
|
|
38
82
|
displays: ScreencastDisplay[];
|
|
39
83
|
}
|
|
84
|
+
|
|
85
|
+
// ─────────────────────────────────────────────
|
|
86
|
+
// App-only cast (MediaRouter — Chromecast / TV)
|
|
87
|
+
// ─────────────────────────────────────────────
|
|
88
|
+
|
|
89
|
+
/** Connection state of the in-app cast session. */
|
|
90
|
+
export type AppCastState =
|
|
91
|
+
| "idle"
|
|
92
|
+
| "scanning"
|
|
93
|
+
| "connecting"
|
|
94
|
+
| "connected"
|
|
95
|
+
| "disconnecting";
|
|
96
|
+
|
|
97
|
+
/** A discovered castable device (TV, Chromecast, etc.). */
|
|
98
|
+
export interface AppCastDevice {
|
|
99
|
+
/** Unique route ID from MediaRouter. */
|
|
100
|
+
id: string;
|
|
101
|
+
/** Human-readable device name e.g. "Living Room TV". */
|
|
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;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Full snapshot of in-app cast state. */
|
|
112
|
+
export interface AppCastInfo {
|
|
113
|
+
state: AppCastState;
|
|
114
|
+
/** Devices found during the last scan. */
|
|
115
|
+
devices: AppCastDevice[];
|
|
116
|
+
/** The device currently connected (or connecting). */
|
|
117
|
+
connectedDevice: AppCastDevice | null;
|
|
118
|
+
/** Error message from the last failed operation. */
|
|
119
|
+
error: string | null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** @deprecated Use SystemScreencastInfo */
|
|
123
|
+
export interface ScreencastInfo extends SystemScreencastInfo {}
|