Kaynağa Gözat

feat(overlays): for filmstrip only mode

j8
hristoterezov 8 yıl önce
ebeveyn
işleme
3ae99ea0b9

+ 82
- 3
css/_inlay.scss Dosyayı Görüntüle

@@ -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 Dosyayı Görüntüle

@@ -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 Dosyayı Görüntüle

@@ -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 Dosyayı Görüntüle

@@ -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 Dosyayı Görüntüle

@@ -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 Dosyayı Görüntüle

@@ -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 Dosyayı Görüntüle

@@ -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
 }

+ 192
- 0
react/features/overlay/components/AbstractPageReloadOverlay.js Dosyayı Görüntüle

@@ -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 Dosyayı Görüntüle

@@ -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 Dosyayı Görüntüle

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

+ 31
- 6
react/features/overlay/components/OverlayFrame.js Dosyayı Görüntüle

@@ -1,10 +1,9 @@
1 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 8
 export default class OverlayFrame extends Component {
10 9
     /**
@@ -27,6 +26,26 @@ export default class OverlayFrame extends Component {
27 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 50
      * Implements React's {@link Component#render()}.
32 51
      *
@@ -34,14 +53,20 @@ export default class OverlayFrame extends Component {
34 53
      * @returns {ReactElement|null}
35 54
      */
36 55
     render() {
37
-        const containerClass = this.props.isLightOverlay
56
+        let containerClass = this.props.isLightOverlay
38 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 65
         return (
41 66
             <div
42 67
                 className = { containerClass }
43 68
                 id = 'overlay'>
44
-                <div className = 'overlay__content'>
69
+                <div className = { contentClass }>
45 70
                     {
46 71
                         this.props.children
47 72
                     }

+ 62
- 0
react/features/overlay/components/PageReloadFilmStripOnlyOverlay.js Dosyayı Görüntüle

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

+ 11
- 151
react/features/overlay/components/PageReloadOverlay.js Dosyayı Görüntüle

@@ -1,42 +1,23 @@
1
-import React, { Component } from 'react';
1
+import React from 'react';
2 2
 
3 3
 import { translate } from '../../base/i18n';
4
-import { randomInt } from '../../base/util';
5 4
 
5
+import AbstractPageReloadOverlay from './AbstractPageReloadOverlay';
6 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 9
  * Implements a React Component for page reload overlay. Shown before the
16 10
  * conference is reloaded. Shows a warning message and counts down towards the
17 11
  * reload.
18 12
  */
19
-class PageReloadOverlay extends Component {
13
+class PageReloadOverlay extends AbstractPageReloadOverlay {
20 14
     /**
21 15
      * PageReloadOverlay component's property types.
22 16
      *
23 17
      * @static
24 18
      */
25 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 23
          * The function to translate human-readable text.
@@ -47,118 +28,6 @@ class PageReloadOverlay extends Component {
47 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 32
      * Implements React's {@link Component#render()}.
164 33
      *
@@ -166,33 +35,24 @@ class PageReloadOverlay extends Component {
166 35
      * @returns {ReactElement|null}
167 36
      */
168 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 41
         return (
174
-            <OverlayFrame isLightOverlay = { this.state.isLightOverlay }>
42
+            <OverlayFrame isLightOverlay = { isNetworkFailure }>
175 43
                 <div className = 'inlay'>
176 44
                     <span
177 45
                         className = 'reload_overlay_title'>
178
-                        { t(this.state.title) }
46
+                        { t(title) }
179 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 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 52
                     { this._renderButton() }
191 53
                 </div>
192 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 Dosyayı Görüntüle

@@ -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 Dosyayı Görüntüle

@@ -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 Dosyayı Görüntüle

@@ -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 Dosyayı Görüntüle

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

+ 2
- 4
react/features/overlay/components/UserMediaPermissionsOverlay.js Dosyayı Görüntüle

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

Loading…
İptal
Kaydet