livekit-client 1.7.1 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. package/README.md +20 -1
  2. package/dist/livekit-client.esm.mjs +2178 -1060
  3. package/dist/livekit-client.esm.mjs.map +1 -1
  4. package/dist/livekit-client.umd.js +1 -1
  5. package/dist/livekit-client.umd.js.map +1 -1
  6. package/dist/src/index.d.ts +3 -1
  7. package/dist/src/index.d.ts.map +1 -1
  8. package/dist/src/proto/google/protobuf/timestamp.d.ts.map +1 -1
  9. package/dist/src/proto/livekit_models.d.ts +32 -0
  10. package/dist/src/proto/livekit_models.d.ts.map +1 -1
  11. package/dist/src/proto/livekit_rtc.d.ts +315 -75
  12. package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
  13. package/dist/src/room/RTCEngine.d.ts +8 -1
  14. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  15. package/dist/src/room/ReconnectPolicy.d.ts +1 -0
  16. package/dist/src/room/ReconnectPolicy.d.ts.map +1 -1
  17. package/dist/src/room/RegionUrlProvider.d.ts +14 -0
  18. package/dist/src/room/RegionUrlProvider.d.ts.map +1 -0
  19. package/dist/src/room/Room.d.ts +4 -0
  20. package/dist/src/room/Room.d.ts.map +1 -1
  21. package/dist/src/room/errors.d.ts +2 -1
  22. package/dist/src/room/errors.d.ts.map +1 -1
  23. package/dist/src/room/events.d.ts +8 -2
  24. package/dist/src/room/events.d.ts.map +1 -1
  25. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  26. package/dist/src/room/track/LocalTrack.d.ts +3 -2
  27. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  28. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  29. package/dist/src/room/track/RemoteTrackPublication.d.ts +1 -1
  30. package/dist/src/room/track/RemoteTrackPublication.d.ts.map +1 -1
  31. package/dist/src/room/track/RemoteVideoTrack.d.ts +1 -1
  32. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  33. package/dist/src/room/track/Track.d.ts +3 -1
  34. package/dist/src/room/track/Track.d.ts.map +1 -1
  35. package/dist/src/room/types.d.ts +4 -0
  36. package/dist/src/room/types.d.ts.map +1 -1
  37. package/dist/src/room/utils.d.ts +4 -0
  38. package/dist/src/room/utils.d.ts.map +1 -1
  39. package/dist/ts4.2/src/index.d.ts +3 -1
  40. package/dist/ts4.2/src/proto/livekit_models.d.ts +32 -0
  41. package/dist/ts4.2/src/proto/livekit_rtc.d.ts +348 -84
  42. package/dist/ts4.2/src/room/RTCEngine.d.ts +8 -1
  43. package/dist/ts4.2/src/room/ReconnectPolicy.d.ts +1 -0
  44. package/dist/ts4.2/src/room/RegionUrlProvider.d.ts +14 -0
  45. package/dist/ts4.2/src/room/Room.d.ts +4 -0
  46. package/dist/ts4.2/src/room/errors.d.ts +2 -1
  47. package/dist/ts4.2/src/room/events.d.ts +8 -2
  48. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +3 -2
  49. package/dist/ts4.2/src/room/track/RemoteTrackPublication.d.ts +1 -1
  50. package/dist/ts4.2/src/room/track/RemoteVideoTrack.d.ts +1 -1
  51. package/dist/ts4.2/src/room/track/Track.d.ts +3 -1
  52. package/dist/ts4.2/src/room/types.d.ts +4 -0
  53. package/dist/ts4.2/src/room/utils.d.ts +4 -0
  54. package/package.json +19 -19
  55. package/src/api/SignalClient.ts +4 -4
  56. package/src/index.ts +3 -0
  57. package/src/proto/google/protobuf/timestamp.ts +15 -6
  58. package/src/proto/livekit_models.ts +903 -222
  59. package/src/proto/livekit_rtc.ts +1053 -279
  60. package/src/room/RTCEngine.ts +143 -40
  61. package/src/room/ReconnectPolicy.ts +2 -0
  62. package/src/room/RegionUrlProvider.ts +73 -0
  63. package/src/room/Room.ts +201 -132
  64. package/src/room/errors.ts +1 -0
  65. package/src/room/events.ts +7 -0
  66. package/src/room/track/LocalAudioTrack.ts +13 -6
  67. package/src/room/track/LocalTrack.ts +22 -8
  68. package/src/room/track/LocalVideoTrack.ts +12 -6
  69. package/src/room/track/RemoteTrackPublication.ts +4 -3
  70. package/src/room/track/RemoteVideoTrack.ts +5 -4
  71. package/src/room/track/Track.ts +46 -31
  72. package/src/room/types.ts +6 -0
  73. package/src/room/utils.ts +53 -0
@@ -42,7 +42,7 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
42
42
 
43
43
  protected _mediaStreamID: string;
44
44
 
45
- protected isInBackground: boolean;
45
+ protected isInBackground: boolean = false;
46
46
 
47
47
  private backgroundTimeout: ReturnType<typeof setTimeout> | undefined;
48
48
 
@@ -57,12 +57,6 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
57
57
  this._mediaStreamTrack = mediaTrack;
58
58
  this._mediaStreamID = mediaTrack.id;
59
59
  this.source = Track.Source.Unknown;
60
- if (isWeb()) {
61
- this.isInBackground = document.visibilityState === 'hidden';
62
- document.addEventListener('visibilitychange', this.appVisibilityChangedListener);
63
- } else {
64
- this.isInBackground = false;
65
- }
66
60
  }
67
61
 
68
62
  /** current receive bits per second */
@@ -97,6 +91,9 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
97
91
  if (this.kind === Track.Kind.Video) {
98
92
  elementType = 'video';
99
93
  }
94
+ if (this.attachedElements.length === 0 && Track.Kind.Video) {
95
+ this.addAppVisibilityListener();
96
+ }
100
97
  if (!element) {
101
98
  if (elementType === 'audio') {
102
99
  recycledElements.forEach((e) => {
@@ -167,37 +164,40 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
167
164
  */
168
165
  detach(element: HTMLMediaElement): HTMLMediaElement;
169
166
  detach(element?: HTMLMediaElement): HTMLMediaElement | HTMLMediaElement[] {
170
- // detach from a single element
171
- if (element) {
172
- detachTrack(this._mediaStreamTrack, element);
173
- const idx = this.attachedElements.indexOf(element);
174
- if (idx >= 0) {
175
- this.attachedElements.splice(idx, 1);
176
- this.recycleElement(element);
177
- this.emit(TrackEvent.ElementDetached, element);
167
+ try {
168
+ // detach from a single element
169
+ if (element) {
170
+ detachTrack(this._mediaStreamTrack, element);
171
+ const idx = this.attachedElements.indexOf(element);
172
+ if (idx >= 0) {
173
+ this.attachedElements.splice(idx, 1);
174
+ this.recycleElement(element);
175
+ this.emit(TrackEvent.ElementDetached, element);
176
+ }
177
+ return element;
178
178
  }
179
- return element;
180
- }
181
179
 
182
- const detached: HTMLMediaElement[] = [];
183
- this.attachedElements.forEach((elm) => {
184
- detachTrack(this._mediaStreamTrack, elm);
185
- detached.push(elm);
186
- this.recycleElement(elm);
187
- this.emit(TrackEvent.ElementDetached, elm);
188
- });
180
+ const detached: HTMLMediaElement[] = [];
181
+ this.attachedElements.forEach((elm) => {
182
+ detachTrack(this._mediaStreamTrack, elm);
183
+ detached.push(elm);
184
+ this.recycleElement(elm);
185
+ this.emit(TrackEvent.ElementDetached, elm);
186
+ });
189
187
 
190
- // remove all tracks
191
- this.attachedElements = [];
192
- return detached;
188
+ // remove all tracks
189
+ this.attachedElements = [];
190
+ return detached;
191
+ } finally {
192
+ if (this.attachedElements.length === 0) {
193
+ this.removeAppVisibilityListener();
194
+ }
195
+ }
193
196
  }
194
197
 
195
198
  stop() {
196
199
  this.stopMonitor();
197
200
  this._mediaStreamTrack.stop();
198
- if (isWeb()) {
199
- document.removeEventListener('visibilitychange', this.appVisibilityChangedListener);
200
- }
201
201
  }
202
202
 
203
203
  protected enable() {
@@ -212,7 +212,7 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
212
212
  abstract startMonitor(signalClient?: SignalClient): void;
213
213
 
214
214
  /* @internal */
215
- protected stopMonitor() {
215
+ stopMonitor() {
216
216
  if (this.monitorInterval) {
217
217
  clearInterval(this.monitorInterval);
218
218
  }
@@ -253,6 +253,21 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
253
253
  protected async handleAppVisibilityChanged() {
254
254
  this.isInBackground = document.visibilityState === 'hidden';
255
255
  }
256
+
257
+ protected addAppVisibilityListener() {
258
+ if (isWeb()) {
259
+ this.isInBackground = document.visibilityState === 'hidden';
260
+ document.addEventListener('visibilitychange', this.appVisibilityChangedListener);
261
+ } else {
262
+ this.isInBackground = false;
263
+ }
264
+ }
265
+
266
+ protected removeAppVisibilityListener() {
267
+ if (isWeb()) {
268
+ document.removeEventListener('visibilitychange', this.appVisibilityChangedListener);
269
+ }
270
+ }
256
271
  }
257
272
 
258
273
  /** @internal */
package/src/room/types.ts CHANGED
@@ -20,3 +20,9 @@ export type DataPublishOptions = {
20
20
  /** the topic under which the message gets published */
21
21
  topic?: string;
22
22
  };
23
+
24
+ export type LiveKitReactNativeInfo = {
25
+ // Corresponds to RN's PlatformOSType
26
+ platform: 'ios' | 'android' | 'windows' | 'macos' | 'web' | 'native';
27
+ devicePixelRatio: number;
28
+ };
package/src/room/utils.ts CHANGED
@@ -4,6 +4,7 @@ import { protocolVersion, version } from '../version';
4
4
  import type LocalAudioTrack from './track/LocalAudioTrack';
5
5
  import type RemoteAudioTrack from './track/RemoteAudioTrack';
6
6
  import { getNewAudioContext } from './track/utils';
7
+ import type { LiveKitReactNativeInfo } from './types';
7
8
 
8
9
  const separator = '|';
9
10
 
@@ -122,6 +123,54 @@ export function isWeb(): boolean {
122
123
  return typeof document !== 'undefined';
123
124
  }
124
125
 
126
+ export function isReactNative(): boolean {
127
+ // navigator.product is deprecated on browsers, but will be set appropriately for react-native.
128
+ return navigator.product == 'ReactNative';
129
+ }
130
+
131
+ export function isCloud(serverUrl: URL) {
132
+ return serverUrl.hostname.endsWith('.livekit.cloud');
133
+ }
134
+
135
+ function getLKReactNativeInfo(): LiveKitReactNativeInfo | undefined {
136
+ // global defined only for ReactNative.
137
+ // @ts-ignore
138
+ if (global && global.LiveKitReactNativeGlobal) {
139
+ // @ts-ignore
140
+ return global.LiveKitReactNativeGlobal as LiveKitReactNativeInfo;
141
+ }
142
+
143
+ return undefined;
144
+ }
145
+
146
+ export function getReactNativeOs(): string | undefined {
147
+ if (!isReactNative()) {
148
+ return undefined;
149
+ }
150
+
151
+ let info = getLKReactNativeInfo();
152
+ if (info) {
153
+ return info.platform;
154
+ }
155
+
156
+ return undefined;
157
+ }
158
+
159
+ export function getDevicePixelRatio(): number {
160
+ if (isWeb()) {
161
+ return window.devicePixelRatio;
162
+ }
163
+
164
+ if (isReactNative()) {
165
+ let info = getLKReactNativeInfo();
166
+ if (info) {
167
+ return info.devicePixelRatio;
168
+ }
169
+ }
170
+
171
+ return 1;
172
+ }
173
+
125
174
  export function compareVersions(v1: string, v2: string): number {
126
175
  const parts1 = v1.split('.');
127
176
  const parts2 = v2.split('.');
@@ -174,6 +223,10 @@ export function getClientInfo(): ClientInfo {
174
223
  protocol: protocolVersion,
175
224
  version,
176
225
  });
226
+
227
+ if (isReactNative()) {
228
+ info.os = getReactNativeOs() ?? '';
229
+ }
177
230
  return info;
178
231
  }
179
232