Przeglądaj źródła

Info dialog: bold labels, no url truncation, only auto show on lonely call (#2619)

* fix(info): bold info labels

* fix(info): do not truncate url

* feat(info): show only during a lonely call
master
virtuacoplenny 7 lat temu
rodzic
commit
2f23f8e400

+ 21
- 16
css/modals/invite/_info.scss Wyświetl plik

@@ -38,7 +38,7 @@
38 38
     .info-dialog-copy-element {
39 39
         opacity: 0;
40 40
         pointer-events: none;
41
-        position: fixed;
41
+        position: absolute;
42 42
         -webkit-user-select: text;
43 43
         user-select: text;
44 44
     }
@@ -56,11 +56,11 @@
56 56
     }
57 57
 
58 58
     .info-dialog-conference-url {
59
-        max-width: 250px;
60
-        overflow: hidden;
61
-        text-overflow: ellipsis;
62
-        user-select: text;
63
-        white-space: nowrap;
59
+        width: max-content;
60
+        width: -moz-max-content;
61
+        width: -webkit-max-content;
62
+        word-break: break-all;
63
+        max-width: 400px;
64 64
     }
65 65
 
66 66
     .info-dialog-dial-in {
@@ -82,14 +82,18 @@
82 82
         margin-bottom: 10px;
83 83
     }
84 84
 
85
-    .info-password,
86 85
     .info-dialog-password,
86
+    .info-password,
87 87
     .info-password-form {
88
+        align-items: baseline;
88 89
         display: flex;
89 90
     }
90 91
 
92
+    .info-label {
93
+        font-weight: bold;
94
+    }
95
+
91 96
     .info-password-field {
92
-        margin-left: 2px;
93 97
         overflow: hidden;
94 98
         text-overflow: ellipsis;
95 99
         white-space: nowrap;
@@ -110,10 +114,6 @@
110 114
     .info-password-local {
111 115
         user-select: text;
112 116
     }
113
-
114
-    .conference-id {
115
-        margin-left: 5px;
116
-    }
117 117
 }
118 118
 
119 119
 .dial-in-page {
@@ -125,10 +125,6 @@
125 125
     justify-content: center;
126 126
     width: 100%;
127 127
 
128
-    * {
129
-        user-select: text;
130
-    }
131
-
132 128
     .dial-in-numbers-list {
133 129
         font-size: 24px;
134 130
         margin-top: 20px;
@@ -139,3 +135,12 @@
139 135
         width: 30%;
140 136
     }
141 137
 }
138
+
139
+.info-dialog,
140
+.dial-in-page {
141
+    * {
142
+        user-select: text;
143
+        -moz-user-select: text;
144
+        -webkit-user-select: text;
145
+    }
146
+}

+ 4
- 4
lang/main.json Wyświetl plik

@@ -516,11 +516,11 @@
516 516
     "info": {
517 517
         "addPassword": "Add password",
518 518
         "cancelPassword": "Cancel password",
519
-        "conferenceURL": "Link: __url__",
519
+        "conferenceURL": "Link:",
520 520
         "country": "Country",
521 521
         "dialANumber": "To join your meeting, dial one of these numbers and then enter this PIN: __conferenceID__#",
522
-        "dialInNumber": "Dial-in: __phoneNumber__",
523
-        "dialInConferenceID": "PIN: __conferenceID__#",
522
+        "dialInNumber": "Dial-in:",
523
+        "dialInConferenceID": "PIN:",
524 524
         "dialInNotSupported": "Sorry, dialing in is currently not suppported.",
525 525
         "genericError": "Whoops, something went wrong.",
526 526
         "invitePhone": "To join by phone, dial __number__ and enter this PIN: __conferenceID__#",
@@ -532,7 +532,7 @@
532 532
         "noRoom": "No room was specified to dial-in into.",
533 533
         "numbers": "Dial-in Numbers",
534 534
         "password": "Password:",
535
-        "title": "Call info",
535
+        "title": "Share",
536 536
         "tooltip": "Get access info about the meeting"
537 537
     },
538 538
     "settingsView": {

+ 0
- 11
react/features/invite/actionTypes.js Wyświetl plik

@@ -1,14 +1,3 @@
1
-/**
2
- * The type of the action which signals a request to display the inline
3
- * conference info dialog.
4
- *
5
- * {
6
- *     type: SET_INFO_DIALOG_VISIBILITY,
7
- *     visible: boolean
8
- * }
9
- */
10
-export const SET_INFO_DIALOG_VISIBILITY = Symbol('SET_INFO_DIALOG_VISIBILITY');
11
-
12 1
 /**
13 2
  * The type of the action which signals an error occurred while requesting dial-
14 3
  * in numbers.

+ 0
- 23
react/features/invite/actions.js Wyświetl plik

@@ -1,34 +1,11 @@
1 1
 // @flow
2 2
 
3 3
 import {
4
-    SET_INFO_DIALOG_VISIBILITY,
5 4
     UPDATE_DIAL_IN_NUMBERS_FAILED,
6 5
     UPDATE_DIAL_IN_NUMBERS_SUCCESS
7 6
 } from './actionTypes';
8 7
 import { getDialInConferenceID, getDialInNumbers } from './functions';
9 8
 
10
-/**
11
- * Opens the inline conference info dialog.
12
- *
13
- * @param {boolean} visible - Whether or not the dialog should be displayed.
14
- * @param {boolean} autoClose - Whether or not the dialog should automatically
15
- * close after a set period of time.
16
- * @returns {{
17
- *     type: SET_INFO_DIALOG_VISIBILITY,
18
- *     autoClose: boolean,
19
- *     visible: boolean
20
- * }}
21
- */
22
-export function setInfoDialogVisibility(
23
-        visible: boolean,
24
-        autoClose: boolean = false) {
25
-    return {
26
-        type: SET_INFO_DIALOG_VISIBILITY,
27
-        autoClose,
28
-        visible
29
-    };
30
-}
31
-
32 9
 /**
33 10
  * Sends AJAX requests for dial-in numbers and conference ID.
34 11
  *

+ 59
- 89
react/features/invite/components/InfoDialogButton.web.js Wyświetl plik

@@ -7,16 +7,16 @@ import { connect } from 'react-redux';
7 7
 
8 8
 import { createToolbarEvent, sendAnalytics } from '../../analytics';
9 9
 import { translate } from '../../base/i18n';
10
+import { getParticipantCount } from '../../base/participants';
10 11
 import {
11 12
     ToolbarButton,
12 13
     ToolbarButtonV2,
13 14
     TOOLTIP_TO_POPUP_POSITION
14 15
 } from '../../toolbox';
15 16
 
16
-import { setInfoDialogVisibility, updateDialInNumbers } from '../actions';
17
-import { InfoDialog } from './info-dialog';
17
+import { updateDialInNumbers } from '../actions';
18 18
 
19
-const { INITIAL_TOOLBAR_TIMEOUT } = interfaceConfig;
19
+import { InfoDialog } from './info-dialog';
20 20
 
21 21
 /**
22 22
  * A configuration object to describe how {@code ToolbarButton} should render
@@ -32,6 +32,14 @@ const DEFAULT_BUTTON_CONFIGURATION = {
32 32
     tooltipKey: 'info.tooltip'
33 33
 };
34 34
 
35
+/**
36
+ * The amount of time, in milliseconds, to wait until automatically showing
37
+ * the {@code InfoDialog}. This is essentially a hack as automatic showing
38
+ * should happen in a lonely call and some time is needed to populate
39
+ * participants already in the call.
40
+ */
41
+const INFO_DIALOG_AUTO_SHOW_TIMEOUT = 1500;
42
+
35 43
 /**
36 44
  * A React Component for displaying a button which opens a dialog with
37 45
  * information about the conference and with ways to invite people.
@@ -55,15 +63,16 @@ class InfoDialogButton extends Component {
55 63
         ]),
56 64
 
57 65
         /**
58
-         * Whether or not the {@code InfoDialog} should close by itself after a
59
-         * a timeout.
66
+         * Whether or not the {@code InfoDialog} should display automatically
67
+         * after {@link INFO_DIALOG_AUTO_SHOW_TIMEOUT}.
60 68
          */
61
-        _shouldAutoClose: PropTypes.bool,
69
+        _disableAutoShow: PropTypes.bool,
62 70
 
63 71
         /**
64
-         * Whether or not {@code InfoDialog} should be displayed.
72
+         * The number of real participants in the call. If in a lonely call,
73
+         * the {@code InfoDialog} will be automatically shown.
65 74
          */
66
-        _showDialog: PropTypes.bool,
75
+        _participantCount: PropTypes.number,
67 76
 
68 77
         /**
69 78
          * Whether or not the toolbox, in which this component exists, are
@@ -98,16 +107,23 @@ class InfoDialogButton extends Component {
98 107
         super(props);
99 108
 
100 109
         /**
101
-         * The timeout to automatically hide the {@code InfoDialog} if it has
102
-         * not been interacted with.
110
+         * The timeout to automatically show the {@code InfoDialog} if it has
111
+         * not been shown yet in a lonely call.
103 112
          *
104 113
          * @type {timeoutID}
105 114
          */
106
-        this._autoHideDialogTimeout = null;
115
+        this._autoShowTimeout = null;
116
+
117
+
118
+        this.state = {
119
+            /**
120
+             * Whether or not {@code InfoDialog} should be visible.
121
+             */
122
+            showDialog: false
123
+        };
107 124
 
108 125
         // Bind event handlers so they are only bound once for every instance.
109 126
         this._onDialogClose = this._onDialogClose.bind(this);
110
-        this._onDialogMouseOver = this._onDialogMouseOver.bind(this);
111 127
         this._onDialogToggle = this._onDialogToggle.bind(this);
112 128
     }
113 129
 
@@ -117,30 +133,15 @@ class InfoDialogButton extends Component {
117 133
      * @inheritdoc
118 134
      */
119 135
     componentDidMount() {
120
-        if (this.props._shouldAutoClose) {
121
-            this._setAutoCloseTimeout();
122
-        }
136
+        this._autoShowTimeout = setTimeout(() => {
137
+            this._maybeAutoShowDialog();
138
+        }, INFO_DIALOG_AUTO_SHOW_TIMEOUT);
123 139
 
124 140
         if (!this.props._dialInNumbers) {
125 141
             this.props.dispatch(updateDialInNumbers());
126 142
         }
127 143
     }
128 144
 
129
-    /**
130
-     * Set or clear the timeout to automatically hide the {@code InfoDialog}.
131
-     *
132
-     * @inheritdoc
133
-     */
134
-    componentDidUpdate(prevProps) {
135
-        // If the _shouldAutoClose flag has been updated to be true then make
136
-        // sure to set _autoHideDialogTimeout.
137
-        if (this.props._shouldAutoClose && !prevProps._shouldAutoClose) {
138
-            this._setAutoCloseTimeout();
139
-        } else {
140
-            this._clearAutoCloseTimeout();
141
-        }
142
-    }
143
-
144 145
     /**
145 146
      * Update the visibility of the {@code InfoDialog}.
146 147
      *
@@ -148,7 +149,7 @@ class InfoDialogButton extends Component {
148 149
      */
149 150
     componentWillReceiveProps(nextProps) {
150 151
         // Ensure the dialog is closed when the toolbox becomes hidden.
151
-        if (nextProps._showDialog && !nextProps._toolboxVisible) {
152
+        if (this.state.showDialog && !nextProps._toolboxVisible) {
152 153
             this._onDialogClose();
153 154
         }
154 155
     }
@@ -159,7 +160,7 @@ class InfoDialogButton extends Component {
159 160
      * @inheritdoc
160 161
      */
161 162
     componentWillUnmount() {
162
-        this._clearAutoCloseTimeout();
163
+        clearTimeout(this._autoShowTimeout);
163 164
     }
164 165
 
165 166
     /**
@@ -175,14 +176,16 @@ class InfoDialogButton extends Component {
175 176
     }
176 177
 
177 178
     /**
178
-     * Cancels the timeout to automatically hide the {@code InfoDialog}.
179
+     * Callback invoked after a timeout to trigger display of the
180
+     * {@code InfoDialog} if certain conditions are met.
179 181
      *
180 182
      * @private
181 183
      * @returns {void}
182 184
      */
183
-    _clearAutoCloseTimeout() {
184
-        clearTimeout(this._autoHideDialogTimeout);
185
-        this._autoHideDialogTimeout = null;
185
+    _maybeAutoShowDialog() {
186
+        if (this.props._participantCount < 2 && !this.props._disableAutoShow) {
187
+            this.setState({ showDialog: true });
188
+        }
186 189
     }
187 190
 
188 191
     /**
@@ -192,17 +195,7 @@ class InfoDialogButton extends Component {
192 195
      * @returns {void}
193 196
      */
194 197
     _onDialogClose() {
195
-        this.props.dispatch(setInfoDialogVisibility(false));
196
-    }
197
-
198
-    /**
199
-     * Cancels the timeout to automatically hide the {@code InfoDialog}.
200
-     *
201
-     * @private
202
-     * @returns {void}
203
-     */
204
-    _onDialogMouseOver() {
205
-        this._clearAutoCloseTimeout();
198
+        this.setState({ showDialog: false });
206 199
     }
207 200
 
208 201
     /**
@@ -214,7 +207,7 @@ class InfoDialogButton extends Component {
214 207
     _onDialogToggle() {
215 208
         sendAnalytics(createToolbarEvent('info'));
216 209
 
217
-        this.props.dispatch(setInfoDialogVisibility(!this.props._showDialog));
210
+        this.setState({ showDialog: !this.state.showDialog });
218 211
     }
219 212
 
220 213
     /**
@@ -225,22 +218,21 @@ class InfoDialogButton extends Component {
225 218
      * @returns {ReactElement}
226 219
      */
227 220
     _renderOldToolbarButton() {
228
-        const { _showDialog, _toolboxVisible, tooltipPosition } = this.props;
221
+        const { tooltipPosition } = this.props;
222
+        const { showDialog } = this.state;
223
+
229 224
         const buttonConfiguration = {
230 225
             ...DEFAULT_BUTTON_CONFIGURATION,
231 226
             classNames: [
232 227
                 ...DEFAULT_BUTTON_CONFIGURATION.classNames,
233
-                _showDialog ? 'toggled button-active' : ''
228
+                showDialog ? 'toggled button-active' : ''
234 229
             ]
235 230
         };
236 231
 
237 232
         return (
238 233
             <InlineDialog
239
-                content = { <InfoDialog
240
-                    autoUpdateNumbers = { false }
241
-                    onClose = { this._onDialogClose }
242
-                    onMouseOver = { this._onDialogMouseOver } /> }
243
-                isOpen = { _toolboxVisible && _showDialog }
234
+                content = { <InfoDialog onClose = { this._onDialogClose } /> }
235
+                isOpen = { showDialog }
244 236
                 onClose = { this._onDialogClose }
245 237
                 position = { TOOLTIP_TO_POPUP_POSITION[tooltipPosition] }>
246 238
                 <ToolbarButton
@@ -259,17 +251,16 @@ class InfoDialogButton extends Component {
259 251
      * @returns {ReactElement}
260 252
      */
261 253
     _renderNewToolbarButton() {
262
-        const { _showDialog, _toolboxVisible, t } = this.props;
263
-        const iconClass = `icon-info ${_showDialog ? 'toggled' : ''}`;
254
+        const { t } = this.props;
255
+        const { showDialog } = this.state;
256
+        const iconClass = `icon-info ${showDialog ? 'toggled' : ''}`;
264 257
 
265 258
         return (
266 259
             <div className = 'toolbox-button-wth-dialog'>
267 260
                 <InlineDialog
268
-                    content = { <InfoDialog
269
-                        autoUpdateNumbers = { false }
270
-                        onClose = { this._onDialogClose }
271
-                        onMouseOver = { this._onDialogMouseOver } /> }
272
-                    isOpen = { _toolboxVisible && _showDialog }
261
+                    content = {
262
+                        <InfoDialog onClose = { this._onDialogClose } /> }
263
+                    isOpen = { showDialog }
273 264
                     onClose = { this._onDialogClose }
274 265
                     position = { 'top right' }>
275 266
                     <ToolbarButtonV2
@@ -281,22 +272,6 @@ class InfoDialogButton extends Component {
281 272
             </div>
282 273
         );
283 274
     }
284
-
285
-    /**
286
-     * Set a timeout to automatically hide the {@code InfoDialog}.
287
-     *
288
-     * @private
289
-     * @returns {void}
290
-     */
291
-    _setAutoCloseTimeout() {
292
-        this._clearAutoCloseTimeout();
293
-
294
-        this._autoHideDialogTimeout = setTimeout(() => {
295
-            if (this.props._showDialog) {
296
-                this._onDialogClose();
297
-            }
298
-        }, INITIAL_TOOLBAR_TIMEOUT);
299
-    }
300 275
 }
301 276
 
302 277
 /**
@@ -307,22 +282,17 @@ class InfoDialogButton extends Component {
307 282
  * @private
308 283
  * @returns {{
309 284
  *     _dialInNumbers: Array,
310
- *     _shouldAutoClose: boolean,
311
- *     _showDialog: boolean,
285
+ *     _disableAutoShow: bolean,
286
+ *     _participantCount: number,
312 287
  *     _toolboxVisible: boolean
313 288
  * }}
314 289
  */
315 290
 function _mapStateToProps(state) {
316
-    const {
317
-        infoDialogVisible,
318
-        infoDialogWillAutoClose,
319
-        numbers
320
-    } = state['features/invite'];
321
-
322 291
     return {
323
-        _dialInNumbers: numbers,
324
-        _shouldAutoClose: infoDialogWillAutoClose,
325
-        _showDialog: infoDialogVisible,
292
+        _dialInNumbers: state['features/invite'].numbers,
293
+        _disableAutoShow: state['features/base/config'].iAmRecorder,
294
+        _participantCount:
295
+            getParticipantCount(state['features/base/participants']),
326 296
         _toolboxVisible: state['features/toolbox'].visible
327 297
     };
328 298
 }

+ 16
- 4
react/features/invite/components/info-dialog/DialInNumber.web.js Wyświetl plik

@@ -41,16 +41,28 @@ class DialInNumber extends Component {
41 41
      * @returns {ReactElement}
42 42
      */
43 43
     render() {
44
-        const { conferenceID, phoneNumber } = this.props;
44
+        const { conferenceID, phoneNumber, t } = this.props;
45 45
 
46 46
         return (
47 47
             <div className = 'dial-in-number'>
48 48
                 <span className = 'phone-number'>
49
-                    { this.props.t('info.dialInNumber', { phoneNumber }) }
49
+                    <span className = 'info-label'>
50
+                        { t('info.dialInNumber') }
51
+                    </span>
52
+                    <span className = 'spacer'>&nbsp;</span>
53
+                    <span className = 'info-value'>
54
+                        { phoneNumber }
55
+                    </span>
50 56
                 </span>
57
+                <span className = 'spacer'>&nbsp;</span>
51 58
                 <span className = 'conference-id'>
52
-                    { this.props.t(
53
-                        'info.dialInConferenceID', { conferenceID }) }
59
+                    <span className = 'info-label'>
60
+                        { t('info.dialInConferenceID') }
61
+                    </span>
62
+                    <span className = 'spacer'>&nbsp;</span>
63
+                    <span className = 'info-value'>
64
+                        { `${conferenceID}#` }
65
+                    </span>
54 66
                 </span>
55 67
             </div>
56 68
         );

+ 13
- 8
react/features/invite/components/info-dialog/InfoDialog.web.js Wyświetl plik

@@ -214,14 +214,13 @@ class InfoDialog extends Component {
214 214
                         { t('info.title') }
215 215
                     </div>
216 216
                     <div className = 'info-dialog-conference-url'>
217
-                        { t('info.conferenceURL',
218
-                            { url: this._getURLToDisplay() }) }
219
-                        <textarea
220
-                            className = 'info-dialog-copy-element'
221
-                            readOnly = { true }
222
-                            ref = { this._setCopyElement }
223
-                            tabIndex = '-1'
224
-                            value = { this._getTextToCopy() } />
217
+                        <span className = 'info-label'>
218
+                            { t('info.conferenceURL') }
219
+                        </span>
220
+                        <span className = 'spacer'>&nbsp;</span>
221
+                        <span className = 'info-value'>
222
+                            { this._getURLToDisplay() }
223
+                        </span>
225 224
                     </div>
226 225
                     <div className = 'info-dialog-dial-in'>
227 226
                         { this._renderDialInDisplay() }
@@ -244,6 +243,12 @@ class InfoDialog extends Component {
244 243
                         { this._renderPasswordAction() }
245 244
                     </div>
246 245
                 </div>
246
+                <textarea
247
+                    className = 'info-dialog-copy-element'
248
+                    readOnly = { true }
249
+                    ref = { this._setCopyElement }
250
+                    tabIndex = '-1'
251
+                    value = { this._getTextToCopy() } />
247 252
             </div>
248 253
         );
249 254
     }

+ 6
- 3
react/features/invite/components/info-dialog/PasswordForm.web.js Wyświetl plik

@@ -94,10 +94,13 @@ class PasswordForm extends Component {
94 94
 
95 95
         return (
96 96
             <div className = 'info-password'>
97
-                <div>{ t('info.password') }</div>
98
-                <div className = 'info-password-field'>
97
+                <span className = 'info-label'>
98
+                    { t('info.password') }
99
+                </span>
100
+                <span className = 'spacer'>&nbsp;</span>
101
+                <span className = 'info-password-field info-value'>
99 102
                     { this._renderPasswordField() }
100
-                </div>
103
+                </span>
101 104
             </div>
102 105
         );
103 106
     }

+ 0
- 9
react/features/invite/middleware.js Wyświetl plik

@@ -1,7 +1,5 @@
1
-import { CONFERENCE_JOINED } from '../base/conference';
2 1
 import { MiddlewareRegistry } from '../base/redux';
3 2
 
4
-import { setInfoDialogVisibility } from './actions';
5 3
 import { UPDATE_DIAL_IN_NUMBERS_FAILED } from './actionTypes';
6 4
 
7 5
 const logger = require('jitsi-meet-logger').getLogger(__filename);
@@ -17,13 +15,6 @@ MiddlewareRegistry.register(store => next => action => {
17 15
     const result = next(action);
18 16
 
19 17
     switch (action.type) {
20
-    case CONFERENCE_JOINED:
21
-        // we do not want to show call info in iAmRecorder mode
22
-        if (store.getState()['features/base/config'].iAmRecorder) {
23
-            return result;
24
-        }
25
-        store.dispatch(setInfoDialogVisibility(true, true));
26
-        break;
27 18
 
28 19
     case UPDATE_DIAL_IN_NUMBERS_FAILED:
29 20
         logger.error(

+ 0
- 8
react/features/invite/reducer.js Wyświetl plik

@@ -1,7 +1,6 @@
1 1
 import { ReducerRegistry } from '../base/redux';
2 2
 
3 3
 import {
4
-    SET_INFO_DIALOG_VISIBILITY,
5 4
     UPDATE_DIAL_IN_NUMBERS_FAILED,
6 5
     UPDATE_DIAL_IN_NUMBERS_SUCCESS
7 6
 } from './actionTypes';
@@ -12,13 +11,6 @@ const DEFAULT_STATE = {
12 11
 
13 12
 ReducerRegistry.register('features/invite', (state = DEFAULT_STATE, action) => {
14 13
     switch (action.type) {
15
-    case SET_INFO_DIALOG_VISIBILITY:
16
-        return {
17
-            ...state,
18
-            infoDialogVisible: action.visible,
19
-            infoDialogWillAutoClose: action.autoClose
20
-        };
21
-
22 14
     case UPDATE_DIAL_IN_NUMBERS_FAILED:
23 15
         return {
24 16
             ...state,

Ładowanie…
Anuluj
Zapisz