浏览代码

Merge pull request #1393 from jitsi/filmstrip_overlays

Filmstrip overlays
master
yanas 8 年前
父节点
当前提交
e8068cf5ac

+ 82
- 3
css/_inlay.scss 查看文件

@@ -27,7 +27,86 @@
27 27
         font-size: 50px;
28 28
     }
29 29
 
30
-    &__button {
31
-        float: none !important;
30
+    &-filmstrip-only {
31
+        background-color: $inlayFilmstripOnlyBg;
32
+        color: $inlayFilmstripOnlyColor;
33
+        margin-left: 20px;
34
+        margin-right: 20px;
35
+        margin-top: 20px;
36
+        bottom: 30px;
37
+        position: absolute;
38
+        display: flex;
39
+        max-height: 120px;
40
+        height: 80%;
41
+        right: 0px;
42
+        border-radius: 4px;
43
+        overflow: hidden;
44
+        &__content {
45
+            padding: 20px;
46
+            display: flex;
47
+            justify-content: center;
48
+            position: relative;
49
+            > .button-control {
50
+                align-self: center;
51
+            }
52
+            > #reloadProgressBar {
53
+                position: absolute;
54
+                left: 0px;
55
+                bottom: 0px;
56
+                margin-bottom: 0px;
57
+                width: 100%;
58
+                border-radius: 0px;
59
+                > .aui-progress-indicator-value {
60
+                    border-radius: 0px;
61
+                }
62
+            }
63
+        }
64
+        &__title {
65
+            font-size: 18px;
66
+            font-weight: 600;
67
+        }
68
+
69
+        &__container {
70
+            align-self: center;
71
+        }
72
+
73
+        &__text {
74
+            margin-top: 10px;
75
+            font-size: 14px;
76
+            font-weight: 600;
77
+        }
78
+
79
+        &__icon {
80
+            font-size: 50px;
81
+            align-self: center;
82
+            color: $inlayIconColor;
83
+            opacity: 0.6;
84
+        }
85
+        &__icon-container {
86
+            text-align: center;
87
+            display: flex;
88
+            justify-content: center;
89
+            position: absolute;
90
+            width: 100%;
91
+            height: 100%;
92
+            top: 0px;
93
+        }
94
+
95
+        &__avatar-container {
96
+            position: relative;
97
+            > img {
98
+                height: 100%;
99
+            }
100
+        }
101
+
102
+        &__icon-background {
103
+            background: $inlayIconBg;
104
+            opacity: 0.6;
105
+            position: absolute;
106
+            width: 100%;
107
+            height: 100%;
108
+            top: 0px;
109
+        }
32 110
     }
33
-}
111
+
112
+}

+ 13
- 1
css/components/_button-control.scss 查看文件

@@ -57,6 +57,18 @@
57 57
         }
58 58
     }
59 59
 
60
+    &_overlay {
61
+        color: $primaryButtonColor;
62
+        background-color: $overlayButtonBg;
63
+        border-radius: 2px;
64
+        border: none;
65
+
66
+        &:hover {
67
+            background-color: $primaryButtonBackground;
68
+            border: none;
69
+        }
70
+    }
71
+
60 72
     &_primary {
61 73
         background-color: $primaryButtonBackground;
62 74
         border: 1px solid $primaryButtonBackground;
@@ -86,4 +98,4 @@
86 98
     &_center {
87 99
         float: none !important;
88 100
     }
89
-}
101
+}

+ 12
- 1
css/overlay/_overlay.scss 查看文件

@@ -8,10 +8,16 @@
8 8
         position: fixed;
9 9
         z-index: $overlayZ;
10 10
         background: $defaultBackground;
11
+        &.filmstrip-only {
12
+            @include transparentBg($filmStripOnlyOverlayBg, 0.8);
13
+        }
11 14
     }
12 15
 
13 16
     &__container-light {
14 17
         @include transparentBg($defaultBackground, 0.7);
18
+        &.filmstrip-only {
19
+            @include transparentBg($filmStripOnlyOverlayBg, 0.2);
20
+        }
15 21
     }
16 22
 
17 23
     &__content {
@@ -21,6 +27,11 @@
21 27
         width: 56%;
22 28
         left: 50%;
23 29
         @include transform(translateX(-50%));
30
+        &.filmstrip-only {
31
+            left: 0px;
32
+            width: 100%;
33
+            @include transform(none);
34
+        }
24 35
 
25 36
         &_bottom {
26 37
             position: absolute;
@@ -33,4 +44,4 @@
33 44
         bottom: 24px;
34 45
         width: 100%;
35 46
     }
36
-}
47
+}

+ 3
- 0
css/reload_overlay/_reload_overlay.scss 查看文件

@@ -13,4 +13,7 @@
13 13
 #reloadProgressBar {
14 14
     width: 180px;
15 15
     margin: 5px auto;
16
+    > .aui-progress-indicator-value {
17
+        background: $reloadProgressBarBg;
18
+    }
16 19
 }

+ 8
- 0
css/themes/_light.scss 查看文件

@@ -35,10 +35,14 @@ $primaryButtonFontWeight: 400;
35 35
 
36 36
 $buttonShadowColor: #192d4f;
37 37
 
38
+$overlayButtonBg: #0074E0;
39
+
38 40
 /**
39 41
 * Color variables
40 42
 **/
41 43
 $defaultBackground: #474747;
44
+$filmStripOnlyOverlayBg: #000;
45
+$reloadProgressBarBg: #0074E0;
42 46
 
43 47
 /**
44 48
 * Connection indicator
@@ -60,6 +64,10 @@ $dialogTitleFontWeight: 400;
60 64
 **/
61 65
 $inlayColorBg: lighten($defaultBackground, 20%);
62 66
 $inlayBorderColor: lighten($auiDialogContentBg, 10%);
67
+$inlayIconBg: #000;
68
+$inlayIconColor: #fff;
69
+$inlayFilmstripOnlyColor: #474747;
70
+$inlayFilmstripOnlyBg: #fff;
63 71
 
64 72
 // Main controls
65 73
 $inputBackground: $controlBackground;

+ 13
- 13
lang/main.json 查看文件

@@ -15,13 +15,13 @@
15 15
     "defaultLink": "e.g. __url__",
16 16
     "callingName": "__name__",
17 17
     "userMedia": {
18
-      "react-nativeGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>Allow</i></b> button",
19
-      "chromeGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>Allow</i></b> button",
20
-      "androidGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>Allow</i></b> button",
21
-      "firefoxGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>Share Selected Device</i></b> button",
22
-      "operaGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>Allow</i></b> button",
23
-      "iexplorerGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>OK</i></b> button",
24
-      "safariGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>OK</i></b> button",
18
+      "react-nativeGrantPermissions": "Select <b><i>Allow</i></b> when your browser asks for permissions.",
19
+      "chromeGrantPermissions": "Select <b><i>Allow</i></b> when your browser asks for permissions.",
20
+      "androidGrantPermissions": "Select <b><i>Allow</i></b> when your browser asks for permissions.",
21
+      "firefoxGrantPermissions": "Select <b><i>Share Selected Device</i></b> when your browser asks for permissions.",
22
+      "operaGrantPermissions": "Select <b><i>Allow</i></b> when your browser asks for permissions.",
23
+      "iexplorerGrantPermissions": "Select <b><i>OK</i></b> when your browser asks for permissions.",
24
+      "safariGrantPermissions": "Select <b><i>OK</i></b> when your browser asks for permissions.",
25 25
       "nwjsGrantPermissions": "Please grant permissions to use your camera and microphone"
26 26
     },
27 27
     "keyboardShortcuts": {
@@ -87,6 +87,7 @@
87 87
     },
88 88
     "suspendedoverlay": {
89 89
         "title": "Your video call was interrupted, because this computer went to sleep.",
90
+        "text": "Press <i>Rejoin</i> button to connect back to your conversation.",
90 91
         "rejoinKeyTitle": "Rejoin"
91 92
     },
92 93
     "toolbar": {
@@ -229,12 +230,11 @@
229 230
         "detectext": "Error when trying to detect desktopsharing extension.",
230 231
         "failtoinstall": "Failed to install desktop sharing extension",
231 232
         "failedpermissions": "Failed to obtain permissions to use the local microphone and/or camera.",
232
-        "conferenceReloadTitle": "Unfortunately, something went wrong",
233
-        "conferenceReloadMsg": "We're trying to fix this",
234
-        "conferenceDisconnectTitle": "You have been disconnected. You may want to check your network connection.",
235
-        "conferenceDisconnectMsg": "Reconnecting in...",
236
-        "reconnectNow": "Reconnect now",
237
-        "conferenceReloadTimeLeft": "__seconds__ sec.",
233
+        "conferenceReloadTitle": "Unfortunately, something went wrong.",
234
+        "conferenceReloadMsg": "We're trying to fix this. Reconnecting in __seconds__ sec...",
235
+        "conferenceDisconnectTitle": "You have been disconnected.",
236
+        "conferenceDisconnectMsg": "You may want to check your network connection. Reconnecting in __seconds__ sec...",
237
+        "rejoinNow": "Rejoin now",
238 238
         "maxUsersLimitReached": "The limit for maximum number of participants in the conference has been reached. The conference is full. Please try again later!",
239 239
         "lockTitle": "Lock failed",
240 240
         "lockMessage": "Failed to lock the conference.",

+ 10
- 3
modules/URL/ConferenceUrl.js 查看文件

@@ -1,6 +1,6 @@
1 1
 const logger = require("jitsi-meet-logger").getLogger(__filename);
2 2
 
3
-import { replace } from '../util/helpers';
3
+import { reload, replace } from '../util/helpers';
4 4
 
5 5
 /**
6 6
  * The modules stores information about the URL used to start the conference and
@@ -67,7 +67,14 @@ export default class ConferenceUrl {
67 67
      * Reloads the conference using original URL with all of the parameters.
68 68
      */
69 69
     reload() {
70
-        logger.info("Reloading the conference using URL: " + this.originalURL);
71
-        replace(this.originalURL);
70
+        logger.info(`Reloading the conference using URL: ${this.originalURL}`);
71
+
72
+        // Check if we are in an iframe and reload with the reload() utility
73
+        // because replace() is not working on an iframe.
74
+        if(window.self !== window.top) {
75
+            reload();
76
+        } else {
77
+            replace(this.originalURL);
78
+        }
72 79
     }
73 80
 }

+ 0
- 80
react/features/overlay/components/AbstractOverlay.js 查看文件

@@ -1,80 +0,0 @@
1
-/* global APP */
2
-
3
-import React, { Component } from 'react';
4
-
5
-/**
6
- * Implements an abstract React Component for overlay - the components which are
7
- * displayed on top of the application covering the whole screen.
8
- *
9
- * @abstract
10
- */
11
-export default class AbstractOverlay extends Component {
12
-    /**
13
-     * Initializes a new AbstractOverlay instance.
14
-     *
15
-     * @param {Object} props - The read-only properties with which the new
16
-     * instance is to be initialized.
17
-     * @public
18
-     */
19
-    constructor(props) {
20
-        super(props);
21
-
22
-        this.state = {
23
-            /**
24
-             * Indicates the CSS style of the overlay. If true, then ighter;
25
-             * darker, otherwise.
26
-             *
27
-             * @type {boolean}
28
-             */
29
-            isLightOverlay: false
30
-        };
31
-    }
32
-
33
-    /**
34
-     * Implements React's {@link Component#render()}.
35
-     *
36
-     * @inheritdoc
37
-     * @returns {ReactElement|null}
38
-     */
39
-    render() {
40
-        const containerClass
41
-            = this.state.isLightOverlay
42
-                ? 'overlay__container-light'
43
-                : 'overlay__container';
44
-
45
-        return (
46
-            <div
47
-                className = { containerClass }
48
-                id = 'overlay'>
49
-                <div className = 'overlay__content'>
50
-                    {
51
-                        this._renderOverlayContent()
52
-                    }
53
-                </div>
54
-            </div>
55
-        );
56
-    }
57
-
58
-    /**
59
-     * Reloads the page.
60
-     *
61
-     * @returns {void}
62
-     * @protected
63
-     */
64
-    _reconnectNow() {
65
-        // FIXME: In future we should dispatch an action here that will result
66
-        // in reload.
67
-        APP.ConferenceUrl.reload();
68
-    }
69
-
70
-    /**
71
-     * Abstract method which should be used by subclasses to provide the overlay
72
-     * content.
73
-     *
74
-     * @returns {ReactElement|null}
75
-     * @protected
76
-     */
77
-    _renderOverlayContent() {
78
-        return null;
79
-    }
80
-}

+ 192
- 0
react/features/overlay/components/AbstractPageReloadOverlay.js 查看文件

@@ -0,0 +1,192 @@
1
+import React, { Component } from 'react';
2
+
3
+import { randomInt } from '../../base/util';
4
+
5
+import { reconnectNow } from '../functions';
6
+import ReloadButton from './ReloadButton';
7
+
8
+declare var AJS: Object;
9
+declare var APP: Object;
10
+
11
+const logger = require('jitsi-meet-logger').getLogger(__filename);
12
+
13
+/**
14
+ * Implements abstract React Component for the page reload overlays.
15
+ */
16
+export default class AbstractPageReloadOverlay extends Component {
17
+    /**
18
+     * AbstractPageReloadOverlay component's property types.
19
+     *
20
+     * @static
21
+     */
22
+    static propTypes = {
23
+        /**
24
+         * The indicator which determines whether the reload was caused by
25
+         * network failure.
26
+         *
27
+         * @public
28
+         * @type {boolean}
29
+         */
30
+        isNetworkFailure: React.PropTypes.bool,
31
+
32
+        /**
33
+         * The reason for the error that will cause the reload.
34
+         * NOTE: Used by PageReloadOverlay only.
35
+         *
36
+         * @public
37
+         * @type {string}
38
+         */
39
+        reason: React.PropTypes.string
40
+    }
41
+
42
+    /**
43
+     * Initializes a new AbstractPageReloadOverlay instance.
44
+     *
45
+     * @param {Object} props - The read-only properties with which the new
46
+     * instance is to be initialized.
47
+     * @public
48
+     */
49
+    constructor(props) {
50
+        super(props);
51
+
52
+        /**
53
+         * How long the overlay dialog will be displayed, before the conference
54
+         * will be reloaded.
55
+         *
56
+         * @type {number}
57
+         */
58
+        const timeoutSeconds = 10 + randomInt(0, 20);
59
+
60
+        let message, title;
61
+
62
+        if (this.props.isNetworkFailure) {
63
+            title = 'dialog.conferenceDisconnectTitle';
64
+            message = 'dialog.conferenceDisconnectMsg';
65
+        } else {
66
+            title = 'dialog.conferenceReloadTitle';
67
+            message = 'dialog.conferenceReloadMsg';
68
+        }
69
+
70
+        this.state = {
71
+            /**
72
+             * The translation key for the title of the overlay.
73
+             *
74
+             * @type {string}
75
+             */
76
+            message,
77
+
78
+            /**
79
+             * Current value(time) of the timer.
80
+             *
81
+             * @type {number}
82
+             */
83
+            timeLeft: timeoutSeconds,
84
+
85
+            /**
86
+             * How long the overlay dialog will be displayed before the
87
+             * conference will be reloaded.
88
+             *
89
+             * @type {number}
90
+             */
91
+            timeoutSeconds,
92
+
93
+            /**
94
+             * The translation key for the title of the overlay.
95
+             *
96
+             * @type {string}
97
+             */
98
+            title
99
+        };
100
+    }
101
+
102
+    /**
103
+     * Renders the button for relaod the page if necessary.
104
+     *
105
+     * @returns {ReactElement|null}
106
+     * @private
107
+     */
108
+    _renderButton() {
109
+        if (this.props.isNetworkFailure) {
110
+            return (
111
+                <ReloadButton textKey = 'dialog.rejoinNow' />
112
+            );
113
+        }
114
+
115
+        return null;
116
+    }
117
+
118
+    /**
119
+     * Renders the progress bar.
120
+     *
121
+     * @returns {ReactElement|null}
122
+     * @protected
123
+     */
124
+    _renderProgressBar() {
125
+        return (
126
+            <div
127
+                className = 'aui-progress-indicator'
128
+                id = 'reloadProgressBar'>
129
+                <span className = 'aui-progress-indicator-value' />
130
+            </div>
131
+        );
132
+    }
133
+
134
+    /**
135
+     * React Component method that executes once component is mounted.
136
+     *
137
+     * @inheritdoc
138
+     * @returns {void}
139
+     * @protected
140
+     */
141
+    componentDidMount() {
142
+        // FIXME (CallStats - issue) This event will not make it to CallStats
143
+        // because the log queue is not flushed before "fabric terminated" is
144
+        // sent to the backed.
145
+        // FIXME: We should dispatch action for this.
146
+        APP.conference.logEvent(
147
+                'page.reload',
148
+                /* value */ undefined,
149
+                /* label */ this.props.reason);
150
+        logger.info(
151
+                'The conference will be reloaded after '
152
+                    + `${this.state.timeoutSeconds} seconds.`);
153
+
154
+        AJS.progressBars.update('#reloadProgressBar', 0);
155
+
156
+        this.intervalId = setInterval(() => {
157
+            if (this.state.timeLeft === 0) {
158
+                clearInterval(this.intervalId);
159
+                reconnectNow();
160
+            } else {
161
+                this.setState(prevState => {
162
+                    return {
163
+                        timeLeft: prevState.timeLeft - 1
164
+                    };
165
+                });
166
+            }
167
+        }, 1000);
168
+    }
169
+
170
+    /**
171
+     * React Component method that executes once component is updated.
172
+     *
173
+     * @inheritdoc
174
+     * @returns {void}
175
+     * @protected
176
+     */
177
+    componentDidUpdate() {
178
+        AJS.progressBars.update('#reloadProgressBar',
179
+            (this.state.timeoutSeconds - this.state.timeLeft)
180
+                / this.state.timeoutSeconds);
181
+    }
182
+
183
+    /**
184
+     * Clears the timer interval.
185
+     *
186
+     * @inheritdoc
187
+     * @returns {void}
188
+     */
189
+    componentWillUnmount() {
190
+        clearInterval(this.intervalId);
191
+    }
192
+}

+ 133
- 0
react/features/overlay/components/FilmStripOnlyOverlayFrame.js 查看文件

@@ -0,0 +1,133 @@
1
+import React, { Component } from 'react';
2
+import { connect } from 'react-redux';
3
+
4
+import {
5
+    Avatar,
6
+    getAvatarURL,
7
+    getLocalParticipant
8
+} from '../../base/participants';
9
+
10
+import OverlayFrame from './OverlayFrame';
11
+
12
+/**
13
+ * Implements a React Component for the frame of the overlays in filmstrip only
14
+ * mode.
15
+ */
16
+class FilmStripOnlyOverlayFrame extends Component {
17
+    /**
18
+     * FilmStripOnlyOverlayFrame component's property types.
19
+     *
20
+     * @static
21
+     */
22
+    static propTypes = {
23
+        /**
24
+         * The source (e.g. URI, URL) of the avatar image of the local
25
+         * participant.
26
+         *
27
+         * @private
28
+         */
29
+        _avatar: React.PropTypes.string,
30
+
31
+        /**
32
+         * The children components to be displayed into the overlay frame for
33
+         * filmstrip only mode.
34
+         *
35
+         * @type {ReactElement}
36
+         */
37
+        children: React.PropTypes.node.isRequired,
38
+
39
+        /**
40
+         * The css class name for the icon that will be displayed over the
41
+         * avatar.
42
+         *
43
+         * @type {string}
44
+         */
45
+        icon: React.PropTypes.string,
46
+
47
+        /**
48
+         * Indicates the css style of the overlay. If true, then lighter;
49
+         * darker, otherwise.
50
+         *
51
+         * @type {boolean}
52
+         */
53
+        isLightOverlay: React.PropTypes.bool
54
+    }
55
+
56
+    /**
57
+     * Renders content related to the icon.
58
+     *
59
+     * @returns {ReactElement|null}
60
+     * @private
61
+     */
62
+    _renderIcon() {
63
+        if (!this.props.icon) {
64
+            return null;
65
+        }
66
+
67
+        const iconClass = `inlay-filmstrip-only__icon ${this.props.icon}`;
68
+        const iconBGClass = 'inlay-filmstrip-only__icon-background';
69
+
70
+        return (
71
+            <div>
72
+                <div className = { iconBGClass } />
73
+                <div className = 'inlay-filmstrip-only__icon-container'>
74
+                    <span className = { iconClass } />
75
+                </div>
76
+            </div>
77
+        );
78
+    }
79
+
80
+    /**
81
+     * Implements React's {@link Component#render()}.
82
+     *
83
+     * @inheritdoc
84
+     * @returns {ReactElement|null}
85
+     */
86
+    render() {
87
+        return (
88
+            <OverlayFrame isLightOverlay = { this.props.isLightOverlay }>
89
+                <div className = 'inlay-filmstrip-only'>
90
+                    <div className = 'inlay-filmstrip-only__content'>
91
+                        {
92
+                            this.props.children
93
+                        }
94
+                    </div>
95
+                    <div className = 'inlay-filmstrip-only__avatar-container'>
96
+                        <Avatar uri = { this.props._avatar } />
97
+                        {
98
+                            this._renderIcon()
99
+                        }
100
+                    </div>
101
+                </div>
102
+            </OverlayFrame>
103
+        );
104
+    }
105
+}
106
+
107
+/**
108
+ * Maps (parts of) the Redux state to the associated FilmStripOnlyOverlayFrame
109
+ * props.
110
+ *
111
+ * @param {Object} state - The Redux state.
112
+ * @private
113
+ * @returns {{
114
+ *     _avatar: string
115
+ * }}
116
+ */
117
+function _mapStateToProps(state) {
118
+    const participant
119
+        = getLocalParticipant(
120
+            state['features/base/participants']);
121
+    const { avatarId, avatarUrl, email } = participant || {};
122
+
123
+    return {
124
+        _avatar: getAvatarURL({
125
+            avatarId,
126
+            avatarUrl,
127
+            email,
128
+            participantId: participant.id
129
+        })
130
+    };
131
+}
132
+
133
+export default connect(_mapStateToProps)(FilmStripOnlyOverlayFrame);

+ 45
- 18
react/features/overlay/components/OverlayContainer.js 查看文件

@@ -1,12 +1,17 @@
1
-/* global APP */
2
-
3 1
 import React, { Component } from 'react';
4 2
 import { connect } from 'react-redux';
5 3
 
4
+import PageReloadFilmStripOnlyOverlay from './PageReloadFilmStripOnlyOverlay';
6 5
 import PageReloadOverlay from './PageReloadOverlay';
6
+import SuspendedFilmStripOnlyOverlay from './SuspendedFilmStripOnlyOverlay';
7 7
 import SuspendedOverlay from './SuspendedOverlay';
8
+import UserMediaPermissionsFilmStripOnlyOverlay
9
+    from './UserMediaPermissionsFilmStripOnlyOverlay';
8 10
 import UserMediaPermissionsOverlay from './UserMediaPermissionsOverlay';
9 11
 
12
+declare var APP: Object;
13
+declare var interfaceConfig: Object;
14
+
10 15
 /**
11 16
  * Implements a React Component that will display the correct overlay when
12 17
  * needed.
@@ -94,6 +99,25 @@ class OverlayContainer extends Component {
94 99
         _suspendDetected: React.PropTypes.bool
95 100
     }
96 101
 
102
+    /**
103
+     * Initializes a new ReloadTimer instance.
104
+     *
105
+     * @param {Object} props - The read-only properties with which the new
106
+     * instance is to be initialized.
107
+     * @public
108
+     */
109
+    constructor(props) {
110
+        super(props);
111
+        this.state = {
112
+            /**
113
+             * Indicates whether the film strip only mode is enabled or not.
114
+             *
115
+             * @type {boolean}
116
+             */
117
+            filmStripOnly: interfaceConfig.filmStripOnly
118
+        };
119
+    }
120
+
97 121
     /**
98 122
      * React Component method that executes once component is updated.
99 123
      *
@@ -117,25 +141,28 @@ class OverlayContainer extends Component {
117 141
      * @public
118 142
      */
119 143
     render() {
120
-        if (this.props._connectionEstablished && this.props._haveToReload) {
121
-            return (
122
-                <PageReloadOverlay
123
-                    isNetworkFailure = { this.props._isNetworkFailure }
124
-                    reason = { this.props._reason } />
125
-            );
126
-        }
144
+        const filmStripOnlyMode = this.state.filmStripOnly;
145
+        let overlayComponent, props;
127 146
 
128
-        if (this.props._suspendDetected) {
129
-            return (
130
-                <SuspendedOverlay />
131
-            );
147
+        if (this.props._connectionEstablished && this.props._haveToReload) {
148
+            overlayComponent = filmStripOnlyMode
149
+                ? PageReloadFilmStripOnlyOverlay : PageReloadOverlay;
150
+            props = {
151
+                isNetworkFailure: this.props._isNetworkFailure,
152
+                reason: this.props._reason
153
+            };
154
+        } else if (this.props._suspendDetected) {
155
+            overlayComponent = filmStripOnlyMode
156
+                ? SuspendedFilmStripOnlyOverlay : SuspendedOverlay;
157
+        } else if (this.props._isMediaPermissionPromptVisible) {
158
+            overlayComponent = filmStripOnlyMode
159
+                ? UserMediaPermissionsFilmStripOnlyOverlay
160
+                    : UserMediaPermissionsOverlay;
161
+            props = { browser: this.props._browser };
132 162
         }
133 163
 
134
-        if (this.props._isMediaPermissionPromptVisible) {
135
-            return (
136
-                <UserMediaPermissionsOverlay
137
-                    browser = { this.props._browser } />
138
-            );
164
+        if (overlayComponent) {
165
+            return React.createElement(overlayComponent, props);
139 166
         }
140 167
 
141 168
         return null;

+ 77
- 0
react/features/overlay/components/OverlayFrame.js 查看文件

@@ -0,0 +1,77 @@
1
+import React, { Component } from 'react';
2
+
3
+declare var interfaceConfig: Object;
4
+
5
+/**
6
+ * Implements a React Component for the frame of the overlays.
7
+ */
8
+export default class OverlayFrame extends Component {
9
+    /**
10
+     * OverlayFrame component's property types.
11
+     *
12
+     * @static
13
+     */
14
+    static propTypes = {
15
+        /**
16
+         * The children components to be displayed into the overlay frame.
17
+         */
18
+        children: React.PropTypes.node.isRequired,
19
+
20
+        /**
21
+         * Indicates the css style of the overlay. If true, then lighter;
22
+         * darker, otherwise.
23
+         *
24
+         * @type {boolean}
25
+         */
26
+        isLightOverlay: React.PropTypes.bool
27
+    }
28
+
29
+    /**
30
+     * Initializes a new AbstractOverlay instance.
31
+     *
32
+     * @param {Object} props - The read-only properties with which the new
33
+     * instance is to be initialized.
34
+     * @public
35
+     */
36
+    constructor(props) {
37
+        super(props);
38
+
39
+        this.state = {
40
+            /**
41
+             * Indicates whether the film strip only mode is enabled or not.
42
+             *
43
+             * @type {boolean}
44
+             */
45
+            filmStripOnly: interfaceConfig.filmStripOnly
46
+        };
47
+    }
48
+
49
+    /**
50
+     * Implements React's {@link Component#render()}.
51
+     *
52
+     * @inheritdoc
53
+     * @returns {ReactElement|null}
54
+     */
55
+    render() {
56
+        let containerClass = this.props.isLightOverlay
57
+            ? 'overlay__container-light' : 'overlay__container';
58
+        let contentClass = 'overlay__content';
59
+
60
+        if (this.state.filmStripOnly) {
61
+            containerClass += ' filmstrip-only';
62
+            contentClass += ' filmstrip-only';
63
+        }
64
+
65
+        return (
66
+            <div
67
+                className = { containerClass }
68
+                id = 'overlay'>
69
+                <div className = { contentClass }>
70
+                    {
71
+                        this.props.children
72
+                    }
73
+                </div>
74
+            </div>
75
+        );
76
+    }
77
+}

+ 62
- 0
react/features/overlay/components/PageReloadFilmStripOnlyOverlay.js 查看文件

@@ -0,0 +1,62 @@
1
+import React from 'react';
2
+
3
+import { translate } from '../../base/i18n';
4
+
5
+import AbstractPageReloadOverlay from './AbstractPageReloadOverlay';
6
+import FilmStripOnlyOverlayFrame from './FilmStripOnlyOverlayFrame';
7
+
8
+/**
9
+ * Implements a React Component for page reload overlay for filmstrip only
10
+ * mode. Shown before the conference is reloaded. Shows a warning message and
11
+ * counts down towards the reload.
12
+ */
13
+class PageReloadFilmStripOnlyOverlay extends AbstractPageReloadOverlay {
14
+    /**
15
+     * PageReloadFilmStripOnlyOverlay component's property types.
16
+     *
17
+     * @static
18
+     */
19
+    static propTypes = {
20
+        ...AbstractPageReloadOverlay.propTypes,
21
+
22
+        /**
23
+         * The function to translate human-readable text.
24
+         *
25
+         * @public
26
+         * @type {Function}
27
+         */
28
+        t: React.PropTypes.func
29
+    }
30
+
31
+    /**
32
+     * Implements React's {@link Component#render()}.
33
+     *
34
+     * @inheritdoc
35
+     * @returns {ReactElement|null}
36
+     */
37
+    render() {
38
+        const { t } = this.props;
39
+        const { message, timeLeft, title } = this.state;
40
+
41
+        return (
42
+            <FilmStripOnlyOverlayFrame>
43
+                <div className = 'inlay-filmstrip-only__container'>
44
+                    <div className = 'inlay-filmstrip-only__title'>
45
+                        { t(title) }
46
+                    </div>
47
+                    <div className = 'inlay-filmstrip-only__text'>
48
+                        { t(message, { seconds: timeLeft }) }
49
+                    </div>
50
+                </div>
51
+                {
52
+                    this._renderButton()
53
+                }
54
+                {
55
+                    this._renderProgressBar()
56
+                }
57
+            </FilmStripOnlyOverlayFrame>
58
+        );
59
+    }
60
+}
61
+
62
+export default translate(PageReloadFilmStripOnlyOverlay);

+ 25
- 161
react/features/overlay/components/PageReloadOverlay.js 查看文件

@@ -1,194 +1,58 @@
1 1
 import React from 'react';
2 2
 
3 3
 import { translate } from '../../base/i18n';
4
-import { randomInt } from '../../base/util';
5 4
 
6
-import AbstractOverlay from './AbstractOverlay';
7
-import ReloadTimer from './ReloadTimer';
8
-
9
-declare var APP: Object;
10
-
11
-const logger = require('jitsi-meet-logger').getLogger(__filename);
5
+import AbstractPageReloadOverlay from './AbstractPageReloadOverlay';
6
+import OverlayFrame from './OverlayFrame';
12 7
 
13 8
 /**
14 9
  * Implements a React Component for page reload overlay. Shown before the
15 10
  * conference is reloaded. Shows a warning message and counts down towards the
16 11
  * reload.
17 12
  */
18
-class PageReloadOverlay extends AbstractOverlay {
13
+class PageReloadOverlay extends AbstractPageReloadOverlay {
19 14
     /**
20 15
      * PageReloadOverlay component's property types.
21 16
      *
22 17
      * @static
23 18
      */
24 19
     static propTypes = {
25
-        /**
26
-         * The indicator which determines whether the reload was caused by
27
-         * network failure.
28
-         * @public
29
-         * @type {boolean}
30
-         */
31
-        isNetworkFailure: React.PropTypes.bool,
20
+        ...AbstractPageReloadOverlay.propTypes,
32 21
 
33 22
         /**
34
-         * The reason for the error that will cause the reload.
35
-         * NOTE: Used by PageReloadOverlay only.
23
+         * The function to translate human-readable text.
24
+         *
36 25
          * @public
37
-         * @type {string}
38
-         */
39
-        reason: React.PropTypes.string
40
-    }
41
-
42
-    /**
43
-     * Initializes a new PageReloadOverlay instance.
44
-     *
45
-     * @param {Object} props - The read-only properties with which the new
46
-     * instance is to be initialized.
47
-     * @public
48
-     */
49
-    constructor(props) {
50
-        super(props);
51
-
52
-        /**
53
-         * How long the overlay dialog will be displayed, before the conference
54
-         * will be reloaded.
55
-         * @type {number}
26
+         * @type {Function}
56 27
          */
57
-        const timeoutSeconds = 10 + randomInt(0, 20);
58
-
59
-        let isLightOverlay, message, title;
60
-
61
-        if (this.props.isNetworkFailure) {
62
-            title = 'dialog.conferenceDisconnectTitle';
63
-            message = 'dialog.conferenceDisconnectMsg';
64
-            isLightOverlay = true;
65
-        } else {
66
-            title = 'dialog.conferenceReloadTitle';
67
-            message = 'dialog.conferenceReloadMsg';
68
-            isLightOverlay = false;
69
-        }
70
-
71
-        this.state = {
72
-            ...this.state,
73
-
74
-            /**
75
-             * Indicates the css style of the overlay. If true, then lighter;
76
-             * darker, otherwise.
77
-             *
78
-             * @type {boolean}
79
-             */
80
-            isLightOverlay,
81
-
82
-            /**
83
-             * The translation key for the title of the overlay.
84
-             *
85
-             * @type {string}
86
-             */
87
-            message,
88
-
89
-            /**
90
-             * How long the overlay dialog will be displayed before the
91
-             * conference will be reloaded.
92
-             *
93
-             * @type {number}
94
-             */
95
-            timeoutSeconds,
96
-
97
-            /**
98
-             * The translation key for the title of the overlay.
99
-             *
100
-             * @type {string}
101
-             */
102
-            title
103
-        };
28
+        t: React.PropTypes.func
104 29
     }
105 30
 
106 31
     /**
107
-     * This method is executed when comonent is mounted.
32
+     * Implements React's {@link Component#render()}.
108 33
      *
109 34
      * @inheritdoc
110
-     * @returns {void}
111
-     */
112
-    componentDidMount() {
113
-        super.componentDidMount();
114
-
115
-        // FIXME (CallStats - issue) This event will not make it to CallStats
116
-        // because the log queue is not flushed before "fabric terminated" is
117
-        // sent to the backed.
118
-        // FIXME: We should dispatch action for this.
119
-        APP.conference.logEvent(
120
-                'page.reload',
121
-                /* value */ undefined,
122
-                /* label */ this.props.reason);
123
-        logger.info(
124
-                'The conference will be reloaded after '
125
-                    + `${this.state.timeoutSeconds} seconds.`);
126
-    }
127
-
128
-    /**
129
-     * Renders the button for relaod the page if necessary.
130
-     *
131 35
      * @returns {ReactElement|null}
132
-     * @private
133 36
      */
134
-    _renderButton() {
135
-        if (this.props.isNetworkFailure) {
136
-            const className
137
-                = 'button-control button-control_primary button-control_center';
138
-            const { t } = this.props;
139
-
140
-            /* eslint-disable react/jsx-handler-names */
141
-
142
-            return (
143
-                <button
144
-                    className = { className }
145
-                    id = 'reconnectNow'
146
-                    onClick = { this._reconnectNow }>
147
-                    { t('dialog.reconnectNow') }
148
-                </button>
149
-            );
150
-
151
-
152
-            /* eslint-enable react/jsx-handler-names */
153
-        }
154
-
155
-        return null;
156
-    }
157
-
158
-    /**
159
-     * Constructs overlay body with the warning message and count down towards
160
-     * the conference reload.
161
-     *
162
-     * @returns {ReactElement|null}
163
-     * @override
164
-     * @protected
165
-     */
166
-    _renderOverlayContent() {
167
-        const { t } = this.props;
168
-
169
-        /* eslint-disable react/jsx-handler-names */
37
+    render() {
38
+        const { isNetworkFailure, t } = this.props;
39
+        const { message, timeLeft, title } = this.state;
170 40
 
171 41
         return (
172
-            <div className = 'inlay'>
173
-                <span
174
-                    className = 'reload_overlay_title'>
175
-                    { t(this.state.title) }
176
-                </span>
177
-                <span
178
-                    className = 'reload_overlay_text'>
179
-                    { t(this.state.message) }
180
-                </span>
181
-                <ReloadTimer
182
-                    end = { 0 }
183
-                    interval = { 1 }
184
-                    onFinish = { this._reconnectNow }
185
-                    start = { this.state.timeoutSeconds }
186
-                    step = { -1 } />
187
-                { this._renderButton() }
188
-            </div>
42
+            <OverlayFrame isLightOverlay = { isNetworkFailure }>
43
+                <div className = 'inlay'>
44
+                    <span
45
+                        className = 'reload_overlay_title'>
46
+                        { t(title) }
47
+                    </span>
48
+                    <span className = 'reload_overlay_text'>
49
+                        { t(message, { seconds: timeLeft }) }
50
+                    </span>
51
+                    { this._renderProgressBar() }
52
+                    { this._renderButton() }
53
+                </div>
54
+            </OverlayFrame>
189 55
         );
190
-
191
-        /* eslint-enable react/jsx-handler-names */
192 56
     }
193 57
 }
194 58
 

+ 60
- 0
react/features/overlay/components/ReloadButton.js 查看文件

@@ -0,0 +1,60 @@
1
+import React, { Component } from 'react';
2
+
3
+import { translate } from '../../base/i18n';
4
+
5
+import { reconnectNow } from '../functions';
6
+
7
+/**
8
+ * Implements a React Component for button for the overlays that will reload
9
+ * the page.
10
+ */
11
+class ReloadButton extends Component {
12
+    /**
13
+     * PageReloadOverlay component's property types.
14
+     *
15
+     * @static
16
+     */
17
+    static propTypes = {
18
+        /**
19
+         * The function to translate human-readable text.
20
+         *
21
+         * @public
22
+         * @type {Function}
23
+         */
24
+        t: React.PropTypes.func,
25
+
26
+        /**
27
+         * The translation key for the text in the button.
28
+         *
29
+         * @type {string}
30
+         */
31
+        textKey: React.PropTypes.string.isRequired
32
+    }
33
+
34
+    /**
35
+     * Renders the button for relaod the page if necessary.
36
+     *
37
+     * @returns {ReactElement|null}
38
+     * @private
39
+     */
40
+    render() {
41
+        const className
42
+            = 'button-control button-control_overlay button-control_center';
43
+        const { t } = this.props;
44
+
45
+        /* eslint-disable react/jsx-handler-names */
46
+
47
+        return (
48
+            <button
49
+                className = { className }
50
+                onClick = { reconnectNow }>
51
+                { t(this.props.textKey) }
52
+            </button>
53
+        );
54
+
55
+        /* eslint-enable react/jsx-handler-names */
56
+    }
57
+
58
+}
59
+
60
+export default translate(ReloadButton);

+ 53
- 0
react/features/overlay/components/SuspendedFilmStripOnlyOverlay.js 查看文件

@@ -0,0 +1,53 @@
1
+import React, { Component } from 'react';
2
+
3
+import { translate, translateToHTML } from '../../base/i18n';
4
+
5
+import FilmStripOnlyOverlayFrame from './FilmStripOnlyOverlayFrame';
6
+import ReloadButton from './ReloadButton';
7
+
8
+/**
9
+ * Implements a React Component for suspended overlay for filmstrip only mode.
10
+ * Shown when suspended is detected.
11
+ */
12
+class SuspendedFilmStripOnlyOverlay extends Component {
13
+    /**
14
+     * SuspendedFilmStripOnlyOverlay component's property types.
15
+     *
16
+     * @static
17
+     */
18
+    static propTypes = {
19
+        /**
20
+         * The function to translate human-readable text.
21
+         *
22
+         * @public
23
+         * @type {Function}
24
+         */
25
+        t: React.PropTypes.func
26
+    }
27
+
28
+    /**
29
+     * Implements React's {@link Component#render()}.
30
+     *
31
+     * @inheritdoc
32
+     * @returns {ReactElement|null}
33
+     */
34
+    render() {
35
+        const { t } = this.props;
36
+
37
+        return (
38
+            <FilmStripOnlyOverlayFrame isLightOverlay = { true }>
39
+                <div className = 'inlay-filmstrip-only__container'>
40
+                    <div className = 'inlay-filmstrip-only__title'>
41
+                        { t('suspendedoverlay.title') }
42
+                    </div>
43
+                    <div className = 'inlay-filmstrip-only__text'>
44
+                        { translateToHTML(t, 'suspendedoverlay.text') }
45
+                    </div>
46
+                </div>
47
+                <ReloadButton textKey = 'suspendedoverlay.rejoinKeyTitle' />
48
+            </FilmStripOnlyOverlayFrame>
49
+        );
50
+    }
51
+}
52
+
53
+export default translate(SuspendedFilmStripOnlyOverlay);

+ 40
- 26
react/features/overlay/components/SuspendedOverlay.js 查看文件

@@ -1,44 +1,58 @@
1
-import React from 'react';
1
+import React, { Component } from 'react';
2 2
 
3
-import { translate } from '../../base/i18n';
3
+import { translate, translateToHTML } from '../../base/i18n';
4 4
 
5
-import AbstractOverlay from './AbstractOverlay';
5
+import OverlayFrame from './OverlayFrame';
6
+import ReloadButton from './ReloadButton';
6 7
 
7 8
 /**
8 9
  * Implements a React Component for suspended overlay. Shown when a suspend is
9 10
  * detected.
10 11
  */
11
-class SuspendedOverlay extends AbstractOverlay {
12
+class SuspendedOverlay extends Component {
12 13
     /**
13
-     * Constructs overlay body with the message and a button to rejoin.
14
+     * SuspendedOverlay component's property types.
14 15
      *
16
+     * @static
17
+     */
18
+    static propTypes = {
19
+        /**
20
+         * The function to translate human-readable text.
21
+         *
22
+         * @public
23
+         * @type {Function}
24
+         */
25
+        t: React.PropTypes.func
26
+    }
27
+
28
+    /**
29
+     * Implements React's {@link Component#render()}.
30
+     *
31
+     * @inheritdoc
15 32
      * @returns {ReactElement|null}
16
-     * @override
17
-     * @protected
18 33
      */
19
-    _renderOverlayContent() {
20
-        const btnClass = 'inlay__button button-control button-control_primary';
34
+    render() {
21 35
         const { t } = this.props;
22 36
 
23
-        /* eslint-disable react/jsx-handler-names */
24
-
25 37
         return (
26
-            <div className = 'inlay'>
27
-                <span className = 'inlay__icon icon-microphone' />
28
-                <span className = 'inlay__icon icon-camera' />
29
-                <h3
30
-                    className = 'inlay__title'>
31
-                    { t('suspendedoverlay.title') }
32
-                </h3>
33
-                <button
34
-                    className = { btnClass }
35
-                    onClick = { this._reconnectNow }>
36
-                    { t('suspendedoverlay.rejoinKeyTitle') }
37
-                </button>
38
-            </div>
38
+            <OverlayFrame>
39
+                <div className = 'inlay'>
40
+                    <span className = 'inlay__icon icon-microphone' />
41
+                    <span className = 'inlay__icon icon-camera' />
42
+                    <h3
43
+                        className = 'inlay__title'>
44
+                        { t('suspendedoverlay.title') }
45
+                    </h3>
46
+                    <span className = 'inlay__text'>
47
+                        {
48
+                            translateToHTML(t, 'suspendedoverlay.title')
49
+                        }
50
+                    </span>
51
+                    <ReloadButton
52
+                        textKey = 'suspendedoverlay.rejoinKeyTitle' />
53
+                </div>
54
+            </OverlayFrame>
39 55
         );
40
-
41
-        /* eslint-enable react/jsx-handler-names */
42 56
     }
43 57
 }
44 58
 

+ 68
- 0
react/features/overlay/components/UserMediaPermissionsFilmStripOnlyOverlay.js 查看文件

@@ -0,0 +1,68 @@
1
+import React, { Component } from 'react';
2
+
3
+import { translate, translateToHTML } from '../../base/i18n';
4
+
5
+import FilmStripOnlyOverlayFrame from './FilmStripOnlyOverlayFrame';
6
+
7
+/**
8
+ * Implements a React Component for overlay with guidance how to proceed with
9
+ * gUM prompt. This component will be displayed only for filmstrip only mode.
10
+ */
11
+class UserMediaPermissionsFilmStripOnlyOverlay extends Component {
12
+    /**
13
+     * UserMediaPermissionsFilmStripOnlyOverlay component's property types.
14
+     *
15
+     * @static
16
+     */
17
+    static propTypes = {
18
+        /**
19
+         * The browser which is used currently. The text is different for every
20
+         * browser.
21
+         *
22
+         * @public
23
+         * @type {string}
24
+         */
25
+        browser: React.PropTypes.string,
26
+
27
+        /**
28
+         * The function to translate human-readable text.
29
+         *
30
+         * @public
31
+         * @type {Function}
32
+         */
33
+        t: React.PropTypes.func
34
+    }
35
+
36
+    /**
37
+     * Implements React's {@link Component#render()}.
38
+     *
39
+     * @inheritdoc
40
+     * @returns {ReactElement|null}
41
+     */
42
+    render() {
43
+        const { t } = this.props;
44
+        const textKey = `userMedia.${this.props.browser}GrantPermissions`;
45
+
46
+        return (
47
+            <FilmStripOnlyOverlayFrame
48
+                icon = 'icon-mic-camera-combined'
49
+                isLightOverlay = { true }>
50
+                <div className = 'inlay-filmstrip-only__container'>
51
+                    <div className = 'inlay-filmstrip-only__title'>
52
+                        {
53
+                            t('startupoverlay.title',
54
+                                { postProcess: 'resolveAppName' })
55
+                        }
56
+                    </div>
57
+                    <div className = 'inlay-filmstrip-only__text'>
58
+                        {
59
+                            translateToHTML(t, textKey)
60
+                        }
61
+                    </div>
62
+                </div>
63
+            </FilmStripOnlyOverlayFrame>
64
+        );
65
+    }
66
+}
67
+
68
+export default translate(UserMediaPermissionsFilmStripOnlyOverlay);

+ 20
- 16
react/features/overlay/components/UserMediaPermissionsOverlay.js 查看文件

@@ -1,16 +1,16 @@
1 1
 /* global interfaceConfig */
2 2
 
3
-import React from 'react';
3
+import React, { Component } from 'react';
4 4
 
5 5
 import { translate, translateToHTML } from '../../base/i18n';
6 6
 
7
-import AbstractOverlay from './AbstractOverlay';
7
+import OverlayFrame from './OverlayFrame';
8 8
 
9 9
 /**
10 10
  * Implements a React Component for overlay with guidance how to proceed with
11 11
  * gUM prompt.
12 12
  */
13
-class UserMediaPermissionsOverlay extends AbstractOverlay {
13
+class UserMediaPermissionsOverlay extends Component {
14 14
     /**
15 15
      * UserMediaPermissionsOverlay component's property types.
16 16
      *
@@ -24,7 +24,15 @@ class UserMediaPermissionsOverlay extends AbstractOverlay {
24 24
          * @public
25 25
          * @type {string}
26 26
          */
27
-        browser: React.PropTypes.string
27
+        browser: React.PropTypes.string,
28
+
29
+        /**
30
+         * The function to translate human-readable text.
31
+         *
32
+         * @public
33
+         * @type {Function}
34
+         */
35
+        t: React.PropTypes.func
28 36
     }
29 37
 
30 38
     /**
@@ -48,45 +56,41 @@ class UserMediaPermissionsOverlay extends AbstractOverlay {
48 56
     }
49 57
 
50 58
     /**
51
-     * Constructs overlay body with the message with guidance how to proceed
52
-     * with gUM prompt.
59
+     * Implements React's {@link Component#render()}.
53 60
      *
61
+     * @inheritdoc
54 62
      * @returns {ReactElement|null}
55
-     * @override
56
-     * @protected
57 63
      */
58
-    _renderOverlayContent() {
64
+    render() {
59 65
         const { browser, t } = this.props;
60 66
 
61 67
         return (
62
-            <div>
68
+            <OverlayFrame>
63 69
                 <div className = 'inlay'>
64 70
                     <span className = 'inlay__icon icon-microphone' />
65 71
                     <span className = 'inlay__icon icon-camera' />
66 72
                     <h3 className = 'inlay__title'>
67 73
                         {
68
-                            t(
69
-                                'startupoverlay.title',
74
+                            t('startupoverlay.title',
70 75
                                 { postProcess: 'resolveAppName' })
71 76
                         }
72 77
                     </h3>
73 78
                     <span className = 'inlay__text'>
74 79
                         {
75
-                            translateToHTML(
76
-                                t,
80
+                            translateToHTML(t,
77 81
                                 `userMedia.${browser}GrantPermissions`)
78 82
                         }
79 83
                     </span>
80 84
                 </div>
81 85
                 <div className = 'policy overlay__policy'>
82 86
                     <p className = 'policy__text'>
83
-                        { t('startupoverlay.policyText') }
87
+                        { translateToHTML(t, 'startupoverlay.policyText') }
84 88
                     </p>
85 89
                     {
86 90
                         this._renderPolicyLogo()
87 91
                     }
88 92
                 </div>
89
-            </div>
93
+            </OverlayFrame>
90 94
         );
91 95
     }
92 96
 

+ 12
- 0
react/features/overlay/functions.js 查看文件

@@ -0,0 +1,12 @@
1
+/* global APP */
2
+/**
3
+ * Reloads the page.
4
+ *
5
+ * @returns {void}
6
+ * @protected
7
+ */
8
+export function reconnectNow() {
9
+    // FIXME: In future we should dispatch an action here that will result
10
+    // in reload.
11
+    APP.ConferenceUrl.reload();
12
+}

正在加载...
取消
保存