Quellcode durchsuchen

feat: add config.startScreenSharing

Will try to use screensharing instead of camera video from
the beginning.
j8
paweldomas vor 7 Jahren
Ursprung
Commit
3926d705ad
5 geänderte Dateien mit 303 neuen und 147 gelöschten Zeilen
  1. 248
    138
      conference.js
  2. 1
    0
      config.js
  3. 2
    0
      lang/main.json
  4. 52
    3
      modules/UI/UI.js
  5. 0
    6
      service/UI/UIEvents.js

+ 248
- 138
conference.js Datei anzeigen

@@ -78,11 +78,6 @@ let connection;
78 78
 let localAudio, localVideo;
79 79
 let initialAudioMutedState = false, initialVideoMutedState = false;
80 80
 
81
-/**
82
- * Indicates whether extension external installation is in progress or not.
83
- */
84
-let DSExternalInstallationInProgress = false;
85
-
86 81
 import {VIDEO_CONTAINER_TYPE} from "./modules/UI/videolayout/VideoContainer";
87 82
 
88 83
 /*
@@ -498,11 +493,14 @@ export default {
498 493
      * show guidance overlay for users on how to give access to camera and/or
499 494
      * microphone,
500 495
      * @param {string} roomName
496
+     * @param {boolean} startScreenSharing - if <tt>true</tt> should start with
497
+     * screensharing instead of camera video.
501 498
      * @returns {Promise.<JitsiLocalTrack[], JitsiConnection>}
502 499
      */
503
-    createInitialLocalTracksAndConnect(roomName) {
500
+    createInitialLocalTracksAndConnect(roomName, startScreenSharing) {
504 501
         let audioAndVideoError,
505 502
             audioOnlyError,
503
+            screenSharingError,
506 504
             videoOnlyError;
507 505
 
508 506
         JitsiMeetJS.mediaDevices.addEventListener(
@@ -513,31 +511,55 @@ export default {
513 511
         );
514 512
 
515 513
         // First try to retrieve both audio and video.
516
-        let tryCreateLocalTracks = createLocalTracks(
517
-            { devices: ['audio', 'video'] }, true)
518
-            .catch(err => {
519
-                // If failed then try to retrieve only audio.
520
-                audioAndVideoError = err;
521
-                return createLocalTracks({ devices: ['audio'] }, true);
522
-            })
523
-            .catch(err => {
524
-                audioOnlyError = err;
525
-
526
-                // Try video only...
527
-                return createLocalTracks({ devices: ['video'] }, true);
528
-            })
529
-            .catch(err => {
530
-                videoOnlyError = err;
531
-
532
-                return [];
533
-            });
514
+        let tryCreateLocalTracks;
515
+
516
+        // FIXME the logic about trying to go audio only on error is duplicated
517
+        if (startScreenSharing) {
518
+            tryCreateLocalTracks = this._createDesktopTrack()
519
+                .then(desktopStream => {
520
+                    return createLocalTracks({ devices: ['audio'] }, true)
521
+                        .then(([audioStream]) => {
522
+                            return [desktopStream, audioStream];
523
+                        })
524
+                        .catch(error => {
525
+                            audioOnlyError = error;
526
+                            return [desktopStream];
527
+                        });
528
+                }).catch(error => {
529
+                    logger.error('Failed to obtain desktop stream', error);
530
+                    screenSharingError = error;
531
+                    return createLocalTracks({ devices: ['audio'] }, true);
532
+                }).catch(error => {
533
+                    audioOnlyError = error;
534
+                    return [];
535
+                });
536
+        } else {
537
+            tryCreateLocalTracks = createLocalTracks(
538
+                {devices: ['audio', 'video']}, true)
539
+                .catch(err => {
540
+                    // If failed then try to retrieve only audio.
541
+                    audioAndVideoError = err;
542
+                    return createLocalTracks({devices: ['audio']}, true);
543
+                })
544
+                .catch(err => {
545
+                    audioOnlyError = err;
546
+
547
+                    // Try video only...
548
+                    return createLocalTracks({devices: ['video']}, true);
549
+                })
550
+                .catch(err => {
551
+                    videoOnlyError = err;
552
+
553
+                    return [];
554
+                });
555
+        }
534 556
 
535 557
         return Promise.all([ tryCreateLocalTracks, connect(roomName) ])
536 558
             .then(([tracks, con]) => {
537 559
                 APP.store.dispatch(
538 560
                     mediaPermissionPromptVisibilityChanged(false));
539
-                if (audioAndVideoError) {
540
-                    if (audioOnlyError) {
561
+                if (audioAndVideoError || audioOnlyError) {
562
+                    if (audioOnlyError || videoOnlyError) {
541 563
                         // If both requests for 'audio' + 'video' and 'audio'
542 564
                         // only failed, we assume that there is some problems
543 565
                         // with user's microphone and show corresponding dialog.
@@ -551,6 +573,18 @@ export default {
551 573
                     }
552 574
                 }
553 575
 
576
+                // FIXME If there was a screen sharing error or the extension
577
+                // needs to be installed it will appear on top of eventual
578
+                // "microphone error" dialog. That is not great, but currently
579
+                // it's pretty hard to chain dialogs since they don't return
580
+                // Promises.
581
+                if (screenSharingError) {
582
+                    // FIXME if _handleScreenSharingError will be dealing with
583
+                    // installing external extension it may close previously
584
+                    // opened microphone dialog ($.prompt.close(); is called).
585
+                    this._handleScreenSharingError(screenSharingError);
586
+                }
587
+
554 588
                 return [tracks, con];
555 589
             });
556 590
     },
@@ -591,7 +625,8 @@ export default {
591 625
             ).then(() => {
592 626
                 analytics.init();
593 627
                 return this.createInitialLocalTracksAndConnect(
594
-                    options.roomName);
628
+                    options.roomName,
629
+                    config.startScreenSharing);
595 630
             }).then(([tracks, con]) => {
596 631
                 tracks.forEach(track => {
597 632
                     if((track.isAudioTrack() && initialAudioMutedState)
@@ -1197,7 +1232,6 @@ export default {
1197 1232
 
1198 1233
     /**
1199 1234
      * Toggles between screensharing and camera video.
1200
-     * @param {boolean} [shareScreen]
1201 1235
      * @param {Object} [options] - Screen sharing options that will be passed to
1202 1236
      * createLocalTracks.
1203 1237
      * @param {Array<string>} [options.desktopSharingSources] - Array with the
@@ -1221,118 +1255,205 @@ export default {
1221 1255
         }
1222 1256
 
1223 1257
         if (!this._untoggleScreenSharing) {
1224
-            this.videoSwitchInProgress = true;
1225
-            let externalInstallation = false;
1226
-            const didHaveVideo = Boolean(localVideo);
1227
-            const wasVideoMuted = this.videoMuted;
1228
-
1229
-            return createLocalTracks({
1230
-                desktopSharingSources: options.desktopSharingSources,
1231
-                devices: ['desktop'],
1232
-                desktopSharingExtensionExternalInstallation: {
1233
-                    interval: 500,
1234
-                    checkAgain: () => {
1235
-                        return DSExternalInstallationInProgress;
1236
-                    },
1237
-                    listener: (status, url) => {
1238
-                        switch(status) {
1239
-                            case "waitingForExtension":
1240
-                                DSExternalInstallationInProgress = true;
1241
-                                externalInstallation = true;
1242
-                                APP.UI.showExtensionExternalInstallationDialog(
1243
-                                    url);
1244
-                                break;
1245
-                            case "extensionFound":
1246
-                                if(externalInstallation) //close the dialog
1247
-                                    $.prompt.close();
1248
-                                break;
1249
-                            default:
1250
-                                //Unknown status
1258
+            return this._switchToScreenSharing(options);
1259
+        } else {
1260
+            return this._untoggleScreenSharing();
1261
+        }
1262
+    },
1263
+
1264
+    /**
1265
+     * Creates desktop (screensharing) {@link JitsiLocalTrack}
1266
+     * @param {Object} [options] - Screen sharing options that will be passed to
1267
+     * createLocalTracks.
1268
+     *
1269
+     * @return {Promise.<JitsiLocalTrack>} - A Promise resolved with
1270
+     * {@link JitsiLocalTrack} for the screensharing or rejected with
1271
+     * {@link JitsiTrackError}.
1272
+     *
1273
+     * @private
1274
+     */
1275
+    _createDesktopTrack(options = {}) {
1276
+        let externalInstallation = false;
1277
+        let DSExternalInstallationInProgress = false;
1278
+        const didHaveVideo = Boolean(localVideo);
1279
+        const wasVideoMuted = this.videoMuted;
1280
+
1281
+        return createLocalTracks({
1282
+            desktopSharingSources: options.desktopSharingSources,
1283
+            devices: ['desktop'],
1284
+            desktopSharingExtensionExternalInstallation: {
1285
+                interval: 500,
1286
+                checkAgain: () => {
1287
+                    return DSExternalInstallationInProgress;
1288
+                },
1289
+                listener: (status, url) => {
1290
+                    switch(status) {
1291
+                        case "waitingForExtension": {
1292
+                            DSExternalInstallationInProgress = true;
1293
+                            externalInstallation = true;
1294
+                            const listener = () => {
1295
+                                // Wait a little bit more just to be sure that
1296
+                                // we won't miss the extension installation
1297
+                                setTimeout(
1298
+                                    () => {
1299
+                                    DSExternalInstallationInProgress = false;
1300
+                                    }, 500);
1301
+                                APP.UI.removeListener(
1302
+                                    UIEvents.EXTERNAL_INSTALLATION_CANCELED,
1303
+                                    listener);
1304
+                            };
1305
+                            APP.UI.addListener(
1306
+                                UIEvents.EXTERNAL_INSTALLATION_CANCELED,
1307
+                                listener);
1308
+                            APP.UI.showExtensionExternalInstallationDialog(url);
1309
+                            break;
1310
+                        }
1311
+                        case "extensionFound": {
1312
+                            if (externalInstallation) //close the dialog
1313
+                                $.prompt.close();
1314
+                            break;
1315
+                        }
1316
+                        default: {
1317
+                            //Unknown status
1251 1318
                         }
1252 1319
                     }
1253 1320
                 }
1254
-            }).then(([stream]) => {
1255
-                // Stores the "untoggle" handler which remembers whether was
1256
-                // there any video before and whether was it muted.
1257
-                this._untoggleScreenSharing
1258
-                    = this._turnScreenSharingOff
1259
-                          .bind(this, didHaveVideo, wasVideoMuted);
1260
-                DSExternalInstallationInProgress = false;
1261
-                // close external installation dialog on success.
1262
-                if(externalInstallation)
1263
-                    $.prompt.close();
1264
-                stream.on(
1265
-                    TrackEvents.LOCAL_TRACK_STOPPED,
1266
-                    () => {
1267
-                        // If the stream was stopped during screen sharing
1268
-                        // session then we should switch back to video.
1269
-                        if (this.isSharingScreen){
1270
-                            this._untoggleScreenSharing
1271
-                                && this._untoggleScreenSharing();
1272
-                        }
1321
+            }
1322
+        }).then(([desktopStream])=> {
1323
+            // Stores the "untoggle" handler which remembers whether was
1324
+            // there any video before and whether was it muted.
1325
+            this._untoggleScreenSharing
1326
+                = this._turnScreenSharingOff
1327
+                      .bind(this, didHaveVideo, wasVideoMuted);
1328
+            desktopStream.on(
1329
+                TrackEvents.LOCAL_TRACK_STOPPED,
1330
+                () => {
1331
+                    // If the stream was stopped during screen sharing
1332
+                    // session then we should switch back to video.
1333
+                    if (this.isSharingScreen) {
1334
+                        this._untoggleScreenSharing
1335
+                            && this._untoggleScreenSharing();
1273 1336
                     }
1274
-                );
1275
-                return this.useVideoStream(stream);
1276
-            }).then(() => {
1277
-                this.videoSwitchInProgress = false;
1278
-                JitsiMeetJS.analytics.sendEvent(
1279
-                    'conference.sharingDesktop.start');
1280
-                logger.log('sharing local desktop');
1281
-            }).catch(err => {
1282
-                // close external installation dialog to show the error.
1283
-                if(externalInstallation)
1284
-                    $.prompt.close();
1285
-                this.videoSwitchInProgress = false;
1286
-
1287
-                if (err.name === TrackErrors.CHROME_EXTENSION_USER_CANCELED) {
1288
-                    return Promise.reject(err);
1289 1337
                 }
1338
+            );
1339
+            // close external installation dialog on success.
1340
+            if (externalInstallation) {
1341
+                $.prompt.close();
1342
+            }
1343
+            return desktopStream;
1344
+        }, error => {
1345
+            DSExternalInstallationInProgress = false;
1346
+            // close external installation dialog on success.
1347
+            if (externalInstallation) {
1348
+                $.prompt.close();
1349
+            }
1350
+            throw error;
1351
+        });
1352
+    },
1290 1353
 
1291
-                // Pawel: With this call I'm trying to preserve the original
1292
-                // behaviour although it is not clear why would we "untoggle"
1293
-                // on failure. I suppose it was to restore video in case there
1294
-                // was some problem during "this.useVideoStream(desktopStream)".
1295
-                // It's important to note that the handler will not be available
1296
-                // if we fail early on trying to get desktop media (which makes
1297
-                // sense, because the camera video is still being used, so
1298
-                // nothing to "untoggle").
1299
-                if (this._untoggleScreenSharing) {
1300
-                    this._untoggleScreenSharing();
1301
-                }
1354
+    /**
1355
+     * Tries to switch to the screenshairng mode by disposing camera stream and
1356
+     * replacing it with a desktop one.
1357
+     *
1358
+     * @param {Object} [options] - Screen sharing options that will be passed to
1359
+     * createLocalTracks.
1360
+     *
1361
+     * @return {Promise} - A Promise resolved if the operation succeeds or
1362
+     * rejected with some unknown type of error in case it fails. Promise will
1363
+     * be rejected immediately if {@link videoSwitchInProgress} is true.
1364
+     *
1365
+     * @private
1366
+     */
1367
+    _switchToScreenSharing(options = {}) {
1368
+        if (this.videoSwitchInProgress) {
1369
+            return Promise.reject('Switch in progress.');
1370
+        }
1302 1371
 
1303
-                logger.error('failed to share local desktop', err);
1372
+        this.videoSwitchInProgress = true;
1373
+        return this._createDesktopTrack(options).then(stream => {
1374
+            return this.useVideoStream(stream);
1375
+        }).then(() => {
1376
+            this.videoSwitchInProgress = false;
1377
+            JitsiMeetJS.analytics.sendEvent('conference.sharingDesktop.start');
1378
+            logger.log('sharing local desktop');
1379
+        }).catch(error => {
1380
+            this.videoSwitchInProgress = false;
1381
+            // Pawel: With this call I'm trying to preserve the original
1382
+            // behaviour although it is not clear why would we "untoggle"
1383
+            // on failure. I suppose it was to restore video in case there
1384
+            // was some problem during "this.useVideoStream(desktopStream)".
1385
+            // It's important to note that the handler will not be available
1386
+            // if we fail early on trying to get desktop media (which makes
1387
+            // sense, because the camera video is still being used, so
1388
+            // nothing to "untoggle").
1389
+            if (this._untoggleScreenSharing) {
1390
+                this._untoggleScreenSharing();
1391
+            }
1304 1392
 
1305
-                if (err.name === TrackErrors.FIREFOX_EXTENSION_NEEDED) {
1306
-                    APP.UI.showExtensionRequiredDialog(
1307
-                        config.desktopSharingFirefoxExtensionURL
1308
-                    );
1309
-                    return Promise.reject(err);
1310
-                }
1393
+            // FIXME the code inside of _handleScreenSharingError is
1394
+            // asynchronous, but does not return a Promise and is not part of
1395
+            // the current Promise chain.
1396
+            this._handleScreenSharingError(error);
1397
+        });
1398
+    },
1311 1399
 
1312
-                // Handling:
1313
-                // TrackErrors.PERMISSION_DENIED
1314
-                // TrackErrors.CHROME_EXTENSION_INSTALLATION_ERROR
1315
-                // TrackErrors.GENERAL
1316
-                // and any other
1317
-                let dialogTxt;
1318
-                let dialogTitleKey;
1319
-
1320
-                if (err.name === TrackErrors.PERMISSION_DENIED) {
1321
-                    dialogTxt = APP.translation.generateTranslationHTML(
1322
-                        "dialog.screenSharingPermissionDeniedError");
1323
-                    dialogTitleKey = "dialog.error";
1324
-                } else {
1325
-                    dialogTxt = APP.translation.generateTranslationHTML(
1326
-                        "dialog.failtoinstall");
1327
-                    dialogTitleKey = "dialog.permissionDenied";
1400
+    /**
1401
+     * Handles {@link JitsiTrackError} returned by the lib-jitsi-meet when
1402
+     * trying to create screensharing track. It will either do nothing if
1403
+     * the dialog was canceled on user's request or display inline installation
1404
+     * dialog and ask the user to install the extension, once the extension is
1405
+     * installed it will switch the conference to screensharing. The last option
1406
+     * is that an unrecoverable error dialog will be displayed.
1407
+     * @param {JitsiTrackError} error - The error returned by
1408
+     * {@link _createDesktopTrack} Promise.
1409
+     * @private
1410
+     */
1411
+    _handleScreenSharingError(error) {
1412
+        if (error.name === TrackErrors.CHROME_EXTENSION_USER_CANCELED) {
1413
+            return;
1414
+        }
1415
+
1416
+        logger.error('failed to share local desktop', error);
1417
+
1418
+        if (error.name === TrackErrors.CHROME_EXTENSION_USER_GESTURE_REQUIRED) {
1419
+            // If start with screen sharing the extension will fail to install
1420
+            // (if not found), because the request has been triggered by the
1421
+            // script. Show a dialog which asks user to click "install" and try
1422
+            // again switching to the screen sharing.
1423
+            APP.UI.showExtensionInlineInstallationDialog(
1424
+                () => {
1425
+                    this.toggleScreenSharing();
1328 1426
                 }
1427
+            );
1329 1428
 
1330
-                APP.UI.messageHandler.openDialog(
1331
-                    dialogTitleKey, dialogTxt, false);
1332
-            });
1429
+            return;
1430
+        } else if (error.name === TrackErrors.FIREFOX_EXTENSION_NEEDED) {
1431
+            APP.UI.showExtensionRequiredDialog(
1432
+                config.desktopSharingFirefoxExtensionURL
1433
+            );
1434
+
1435
+            return;
1436
+        }
1437
+
1438
+        // Handling:
1439
+        // TrackErrors.PERMISSION_DENIED
1440
+        // TrackErrors.CHROME_EXTENSION_INSTALLATION_ERROR
1441
+        // TrackErrors.GENERAL
1442
+        // and any other
1443
+        let dialogTxt;
1444
+        let dialogTitleKey;
1445
+
1446
+        if (error.name === TrackErrors.PERMISSION_DENIED) {
1447
+            dialogTxt = APP.translation.generateTranslationHTML(
1448
+                "dialog.screenSharingPermissionDeniedError");
1449
+            dialogTitleKey = "dialog.error";
1333 1450
         } else {
1334
-            return this._untoggleScreenSharing();
1451
+            dialogTxt = APP.translation.generateTranslationHTML(
1452
+                "dialog.failtoinstall");
1453
+            dialogTitleKey = "dialog.permissionDenied";
1335 1454
         }
1455
+
1456
+        APP.UI.messageHandler.openDialog(dialogTitleKey, dialogTxt, false);
1336 1457
     },
1337 1458
     /**
1338 1459
      * Setup interaction between conference and UI.
@@ -1619,17 +1740,6 @@ export default {
1619 1740
             APP.UI.updateDTMFSupport(isDTMFSupported);
1620 1741
         });
1621 1742
 
1622
-        APP.UI.addListener(UIEvents.EXTERNAL_INSTALLATION_CANCELED, () => {
1623
-            // Wait a little bit more just to be sure that we won't miss the
1624
-            // extension installation
1625
-            setTimeout(() => DSExternalInstallationInProgress = false, 500);
1626
-        });
1627
-        APP.UI.addListener(UIEvents.OPEN_EXTENSION_STORE, (url) => {
1628
-            window.open(
1629
-                url, "extension_store_window",
1630
-                "resizable,scrollbars=yes,status=1");
1631
-        });
1632
-
1633 1743
         APP.UI.addListener(UIEvents.AUDIO_MUTED, muteLocalAudio);
1634 1744
         APP.UI.addListener(UIEvents.VIDEO_MUTED, muted => {
1635 1745
             if (this.isAudioOnly() && !muted) {

+ 1
- 0
config.js Datei anzeigen

@@ -69,6 +69,7 @@ var config = { // eslint-disable-line no-unused-vars
69 69
                               // page redirection when call is hangup
70 70
     disableSimulcast: false,
71 71
 //    requireDisplayName: true, // Forces the participants that doesn't have display name to enter it when they enter the room.
72
+    startScreenSharing: false, // Will try to start with screensharing instead of camera
72 73
 //    startAudioMuted: 10, // every participant after the Nth will start audio muted
73 74
 //    startVideoMuted: 10, // every participant after the Nth will start video muted
74 75
 //    defaultLanguage: "en",

+ 2
- 0
lang/main.json Datei anzeigen

@@ -332,6 +332,8 @@
332 332
         "goToStore": "Go to the webstore",
333 333
         "externalInstallationTitle": "Extension required",
334 334
         "externalInstallationMsg": "You need to install our desktop sharing extension.",
335
+        "inlineInstallationMsg": "You need to install our desktop sharing extension.",
336
+        "inlineInstallExtension": "Install now",
335 337
         "muteParticipantTitle": "Mute this participant?",
336 338
         "muteParticipantBody": "You won't be able to unmute them, but they can unmute themselves at any time.",
337 339
         "muteParticipantButton": "Mute",

+ 52
- 3
modules/UI/UI.js Datei anzeigen

@@ -1158,15 +1158,34 @@ UI.showExtensionRequiredDialog = function (url) {
1158 1158
  * @param url {string} the url of the extension.
1159 1159
  */
1160 1160
 UI.showExtensionExternalInstallationDialog = function (url) {
1161
+    let openedWindow = null;
1162
+
1161 1163
     let submitFunction = function(e,v){
1162 1164
         if (v) {
1163 1165
             e.preventDefault();
1164
-            eventEmitter.emit(UIEvents.OPEN_EXTENSION_STORE, url);
1166
+            if (openedWindow === null || openedWindow.closed) {
1167
+                openedWindow
1168
+                    = window.open(
1169
+                        url,
1170
+                        "extension_store_window",
1171
+                        "resizable,scrollbars=yes,status=1");
1172
+            } else {
1173
+                openedWindow.focus();
1174
+            }
1165 1175
         }
1166 1176
     };
1167 1177
 
1168
-    let closeFunction = function () {
1169
-        eventEmitter.emit(UIEvents.EXTERNAL_INSTALLATION_CANCELED);
1178
+    let closeFunction = function (e, v) {
1179
+        if (openedWindow) {
1180
+            // Ideally we would close the popup, but this does not seem to work
1181
+            // on Chrome. Leaving it uncommented in case it could work
1182
+            // in some version.
1183
+            openedWindow.close();
1184
+            openedWindow = null;
1185
+        }
1186
+        if (!v) {
1187
+            eventEmitter.emit(UIEvents.EXTERNAL_INSTALLATION_CANCELED);
1188
+        }
1170 1189
     };
1171 1190
 
1172 1191
     messageHandler.openTwoButtonDialog({
@@ -1179,6 +1198,36 @@ UI.showExtensionExternalInstallationDialog = function (url) {
1179 1198
     });
1180 1199
 };
1181 1200
 
1201
+/**
1202
+ * Shows a dialog which asks user to install the extension. This one is
1203
+ * displayed after installation is triggered from the script, but fails because
1204
+ * it must be initiated by user gesture.
1205
+ * @param callback {function} function to be executed after user clicks
1206
+ * the install button - it should make another attempt to install the extension.
1207
+ */
1208
+UI.showExtensionInlineInstallationDialog = function (callback) {
1209
+    let submitFunction = function(e,v){
1210
+        if (v) {
1211
+            callback();
1212
+        }
1213
+    };
1214
+
1215
+    let closeFunction = function (e, v) {
1216
+        if (!v) {
1217
+            eventEmitter.emit(UIEvents.EXTERNAL_INSTALLATION_CANCELED);
1218
+        }
1219
+    };
1220
+
1221
+    messageHandler.openTwoButtonDialog({
1222
+        titleKey: 'dialog.externalInstallationTitle',
1223
+        msgKey: 'dialog.inlineInstallationMsg',
1224
+        leftButtonKey: 'dialog.inlineInstallExtension',
1225
+        submitFunction,
1226
+        loadedFunction: $.noop,
1227
+        closeFunction
1228
+    });
1229
+};
1230
+
1182 1231
 
1183 1232
 /**
1184 1233
  * Shows dialog with combined information about camera and microphone errors.

+ 0
- 6
service/UI/UIEvents.js Datei anzeigen

@@ -97,12 +97,6 @@ export default {
97 97
     // changed.
98 98
     RESOLUTION_CHANGED: "UI.resolution_changed",
99 99
 
100
-    /**
101
-     * Notifies that the button "Go to webstore" is pressed on the dialog for
102
-     * external extension installation.
103
-     */
104
-    OPEN_EXTENSION_STORE: "UI.open_extension_store",
105
-
106 100
     /**
107 101
      * Notifies that the button "Cancel" is pressed on the dialog for
108 102
      * external extension installation.

Laden…
Abbrechen
Speichern