twilio-video 2.18.1 → 2.18.2
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/CHANGELOG.md +8 -0
- package/COMMON_ISSUES.md +91 -8
- package/README.md +1 -1
- package/dist/twilio-video.js +79 -22
- package/dist/twilio-video.min.js +21 -21
- package/es5/media/track/localmediatrack.js +2 -0
- package/es5/media/track/localmediatrack.js.map +1 -1
- package/es5/media/track/remotevideotrack.js +68 -14
- package/es5/media/track/remotevideotrack.js.map +1 -1
- package/es5/signaling/v2/mediasignaling.js +2 -4
- package/es5/signaling/v2/mediasignaling.js.map +1 -1
- package/es5/signaling/v2/peerconnection.js +3 -1
- package/es5/signaling/v2/peerconnection.js.map +1 -1
- package/lib/media/track/localmediatrack.js +2 -0
- package/lib/media/track/remotevideotrack.js +74 -14
- package/lib/signaling/v2/mediasignaling.js +2 -5
- package/lib/signaling/v2/peerconnection.js +3 -1
- package/package.json +3 -2
|
@@ -67,6 +67,12 @@ class RemoteVideoTrack extends RemoteMediaVideoTrack {
|
|
|
67
67
|
_invisibleElements: {
|
|
68
68
|
value: new WeakSet(),
|
|
69
69
|
},
|
|
70
|
+
_elToPipCallbacks: {
|
|
71
|
+
value: new WeakMap(),
|
|
72
|
+
},
|
|
73
|
+
_elToPipWindows: {
|
|
74
|
+
value: new WeakMap(),
|
|
75
|
+
},
|
|
70
76
|
_turnOffTimer: {
|
|
71
77
|
value: new Timeout(() => {
|
|
72
78
|
this._setRenderHint({ enabled: false });
|
|
@@ -165,6 +171,50 @@ class RemoteVideoTrack extends RemoteMediaVideoTrack {
|
|
|
165
171
|
return this;
|
|
166
172
|
}
|
|
167
173
|
|
|
174
|
+
_unObservePip(el) {
|
|
175
|
+
const pipCallbacks = this._elToPipCallbacks.get(el);
|
|
176
|
+
if (pipCallbacks) {
|
|
177
|
+
el.removeEventListener('enterpictureinpicture', pipCallbacks.onEnterPip);
|
|
178
|
+
el.removeEventListener('leavepictureinpicture', pipCallbacks.onLeavePip);
|
|
179
|
+
this._elToPipCallbacks.delete(el);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
_observePip(el) {
|
|
184
|
+
const pipCallbacks = this._elToPipCallbacks.get(el);
|
|
185
|
+
if (!pipCallbacks) {
|
|
186
|
+
const onEnterPip = event => this._onEnterPip(event, el);
|
|
187
|
+
const onLeavePip = event => this._onLeavePip(event, el);
|
|
188
|
+
const onResizePip = event => this._onResizePip(event, el);
|
|
189
|
+
|
|
190
|
+
el.addEventListener('enterpictureinpicture', onEnterPip);
|
|
191
|
+
el.addEventListener('leavepictureinpicture', onLeavePip);
|
|
192
|
+
this._elToPipCallbacks.set(el, { onEnterPip, onLeavePip, onResizePip });
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
_onEnterPip(event, videoEl) {
|
|
197
|
+
this._log.debug('onEnterPip');
|
|
198
|
+
const pipWindow = event.pictureInPictureWindow;
|
|
199
|
+
this._elToPipWindows.set(videoEl, pipWindow);
|
|
200
|
+
const { onResizePip } = this._elToPipCallbacks.get(videoEl);
|
|
201
|
+
pipWindow.addEventListener('resize', onResizePip);
|
|
202
|
+
maybeUpdateEnabledHint(this);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
_onLeavePip(event, videoEl) {
|
|
206
|
+
this._log.debug('onLeavePip');
|
|
207
|
+
this._elToPipWindows.delete(videoEl);
|
|
208
|
+
const { onResizePip } = this._elToPipCallbacks.get(videoEl);
|
|
209
|
+
const pipWindow = event.pictureInPictureWindow;
|
|
210
|
+
pipWindow.removeEventListener('resize', onResizePip);
|
|
211
|
+
maybeUpdateEnabledHint(this);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
_onResizePip() {
|
|
215
|
+
maybeUpdateDimensionHint(this);
|
|
216
|
+
}
|
|
217
|
+
|
|
168
218
|
attach(el) {
|
|
169
219
|
const result = super.attach(el);
|
|
170
220
|
|
|
@@ -181,6 +231,7 @@ class RemoteVideoTrack extends RemoteMediaVideoTrack {
|
|
|
181
231
|
this._documentVisibilityTurnOffCleanup = this._documentVisibilityTurnOffCleanup || setupDocumentVisibilityTurnOff(this);
|
|
182
232
|
}
|
|
183
233
|
|
|
234
|
+
this._observePip(result);
|
|
184
235
|
return result;
|
|
185
236
|
}
|
|
186
237
|
|
|
@@ -191,6 +242,7 @@ class RemoteVideoTrack extends RemoteMediaVideoTrack {
|
|
|
191
242
|
this._intersectionObserver.unobserve(element);
|
|
192
243
|
this._resizeObserver.unobserve(element);
|
|
193
244
|
this._invisibleElements.delete(element);
|
|
245
|
+
this._unObservePip(element);
|
|
194
246
|
});
|
|
195
247
|
|
|
196
248
|
if (this._attachments.size === 0) {
|
|
@@ -297,34 +349,42 @@ function setupDocumentVisibilityTurnOff(removeVideoTrack) {
|
|
|
297
349
|
};
|
|
298
350
|
}
|
|
299
351
|
|
|
300
|
-
function maybeUpdateEnabledHint(
|
|
301
|
-
if (
|
|
352
|
+
function maybeUpdateEnabledHint(remoteVideoTrack) {
|
|
353
|
+
if (remoteVideoTrack._clientTrackSwitchOffControl !== 'auto') {
|
|
302
354
|
return;
|
|
303
355
|
}
|
|
304
356
|
|
|
305
|
-
const visibleElements =
|
|
306
|
-
const
|
|
357
|
+
const visibleElements = remoteVideoTrack._getAllAttachedElements().filter(el => !remoteVideoTrack._invisibleElements.has(el));
|
|
358
|
+
const pipWindows = remoteVideoTrack._getAllAttachedElements().filter(el => remoteVideoTrack._elToPipWindows.has(el));
|
|
359
|
+
|
|
360
|
+
// even when document is invisible we may have track playing in pip window.
|
|
361
|
+
const enabled = pipWindows.length > 0 || (document.visibilityState === 'visible' && visibleElements.length > 0);
|
|
307
362
|
|
|
308
363
|
if (enabled === true) {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
} else if (!
|
|
364
|
+
remoteVideoTrack._turnOffTimer.clear();
|
|
365
|
+
remoteVideoTrack._setRenderHint({ enabled: true });
|
|
366
|
+
} else if (!remoteVideoTrack._turnOffTimer.isSet) {
|
|
312
367
|
// set the track to be turned off after some delay.
|
|
313
|
-
|
|
368
|
+
remoteVideoTrack._turnOffTimer.start();
|
|
314
369
|
}
|
|
315
370
|
}
|
|
316
371
|
|
|
317
|
-
function maybeUpdateDimensionHint(
|
|
318
|
-
if (
|
|
372
|
+
function maybeUpdateDimensionHint(remoteVideoTrack) {
|
|
373
|
+
if (remoteVideoTrack._contentPreferencesMode !== 'auto') {
|
|
319
374
|
return;
|
|
320
375
|
}
|
|
321
376
|
|
|
322
|
-
const visibleElements =
|
|
323
|
-
|
|
324
|
-
const
|
|
377
|
+
const visibleElements = remoteVideoTrack._getAllAttachedElements().filter(el => !remoteVideoTrack._invisibleElements.has(el));
|
|
378
|
+
const pipElements = remoteVideoTrack._getAllAttachedElements().map(el => {
|
|
379
|
+
const pipWindow = remoteVideoTrack._elToPipWindows.get(el);
|
|
380
|
+
return pipWindow ? { clientHeight: pipWindow.height, clientWidth: pipWindow.width } : { clientHeight: 0, clientWidth: 0 };
|
|
381
|
+
});
|
|
382
|
+
const totalElements = visibleElements.concat(pipElements);
|
|
383
|
+
if (totalElements.length > 0) {
|
|
384
|
+
const [{ clientHeight, clientWidth }] = totalElements.sort((el1, el2) =>
|
|
325
385
|
el2.clientHeight + el2.clientWidth - el1.clientHeight - el1.clientWidth - 1);
|
|
326
386
|
const renderDimensions = { height: clientHeight, width: clientWidth };
|
|
327
|
-
|
|
387
|
+
remoteVideoTrack._setRenderHint({ renderDimensions });
|
|
328
388
|
}
|
|
329
389
|
}
|
|
330
390
|
|
|
@@ -50,19 +50,16 @@ class MediaSignaling extends EventEmitter {
|
|
|
50
50
|
const receiverPromise = this._getReceiver(id).then(receiver => {
|
|
51
51
|
if (receiver.kind !== 'data') {
|
|
52
52
|
this._log.error('Expected a DataTrackReceiver');
|
|
53
|
-
throw new Error('Expected a DataTrackReceiver');
|
|
54
53
|
} if (this._receiverPromise !== receiverPromise) {
|
|
55
54
|
return;
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
try {
|
|
59
58
|
this._transport = receiver.toDataTransport();
|
|
59
|
+
this.emit('ready', this._transport);
|
|
60
60
|
} catch (ex) {
|
|
61
|
-
this._log.error(
|
|
62
|
-
throw new Error('Failed to toDataTransport');
|
|
61
|
+
this._log.error(`Failed to toDataTransport: ${ex.message}`);
|
|
63
62
|
}
|
|
64
|
-
this.emit('ready', this._transport);
|
|
65
|
-
|
|
66
63
|
receiver.once('close', () => this._teardown());
|
|
67
64
|
});
|
|
68
65
|
this._receiverPromise = receiverPromise;
|
|
@@ -904,7 +904,9 @@ class PeerConnectionV2 extends StateMachine {
|
|
|
904
904
|
log.debug(`Starting ICE reconnect timeout: ${delay}`);
|
|
905
905
|
this._iceReconnectTimeout.start();
|
|
906
906
|
}
|
|
907
|
-
this.offer()
|
|
907
|
+
this.offer().catch(ex => {
|
|
908
|
+
log.error(`offer failed in _initiateIceRestart with: ${ex.message}`);
|
|
909
|
+
});
|
|
908
910
|
}
|
|
909
911
|
|
|
910
912
|
/**
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "twilio-video",
|
|
3
3
|
"title": "Twilio Video",
|
|
4
4
|
"description": "Twilio Video JavaScript Library",
|
|
5
|
-
"version": "2.18.
|
|
5
|
+
"version": "2.18.2",
|
|
6
6
|
"homepage": "https://twilio.com",
|
|
7
7
|
"author": "Mark Andrus Roberts <mroberts@twilio.com>",
|
|
8
8
|
"contributors": [
|
|
@@ -97,7 +97,8 @@
|
|
|
97
97
|
"lint:js": "eslint ./lib ./test/*.js ./docker/**/*.js ./test/framework/*.js ./test/lib/*.js ./test/integration/** ./test/unit/** ",
|
|
98
98
|
"lint:ts": "eslint ./tsdef/*.ts ./lib/**/*.ts",
|
|
99
99
|
"lint": "npm-run-all lint:js lint:ts",
|
|
100
|
-
"
|
|
100
|
+
"printVersion": "node --version && npm --version",
|
|
101
|
+
"test:unit": "npm-run-all printVersion build:es5 test:unit:js test:unit:ts",
|
|
101
102
|
"test:unit:js": "nyc --report-dir=./coverage/js --extension=.js --include=lib/**/* --reporter=html --reporter=lcov --reporter=text mocha ./test/unit/index.js",
|
|
102
103
|
"test:unit:ts": "nyc --report-dir=./coverage/ts --extension=.ts --include=lib/**/* --reporter=html --reporter=lcov --reporter=text mocha -r ts-node/register ./test/unit/index.ts",
|
|
103
104
|
"test:serversiderender": "mocha ./test/serversiderender/index.js",
|