@limrun/ui 0.18.2 → 0.20.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.
@@ -0,0 +1,62 @@
1
+ import { AxSnapshot } from './ax-tree';
2
+ import { AndroidElementTreeOptions, AxStatus } from './ax-fetcher';
3
+ import { CameraCaptureInfo } from './camera';
4
+ import { DuoState } from './duo';
5
+ import { PlaybackStats } from './playback-stats';
6
+ import { CameraStreamStats, MicrophoneState, RemoteControlConnectionState } from './stream-types';
7
+ export type StreamDisplay = 'primary' | 'inner';
8
+ export interface DeviceFrameSink {
9
+ /** The source is borrowed for this call. Copy it before returning if retaining a frame. */
10
+ present(source: CanvasImageSource, width: number, height: number, display: StreamDisplay): void;
11
+ }
12
+ export interface DeviceStreamState {
13
+ connection: RemoteControlConnectionState | 'idle';
14
+ videoReady: boolean;
15
+ controlReady: boolean;
16
+ duo: boolean;
17
+ duoState: DuoState | null;
18
+ duoError?: string;
19
+ }
20
+ export interface DeviceStreamTransport {
21
+ /** Return a fresh, unopened or open WebSocket for each attempt. The client owns its lifetime. */
22
+ connect(): WebSocket | Promise<WebSocket>;
23
+ /** Optional authoritative lifecycle check. Omit when the proxy cannot distinguish termination. */
24
+ isTerminated?(): Promise<boolean>;
25
+ }
26
+ /** Options that can change without replacing the connection. */
27
+ export interface DeviceStreamLiveOptions {
28
+ /** Applied on the next connection attempt. */
29
+ openUrl?: string;
30
+ axPollIntervalMs?: number;
31
+ axMaxBackoffMs?: number;
32
+ androidElementTreeOptions?: AndroidElementTreeOptions;
33
+ autoReconnect?: boolean;
34
+ jitterBufferTargetMs?: number | null;
35
+ microphoneEnabled?: boolean;
36
+ inspectMode?: boolean | 'hover-only';
37
+ onStateChange?: (state: DeviceStreamState) => void;
38
+ onConnectionStateChange?: (state: RemoteControlConnectionState) => void;
39
+ onTerminated?: () => void;
40
+ onPlaybackStats?: (stats: PlaybackStats | null) => void;
41
+ onTrace?: (message: Record<string, unknown>) => void;
42
+ onAxSnapshotChange?: (snapshot: AxSnapshot | null) => void;
43
+ onAxStatusChange?: (status: AxStatus, error?: string) => void;
44
+ onCameraDemandChange?: (active: boolean, granted?: boolean, camera?: CameraCaptureInfo) => void;
45
+ onCameraStats?: (stats: CameraStreamStats | null) => void;
46
+ onMicrophoneStateChange?: (state: MicrophoneState) => void;
47
+ }
48
+ export type DeviceStreamOptions = DeviceStreamLiveOptions & {
49
+ sessionId?: string;
50
+ /** Required with proxy transports; direct instance URLs can supply the platform implicitly. */
51
+ platform?: 'ios' | 'android';
52
+ deviceModel?: 'iphone-duo';
53
+ } & ({
54
+ url: string;
55
+ token: string;
56
+ transport?: never;
57
+ } | {
58
+ transport: DeviceStreamTransport;
59
+ platform: 'ios' | 'android';
60
+ url?: never;
61
+ token?: never;
62
+ });
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Snapshot of the live-microphone pipeline, reported through
3
+ * `onMicrophoneStateChange`.
4
+ */
5
+ export interface MicrophoneState {
6
+ /** True while the browser mic is captured and streaming to the sim. */
7
+ active: boolean;
8
+ /**
9
+ * Human-readable failure from the last attempt, if any (permission
10
+ * denied, no device, host rejection, ...).
11
+ */
12
+ error?: string;
13
+ /** Device label of the captured microphone, when available. */
14
+ label?: string;
15
+ }
16
+ /**
17
+ * Live outbound-camera quality snapshot. Derived from
18
+ * `RTCPeerConnection.getStats()` and rate-derived deltas, sampled
19
+ * once per second while the camera is sending. All fields optional:
20
+ * some browsers omit fields (Safari rarely reports
21
+ * `encoderImplementation`), and the first sample after camera start
22
+ * has no delta-derived numbers yet.
23
+ */
24
+ export interface CameraStreamStats {
25
+ /** "H264", "HEVC"/"H265", "VP9", "VP8", "AV1", etc. (uppercased). */
26
+ codec?: string;
27
+ /** e.g. "VideoToolbox" (hw), "OpenH264" (sw), "ExternalEncoder". */
28
+ encoderImplementation?: string;
29
+ /**
30
+ * Browser-reported hardware-acceleration hint. Some Chromium
31
+ * versions expose this via `powerEfficientEncoder`; we mirror it
32
+ * here so consumers don't have to know the spec quirk.
33
+ */
34
+ hardwareAccelerated?: boolean;
35
+ /** Outbound encoded fps over the last sample window. */
36
+ framesPerSecond?: number;
37
+ /** Cumulative encoded frame count. */
38
+ framesEncoded?: number;
39
+ /** Outbound encoded bitrate (bits/s) over the last window. */
40
+ bitrateBps?: number;
41
+ /** Width/height the encoder is currently producing. */
42
+ width?: number;
43
+ height?: number;
44
+ /**
45
+ * One of `'none' | 'cpu' | 'bandwidth' | 'other'`. Mirrors
46
+ * Meet/Zoom's "limited by …" banners. Anything other than
47
+ * `'none'` means the encoder dropped resolution to keep up.
48
+ */
49
+ qualityLimitationReason?: string;
50
+ /** Round-trip time in milliseconds, from the matching RTCP. */
51
+ rttMs?: number;
52
+ /** Packet-loss percentage over the last sample window (0..100). */
53
+ packetsLostPct?: number;
54
+ }
55
+ export interface ScreenshotData {
56
+ dataUri: string;
57
+ }
58
+ export interface ImperativeKeyboardEvent {
59
+ type: 'keydown' | 'keyup';
60
+ code: string;
61
+ shiftKey?: boolean;
62
+ altKey?: boolean;
63
+ ctrlKey?: boolean;
64
+ metaKey?: boolean;
65
+ }
66
+ export type RemoteControlConnectionState = 'connecting' | 'connected' | 'reconnecting' | 'failed' | 'terminated';
@@ -0,0 +1,6 @@
1
+ export declare const debugLog: (...args: any[]) => void;
2
+ export declare const debugWarn: (...args: any[]) => void;
3
+ export declare const safeInvoke: <Args extends unknown[]>(label: string, fn: ((...args: Args) => unknown) | undefined, ...args: Args) => void;
4
+ export type DevicePlatform = 'ios' | 'android';
5
+ export declare const detectPlatform: (url: string) => DevicePlatform;
6
+ export declare const withAuthenticationToken: (url: string, token: string) => string;
@@ -0,0 +1,4 @@
1
+ import { PlaybackStats } from './playback-stats';
2
+ import { PlaybackConnection } from './playback-subscription';
3
+ export type { PlaybackConnection } from './playback-subscription';
4
+ export declare function usePlaybackStats(connection: PlaybackConnection | null, callback: ((stats: PlaybackStats | null) => void) | undefined, target: number | null | undefined): void;