Bläddra i källkod

feat(overlays): for filmstrip only mode

master
hristoterezov 8 år sedan
förälder
incheckning
3ae99ea0b9

+ 82
- 3
css/_inlay.scss Visa fil

27
         font-size: 50px;
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 Visa fil

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
     &_primary {
72
     &_primary {
61
         background-color: $primaryButtonBackground;
73
         background-color: $primaryButtonBackground;
62
         border: 1px solid $primaryButtonBackground;
74
         border: 1px solid $primaryButtonBackground;
86
     &_center {
98
     &_center {
87
         float: none !important;
99
         float: none !important;
88
     }
100
     }
89
-}
101
+}

+ 12
- 1
css/overlay/_overlay.scss Visa fil

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

+ 3
- 0
css/reload_overlay/_reload_overlay.scss Visa fil

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

+ 8
- 0
css/themes/_light.scss Visa fil

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

+ 13
- 13
lang/main.json Visa fil

15
     "defaultLink": "e.g. __url__",
15
     "defaultLink": "e.g. __url__",
16
     "callingName": "__name__",
16
     "callingName": "__name__",
17
     "userMedia": {
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
       "nwjsGrantPermissions": "Please grant permissions to use your camera and microphone"
25
       "nwjsGrantPermissions": "Please grant permissions to use your camera and microphone"
26
     },
26
     },
27
     "keyboardShortcuts": {
27
     "keyboardShortcuts": {
87
     },
87
     },
88
     "suspendedoverlay": {
88
     "suspendedoverlay": {
89
         "title": "Your video call was interrupted, because this computer went to sleep.",
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
         "rejoinKeyTitle": "Rejoin"
91
         "rejoinKeyTitle": "Rejoin"
91
     },
92
     },
92
     "toolbar": {
93
     "toolbar": {
229
         "detectext": "Error when trying to detect desktopsharing extension.",
230
         "detectext": "Error when trying to detect desktopsharing extension.",
230
         "failtoinstall": "Failed to install desktop sharing extension",
231
         "failtoinstall": "Failed to install desktop sharing extension",
231
         "failedpermissions": "Failed to obtain permissions to use the local microphone and/or camera.",
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
         "maxUsersLimitReached": "The limit for maximum number of participants in the conference has been reached. The conference is full. Please try again later!",
238
         "maxUsersLimitReached": "The limit for maximum number of participants in the conference has been reached. The conference is full. Please try again later!",
239
         "lockTitle": "Lock failed",
239
         "lockTitle": "Lock failed",
240
         "lockMessage": "Failed to lock the conference.",
240
         "lockMessage": "Failed to lock the conference.",

+ 10
- 3
modules/URL/ConferenceUrl.js Visa fil

1
 const logger = require("jitsi-meet-logger").getLogger(__filename);
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
  * The modules stores information about the URL used to start the conference and
6
  * The modules stores information about the URL used to start the conference and
67
      * Reloads the conference using original URL with all of the parameters.
67
      * Reloads the conference using original URL with all of the parameters.
68
      */
68
      */
69
     reload() {
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
 }

+ 192
- 0
react/features/overlay/components/AbstractPageReloadOverlay.js Visa fil

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 Visa fil

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 Visa fil

1
-/* global APP */
2
-
3
 import React, { Component } from 'react';
1
 import React, { Component } from 'react';
4
 import { connect } from 'react-redux';
2
 import { connect } from 'react-redux';
5
 
3
 
4
+import PageReloadFilmStripOnlyOverlay from './PageReloadFilmStripOnlyOverlay';
6
 import PageReloadOverlay from './PageReloadOverlay';
5
 import PageReloadOverlay from './PageReloadOverlay';
6
+import SuspendedFilmStripOnlyOverlay from './SuspendedFilmStripOnlyOverlay';
7
 import SuspendedOverlay from './SuspendedOverlay';
7
 import SuspendedOverlay from './SuspendedOverlay';
8
+import UserMediaPermissionsFilmStripOnlyOverlay
9
+    from './UserMediaPermissionsFilmStripOnlyOverlay';
8
 import UserMediaPermissionsOverlay from './UserMediaPermissionsOverlay';
10
 import UserMediaPermissionsOverlay from './UserMediaPermissionsOverlay';
9
 
11
 
12
+declare var APP: Object;
13
+declare var interfaceConfig: Object;
14
+
10
 /**
15
 /**
11
  * Implements a React Component that will display the correct overlay when
16
  * Implements a React Component that will display the correct overlay when
12
  * needed.
17
  * needed.
94
         _suspendDetected: React.PropTypes.bool
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
      * React Component method that executes once component is updated.
122
      * React Component method that executes once component is updated.
99
      *
123
      *
117
      * @public
141
      * @public
118
      */
142
      */
119
     render() {
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
         return null;
168
         return null;

+ 31
- 6
react/features/overlay/components/OverlayFrame.js Visa fil

1
 import React, { Component } from 'react';
1
 import React, { Component } from 'react';
2
 
2
 
3
+declare var interfaceConfig: Object;
4
+
3
 /**
5
 /**
4
- * Implements an abstract React Component for overlay - the components which are
5
- * displayed on top of the application covering the whole screen.
6
- *
7
- * @abstract
6
+ * Implements a React Component for the frame of the overlays.
8
  */
7
  */
9
 export default class OverlayFrame extends Component {
8
 export default class OverlayFrame extends Component {
10
     /**
9
     /**
27
         isLightOverlay: React.PropTypes.bool
26
         isLightOverlay: React.PropTypes.bool
28
     }
27
     }
29
 
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
+
30
     /**
49
     /**
31
      * Implements React's {@link Component#render()}.
50
      * Implements React's {@link Component#render()}.
32
      *
51
      *
34
      * @returns {ReactElement|null}
53
      * @returns {ReactElement|null}
35
      */
54
      */
36
     render() {
55
     render() {
37
-        const containerClass = this.props.isLightOverlay
56
+        let containerClass = this.props.isLightOverlay
38
             ? 'overlay__container-light' : 'overlay__container';
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
+        }
39
 
64
 
40
         return (
65
         return (
41
             <div
66
             <div
42
                 className = { containerClass }
67
                 className = { containerClass }
43
                 id = 'overlay'>
68
                 id = 'overlay'>
44
-                <div className = 'overlay__content'>
69
+                <div className = { contentClass }>
45
                     {
70
                     {
46
                         this.props.children
71
                         this.props.children
47
                     }
72
                     }

+ 62
- 0
react/features/overlay/components/PageReloadFilmStripOnlyOverlay.js Visa fil

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);

+ 11
- 151
react/features/overlay/components/PageReloadOverlay.js Visa fil

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

+ 60
- 0
react/features/overlay/components/ReloadButton.js Visa fil

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 Visa fil

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 Visa fil

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
  * Implements a React Component for suspended overlay. Shown when a suspend is
9
  * Implements a React Component for suspended overlay. Shown when a suspend is
9
  * detected.
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
      * @returns {ReactElement|null}
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
         const { t } = this.props;
35
         const { t } = this.props;
22
 
36
 
23
-        /* eslint-disable react/jsx-handler-names */
24
-
25
         return (
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 Visa fil

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);

+ 2
- 4
react/features/overlay/components/UserMediaPermissionsOverlay.js Visa fil

71
                     <span className = 'inlay__icon icon-camera' />
71
                     <span className = 'inlay__icon icon-camera' />
72
                     <h3 className = 'inlay__title'>
72
                     <h3 className = 'inlay__title'>
73
                         {
73
                         {
74
-                            t(
75
-                                'startupoverlay.title',
74
+                            t('startupoverlay.title',
76
                                 { postProcess: 'resolveAppName' })
75
                                 { postProcess: 'resolveAppName' })
77
                         }
76
                         }
78
                     </h3>
77
                     </h3>
79
                     <span className = 'inlay__text'>
78
                     <span className = 'inlay__text'>
80
                         {
79
                         {
81
-                            translateToHTML(
82
-                                t,
80
+                            translateToHTML(t,
83
                                 `userMedia.${browser}GrantPermissions`)
81
                                 `userMedia.${browser}GrantPermissions`)
84
                         }
82
                         }
85
                     </span>
83
                     </span>

Laddar…
Avbryt
Spara