Browse Source

Show overlay with guidance for gUM permission prompts

master
tsareg 9 years ago
parent
commit
9d3b2aee02
5 changed files with 110 additions and 7 deletions
  1. 24
    5
      conference.js
  2. 15
    0
      css/overlay.css
  3. 11
    2
      lang/main.json
  4. 15
    0
      modules/UI/UI.js
  5. 45
    0
      modules/UI/gum_overlay/UserMediaPermissionsGuidanceOverlay.js

+ 24
- 5
conference.js View File

27
 
27
 
28
 import {VIDEO_CONTAINER_TYPE} from "./modules/UI/videolayout/LargeVideo";
28
 import {VIDEO_CONTAINER_TYPE} from "./modules/UI/videolayout/LargeVideo";
29
 
29
 
30
+const USER_MEDIA_PERMISSIONS_GUIDANCE_OVERLAY_TIMEOUT = 500;
31
+
30
 /**
32
 /**
31
  * Known custom conference commands.
33
  * Known custom conference commands.
32
  */
34
  */
427
             };
429
             };
428
         }
430
         }
429
 
431
 
430
-        let audioAndVideoError, audioOnlyError;
432
+        let audioAndVideoError,
433
+            audioOnlyError,
434
+            tracksCreated;
431
 
435
 
432
         return JitsiMeetJS.init(config).then(() => {
436
         return JitsiMeetJS.init(config).then(() => {
433
-            return Promise.all([
437
+            let tryCreateLocalTracks =
434
                 // try to retrieve audio and video
438
                 // try to retrieve audio and video
435
                 createLocalTracks(['audio', 'video'])
439
                 createLocalTracks(['audio', 'video'])
436
-                // if failed then try to retrieve only audio
440
+                    // if failed then try to retrieve only audio
437
                     .catch(err => {
441
                     .catch(err => {
438
                         audioAndVideoError = err;
442
                         audioAndVideoError = err;
439
                         return createLocalTracks(['audio']);
443
                         return createLocalTracks(['audio']);
440
                     })
444
                     })
441
-                // if audio also failed then just return empty array
445
+                    // if audio also failed then just return empty array
442
                     .catch(err => {
446
                     .catch(err => {
443
                         audioOnlyError = err;
447
                         audioOnlyError = err;
444
                         return [];
448
                         return [];
445
-                    }),
449
+                    })
450
+                    .then(tracks => {
451
+                        tracksCreated = true;
452
+                        return tracks;
453
+                    });
454
+
455
+            window.setTimeout(() => {
456
+                if (!audioAndVideoError && !audioOnlyError && !tracksCreated) {
457
+                    APP.UI.showUserMediaPermissionsGuidanceOverlay();
458
+                }
459
+            }, USER_MEDIA_PERMISSIONS_GUIDANCE_OVERLAY_TIMEOUT);
460
+
461
+            return Promise.all([
462
+                tryCreateLocalTracks,
446
                 connect(options.roomName)
463
                 connect(options.roomName)
447
             ]);
464
             ]);
448
         }).then(([tracks, con]) => {
465
         }).then(([tracks, con]) => {
466
+            APP.UI.hideUserMediaPermissionsGuidanceOverlay();
467
+
449
             if (audioAndVideoError) {
468
             if (audioAndVideoError) {
450
                 if (audioOnlyError) {
469
                 if (audioOnlyError) {
451
                     // If both requests for 'audio' + 'video' and 'audio' only
470
                     // If both requests for 'audio' + 'video' and 'audio' only

+ 15
- 0
css/overlay.css View File

11
     display: block;
11
     display: block;
12
 }
12
 }
13
 
13
 
14
+.overlay_transparent {
15
+    background: none;
16
+}
17
+
14
 .overlay_container {
18
 .overlay_container {
15
     width: 100%;
19
     width: 100%;
16
     height: 100%;
20
     height: 100%;
49
     margin-top: 20px;
53
     margin-top: 20px;
50
     float: left;
54
     float: left;
51
 }
55
 }
56
+
57
+.overlay_text_small {
58
+    font-size: 18px;
59
+}
60
+
61
+.overlay_icon {
62
+    position: relative;
63
+    z-index: 1013;
64
+    float: none;
65
+    font-size: 100px;
66
+}

+ 11
- 2
lang/main.json View File

11
     "defaultNickname": "ex. Jane Pink",
11
     "defaultNickname": "ex. Jane Pink",
12
     "defaultLink": "e.g. __url__",
12
     "defaultLink": "e.g. __url__",
13
     "calling": "Calling __name__ ...",
13
     "calling": "Calling __name__ ...",
14
+    "userMedia": {
15
+      "react-nativeGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <i>Allow</i> button",
16
+      "chromeGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <i>Allow</i> button",
17
+      "firefoxGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <i>Share Selected Device</i> button",
18
+      "operaGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <i>Allow</i> button",
19
+      "iexplorerGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <i>OK</i> button",
20
+      "safariGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <i>OK</i> button",
21
+      "nwjsGrantPermissions": "Please grant permissions to use your camera and microphone"
22
+    },
14
     "keyboardShortcuts": {
23
     "keyboardShortcuts": {
15
         "keyboardShortcuts": "Keyboard shortcuts:",
24
         "keyboardShortcuts": "Keyboard shortcuts:",
16
         "raiseHand": "Raise your hand.",
25
         "raiseHand": "Raise your hand.",
245
         "cameraErrorPresent": "There was an error connecting to your camera.",
254
         "cameraErrorPresent": "There was an error connecting to your camera.",
246
         "cameraUnsupportedResolutionError": "Your camera does not support required video resolution.",
255
         "cameraUnsupportedResolutionError": "Your camera does not support required video resolution.",
247
         "cameraUnknownError": "Cannot use camera for a unknown reason.",
256
         "cameraUnknownError": "Cannot use camera for a unknown reason.",
248
-        "cameraPermissionDeniedError": "You have not granted permission to use your camera.",
257
+        "cameraPermissionDeniedError": "You have not granted permission to use your camera. You can still join the conference but others won't see you. Use the camera button in the address bar to fix this.",
249
         "cameraNotFoundError": "Requested camera was not found.",
258
         "cameraNotFoundError": "Requested camera was not found.",
250
         "cameraConstraintFailedError": "Yor camera does not satisfy some of required constraints.",
259
         "cameraConstraintFailedError": "Yor camera does not satisfy some of required constraints.",
251
         "micUnknownError": "Cannot use microphone for a unknown reason.",
260
         "micUnknownError": "Cannot use microphone for a unknown reason.",
252
-        "micPermissionDeniedError": "You have not granted permission to use your microphone.",
261
+        "micPermissionDeniedError": "You have not granted permission to use your microphone. You can still join the conference but others won't hear you. Use the camera button in the address bar to fix this.",
253
         "micNotFoundError": "Requested microphone was not found.",
262
         "micNotFoundError": "Requested microphone was not found.",
254
         "micConstraintFailedError": "Yor microphone does not satisfy some of required constraints."
263
         "micConstraintFailedError": "Yor microphone does not satisfy some of required constraints."
255
     },
264
     },

+ 15
- 0
modules/UI/UI.js View File

15
 import EtherpadManager from './etherpad/Etherpad';
15
 import EtherpadManager from './etherpad/Etherpad';
16
 import SharedVideoManager from './shared_video/SharedVideo';
16
 import SharedVideoManager from './shared_video/SharedVideo';
17
 import Recording from "./recording/Recording";
17
 import Recording from "./recording/Recording";
18
+import GumPermissionsOverlay from './gum_overlay/UserMediaPermissionsGuidanceOverlay';
18
 
19
 
19
 import VideoLayout from "./videolayout/VideoLayout";
20
 import VideoLayout from "./videolayout/VideoLayout";
20
 import FilmStrip from "./videolayout/FilmStrip";
21
 import FilmStrip from "./videolayout/FilmStrip";
1385
     FilmStrip.toggleFilmStrip(true);
1386
     FilmStrip.toggleFilmStrip(true);
1386
 };
1387
 };
1387
 
1388
 
1389
+/**
1390
+ * Shows browser-specific overlay with guidance how to proceed with gUM prompt.
1391
+ */
1392
+UI.showUserMediaPermissionsGuidanceOverlay = function () {
1393
+    GumPermissionsOverlay.show();
1394
+};
1395
+
1396
+/**
1397
+ * Hides browser-specific overlay with guidance how to proceed with gUM prompt.
1398
+ */
1399
+UI.hideUserMediaPermissionsGuidanceOverlay = function () {
1400
+    GumPermissionsOverlay.hide();
1401
+};
1402
+
1388
 /**
1403
 /**
1389
  * Shows or hides the keyboard shortcuts panel.'
1404
  * Shows or hides the keyboard shortcuts panel.'
1390
  */
1405
  */

+ 45
- 0
modules/UI/gum_overlay/UserMediaPermissionsGuidanceOverlay.js View File

1
+/* global $, APP, JitsiMeetJS */
2
+
3
+let $overlay;
4
+
5
+/**
6
+ * Internal function that constructs overlay with guidance how to proceed with
7
+ * gUM prompt.
8
+ */
9
+function buildOverlayHtml() {
10
+    let browser = JitsiMeetJS.environment.getBrowserType()
11
+            .split('rtc_browser.')[1] || 'chrome';
12
+
13
+    $overlay = $(`
14
+        <div class='overlay_container'>
15
+            <div class='overlay overlay_transparent' />
16
+            <div class='overlay_content'>
17
+                <span class="overlay_icon icon-microphone"></span>
18
+                <span class="overlay_icon icon-camera"></span>
19
+                <span data-i18n='[html]userMedia.${browser}GrantPermissions' 
20
+                    class='overlay_text overlay_text_small'></span>
21
+            </div>
22
+        </div>`);
23
+
24
+    APP.translation.translateElement($overlay);
25
+}
26
+
27
+export default {
28
+    /**
29
+     * Shows browser-specific overlay with guidance how to proceed with
30
+     * gUM prompt.
31
+     */
32
+    show() {
33
+        !$overlay && buildOverlayHtml();
34
+
35
+        $overlay && $overlay.appendTo('body');
36
+    },
37
+
38
+    /**
39
+     * Hides browser-specific overlay with guidance how to proceed with
40
+     * gUM prompt.
41
+     */
42
+    hide() {
43
+        $overlay && $overlay.detach();
44
+    }
45
+};

Loading…
Cancel
Save