@stream-io/video-react-native-sdk 1.45.1 → 1.46.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.
Files changed (118) hide show
  1. package/CHANGELOG.md +36 -2
  2. package/android/build.gradle +7 -1
  3. package/dist/commonjs/components/Call/CallContent/CallContent.js +1 -1
  4. package/dist/commonjs/components/Call/CallContent/CallContent.js.map +1 -1
  5. package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js +78 -7
  6. package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js.map +1 -1
  7. package/dist/commonjs/components/Call/CallContent/RTCViewPipNative.js +3 -0
  8. package/dist/commonjs/components/Call/CallContent/RTCViewPipNative.js.map +1 -1
  9. package/dist/commonjs/components/Call/RingingCallContent/OutgoingCall.js +4 -12
  10. package/dist/commonjs/components/Call/RingingCallContent/OutgoingCall.js.map +1 -1
  11. package/dist/commonjs/components/Participant/ParticipantView/VideoRenderer/TrackSubscriber.js +27 -4
  12. package/dist/commonjs/components/Participant/ParticipantView/VideoRenderer/TrackSubscriber.js.map +1 -1
  13. package/dist/commonjs/index.js +14 -1
  14. package/dist/commonjs/index.js.map +1 -1
  15. package/dist/commonjs/modules/encryption/EncryptionManager.js +305 -0
  16. package/dist/commonjs/modules/encryption/EncryptionManager.js.map +1 -0
  17. package/dist/commonjs/modules/encryption/eventMapping.js +143 -0
  18. package/dist/commonjs/modules/encryption/eventMapping.js.map +1 -0
  19. package/dist/commonjs/modules/encryption/index.js +13 -0
  20. package/dist/commonjs/modules/encryption/index.js.map +1 -0
  21. package/dist/commonjs/modules/encryption/parity.js +6 -0
  22. package/dist/commonjs/modules/encryption/parity.js.map +1 -0
  23. package/dist/commonjs/utils/StreamVideoRN/index.js +23 -0
  24. package/dist/commonjs/utils/StreamVideoRN/index.js.map +1 -1
  25. package/dist/commonjs/utils/internal/callingx/callingx.js +29 -4
  26. package/dist/commonjs/utils/internal/callingx/callingx.js.map +1 -1
  27. package/dist/commonjs/utils/internal/iosPipTrack.js +41 -0
  28. package/dist/commonjs/utils/internal/iosPipTrack.js.map +1 -0
  29. package/dist/commonjs/utils/internal/registerSDKGlobals.js +6 -0
  30. package/dist/commonjs/utils/internal/registerSDKGlobals.js.map +1 -1
  31. package/dist/commonjs/utils/internal/ringingCallLifecycle.js +142 -0
  32. package/dist/commonjs/utils/internal/ringingCallLifecycle.js.map +1 -0
  33. package/dist/commonjs/utils/push/internal/utils.js +4 -0
  34. package/dist/commonjs/utils/push/internal/utils.js.map +1 -1
  35. package/dist/commonjs/version.js +1 -1
  36. package/dist/module/components/Call/CallContent/CallContent.js +1 -1
  37. package/dist/module/components/Call/CallContent/CallContent.js.map +1 -1
  38. package/dist/module/components/Call/CallContent/RTCViewPipIOS.js +80 -9
  39. package/dist/module/components/Call/CallContent/RTCViewPipIOS.js.map +1 -1
  40. package/dist/module/components/Call/CallContent/RTCViewPipNative.js +3 -0
  41. package/dist/module/components/Call/CallContent/RTCViewPipNative.js.map +1 -1
  42. package/dist/module/components/Call/RingingCallContent/OutgoingCall.js +4 -12
  43. package/dist/module/components/Call/RingingCallContent/OutgoingCall.js.map +1 -1
  44. package/dist/module/components/Participant/ParticipantView/VideoRenderer/TrackSubscriber.js +28 -5
  45. package/dist/module/components/Participant/ParticipantView/VideoRenderer/TrackSubscriber.js.map +1 -1
  46. package/dist/module/index.js +5 -0
  47. package/dist/module/index.js.map +1 -1
  48. package/dist/module/modules/encryption/EncryptionManager.js +301 -0
  49. package/dist/module/modules/encryption/EncryptionManager.js.map +1 -0
  50. package/dist/module/modules/encryption/eventMapping.js +135 -0
  51. package/dist/module/modules/encryption/eventMapping.js.map +1 -0
  52. package/dist/module/modules/encryption/index.js +4 -0
  53. package/dist/module/modules/encryption/index.js.map +1 -0
  54. package/dist/module/modules/encryption/parity.js +4 -0
  55. package/dist/module/modules/encryption/parity.js.map +1 -0
  56. package/dist/module/utils/StreamVideoRN/index.js +23 -0
  57. package/dist/module/utils/StreamVideoRN/index.js.map +1 -1
  58. package/dist/module/utils/internal/callingx/callingx.js +29 -4
  59. package/dist/module/utils/internal/callingx/callingx.js.map +1 -1
  60. package/dist/module/utils/internal/iosPipTrack.js +35 -0
  61. package/dist/module/utils/internal/iosPipTrack.js.map +1 -0
  62. package/dist/module/utils/internal/registerSDKGlobals.js +6 -0
  63. package/dist/module/utils/internal/registerSDKGlobals.js.map +1 -1
  64. package/dist/module/utils/internal/ringingCallLifecycle.js +134 -0
  65. package/dist/module/utils/internal/ringingCallLifecycle.js.map +1 -0
  66. package/dist/module/utils/push/internal/utils.js +4 -0
  67. package/dist/module/utils/push/internal/utils.js.map +1 -1
  68. package/dist/module/version.js +1 -1
  69. package/dist/typescript/components/Call/CallContent/RTCViewPipIOS.d.ts.map +1 -1
  70. package/dist/typescript/components/Call/CallContent/RTCViewPipNative.d.ts +12 -0
  71. package/dist/typescript/components/Call/CallContent/RTCViewPipNative.d.ts.map +1 -1
  72. package/dist/typescript/components/Call/RingingCallContent/OutgoingCall.d.ts.map +1 -1
  73. package/dist/typescript/components/Participant/ParticipantView/VideoRenderer/TrackSubscriber.d.ts +11 -0
  74. package/dist/typescript/components/Participant/ParticipantView/VideoRenderer/TrackSubscriber.d.ts.map +1 -1
  75. package/dist/typescript/index.d.ts +1 -0
  76. package/dist/typescript/index.d.ts.map +1 -1
  77. package/dist/typescript/modules/encryption/EncryptionManager.d.ts +190 -0
  78. package/dist/typescript/modules/encryption/EncryptionManager.d.ts.map +1 -0
  79. package/dist/typescript/modules/encryption/eventMapping.d.ts +38 -0
  80. package/dist/typescript/modules/encryption/eventMapping.d.ts.map +1 -0
  81. package/dist/typescript/modules/encryption/index.d.ts +2 -0
  82. package/dist/typescript/modules/encryption/index.d.ts.map +1 -0
  83. package/dist/typescript/modules/encryption/parity.d.ts +55 -0
  84. package/dist/typescript/modules/encryption/parity.d.ts.map +1 -0
  85. package/dist/typescript/utils/StreamVideoRN/index.d.ts +20 -1
  86. package/dist/typescript/utils/StreamVideoRN/index.d.ts.map +1 -1
  87. package/dist/typescript/utils/StreamVideoRN/types.d.ts +67 -0
  88. package/dist/typescript/utils/StreamVideoRN/types.d.ts.map +1 -1
  89. package/dist/typescript/utils/internal/callingx/callingx.d.ts +1 -1
  90. package/dist/typescript/utils/internal/callingx/callingx.d.ts.map +1 -1
  91. package/dist/typescript/utils/internal/iosPipTrack.d.ts +9 -0
  92. package/dist/typescript/utils/internal/iosPipTrack.d.ts.map +1 -0
  93. package/dist/typescript/utils/internal/registerSDKGlobals.d.ts.map +1 -1
  94. package/dist/typescript/utils/internal/ringingCallLifecycle.d.ts +27 -0
  95. package/dist/typescript/utils/internal/ringingCallLifecycle.d.ts.map +1 -0
  96. package/dist/typescript/utils/push/internal/utils.d.ts.map +1 -1
  97. package/dist/typescript/version.d.ts +1 -1
  98. package/ios/RTCViewPip.swift +33 -8
  99. package/ios/RTCViewPipManager.mm +1 -0
  100. package/package.json +8 -8
  101. package/src/components/Call/CallContent/CallContent.tsx +1 -1
  102. package/src/components/Call/CallContent/RTCViewPipIOS.tsx +92 -10
  103. package/src/components/Call/CallContent/RTCViewPipNative.tsx +13 -0
  104. package/src/components/Call/RingingCallContent/OutgoingCall.tsx +4 -12
  105. package/src/components/Participant/ParticipantView/VideoRenderer/TrackSubscriber.tsx +58 -5
  106. package/src/index.ts +5 -0
  107. package/src/modules/encryption/EncryptionManager.ts +360 -0
  108. package/src/modules/encryption/eventMapping.ts +151 -0
  109. package/src/modules/encryption/index.ts +1 -0
  110. package/src/modules/encryption/parity.ts +83 -0
  111. package/src/utils/StreamVideoRN/index.ts +24 -1
  112. package/src/utils/StreamVideoRN/types.ts +68 -0
  113. package/src/utils/internal/callingx/callingx.ts +37 -2
  114. package/src/utils/internal/iosPipTrack.ts +39 -0
  115. package/src/utils/internal/registerSDKGlobals.ts +2 -0
  116. package/src/utils/internal/ringingCallLifecycle.ts +148 -0
  117. package/src/utils/push/internal/utils.ts +4 -0
  118. package/src/version.ts +1 -1
@@ -0,0 +1,190 @@
1
+ import { type E2EEEventMap, type E2EEManager, type EncryptionManagerOptions, type Listener } from '@stream-io/video-client';
2
+ /**
3
+ * Distributes keys to the native encryption manager and attaches
4
+ * encrypt/decrypt transforms to RTCRtpSenders and RTCRtpReceivers.
5
+ *
6
+ * The public surface matches the web
7
+ * {@link https://github.com/GetStream/stream-video-js/blob/main/packages/client/src/rtc/e2ee/EncryptionManager.ts | EncryptionManager}
8
+ * method for method, so host code is portable between the two SDKs.
9
+ *
10
+ * The crypto itself lives in the WebRTC binary, not here: frames never cross
11
+ * the React Native bridge. This class carries key and attach commands over it,
12
+ * and diagnostic events back.
13
+ *
14
+ * Like the keys it installs, the manager is application-owned: create one per
15
+ * call, attach it before {@link https://github.com/GetStream/stream-video-js/blob/main/packages/client/src/Call.ts | Call}`.join()`,
16
+ * and {@link EncryptionManager.dispose | dispose} it when that call is done.
17
+ * Nothing in the SDK will do it for you, and on React Native the leak is native
18
+ * rather than collectable.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * if (EncryptionManager.isSupported()) {
23
+ * const e2ee = await EncryptionManager.create(call.currentUserId);
24
+ * e2ee.setSharedKey(0, keyBytes);
25
+ * call.setE2EEManager(e2ee); // must happen before call.join()
26
+ * }
27
+ * ```
28
+ */
29
+ export declare class EncryptionManager implements E2EEManager {
30
+ private readonly algorithm;
31
+ private readonly native;
32
+ private readonly events;
33
+ private readonly logger;
34
+ private readonly bridged;
35
+ private disposed;
36
+ private constructor();
37
+ private handleNativeEvent;
38
+ /**
39
+ * Whether E2EE can run here. Use it to guard UI, or to avoid calling
40
+ * {@link create} where it would throw.
41
+ *
42
+ * `false` means the installed `@stream-io/react-native-webrtc` predates E2EE
43
+ * support.
44
+ */
45
+ static isSupported: () => boolean;
46
+ /**
47
+ * Create an EncryptionManager and initialize the underlying native manager.
48
+ *
49
+ * Attach it with `call.setE2EEManager()` **before** `call.join()`: the join
50
+ * request carries the E2EE flag, and the peer connections are built with the
51
+ * transforms in place.
52
+ *
53
+ * Resolves rather than returning directly because every Stream SDK exposes
54
+ * this as a promise; nothing here is actually asynchronous, since a blocking
55
+ * native create is what keeps a sender from ever existing unencrypted.
56
+ *
57
+ * @param userId - The local user's ID, normally `call.currentUserId`.
58
+ * @param options - the create options.
59
+ * @throws {Error} If E2EE is unavailable. It never degrades to plaintext.
60
+ */
61
+ static create: (userId: string, options?: EncryptionManagerOptions) => Promise<EncryptionManager>;
62
+ /**
63
+ * Subscribe to an E2EE event.
64
+ *
65
+ * @returns a function that unsubscribes the listener.
66
+ */
67
+ on: <E extends keyof E2EEEventMap>(event: E, fn: Listener<E2EEEventMap[E]>) => (() => void);
68
+ /** Unsubscribe a listener registered with {@link on}. */
69
+ off: <E extends keyof E2EEEventMap>(event: E, fn: Listener<E2EEEventMap[E]>) => void;
70
+ /** Drop every listener, or every listener of one event. */
71
+ removeAllListeners: (event?: keyof E2EEEventMap) => void;
72
+ /**
73
+ * Set a per-user AES-GCM encryption key in the native key store.
74
+ *
75
+ * Use it when each participant has their own key from a central authority.
76
+ * The receiver picks the right one by the `keyIndex` in the frame trailer.
77
+ *
78
+ * @param userId - The key owner.
79
+ * @param keyIndex - Increases with each rotation.
80
+ * @param rawKey - 16 bytes for AES-128-GCM, 32 for AES-256-GCM.
81
+ */
82
+ setKey: (userId: string, keyIndex: number, rawKey: ArrayBuffer) => void;
83
+ /**
84
+ * Fallback key for any user without a per-user key. The simplest E2EE mode:
85
+ * one key for everyone, usually passphrase-derived, no distribution needed.
86
+ * Setting an epoch makes it active for encryption while older epochs remain
87
+ * available to decrypt in-flight frames until {@link removeSharedKey}.
88
+ *
89
+ * @param keyIndex - An integer 0-255, since one trailer byte carries it.
90
+ * @param rawKey - 16 bytes for AES-128-GCM, 32 for AES-256-GCM.
91
+ */
92
+ setSharedKey: (keyIndex: number, rawKey: ArrayBuffer) => void;
93
+ /**
94
+ * Retire one of a user's key epochs, leaving their other epochs usable.
95
+ *
96
+ * @param userId - The key owner.
97
+ * @param keyIndex - The exact epoch to remove. Absent epochs are a no-op.
98
+ */
99
+ removeKey: (userId: string, keyIndex: number) => void;
100
+ /**
101
+ * Drop every key a user holds from the local key store, so later frames of
102
+ * theirs no longer decrypt.
103
+ *
104
+ * This is local cleanup, not remote revocation: it cannot stop that
105
+ * participant from decrypting anything, and a shared key still decrypts them.
106
+ * Revoking access means withholding future keys, which the application owns.
107
+ *
108
+ * To retire one rotated epoch instead, use {@link removeKey}.
109
+ */
110
+ removeAllKeys: (userId: string) => void;
111
+ /**
112
+ * Remove one shared-key epoch from the native receive key ring.
113
+ *
114
+ * If this is the active epoch, shared-key encryption stops until
115
+ * {@link setSharedKey} succeeds again. An older epoch is not reactivated.
116
+ *
117
+ * @param keyIndex - The exact shared-key epoch to remove.
118
+ */
119
+ removeSharedKey: (keyIndex: number) => void;
120
+ /**
121
+ * Called by the Publisher when it adds a transceiver.
122
+ *
123
+ * Synchronous all the way to the native `SetFrameTransformer` call: were it
124
+ * async, the sender would exist before its transform did, which is a
125
+ * plaintext window. A failure throws instead of publishing cleartext.
126
+ *
127
+ * @param sender - The sender to encrypt.
128
+ * @param codec - Codec name, e.g. 'vp8', selecting the clear-byte rules.
129
+ * @param trackType - `TrackType` enum name, e.g. 'SCREEN_SHARE_AUDIO'.
130
+ * @internal
131
+ */
132
+ encrypt: (sender: RTCRtpSender, codec?: string, trackType?: string) => void;
133
+ /**
134
+ * Called by the Subscriber when a remote track arrives.
135
+ *
136
+ * @param receiver - The receiver to decrypt.
137
+ * @param userId - The remote user, for key lookup.
138
+ * @param trackType - `TrackType` enum name, e.g. 'SCREEN_SHARE_AUDIO'.
139
+ * @internal
140
+ */
141
+ decrypt: (receiver: RTCRtpReceiver, userId: string, trackType?: string) => void;
142
+ /**
143
+ * Toggle periodic performance reporting.
144
+ *
145
+ * While on, `e2ee.perf_report` is emitted once per second with per-track FPS
146
+ * and crypto timings. Useful for debugging throughput.
147
+ */
148
+ enablePerformanceReporting: (enabled: boolean) => void;
149
+ /**
150
+ * Request a snapshot of the installed keys. It arrives later as the
151
+ * `e2ee.key_state` event, listing fingerprints only, never key material.
152
+ */
153
+ requestKeyState: () => void;
154
+ /**
155
+ * Release the native manager and all resources.
156
+ *
157
+ * **The application owns this object's lifetime — the SDK never disposes it.**
158
+ * Nothing releases the native manager when a peer connection closes, and there
159
+ * is no detach API, so an undisposed manager keeps its transforms and its key
160
+ * material alive for the lifetime of the process. Dispose it together with the
161
+ * call instance whose flow has ended; a later flow gets a fresh call and a
162
+ * fresh manager (see `Call.setE2EEManager`).
163
+ *
164
+ * In-flight frames are dropped rather than drained.
165
+ *
166
+ * The manager is unusable afterwards and every key or attach method throws.
167
+ * Call {@link create} for a new one. Safe to call more than once.
168
+ */
169
+ dispose: () => void;
170
+ /**
171
+ * {@link dispose} releases the native manager, so an attached transform would
172
+ * point at nothing: frames would stall with no error and no event. Throwing
173
+ * is also fail-closed, since a caller that swallows it still publishes
174
+ * nothing rather than cleartext.
175
+ */
176
+ private assertUsable;
177
+ /**
178
+ * The caller keeps ownership of its buffer and may re-import the same bytes,
179
+ * so hand native a copy rather than a view onto memory that can change.
180
+ */
181
+ private copyKey;
182
+ private validateKeyLength;
183
+ /**
184
+ * One trailer byte carries the keyIndex. A larger value would truncate to
185
+ * `keyIndex & 0xFF`, so the receiver would look up the wrong key and fail
186
+ * every decrypt. Reject it rather than ship a silently broken key epoch.
187
+ */
188
+ private validateKeyIndex;
189
+ }
190
+ //# sourceMappingURL=EncryptionManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EncryptionManager.d.ts","sourceRoot":"","sources":["../../../../src/modules/encryption/EncryptionManager.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,wBAAwB,EAC7B,KAAK,QAAQ,EAEd,MAAM,yBAAyB,CAAC;AAQjC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAEjB;IACP,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO;IAaP,OAAO,CAAC,iBAAiB,CAIvB;IAEF;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,QAAO,OAAO,CACe;IAE/C;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,MAAM,GACX,QAAQ,MAAM,EACd,UAAU,wBAAwB,KACjC,OAAO,CAAC,iBAAiB,CAAC,CAc3B;IAEF;;;;OAIG;IACH,EAAE,GAAI,CAAC,SAAS,MAAM,YAAY,EAChC,OAAO,CAAC,EACR,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,KAC5B,CAAC,MAAM,IAAI,CAAC,CAA8B;IAE7C,yDAAyD;IACzD,GAAG,GAAI,CAAC,SAAS,MAAM,YAAY,EACjC,OAAO,CAAC,EACR,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,KAC5B,IAAI,CAA+B;IAEtC,2DAA2D;IAC3D,kBAAkB,GAAI,QAAQ,MAAM,YAAY,KAAG,IAAI,CACf;IAExC;;;;;;;;;OASG;IACH,MAAM,GAAI,QAAQ,MAAM,EAAE,UAAU,MAAM,EAAE,QAAQ,WAAW,KAAG,IAAI,CAKpE;IAEF;;;;;;;;OAQG;IACH,YAAY,GAAI,UAAU,MAAM,EAAE,QAAQ,WAAW,KAAG,IAAI,CAK1D;IAEF;;;;;OAKG;IACH,SAAS,GAAI,QAAQ,MAAM,EAAE,UAAU,MAAM,KAAG,IAAI,CAIlD;IAEF;;;;;;;;;OASG;IACH,aAAa,GAAI,QAAQ,MAAM,KAAG,IAAI,CAGpC;IAEF;;;;;;;OAOG;IACH,eAAe,GAAI,UAAU,MAAM,KAAG,IAAI,CAIxC;IAEF;;;;;;;;;;;OAWG;IACH,OAAO,GACL,QAAQ,YAAY,EACpB,QAAQ,MAAM,EACd,YAAY,MAAM,KACjB,IAAI,CAGL;IAEF;;;;;;;OAOG;IACH,OAAO,GACL,UAAU,cAAc,EACxB,QAAQ,MAAM,EACd,YAAY,MAAM,KACjB,IAAI,CAOL;IAEF;;;;;OAKG;IACH,0BAA0B,GAAI,SAAS,OAAO,KAAG,IAAI,CASnD;IAEF;;;OAGG;IACH,eAAe,QAAO,IAAI,CAKxB;IAEF;;;;;;;;;;;;;;OAcG;IACH,OAAO,QAAO,IAAI,CAchB;IAEF;;;;;OAKG;IACH,OAAO,CAAC,YAAY,CAElB;IAEF;;;OAGG;IACH,OAAO,CAAC,OAAO,CAIb;IAEF,OAAO,CAAC,iBAAiB,CAQvB;IAEF;;;;OAIG;IACH,OAAO,CAAC,gBAAgB,CAMtB;CACH"}
@@ -0,0 +1,38 @@
1
+ import { RTCEncryptionAlgorithm, RTCEncryptionTrackType, type RTCEncryptionEventData } from '@stream-io/react-native-webrtc';
2
+ import type { E2EEAlgorithm, E2EEEventMap } from '@stream-io/video-client';
3
+ /**
4
+ * The core RTC layer labels tracks with the `TrackType` enum *name*
5
+ * (`SfuModels.TrackType[trackType]`), while the native manager takes a numeric
6
+ * enum. Screen-share audio is deliberately its own value: native keeps replay
7
+ * state per (userId, trackType), so folding it into `AUDIO` mis-groups it.
8
+ *
9
+ * These read the native enums inside the function body on purpose. This module
10
+ * is reachable from the SDK's public entry point, so an app whose
11
+ * `@stream-io/react-native-webrtc` predates E2EE would crash on import if the
12
+ * enums were dereferenced at module scope - even if it never touches E2EE.
13
+ */
14
+ export declare const trackTypeToNative: (trackType?: string) => RTCEncryptionTrackType | undefined;
15
+ /** Map a native track type back to the name the web events carry. */
16
+ export declare const trackTypeFromNative: (trackType?: RTCEncryptionTrackType | number) => string | undefined;
17
+ /** Map the public algorithm name to the native enum. */
18
+ export declare const algorithmToNative: (algorithm: E2EEAlgorithm) => RTCEncryptionAlgorithm;
19
+ /**
20
+ * Translate a native event into the payload the web manager emits, so a host
21
+ * can write one set of handlers for both platforms.
22
+ *
23
+ * Two things have to be reshaped rather than passed through: native track types
24
+ * are numeric, and native flattens `managerId`/`type`/`userId` alongside the
25
+ * payload of every event, including the two (`perf_report`, `key_state`) that
26
+ * are not about a single user. Fields the web types require but native leaves
27
+ * optional get an explicit default, so a handler never reads `undefined` where
28
+ * its type promises a value.
29
+ *
30
+ * @returns the mapped event, or `undefined` for an unrecognized event name.
31
+ */
32
+ export declare const mapNativeEvent: <E extends keyof E2EEEventMap>(event: RTCEncryptionEventData) => {
33
+ type: E;
34
+ payload: E2EEEventMap[E];
35
+ } | undefined;
36
+ /** Every event the native manager emits, i.e. what the bridge subscribes to. */
37
+ export declare const E2EE_EVENT_TYPES: readonly ["e2ee.decryption_failed", "e2ee.decryption_resumed", "e2ee.decryption_stalled", "e2ee.encryption_failed", "e2ee.missing_key", "e2ee.unencrypted_frame", "e2ee.unsupported_version", "e2ee.perf_report", "e2ee.key_state"];
38
+ //# sourceMappingURL=eventMapping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eventMapping.d.ts","sourceRoot":"","sources":["../../../../src/modules/encryption/eventMapping.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,sBAAsB,EAE5B,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EAEb,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,GAC5B,YAAY,MAAM,KACjB,sBAAsB,GAAG,SAe3B,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,mBAAmB,GAC9B,YAAY,sBAAsB,GAAG,MAAM,KAC1C,MAAM,GAAG,SAaX,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,GAC5B,WAAW,aAAa,KACvB,sBAGqC,CAAC;AASzC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,MAAM,YAAY,EACzD,OAAO,sBAAsB,KAC5B;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAA;CAAE,GAAG,SA+C1C,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,gBAAgB,qOAUnB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { EncryptionManager } from './EncryptionManager';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/encryption/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Compile-time proof that the React Native {@link EncryptionManager} exposes the
3
+ * same public surface as the web one in `@stream-io/video-client`.
4
+ *
5
+ * This file has no runtime output and is imported by nothing. It exists because
6
+ * the SDK's entry point deliberately *shadows* the client's `EncryptionManager`
7
+ * export with this platform's implementation: a host writing against the
8
+ * documented API gets whichever class its platform ships, so the two surfaces
9
+ * diverging would be a silent break for that host rather than a build error.
10
+ * Both directions are asserted, so adding a method to either manager fails the
11
+ * build until the other one follows. Keep it that way, or delete both managers'
12
+ * claim to a shared API.
13
+ *
14
+ * `test:types` and the `tsc` pass in `bob build` both cover `src`, so CI runs
15
+ * this whether or not anything imports it.
16
+ */
17
+ import type { EncryptionManager as WebEncryptionManager } from '@stream-io/video-client';
18
+ import type { EncryptionManager } from './EncryptionManager';
19
+ /** Fails to compile unless `T` is exactly `true`. */
20
+ type AssertTrue<T extends true> = T;
21
+ /**
22
+ * Public members only.
23
+ *
24
+ * A class type carrying `private` members is nominal, so the two managers can
25
+ * never be compared as classes however identical their APIs. `keyof` yields
26
+ * public keys alone, which is also precisely the surface a host can touch.
27
+ */
28
+ type PublicSurface<T> = {
29
+ [K in keyof T]: T[K];
30
+ };
31
+ /**
32
+ * `emit` is public on the web manager only because it extends the shared
33
+ * `TypedEventEmitter`. Dispatching a forged E2EE event is not part of the
34
+ * documented API — `SPEC.md` §2 lists `on`/`off` and nothing else — so it is
35
+ * excluded here rather than mirrored on this side.
36
+ */
37
+ type WebSurface = Omit<PublicSurface<WebEncryptionManager>, 'emit'>;
38
+ type NativeSurface = PublicSurface<EncryptionManager>;
39
+ /** Every documented web member exists here, with a compatible signature. */
40
+ export type NativeCoversWeb = AssertTrue<NativeSurface extends WebSurface ? true : false>;
41
+ /**
42
+ * ...and nothing extra. A React Native-only method would compile fine but make
43
+ * host code silently unportable, which is the failure this file exists to catch.
44
+ */
45
+ export type WebCoversNative = AssertTrue<WebSurface extends NativeSurface ? true : false>;
46
+ /**
47
+ * The statics are checked by signature rather than by assignability: both
48
+ * `create`s return their own class, so comparing them whole would only ever
49
+ * restate that the two classes are nominally distinct.
50
+ */
51
+ export type CreateAcceptsSameArguments = AssertTrue<Parameters<typeof EncryptionManager.create> extends Parameters<typeof WebEncryptionManager.create> ? Parameters<typeof WebEncryptionManager.create> extends Parameters<typeof EncryptionManager.create> ? true : false : false>;
52
+ export type CreateResolvesAManager = AssertTrue<Awaited<ReturnType<typeof EncryptionManager.create>> extends NativeSurface ? true : false>;
53
+ export type IsSupportedMatches = AssertTrue<typeof EncryptionManager.isSupported extends typeof WebEncryptionManager.isSupported ? typeof WebEncryptionManager.isSupported extends typeof EncryptionManager.isSupported ? true : false : false>;
54
+ export {};
55
+ //# sourceMappingURL=parity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parity.d.ts","sourceRoot":"","sources":["../../../../src/modules/encryption/parity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,iBAAiB,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACzF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,qDAAqD;AACrD,KAAK,UAAU,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;AAEpC;;;;;;GAMG;AACH,KAAK,aAAa,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC;AAEjD;;;;;GAKG;AACH,KAAK,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAAC;AACpE,KAAK,aAAa,GAAG,aAAa,CAAC,iBAAiB,CAAC,CAAC;AAEtD,4EAA4E;AAC5E,MAAM,MAAM,eAAe,GAAG,UAAU,CACtC,aAAa,SAAS,UAAU,GAAG,IAAI,GAAG,KAAK,CAChD,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,CACtC,UAAU,SAAS,aAAa,GAAG,IAAI,GAAG,KAAK,CAChD,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG,UAAU,CACjD,UAAU,CAAC,OAAO,iBAAiB,CAAC,MAAM,CAAC,SAAS,UAAU,CAC5D,OAAO,oBAAoB,CAAC,MAAM,CACnC,GACG,UAAU,CAAC,OAAO,oBAAoB,CAAC,MAAM,CAAC,SAAS,UAAU,CAC/D,OAAO,iBAAiB,CAAC,MAAM,CAChC,GACC,IAAI,GACJ,KAAK,GACP,KAAK,CACV,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,UAAU,CAC7C,OAAO,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC,SAAS,aAAa,GACtE,IAAI,GACJ,KAAK,CACV,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,UAAU,CACzC,OAAO,iBAAiB,CAAC,WAAW,SAAS,OAAO,oBAAoB,CAAC,WAAW,GAChF,OAAO,oBAAoB,CAAC,WAAW,SAAS,OAAO,iBAAiB,CAAC,WAAW,GAClF,IAAI,GACJ,KAAK,GACP,KAAK,CACV,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { StreamVideoConfig } from './types';
1
+ import type { RingingCallLifecycleHooks, StreamVideoConfig } from './types';
2
2
  type DeepPartial<T> = {
3
3
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
4
4
  };
@@ -47,6 +47,25 @@ export declare class StreamVideoRN {
47
47
  * AppRegistry.registerComponent('app', () => App);
48
48
  */
49
49
  static setPushConfig(pushConfig: NonNullable<StreamVideoConfig['push']>): void;
50
+ /**
51
+ * Register hooks that run around a ringing call's join, for every ringing path:
52
+ * accepted from the CallKit/Telecom UI, accepted inside the app, and outgoing.
53
+ *
54
+ * Call this at your application's entry point, alongside
55
+ * {@link StreamVideoRN.setPushConfig} and **outside** the React tree. A call
56
+ * accepted from a push notification can be created and joined before any
57
+ * component mounts, so hooks registered from inside React would be missed on
58
+ * exactly the path that most needs them.
59
+ *
60
+ * Calling it again replaces the previously registered hooks.
61
+ *
62
+ * @example // in index.js
63
+ * StreamVideoRN.setRingingCallLifecycleHooks({
64
+ * onBeforeCallJoin: (call) => attachE2EEIfConfigured(call),
65
+ * onAfterCallLeave: (call) => disposeE2EEManager(call),
66
+ * });
67
+ */
68
+ static setRingingCallLifecycleHooks: (hooks: RingingCallLifecycleHooks) => void;
50
69
  static getConfig(): StreamVideoConfig;
51
70
  /**
52
71
  * This is the function to be called when the push token must be removed.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/StreamVideoRN/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAajD,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAChE,CAAC;AAgDF,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,MAAM,CAA+B;IAEpD;;;;OAIG;IACH,MAAM,CAAC,YAAY,CACjB,YAAY,EAAE,WAAW,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IAK5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IA0BvE,MAAM,CAAC,SAAS;IAIhB;;;OAGG;IACH,MAAM,CAAC,YAAY;IASnB,MAAM,CAAC,wBAAwB;IAI/B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,qCAAqC,CAAC,QAAQ,EAAE,OAAO;IAe9D;;OAEG;WACU,YAAY;IAIzB;;OAEG;WACU,YAAY;IAIzB;;;OAGG;WACU,6BAA6B,IAAI,OAAO,CAAC,OAAO,CAAC;IAQ9D;;;OAGG;WACU,4BAA4B,IAAI,OAAO,CAAC,OAAO,CAAC;IAQ7D;;;OAGG;WACU,wBAAwB,IAAI,OAAO,CAAC,OAAO,CAAC;CAO1D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/StreamVideoRN/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAc5E,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAChE,CAAC;AAgDF,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,MAAM,CAA+B;IAEpD;;;;OAIG;IACH,MAAM,CAAC,YAAY,CACjB,YAAY,EAAE,WAAW,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IAK5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IA0BvE;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAC,4BAA4B,GAAI,OAAO,yBAAyB,UAErE;IAEF,MAAM,CAAC,SAAS;IAIhB;;;OAGG;IACH,MAAM,CAAC,YAAY;IASnB,MAAM,CAAC,wBAAwB;IAI/B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,qCAAqC,CAAC,QAAQ,EAAE,OAAO;IAe9D;;OAEG;WACU,YAAY;IAIzB;;OAEG;WACU,YAAY;IAIzB;;;OAGG;WACU,6BAA6B,IAAI,OAAO,CAAC,OAAO,CAAC;IAQ9D;;;OAGG;WACU,4BAA4B,IAAI,OAAO,CAAC,OAAO,CAAC;IAQ7D;;;OAGG;WACU,wBAAwB,IAAI,OAAO,CAAC,OAAO,CAAC;CAO1D"}
@@ -10,6 +10,73 @@ export type KeepAliveAndroidNotificationTexts = {
10
10
  body: string;
11
11
  };
12
12
  export type NonRingingPushEvent = 'call.live_started' | 'call.notification' | 'call.missed';
13
+ /**
14
+ * Hooks that run around a ringing call's join, wherever that join is triggered.
15
+ *
16
+ * A ringing call is joined by the SDK, not by your code: the accept button joins
17
+ * internally, and an outgoing call joins itself once the callee answers. That
18
+ * leaves no moment in which app code holds the call and the join has not yet
19
+ * happened - which is a problem for anything that must be installed first, most
20
+ * notably `call.setE2EEManager()`, since it throws once a call has peer
21
+ * connections.
22
+ *
23
+ * These hooks are that moment. They run for every ringing path: accepted from the
24
+ * CallKit/Telecom UI, accepted inside the app, and outgoing.
25
+ *
26
+ * Register them with {@link StreamVideoRN.setRingingCallLifecycleHooks} at your app's
27
+ * entry point, next to `setPushConfig`. A call accepted from a push notification
28
+ * can be created and joined before any component mounts - the app may be launched
29
+ * from a killed state - so registering them from inside React is too late.
30
+ */
31
+ export type RingingCallLifecycleHooks = {
32
+ /**
33
+ * Awaited by `Call.join()` for a ringing call, before any peer connection exists.
34
+ * **Throwing aborts the join** and the call is not entered.
35
+ *
36
+ * That is deliberate: joining without whatever this hook installs would, in the
37
+ * E2EE case, publish unencrypted media on a call the user believes is private.
38
+ * On the push path there is no UI to reveal it, so the join fails closed instead.
39
+ * A failed join also ends the call, so the `Call` it failed on is finished with -
40
+ * a later attempt happens on a new incoming call or a newly created one.
41
+ *
42
+ * Keep it fast. On the CallKit accept path it runs inside iOS's accept deadline
43
+ * (roughly 30s before the app is killed) and anything slower than five seconds is
44
+ * treated as a failure. Deriving a key locally is fine; fetching one over the
45
+ * network does not belong here.
46
+ *
47
+ * @example
48
+ * onBeforeCallJoin: async (call) => {
49
+ * await attachE2EEIfConfigured(call);
50
+ * }
51
+ */
52
+ onBeforeCallJoin?: (call: Call) => Promise<void>;
53
+ /**
54
+ * Called once, when a ringing call is finished with - it left, whether because
55
+ * the user hung up, the other side ended it, or its join failed and the SDK
56
+ * ended the flow.
57
+ *
58
+ * Use it to free per-call resources the SDK does not own. An E2EE manager is the
59
+ * motivating case: it has no native detach, closing the peer connections does not
60
+ * free it, and on the push path the call can end while the app is still in the
61
+ * background, where no React cleanup ever runs.
62
+ *
63
+ * When an {@link onBeforeCallJoin} is also registered, this is only called for a
64
+ * call that hook actually entered, so it always pairs with a setup that happened -
65
+ * a call that rings and is then rejected, cancelled or missed was never set up and
66
+ * releases nothing. Registered on its own it has no such pairing to honour and is
67
+ * called for every ringing call that ends. Either way it is tied to the call
68
+ * ending rather than to any view's lifetime, so navigating away from a live call
69
+ * does not release it.
70
+ *
71
+ * If the setup hook is still running when the call ends - it timed out, say - the
72
+ * release waits for it to settle, so it cannot free something that hook is about
73
+ * to create.
74
+ *
75
+ * May return a promise; rejections are logged. Nothing is gated on it, so do not
76
+ * rely on it completing before the OS suspends the app.
77
+ */
78
+ onAfterCallLeave?: (call: Call) => void | Promise<void>;
79
+ };
13
80
  export type StreamVideoConfig = {
14
81
  /**
15
82
  * The configuration to be used for push notifications.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/utils/StreamVideoRN/types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,oBAAoB,EACzB,iBAAiB,EACjB,KAAK,IAAI,EACV,MAAM,yBAAyB,CAAC;AAEjC,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAC7B,mBAAmB,GAAG,mBAAmB,GAAG,aAAa,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;OAIG;IACH,IAAI,CAAC,EAAE;QACL;;WAEG;QACH,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB;;;;WAIG;QACH,cAAc,CAAC,EAAE,oBAAoB,CAAC;QAEtC,GAAG,CAAC,EAAE;YACJ;;;;eAIG;YACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;YAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;YACxB;;;eAGG;YACH,KAAK,CAAC,EAAE,MAAM,CAAC;YACf;;;eAGG;YACH,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB;;;eAGG;YACH,YAAY,CAAC,EAAE,OAAO,CAAC;YACvB;;;eAGG;YACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;YAC5B;;;eAGG;YACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;YAC7B;;;;;;eAMG;YACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;YACvC;;;;;eAKG;YACH,yBAAyB,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;SACpD,CAAC;QACF,OAAO,CAAC,EAAE;YACR;;;;eAIG;YACH,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB;;;;eAIG;YACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;YAC1B;;;;;;;;;eASG;YACH,eAAe,CAAC,EAAE,oBAAoB,CAAC;YACvC;;;;;;;;eAQG;YACH,iBAAiB,CAAC,EAAE;gBAClB,SAAS,CAAC,EAAE,MAAM,CAAC;gBACnB,SAAS,CAAC,EAAE,MAAM,CAAC;aACpB,CAAC;YACF;;eAEG;YACH,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAC;YACrE,kBAAkB,CAAC,EAAE,OAAO,CAAC;YAC7B;;;;eAIG;YACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;YACvC;;;eAGG;YACH,yBAAyB,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;SACpD,CAAC;QACF;;;WAGG;QACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;QACnC;;;;;;;;;;;;;;;;;WAiBG;QACH,uBAAuB,EAAE,MAAM,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAAC;KACvE,CAAC;IACF,iBAAiB,EAAE;QACjB,OAAO,EAAE;YACP;;eAEG;YACH,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,OAAO,GAAG,WAAW,CAAC,CAAC;YAC3D;;eAEG;YACH,iBAAiB,EAAE,iCAAiC,CAAC;YACrD;;eAEG;YACH,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;SAC1C,CAAC;KACH,CAAC;CACH,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/utils/StreamVideoRN/types.ts"],"names":[],"mappings":"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"}
@@ -13,7 +13,7 @@ export declare function registerOutgoingCall(call: Call): Promise<void>;
13
13
  * 2. Displays the incoming call in the callingx library
14
14
  * 3. Optionally for non-ringing calls also when ongoing calls are enabled.
15
15
  */
16
- export declare function joinCallingxCall(call: Call, activeCalls: Call[]): Promise<void>;
16
+ export declare function joinCallingxCall(call: Call, activeCalls: Call[], isCancelled?: () => boolean): Promise<void>;
17
17
  export declare function endCallingxCall(call: Call, reason?: EndCallReason): Promise<void>;
18
18
  export declare function wireAudioEngineSubscription(): Promise<void>;
19
19
  export declare function unwireAudioEngineSubscription(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"callingx.d.ts","sourceRoot":"","sources":["../../../../../src/utils/internal/callingx/callingx.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,KAAK,EACV,IAAI,EACJ,cAAc,EACd,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AAKjC;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,cAAc,EAAE,GAAG,SAAS,EACzC,YAAY,EAAE,sBAAsB,EAAE,GAAG,SAAS,EAClD,aAAa,EAAE,MAAM,GAAG,SAAS,GAChC,MAAM,CAgCR;AAsBD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,IAAI,iBAyBpD;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,iBAoDrE;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,aAAa,iBAmBvE;AAED,wBAAsB,2BAA2B,kBAehD;AAED,wBAAgB,6BAA6B,SAe5C"}
1
+ {"version":3,"file":"callingx.d.ts","sourceRoot":"","sources":["../../../../../src/utils/internal/callingx/callingx.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,KAAK,EACV,IAAI,EACJ,cAAc,EACd,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AAKjC;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,cAAc,EAAE,GAAG,SAAS,EACzC,YAAY,EAAE,sBAAsB,EAAE,GAAG,SAAS,EAClD,aAAa,EAAE,MAAM,GAAG,SAAS,GAChC,MAAM,CAgCR;AA2BD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,IAAI,iBAyBpD;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,IAAI,EAAE,EACnB,WAAW,CAAC,EAAE,MAAM,OAAO,iBA+E5B;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,aAAa,iBAmBvE;AAED,wBAAsB,2BAA2B,kBAehD;AAED,wBAAgB,6BAA6B,SAe5C"}
@@ -0,0 +1,9 @@
1
+ import { type Call, type VideoTrackType } from '@stream-io/video-client';
2
+ import { BehaviorSubject } from 'rxjs';
3
+ export type PipTrack = {
4
+ sessionId: string;
5
+ trackType: VideoTrackType;
6
+ };
7
+ export declare const getIosPipTrack$: (call: Call) => BehaviorSubject<PipTrack | undefined>;
8
+ export declare const setIosPipTrack: (call: Call, track: PipTrack | undefined) => void;
9
+ //# sourceMappingURL=iosPipTrack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iosPipTrack.d.ts","sourceRoot":"","sources":["../../../../src/utils/internal/iosPipTrack.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,IAAI,EAET,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAEvC,MAAM,MAAM,QAAQ,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,cAAc,CAAA;CAAE,CAAC;AASxE,eAAO,MAAM,eAAe,GAAI,MAAM,IAAI,0CAOzC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,IAAI,EAAE,OAAO,QAAQ,GAAG,SAAS,SAarE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"registerSDKGlobals.d.ts","sourceRoot":"","sources":["../../../../src/utils/internal/registerSDKGlobals.ts"],"names":[],"mappings":"AA8OA,wBAAgB,kBAAkB,SAMjC"}
1
+ {"version":3,"file":"registerSDKGlobals.d.ts","sourceRoot":"","sources":["../../../../src/utils/internal/registerSDKGlobals.ts"],"names":[],"mappings":"AAgPA,wBAAgB,kBAAkB,SAMjC"}
@@ -0,0 +1,27 @@
1
+ import { type Call } from '@stream-io/video-client';
2
+ import type { RingingCallLifecycleHooks } from '../StreamVideoRN/types';
3
+ export declare const setRingingCallLifecycleHooks: (next: RingingCallLifecycleHooks) => void;
4
+ /**
5
+ * Runs the app's pre-join setup, bounded by the deadline.
6
+ *
7
+ * Rejecting fails the join closed - joining without whatever this installs would
8
+ * publish unencrypted media on a call the user believes is private.
9
+ */
10
+ export declare const beforeJoin: (call: Call) => Promise<void>;
11
+ /**
12
+ * The join failed and will not be retried on this call.
13
+ *
14
+ * Ends the ringing flow rather than leaving the call sitting in `RINGING`: one
15
+ * `Call` is one call flow, so the accept button must not be able to offer this
16
+ * instance again. Never rejects, so the original join error survives.
17
+ */
18
+ export declare const onJoinFailed: (call: Call) => Promise<void>;
19
+ /**
20
+ * The call has ended.
21
+ *
22
+ * Releases what the setup hook installed, once the hook has actually settled -
23
+ * a hook still running may yet install something, and releasing before it
24
+ * finishes would strand that.
25
+ */
26
+ export declare const onLeave: (call: Call) => void;
27
+ //# sourceMappingURL=ringingCallLifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ringingCallLifecycle.d.ts","sourceRoot":"","sources":["../../../../src/utils/internal/ringingCallLifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,IAAI,EACV,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAuBxE,eAAO,MAAM,4BAA4B,GACvC,MAAM,yBAAyB,SAGhC,CAAC;AAmCF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,MAAM,IAAI,KAAG,OAAO,CAAC,IAAI,CAiCnD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,GAAU,MAAM,IAAI,KAAG,OAAO,CAAC,IAAI,CAc3D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,GAAI,MAAM,IAAI,KAAG,IASpC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/utils/push/internal/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EAIL,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAKnE,KAAK,UAAU,GAAG,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;AAGzD,KAAK,4BAA4B,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,cAAc,IAAI,EAClB,eAAe,MAAM,GAAG,SAAS,EACjC,aAAa,MAAM,GAAG,SAAS;;;CAoChC,CAAC;AAMF,eAAO,MAAM,+BAA+B,GAC1C,YAAY,UAAU,EACtB,UAAU,MAAM,EAChB,QAAQ,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,qBAAqB;AAChE;;;;;GAKG;AACH,2BAA2B,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,kBAmFtD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,6BAA6B,GAAI,UAAU,MAAM,SAM7D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,4BAA4B,EAAE,4BAE1C,CAAC;AAEF,eAAO,MAAM,aAAa,eACkD,CAAC;AAE7E,eAAO,MAAM,kBAAkB,GAC7B,MAAM,IAAI,EACV,UAAU;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;CAAE;;;CAW7C,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/utils/push/internal/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EAIL,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAKnE,KAAK,UAAU,GAAG,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;AAGzD,KAAK,4BAA4B,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,cAAc,IAAI,EAClB,eAAe,MAAM,GAAG,SAAS,EACjC,aAAa,MAAM,GAAG,SAAS;;;CAoChC,CAAC;AAMF,eAAO,MAAM,+BAA+B,GAC1C,YAAY,UAAU,EACtB,UAAU,MAAM,EAChB,QAAQ,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,qBAAqB;AAChE;;;;;GAKG;AACH,2BAA2B,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,kBAuFtD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,6BAA6B,GAAI,UAAU,MAAM,SAM7D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,4BAA4B,EAAE,4BAE1C,CAAC;AAEF,eAAO,MAAM,aAAa,eACkD,CAAC;AAE7E,eAAO,MAAM,kBAAkB,GAC7B,MAAM,IAAI,EACV,UAAU;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;CAAE;;;CAW7C,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare const version = "1.45.1";
1
+ export declare const version = "1.46.0";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -17,6 +17,9 @@ class RTCViewPip: UIView {
17
17
  weak var manager: RTCViewPipManager?
18
18
 
19
19
  @objc var onPiPChange: RCTBubblingEventBlock?
20
+ /// Actual PiP window bounds in logical points.
21
+ @objc var onPiPBoundsChange: RCTBubblingEventBlock?
22
+ private var lastEmittedBounds: CGSize?
20
23
 
21
24
  // MARK: - Avatar Placeholder Properties
22
25
 
@@ -156,8 +159,11 @@ class RTCViewPip: UIView {
156
159
  @objc
157
160
  func onCallClosed() {
158
161
  PictureInPictureLogger.log("pictureInPictureController cleanup called")
162
+ self.pictureInPictureController?.onPiPStateChange = nil
163
+ self.pictureInPictureController?.onSizeUpdate = nil
159
164
  self.pictureInPictureController?.cleanup()
160
165
  self.pictureInPictureController = nil
166
+ self.lastEmittedBounds = nil
161
167
  }
162
168
 
163
169
  @objc
@@ -191,9 +197,8 @@ class RTCViewPip: UIView {
191
197
  }
192
198
  self.pictureInPictureController?.sourceView = self
193
199
  self.pictureInPictureController?.isMirrored = self.mirror
194
- // Set up PiP state change callback
195
- self.pictureInPictureController?.onPiPStateChange = { [weak self] isActive in
196
- self?.sendPiPChangeEvent(isActive: isActive)
200
+ if let controller = self.pictureInPictureController {
201
+ self.installCallbacks(on: controller)
197
202
  }
198
203
  if let reactTag = self.reactTag,
199
204
  let size = self.manager?.getCachedSize(for: reactTag) {
@@ -277,12 +282,32 @@ class RTCViewPip: UIView {
277
282
  }
278
283
  }
279
284
 
280
- private func sendPiPChangeEvent(isActive: Bool) {
281
- guard let onPiPChange = onPiPChange else {
282
- return
285
+ // MARK: - Picture in Picture Events
286
+
287
+ /// Ignore callbacks from a controller that has already been disposed.
288
+ private func installCallbacks(on controller: StreamPictureInPictureController) {
289
+ controller.onPiPStateChange = { [weak self, weak controller] isActive in
290
+ guard let self, let controller,
291
+ self.pictureInPictureController === controller else { return }
292
+ self.onPiPChange?(["active": isActive])
293
+ }
294
+ controller.onSizeUpdate = { [weak self, weak controller] size in
295
+ guard let self, let controller,
296
+ self.pictureInPictureController === controller else { return }
297
+ self.handleSizeUpdate(size)
283
298
  }
299
+ }
284
300
 
285
- PictureInPictureLogger.log("Sending PiP state change event: \(isActive)")
286
- onPiPChange(["active": isActive])
301
+ private func handleSizeUpdate(_ size: CGSize) {
302
+ guard size.width.isFinite, size.height.isFinite else { return }
303
+ // truncated to match the integer dimensions the inline views report.
304
+ let bounds = CGSize(
305
+ width: size.width.rounded(.towardZero),
306
+ height: size.height.rounded(.towardZero)
307
+ )
308
+ guard bounds.width > 0, bounds.height > 0 else { return }
309
+ guard let onPiPBoundsChange, lastEmittedBounds != bounds else { return }
310
+ lastEmittedBounds = bounds
311
+ onPiPBoundsChange(["width": bounds.width, "height": bounds.height])
287
312
  }
288
313
  }
@@ -13,6 +13,7 @@
13
13
  RCT_EXPORT_VIEW_PROPERTY(streamURL, NSString)
14
14
  RCT_EXPORT_VIEW_PROPERTY(mirror, BOOL)
15
15
  RCT_EXPORT_VIEW_PROPERTY(onPiPChange, RCTBubblingEventBlock)
16
+ RCT_EXPORT_VIEW_PROPERTY(onPiPBoundsChange, RCTBubblingEventBlock)
16
17
  RCT_EXPORT_VIEW_PROPERTY(participantName, NSString)
17
18
  RCT_EXPORT_VIEW_PROPERTY(participantImageURL, NSString)
18
19
  RCT_EXPORT_VIEW_PROPERTY(isReconnecting, BOOL)