Преглед на файлове

ref(invite): remove InviteDialog (#2483)

* ref(invite): remove InviteDialog

InviteDialog functionality has been moved into InfoDialog.
The InviteButton has been temporarily hacked to show one
of its dropdown options instead as the button. Future
work will bring in a redesigned InviteModal that the button
will open.

* squash: filter invalid options and map valid options

* squash: update strings
master
virtuacoplenny преди 7 години
родител
ревизия
e47802538e

+ 0
- 5
css/_contact_list.scss Целия файл

13
     .clickable {
13
     .clickable {
14
         cursor: pointer;
14
         cursor: pointer;
15
     }
15
     }
16
-
17
-    .icon-security,
18
-    .icon-security-locked {
19
-        font-size: 16px;
20
-    }
21
 }
16
 }
22
 
17
 
23
 #contacts {
18
 #contacts {

+ 0
- 1
css/main.scss Целия файл

65
 @import 'components/button-control';
65
 @import 'components/button-control';
66
 @import 'components/input-control';
66
 @import 'components/input-control';
67
 @import 'components/input-slider';
67
 @import 'components/input-slider';
68
-@import "modals/invite/invite";
69
 @import "connection-info";
68
 @import "connection-info";
70
 @import 'aui-components/dropdown';
69
 @import 'aui-components/dropdown';
71
 @import '404';
70
 @import '404';

+ 0
- 96
css/modals/invite/_invite.scss Целия файл

1
-/*
2
- * Sets the default cursor the remove password link. The link doesn't use
3
- * the href attribute, so we need to set the  cursor manually.
4
- */
5
-#inviteDialogRemovePassword {
6
-    cursor: hand;
7
-}
8
-
9
-.invite-dialog {
10
-    .dial-in-numbers {
11
-        .dial-in-numbers-conference-id {
12
-            color: orange;
13
-            margin-left: 3px;
14
-        }
15
-
16
-        /*
17
-         * dial-in-numbers-copy styling is needed for the feature of copying
18
-         * text to the clipboard. The styling keeps the element invisible
19
-         * to the user but still programmatically selectable for copying.
20
-         */
21
-        .dial-in-numbers-copy {
22
-            opacity: 0;
23
-            pointer-events: none;
24
-            position: fixed;
25
-            -webkit-user-select: text;
26
-            user-select: text;
27
-        }
28
-
29
-        .is-disabled,
30
-        .is-loading {
31
-            .dial-in-numbers-trigger-icon {
32
-                display: none;
33
-            }
34
-        }
35
-    }
36
-
37
-    .form-control {
38
-        padding: 0;
39
-
40
-        &__container {
41
-            /**
42
-             * Ensure contents display in a line and vertically centered.
43
-             */
44
-            align-items: center;
45
-
46
-            button {
47
-                font-size: $modalButtonFontSize;
48
-            }
49
-        }
50
-
51
-        &__input-container {
52
-            flex: 1;
53
-            margin-right: 10px;
54
-
55
-            .dropdown-button-trigger {
56
-                text-align: left;
57
-            }
58
-        }
59
-    }
60
-
61
-    .inviteLink {
62
-        color: $readOnlyInputColor;
63
-    }
64
-
65
-    .lock-state {
66
-        display: flex;
67
-    }
68
-
69
-    .password-overview {
70
-        margin-top: 10px;
71
-
72
-        .form-control {
73
-            margin-top: 10px;
74
-        }
75
-
76
-        .password-overview-status,
77
-        .remove-password {
78
-            display: flex;
79
-            justify-content: space-between;
80
-        }
81
-
82
-        .password-overview-toggle-edit,
83
-        .remove-password-link {
84
-            cursor: pointer;
85
-            text-decoration: none;
86
-        }
87
-
88
-        .remove-password {
89
-            margin-top: 15px;
90
-        }
91
-    }
92
-
93
-    .remove-password-current {
94
-        color: $inputControlEmColor;
95
-    }
96
-}

+ 2
- 2
interface_config.js Целия файл

40
     TOOLBAR_BUTTONS: [
40
     TOOLBAR_BUTTONS: [
41
 
41
 
42
         // main toolbar
42
         // main toolbar
43
-        'microphone', 'camera', 'desktop', 'invite', 'fullscreen', 'fodeviceselection', 'hangup',
43
+        'microphone', 'camera', 'desktop', 'fullscreen', 'fodeviceselection', 'hangup',
44
 
44
 
45
         // extended toolbar
45
         // extended toolbar
46
         'profile', 'contacts', 'info', 'chat', 'recording', 'etherpad', 'sharedvideo', 'settings', 'raisehand', 'videoquality', 'filmstrip' ],
46
         'profile', 'contacts', 'info', 'chat', 'recording', 'etherpad', 'sharedvideo', 'settings', 'raisehand', 'videoquality', 'filmstrip' ],
49
      * Main Toolbar Buttons
49
      * Main Toolbar Buttons
50
      * All of them should be in TOOLBAR_BUTTONS
50
      * All of them should be in TOOLBAR_BUTTONS
51
      */
51
      */
52
-    MAIN_TOOLBAR_BUTTONS: [ 'microphone', 'camera', 'desktop', 'invite', 'fullscreen', 'fodeviceselection', 'hangup' ],
52
+    MAIN_TOOLBAR_BUTTONS: [ 'microphone', 'camera', 'desktop', 'fullscreen', 'fodeviceselection', 'hangup' ],
53
     SETTINGS_SECTIONS: [ 'language', 'devices', 'moderator' ],
53
     SETTINGS_SECTIONS: [ 'language', 'devices', 'moderator' ],
54
     INVITE_OPTIONS: [ 'invite', 'dialout', 'addtocall' ],
54
     INVITE_OPTIONS: [ 'invite', 'dialout', 'addtocall' ],
55
 
55
 

+ 2
- 21
lang/main.json Целия файл

103
         "videomute": "Start / Stop camera",
103
         "videomute": "Start / Stop camera",
104
         "authenticate": "Authenticate",
104
         "authenticate": "Authenticate",
105
         "lock": "Lock / Unlock room",
105
         "lock": "Lock / Unlock room",
106
-        "invite": "Share the link",
107
         "chat": "Open / Close chat",
106
         "chat": "Open / Close chat",
108
         "etherpad": "Open / Close shared document",
107
         "etherpad": "Open / Close shared document",
109
         "sharedvideo": "Share a YouTube video",
108
         "sharedvideo": "Share a YouTube video",
228
         "suboptimalExperienceDescription": "Eer... we are afraid your experience with __appName__ isn't going to be that great here. We are looking for ways to improve this but, until then, please try using one of the <a href='static/recommendedBrowsers.html' target='_blank'>fully supported browsers</a>."
227
         "suboptimalExperienceDescription": "Eer... we are afraid your experience with __appName__ isn't going to be that great here. We are looking for ways to improve this but, until then, please try using one of the <a href='static/recommendedBrowsers.html' target='_blank'>fully supported browsers</a>."
229
     },
228
     },
230
     "dialog": {
229
     "dialog": {
231
-        "add": "Add",
232
         "allow": "Allow",
230
         "allow": "Allow",
233
         "kickMessage": "Ouch! You have been kicked out of the meet!",
231
         "kickMessage": "Ouch! You have been kicked out of the meet!",
234
         "popupErrorTitle": "Pop-up blocked",
232
         "popupErrorTitle": "Pop-up blocked",
243
         "copy": "Copy",
241
         "copy": "Copy",
244
         "contactSupport": "Contact support",
242
         "contactSupport": "Contact support",
245
         "error": "Error",
243
         "error": "Error",
246
-        "createPassword": "Create password",
247
         "detectext": "Error when trying to detect desktopsharing extension.",
244
         "detectext": "Error when trying to detect desktopsharing extension.",
248
         "failedpermissions": "Failed to obtain permissions to use the local microphone and/or camera.",
245
         "failedpermissions": "Failed to obtain permissions to use the local microphone and/or camera.",
249
         "conferenceReloadTitle": "Unfortunately, something went wrong.",
246
         "conferenceReloadTitle": "Unfortunately, something went wrong.",
294
         "Save": "Save",
291
         "Save": "Save",
295
         "recording": "Recording",
292
         "recording": "Recording",
296
         "recordingToken": "Enter recording token",
293
         "recordingToken": "Enter recording token",
297
-        "passwordCheck": "Are you sure you would like to remove your password?",
298
-        "passwordMsg": "Set a password to lock your room",
299
-        "shareLink": "Share the link to the call",
300
-        "yourPassword": "Enter new password",
301
         "Back": "Back",
294
         "Back": "Back",
302
         "serviceUnavailable": "Service unavailable",
295
         "serviceUnavailable": "Service unavailable",
303
         "gracefulShutdown": "Our service is currently down for maintenance. Please try again later.",
296
         "gracefulShutdown": "Our service is currently down for maintenance. Please try again later.",
468
         "selectADevice": "Select a device",
461
         "selectADevice": "Select a device",
469
         "testAudio": "Test sound"
462
         "testAudio": "Test sound"
470
     },
463
     },
471
-    "invite": {
472
-        "addPassword": "Add password",
473
-        "callNumber": "Call __number__",
474
-        "enterID": "Enter Meeting ID: __conferenceID__ following by # to dial in from a phone",
475
-        "howToDialIn": "To dial in, use one of the following numbers and meeting ID",
476
-        "hidePassword": "Hide password",
477
-        "inviteTo": "Invite people to __conferenceName__",
478
-        "invitedYouTo": "__userName__ has invited you to the __inviteURL__ conference",
479
-        "invitePeople": "Invite",
480
-        "locked": "This call is locked. New callers must have the link and enter the password to join.",
481
-        "showPassword": "Show password",
482
-        "unlocked": "This call is unlocked. Any new caller with the link may join the call."
483
-    },
484
     "videoStatus": {
464
     "videoStatus": {
485
         "callQuality": "Call Quality",
465
         "callQuality": "Call Quality",
486
         "hd": "HD",
466
         "hd": "HD",
500
     },
480
     },
501
     "dialOut": {
481
     "dialOut": {
502
         "dial": "Dial",
482
         "dial": "Dial",
503
-        "dialOut": "Call a #",
483
+        "dialOut": "Call a number",
504
         "statusMessage": "is now __status__",
484
         "statusMessage": "is now __status__",
505
         "enterPhone": "Enter phone number",
485
         "enterPhone": "Enter phone number",
506
         "phoneNotAllowed": "Oh, we don't support that destination yet! Sorry!"
486
         "phoneNotAllowed": "Oh, we don't support that destination yet! Sorry!"
533
         "veryGood": "Very Good"
513
         "veryGood": "Very Good"
534
     },
514
     },
535
     "info": {
515
     "info": {
516
+        "addPassword": "Add password",
536
         "cancelPassword": "Cancel password",
517
         "cancelPassword": "Cancel password",
537
         "conferenceURL": "Link: __url__",
518
         "conferenceURL": "Link: __url__",
538
         "country": "Country",
519
         "country": "Country",

+ 0
- 12
react/features/invite/actions.js Целия файл

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { openDialog } from '../../features/base/dialog';
4
-
5
 import {
3
 import {
6
     SET_INFO_DIALOG_VISIBILITY,
4
     SET_INFO_DIALOG_VISIBILITY,
7
     UPDATE_DIAL_IN_NUMBERS_FAILED,
5
     UPDATE_DIAL_IN_NUMBERS_FAILED,
8
     UPDATE_DIAL_IN_NUMBERS_SUCCESS
6
     UPDATE_DIAL_IN_NUMBERS_SUCCESS
9
 } from './actionTypes';
7
 } from './actionTypes';
10
-import { InviteDialog } from './components';
11
 
8
 
12
 declare var $: Function;
9
 declare var $: Function;
13
 
10
 
14
-/**
15
- * Opens the Invite Dialog.
16
- *
17
- * @returns {Function}
18
- */
19
-export function openInviteDialog() {
20
-    return openDialog(InviteDialog);
21
-}
22
-
23
 /**
11
 /**
24
  * Opens the inline conference info dialog.
12
  * Opens the inline conference info dialog.
25
  *
13
  *

+ 0
- 199
react/features/invite/components/AddPasswordForm.js Целия файл

1
-import Button from '@atlaskit/button';
2
-import { FieldTextStateless as TextField } from '@atlaskit/field-text';
3
-import PropTypes from 'prop-types';
4
-import React, { Component } from 'react';
5
-import { connect } from 'react-redux';
6
-
7
-import { setPassword } from '../../base/conference';
8
-import { translate } from '../../base/i18n';
9
-
10
-/**
11
- * A React {@code Component} for locking a JitsiConference with a password.
12
- */
13
-class AddPasswordForm extends Component {
14
-    /**
15
-     * {@code AddPasswordForm}'s property types.
16
-     *
17
-     * @static
18
-     */
19
-    static propTypes = {
20
-        /**
21
-         * The JitsiConference on which to lock and set a password.
22
-         *
23
-         * @type {JitsiConference}
24
-         */
25
-        conference: PropTypes.object,
26
-
27
-        /**
28
-         * Invoked to set a password on the conference.
29
-         */
30
-        dispatch: PropTypes.func,
31
-
32
-        /**
33
-         * Invoked to obtain translated strings.
34
-         */
35
-        t: PropTypes.func
36
-    };
37
-
38
-    /**
39
-     * Initializes a new {@code AddPasswordForm} instance.
40
-     *
41
-     * @param {Object} props - The read-only properties with which the new
42
-     * instance is to be initialized.
43
-     */
44
-    constructor(props) {
45
-        super(props);
46
-
47
-        this.state = {
48
-            /**
49
-             * The current value to display in {@code AddPasswordForm}
50
-             * component's input field. The value is also used as the desired
51
-             * new password when creating a {@code setPassword} action.
52
-             *
53
-             * @type {string}
54
-             */
55
-            password: ''
56
-        };
57
-
58
-        /**
59
-         * The internal reference to the React {@code component} for entering a
60
-         * password.
61
-         *
62
-         * @private
63
-         * @type {ReactComponent}
64
-         */
65
-        this._inputComponent = null;
66
-
67
-        // Bind event handlers so they are only bound once for every instance.
68
-        this._onKeyDown = this._onKeyDown.bind(this);
69
-        this._onPasswordChange = this._onPasswordChange.bind(this);
70
-        this._onSubmit = this._onSubmit.bind(this);
71
-        this._setInput = this._setInput.bind(this);
72
-    }
73
-
74
-    /**
75
-     * Directly bind a handler to the input element. This is done in order to
76
-     * intercept enter presses so any outer forms do not become submitted.
77
-     * Atlaskit Button does not expose a way to hook onto keydown events.
78
-     *
79
-     * @inheritdoc
80
-     */
81
-    componentDidMount() {
82
-        this._inputComponent.input.onkeydown = this._onKeyDown;
83
-    }
84
-
85
-    /**
86
-     * Remove any handlers set directly on DOM elements.
87
-     *
88
-     * @inheritdoc
89
-     */
90
-    componentWillUnmount() {
91
-        this._inputComponent.input.onkeydown = null;
92
-    }
93
-
94
-    /**
95
-     * Implements React's {@link Component#render()}.
96
-     *
97
-     * @inheritdoc
98
-     * @returns {ReactElement}
99
-     */
100
-    render() {
101
-        const { t } = this.props;
102
-
103
-        return (
104
-            <div
105
-                className = 'form-control'
106
-                onSubmit = { this._onSubmit } >
107
-                <div className = 'form-control__container'>
108
-                    <div className = 'form-control__input-container'>
109
-                        <TextField
110
-                            autoFocus = { true }
111
-                            compact = { true }
112
-                            id = 'newPasswordInput'
113
-                            isLabelHidden = { true }
114
-                            label = 'Enter Password'
115
-                            onChange = { this._onPasswordChange }
116
-                            onKeyDown = { this._onKeyDown }
117
-                            placeholder = { t('dialog.createPassword') }
118
-                            ref = { this._setInput }
119
-                            shouldFitContainer = { true }
120
-                            type = 'text' />
121
-                    </div>
122
-                    <Button
123
-                        id = 'addPasswordBtn'
124
-                        isDisabled = { !this.state.password }
125
-                        onClick = { this._onSubmit }
126
-                        type = 'button'>
127
-                        { t('dialog.add') }
128
-                    </Button>
129
-                </div>
130
-            </div>
131
-        );
132
-    }
133
-
134
-    /**
135
-     * Mimics form behavior by listening for enter key press and submitting the
136
-     * entered password.
137
-     *
138
-     * @param {Object} event - DOM Event for keydown.
139
-     * @private
140
-     * @returns {void}
141
-     */
142
-    _onKeyDown(event) {
143
-        event.stopPropagation();
144
-
145
-        if (event.keyCode === /* Enter */ 13) {
146
-            this._onSubmit();
147
-        }
148
-    }
149
-
150
-    /**
151
-     * Updates the internal state of the entered password.
152
-     *
153
-     * @param {Object} event - DOM Event for value change.
154
-     * @private
155
-     * @returns {void}
156
-     */
157
-    _onPasswordChange(event) {
158
-        this.setState({ password: event.target.value });
159
-    }
160
-
161
-    /**
162
-     * Dispatches a request to lock the conference with a password.
163
-     *
164
-     * @private
165
-     * @returns {void}
166
-     */
167
-    _onSubmit() {
168
-        if (!this.state.password) {
169
-            return;
170
-        }
171
-
172
-        const { conference } = this.props;
173
-
174
-        this.props.dispatch(setPassword(
175
-            conference,
176
-            conference.lock,
177
-            this.state.password
178
-        ));
179
-
180
-        this.setState({ password: '' });
181
-    }
182
-
183
-    /**
184
-     * Sets the instance variable for the React Component used for entering a
185
-     * password.
186
-     *
187
-     * @param {Object} inputComponent - The React Component for the input
188
-     * field.
189
-     * @private
190
-     * @returns {void}
191
-     */
192
-    _setInput(inputComponent) {
193
-        if (inputComponent !== this._inputComponent) {
194
-            this._inputComponent = inputComponent;
195
-        }
196
-    }
197
-}
198
-
199
-export default translate(connect()(AddPasswordForm));

+ 0
- 406
react/features/invite/components/DialInNumbersForm.js Целия файл

1
-import Button from '@atlaskit/button';
2
-import DropdownMenu, {
3
-    DropdownItem, DropdownItemGroup } from '@atlaskit/dropdown-menu';
4
-import PropTypes from 'prop-types';
5
-import React, { Component } from 'react';
6
-import { connect } from 'react-redux';
7
-
8
-import { translate } from '../../base/i18n';
9
-import { getLocalParticipant } from '../../base/participants';
10
-
11
-import { updateDialInNumbers } from '../actions';
12
-
13
-const logger = require('jitsi-meet-logger').getLogger(__filename);
14
-
15
-/**
16
- * React {@code Component} responsible for fetching and displaying telephone
17
- * numbers for dialing into a conference. Also supports copying a selected
18
- * dial-in number to the clipboard.
19
- *
20
- * @extends Component
21
- */
22
-class DialInNumbersForm extends Component {
23
-    /**
24
-     * {@code DialInNumbersForm}'s property types.
25
-     *
26
-     * @static
27
-     */
28
-    static propTypes = {
29
-        /**
30
-         * The redux state representing the dial-in numbers feature.
31
-         */
32
-        _dialIn: PropTypes.object,
33
-
34
-        /**
35
-         * The display name of the local user.
36
-         */
37
-        _localUserDisplayName: PropTypes.string,
38
-
39
-        /**
40
-         * Invoked to send an ajax request for dial-in numbers.
41
-         */
42
-        dispatch: PropTypes.func,
43
-
44
-        /**
45
-         * The URL of the conference into which this {@code DialInNumbersForm}
46
-         * is inviting the local participant.
47
-         */
48
-        inviteURL: PropTypes.string,
49
-
50
-        /**
51
-         * Invoked to obtain translated strings.
52
-         */
53
-        t: PropTypes.func
54
-    };
55
-
56
-    /**
57
-     * Initializes a new {@code DialInNumbersForm} instance.
58
-     *
59
-     * @param {Object} props - The read-only properties with which the new
60
-     * instance is to be initialized.
61
-     */
62
-    constructor(props) {
63
-        super(props);
64
-
65
-        this.state = {
66
-            /**
67
-             * Whether or not the dropdown should be open.
68
-             *
69
-             * @type {boolean}
70
-             */
71
-            isDropdownOpen: false,
72
-
73
-            /**
74
-             * The dial-in number to display as currently selected in the
75
-             * dropdown. The value should be an object which has two key/value
76
-             * pairs, content and number. The value of "content" will display in
77
-             * the dropdown while the value of "number" is a substring of
78
-             * "content" which will be copied to clipboard.
79
-             *
80
-             * @type {object}
81
-             */
82
-            selectedNumber: null
83
-        };
84
-
85
-        /**
86
-         * The internal reference to the DOM/HTML element backing the React
87
-         * {@code Component} text area. It is necessary for the implementation
88
-         * of copying to the clipboard.
89
-         *
90
-         * @private
91
-         * @type {HTMLTextAreaElement}
92
-         */
93
-        this._copyElement = null;
94
-
95
-        // Bind event handlers so they are only bound once for every instance.
96
-        this._onCopyClick = this._onCopyClick.bind(this);
97
-        this._onOpenChange = this._onOpenChange.bind(this);
98
-        this._onSelect = this._onSelect.bind(this);
99
-        this._setCopyElement = this._setCopyElement.bind(this);
100
-    }
101
-
102
-    /**
103
-     * Sets a default number to display in the dropdown trigger.
104
-     *
105
-     * @inheritdoc
106
-     * returns {void}
107
-     */
108
-    componentWillMount() {
109
-        const { numbers } = this.props._dialIn;
110
-
111
-        if (numbers) {
112
-            this._setDefaultNumber(numbers);
113
-        } else {
114
-            this.props.dispatch(updateDialInNumbers());
115
-        }
116
-    }
117
-
118
-    /**
119
-     * Monitors for number updates and sets a default number to display in the
120
-     * dropdown trigger if not already set.
121
-     *
122
-     * @inheritdoc
123
-     * returns {void}
124
-     */
125
-    componentWillReceiveProps(nextProps) {
126
-        if (!this.state.selectedNumber && nextProps._dialIn.numbers) {
127
-            this._setDefaultNumber(nextProps._dialIn.numbers);
128
-        }
129
-    }
130
-
131
-    /**
132
-     * Implements React's {@link Component#render()}. Returns null if the
133
-     * component is not ready for display.
134
-     *
135
-     * @inheritdoc
136
-     * @returns {ReactElement|null}
137
-     */
138
-    render() {
139
-        const { _dialIn, t } = this.props;
140
-        const { conferenceID, numbers, numbersEnabled } = _dialIn;
141
-        const { selectedNumber } = this.state;
142
-
143
-        if (!conferenceID || !numbers || !numbersEnabled || !selectedNumber) {
144
-            return null;
145
-        }
146
-
147
-        const items = this._renderDropdownItems(numbers);
148
-
149
-        return (
150
-            <div className = 'form-control dial-in-numbers'>
151
-                <label className = 'form-control__label'>
152
-                    { t('invite.howToDialIn') }
153
-                    <span className = 'dial-in-numbers-conference-id'>
154
-                        { conferenceID }
155
-                    </span>
156
-                </label>
157
-                <div className = 'form-control__container'>
158
-                    <div className = 'form-control__input-container'>
159
-                        { this._createDropdownMenu(items, selectedNumber) }
160
-                    </div>
161
-                    <Button
162
-                        appearance = 'default'
163
-                        onClick = { this._onCopyClick }
164
-                        type = 'button'>
165
-                        { t('dialog.copy') }
166
-                    </Button>
167
-                </div>
168
-                <textarea
169
-                    className = 'dial-in-numbers-copy'
170
-                    readOnly = { true }
171
-                    ref = { this._setCopyElement }
172
-                    tabIndex = '-1'
173
-                    value = { this._generateCopyText() } />
174
-            </div>
175
-        );
176
-    }
177
-
178
-    /**
179
-     * Creates a {@code DropdownMenu} instance.
180
-     *
181
-     * @param {Array} items - The content to display within the dropdown.
182
-     * @param {string} triggerText - The text to display within the
183
-     * trigger element.
184
-     * @returns {ReactElement}
185
-     */
186
-    _createDropdownMenu(items, triggerText) {
187
-        return (
188
-            <DropdownMenu
189
-                isOpen = { this.state.isDropdownOpen }
190
-                onOpenChange = { this._onOpenChange }
191
-                shouldFitContainer = { true }
192
-                trigger = { triggerText || '' }
193
-                triggerButtonProps = {{
194
-                    className: 'dropdown-button-trigger',
195
-                    shouldFitContainer: true }}
196
-                triggerType = 'button'>
197
-                <DropdownItemGroup>
198
-                    { items }
199
-                </DropdownItemGroup>
200
-            </DropdownMenu>
201
-        );
202
-    }
203
-
204
-    /**
205
-     * Formats the region and number string.
206
-     *
207
-     * @param {string} region - The region string.
208
-     * @param {string} number - The number string.
209
-     * @returns {string} - The new formatted string.
210
-     * @private
211
-     */
212
-    _formatRegionNumber(region, number) {
213
-        return `${region}: ${number}`;
214
-    }
215
-
216
-    /**
217
-     * Creates a message describing how to dial in to the conference.
218
-     *
219
-     * @private
220
-     * @returns {string}
221
-     */
222
-    _generateCopyText() {
223
-        const { t } = this.props;
224
-        const welcome = t('invite.invitedYouTo', {
225
-            inviteURL: this.props.inviteURL,
226
-            userName: this.props._localUserDisplayName
227
-        });
228
-
229
-        const callNumber = t('invite.callNumber', {
230
-            number: this.state.selectedNumber
231
-        });
232
-        const stepOne = `1) ${callNumber}`;
233
-
234
-        const enterID = t('invite.enterID', {
235
-            conferenceID: this.props._dialIn.conferenceID
236
-        });
237
-        const stepTwo = `2) ${enterID}`;
238
-
239
-        return `${welcome}\n${stepOne}\n${stepTwo}`;
240
-    }
241
-
242
-    /**
243
-     * Copies part of the number displayed in the dropdown trigger into the
244
-     * clipboard. Only the value specified in selectedNumber.number, which
245
-     * should be a substring of the displayed value, will be copied.
246
-     *
247
-     * @private
248
-     * @returns {void}
249
-     */
250
-    _onCopyClick() {
251
-        try {
252
-            this._copyElement.select();
253
-            document.execCommand('copy');
254
-            this._copyElement.blur();
255
-        } catch (err) {
256
-            logger.error('error when copying the text', err);
257
-        }
258
-    }
259
-
260
-    /**
261
-     * Sets the internal state to either open or close the dropdown. If the
262
-     * dropdown is disabled, the state will always be set to false.
263
-     *
264
-     * @param {Object} dropdownEvent - The even returned from clicking on the
265
-     * dropdown trigger.
266
-     * @private
267
-     * @returns {void}
268
-     */
269
-    _onOpenChange(dropdownEvent) {
270
-        this.setState({
271
-            isDropdownOpen: dropdownEvent.isOpen
272
-        });
273
-    }
274
-
275
-    /**
276
-     * Updates the internal state of the currently selected number.
277
-     *
278
-     * @param {Object} selection - Event from choosing an dropdown option.
279
-     * @private
280
-     * @returns {void}
281
-     */
282
-    _onSelect(selection) {
283
-        this.setState({
284
-            isDropdownOpen: false,
285
-            selectedNumber: selection
286
-        });
287
-    }
288
-
289
-    /**
290
-     * Renders a DropDownItem for the given id and text.
291
-     *
292
-     * @param {string} id - The key identifier of the DropdownItem.
293
-     * @param {string} text - The text to display in the dropdown item.
294
-     * @returns {React.Component}
295
-     * @private
296
-     */
297
-    _renderDropDownItem(id, text) {
298
-        return (
299
-
300
-            /**
301
-             * Arrow functions are not allowed in props, but I leave this until
302
-             * I figure a better way to implement the same thing.
303
-             */
304
-            /* eslint-disable react/jsx-no-bind */
305
-            <DropdownItem
306
-                key = { id }
307
-                onClick = { () => this._onSelect(text || id) }>
308
-                { text }
309
-            </DropdownItem>
310
-            /* eslint-disable react/jsx-no-bind */
311
-        );
312
-    }
313
-
314
-    /**
315
-     * Detects whether the response from dialInNumbersUrl returned an array or
316
-     * an object with dial-in numbers and calls the appropriate method to
317
-     * transform the numbers into the format expected by
318
-     * {@code DropdownMenu}.
319
-     *
320
-     * @param {Array<string>|Object} dialInNumbers - The numbers returned from
321
-     * requesting dialInNumbersUrl.
322
-     * @private
323
-     * @returns {Array<Object>}
324
-     */
325
-    _renderDropdownItems(dialInNumbers) {
326
-        if (Array.isArray(dialInNumbers)) {
327
-            return dialInNumbers.map(number =>
328
-                this._renderDropDownItem(number)
329
-            );
330
-        }
331
-
332
-        const phoneRegions = Object.keys(dialInNumbers);
333
-
334
-        if (!phoneRegions.length) {
335
-            return [];
336
-        }
337
-
338
-        const dropdownItems = phoneRegions.map(region => {
339
-            const numbers = dialInNumbers[region];
340
-
341
-            return numbers.map(number =>
342
-                this._renderDropDownItem(number,
343
-                    this._formatRegionNumber(region, number))
344
-            );
345
-        });
346
-
347
-        return Array.prototype.concat(...dropdownItems);
348
-    }
349
-
350
-    /**
351
-     * Sets the internal reference to the DOM/HTML element backing the React
352
-     * {@code Component} text area.
353
-     *
354
-     * @param {HTMLTextAreaElement} element - The DOM/HTML element for this
355
-     * {@code Component}'s text area.
356
-     * @private
357
-     * @returns {void}
358
-     */
359
-    _setCopyElement(element) {
360
-        this._copyElement = element;
361
-    }
362
-
363
-    /**
364
-     * Updates the internal state of the currently selected number by defaulting
365
-     * to the first available number.
366
-     *
367
-     * @param {Object} dialInNumbers - The array or object of numbers to parse.
368
-     * @private
369
-     * @returns {void}
370
-     */
371
-    _setDefaultNumber(dialInNumbers) {
372
-        let number = '';
373
-
374
-        if (Array.isArray(dialInNumbers)) {
375
-            number = dialInNumbers[0];
376
-        } else if (Object.keys(dialInNumbers).length > 0) {
377
-            const region = Object.keys(dialInNumbers)[0];
378
-
379
-            number = this._formatRegionNumber(region, dialInNumbers[region]);
380
-        }
381
-
382
-        this.setState({
383
-            selectedNumber: number
384
-        });
385
-    }
386
-}
387
-
388
-/**
389
- * Maps (parts of) the Redux state to the associated
390
- * {@code DialInNumbersForm}'s props.
391
- *
392
- * @param {Object} state - The Redux state.
393
- * @private
394
- * @returns {{
395
- *     _dialIn: Object,
396
- *     _localUserDisplayName: string
397
- * }}
398
- */
399
-function _mapStateToProps(state) {
400
-    return {
401
-        _localUserDisplayName: getLocalParticipant(state).name,
402
-        _dialIn: state['features/invite']
403
-    };
404
-}
405
-
406
-export default translate(connect(_mapStateToProps)(DialInNumbersForm));

+ 44
- 52
react/features/invite/components/InviteButton.web.js Целия файл

10
 import { getLocalParticipant, PARTICIPANT_ROLE } from '../../base/participants';
10
 import { getLocalParticipant, PARTICIPANT_ROLE } from '../../base/participants';
11
 
11
 
12
 import { openDialog } from '../../base/dialog';
12
 import { openDialog } from '../../base/dialog';
13
-import { AddPeopleDialog, InviteDialog } from '.';
13
+import { AddPeopleDialog } from '.';
14
 import { DialOutDialog } from '../../dial-out';
14
 import { DialOutDialog } from '../../dial-out';
15
-import { isInviteOptionEnabled, getInviteOptionPosition } from '../functions';
15
+import { isInviteOptionEnabled } from '../functions';
16
 
16
 
17
-const SHARE_LINK_OPTION = 'invite';
18
 const DIAL_OUT_OPTION = 'dialout';
17
 const DIAL_OUT_OPTION = 'dialout';
19
 const ADD_TO_CALL_OPTION = 'addtocall';
18
 const ADD_TO_CALL_OPTION = 'addtocall';
20
 
19
 
58
     constructor(props) {
57
     constructor(props) {
59
         super(props);
58
         super(props);
60
 
59
 
61
-        this._onInviteClick = this._onInviteClick.bind(this);
62
         this._onInviteOptionSelected = this._onInviteOptionSelected.bind(this);
60
         this._onInviteOptionSelected = this._onInviteOptionSelected.bind(this);
63
         this._updateInviteItems = this._updateInviteItems.bind(this);
61
         this._updateInviteItems = this._updateInviteItems.bind(this);
64
 
62
 
87
      * @returns {ReactElement}
85
      * @returns {ReactElement}
88
      */
86
      */
89
     render() {
87
     render() {
90
-        const { t } = this.props;
88
+        // HACK ALERT: Normally children should not be controlling their own
89
+        // visibility; parents should control that. However, this component is
90
+        // in a transitionary state while the Invite Dialog is being redone.
91
+        // This hack will go away when the Invite Dialog is back.
92
+        if (!this.state.buttonOption) {
93
+            return null;
94
+        }
91
 
95
 
92
         const { VERTICAL_FILMSTRIP } = interfaceConfig;
96
         const { VERTICAL_FILMSTRIP } = interfaceConfig;
93
 
97
 
95
             <div className = 'filmstrip__invite'>
99
             <div className = 'filmstrip__invite'>
96
                 <div className = 'invite-button-group'>
100
                 <div className = 'invite-button-group'>
97
                     <Button
101
                     <Button
98
-                        onClick = { this._onInviteClick }
102
+                        // eslint-disable-next-line react/jsx-handler-names
103
+                        onClick = { this.state.buttonOption.action }
99
                         shouldFitContainer = { true }>
104
                         shouldFitContainer = { true }>
100
-                        { t('invite.invitePeople') }
105
+                        { this.state.buttonOption.content }
101
                     </Button>
106
                     </Button>
102
-                    { this.props._isDialOutAvailable
103
-                        || this.props._isAddToCallAvailable
107
+                    { this.state.inviteOptions[0].items.length
104
                         ? <DropdownMenu
108
                         ? <DropdownMenu
105
                             items = { this.state.inviteOptions }
109
                             items = { this.state.inviteOptions }
106
                             onItemActivated = { this._onInviteOptionSelected }
110
                             onItemActivated = { this._onInviteOptionSelected }
115
         );
119
         );
116
     }
120
     }
117
 
121
 
118
-    /**
119
-     * Handles the click of the invite button.
120
-     *
121
-     * @private
122
-     * @returns {void}
123
-     */
124
-    _onInviteClick() {
125
-        this.props.openDialog(InviteDialog);
126
-    }
127
-
128
     /**
122
     /**
129
      * Handles selection of the invite options.
123
      * Handles selection of the invite options.
130
      *
124
      *
150
      * @returns {void}
144
      * @returns {void}
151
      */
145
      */
152
     _updateInviteItems(props) {
146
     _updateInviteItems(props) {
153
-        const { t } = this.props;
154
-
155
-        const inviteItems = [];
156
-
157
-        inviteItems.splice(
158
-            getInviteOptionPosition(SHARE_LINK_OPTION),
159
-            0,
160
-            {
161
-                content: t('toolbar.invite'),
162
-                action: () => this.props.openDialog(InviteDialog)
163
-            }
164
-        );
165
-
166
-        if (props._isDialOutAvailable) {
167
-            inviteItems.splice(
168
-                getInviteOptionPosition(DIAL_OUT_OPTION),
169
-                0,
170
-                {
171
-                    content: t('dialOut.dialOut'),
147
+        const { INVITE_OPTIONS = [] } = interfaceConfig;
148
+        const validOptions = INVITE_OPTIONS.filter(option =>
149
+            (option === DIAL_OUT_OPTION && props._isDialOutAvailable)
150
+            || (option === ADD_TO_CALL_OPTION && props._isAddToCallAvailable));
151
+
152
+        /* eslint-disable array-callback-return */
153
+
154
+        const inviteItems = validOptions.map(option => {
155
+            switch (option) {
156
+            case DIAL_OUT_OPTION:
157
+                return {
158
+                    content: this.props.t('dialOut.dialOut'),
172
                     action: () => this.props.openDialog(DialOutDialog)
159
                     action: () => this.props.openDialog(DialOutDialog)
173
-                }
174
-            );
175
-        }
176
-
177
-        if (props._isAddToCallAvailable) {
178
-            inviteItems.splice(
179
-                getInviteOptionPosition(ADD_TO_CALL_OPTION),
180
-                0,
181
-                {
160
+                };
161
+            case ADD_TO_CALL_OPTION:
162
+                return {
182
                     content: interfaceConfig.ADD_PEOPLE_APP_NAME,
163
                     content: interfaceConfig.ADD_PEOPLE_APP_NAME,
183
                     action: () => this.props.openDialog(AddPeopleDialog)
164
                     action: () => this.props.openDialog(AddPeopleDialog)
184
-                }
185
-            );
186
-        }
165
+                };
166
+            }
167
+        });
168
+
169
+        /* eslint-enable array-callback-return */
170
+
171
+        const buttonOption = inviteItems[0];
172
+        const dropdownOptions = inviteItems.splice(1, inviteItems.length);
187
 
173
 
188
         const nextState = {
174
         const nextState = {
189
             /**
175
             /**
190
-             * The list of invite options.
176
+             * The configuration for how the invite button should display and
177
+             * behave on click.
178
+             */
179
+            buttonOption,
180
+
181
+            /**
182
+             * The list of invite options in the dropdown.
191
              */
183
              */
192
             inviteOptions: [
184
             inviteOptions: [
193
                 {
185
                 {
194
-                    items: inviteItems
186
+                    items: dropdownOptions
195
                 }
187
                 }
196
             ]
188
             ]
197
         };
189
         };

+ 0
- 0
react/features/invite/components/InviteDialog.native.js Целия файл


+ 0
- 120
react/features/invite/components/InviteDialog.web.js Целия файл

1
-import PropTypes from 'prop-types';
2
-import React, { Component } from 'react';
3
-import { connect } from 'react-redux';
4
-
5
-import {
6
-    createInviteDialogClosedEvent,
7
-    sendAnalytics
8
-} from '../../analytics';
9
-import { getInviteURL } from '../../base/connection';
10
-import { Dialog } from '../../base/dialog';
11
-import { translate } from '../../base/i18n';
12
-import { getLocalParticipant, PARTICIPANT_ROLE } from '../../base/participants';
13
-
14
-import DialInNumbersForm from './DialInNumbersForm';
15
-import PasswordContainer from './PasswordContainer';
16
-import ShareLinkForm from './ShareLinkForm';
17
-
18
-/**
19
- * A React {@code Component} for displaying other components responsible for
20
- * copying the current conference url and for setting or removing a conference
21
- * password.
22
- */
23
-class InviteDialog extends Component {
24
-    /**
25
-     * {@code InviteDialog} component's property types.
26
-     *
27
-     * @static
28
-     */
29
-    static propTypes = {
30
-        /**
31
-         * Whether or not the current user can modify the current password.
32
-         */
33
-        _canEditPassword: PropTypes.bool,
34
-
35
-        /**
36
-         * The redux store representation of the JitsiConference.
37
-         */
38
-        _conference: PropTypes.object,
39
-
40
-        /**
41
-         * The url for the JitsiConference.
42
-         */
43
-        _inviteURL: PropTypes.string,
44
-
45
-        /**
46
-         * Invoked to obtain translated strings.
47
-         */
48
-        t: PropTypes.func
49
-    };
50
-
51
-    /**
52
-     * Reports an analytics event for the invite modal being closed.
53
-     *
54
-     * @inheritdoc
55
-     */
56
-    componentWillUnmount() {
57
-        sendAnalytics(createInviteDialogClosedEvent());
58
-    }
59
-
60
-    /**
61
-     * Implements React's {@link Component#render()}.
62
-     *
63
-     * @inheritdoc
64
-     * @returns {ReactElement}
65
-     */
66
-    render() {
67
-        const { _canEditPassword, _conference, _inviteURL, t } = this.props;
68
-        const titleString
69
-            = t('invite.inviteTo', { conferenceName: _conference.room });
70
-
71
-        return (
72
-            <Dialog
73
-                cancelDisabled = { true }
74
-                okTitleKey = 'dialog.done'
75
-                titleString = { titleString }>
76
-                <div className = 'invite-dialog'>
77
-                    <ShareLinkForm toCopy = { _inviteURL } />
78
-                    <DialInNumbersForm inviteURL = { _inviteURL } />
79
-                    <PasswordContainer
80
-                        conference = { _conference.conference }
81
-                        locked = { _conference.locked }
82
-                        password = { _conference.password }
83
-                        showPasswordEdit = { _canEditPassword } />
84
-                </div>
85
-            </Dialog>
86
-        );
87
-    }
88
-}
89
-
90
-/**
91
- * Maps (parts of) the Redux state to the associated {@code InviteDialog}'s
92
- * props.
93
- *
94
- * @param {Object} state - The Redux state.
95
- * @private
96
- * @returns {{
97
- *     _canEditPassword: boolean,
98
- *     _conference: Object,
99
- *     _inviteURL: string
100
- * }}
101
- */
102
-function _mapStateToProps(state) {
103
-    const isModerator
104
-        = getLocalParticipant(state).role === PARTICIPANT_ROLE.MODERATOR;
105
-    let canEditPassword;
106
-
107
-    if (state['features/base/config'].enableUserRolesBasedOnToken) {
108
-        canEditPassword = isModerator && !state['features/base/jwt'].isGuest;
109
-    } else {
110
-        canEditPassword = isModerator;
111
-    }
112
-
113
-    return {
114
-        _canEditPassword: canEditPassword,
115
-        _conference: state['features/base/conference'],
116
-        _inviteURL: getInviteURL(state)
117
-    };
118
-}
119
-
120
-export default translate(connect(_mapStateToProps)(InviteDialog));

+ 0
- 59
react/features/invite/components/LockStatePanel.js Целия файл

1
-import PropTypes from 'prop-types';
2
-import React, { Component } from 'react';
3
-
4
-import { translate } from '../../base/i18n';
5
-
6
-/**
7
- * A React Component for displaying the conference lock state.
8
- */
9
-class LockStatePanel extends Component {
10
-    /**
11
-     * {@code LockStatePanel}'s property types.
12
-     *
13
-     * @static
14
-     */
15
-    static propTypes = {
16
-        /**
17
-         * Whether or not the conference is currently locked.
18
-         */
19
-        locked: PropTypes.bool,
20
-
21
-        /**
22
-         * Invoked to obtain translated strings.
23
-         */
24
-        t: PropTypes.func
25
-    };
26
-
27
-    /**
28
-     * Implements React's {@link Component#render()}.
29
-     *
30
-     * @inheritdoc
31
-     * @returns {ReactElement}
32
-     */
33
-    render() {
34
-        let iconClass;
35
-        let stateClass;
36
-        let textKey;
37
-
38
-        if (this.props.locked) {
39
-            iconClass = 'icon-security-locked';
40
-            stateClass = 'is-locked';
41
-            textKey = 'invite.locked';
42
-        } else {
43
-            iconClass = 'icon-security';
44
-            stateClass = 'is-unlocked';
45
-            textKey = 'invite.unlocked';
46
-        }
47
-
48
-        return (
49
-            <div className = { `lock-state ${stateClass}` }>
50
-                <span className = { iconClass } />
51
-                <span>
52
-                    { this.props.t(textKey) }
53
-                </span>
54
-            </div>
55
-        );
56
-    }
57
-}
58
-
59
-export default translate(LockStatePanel);

+ 0
- 157
react/features/invite/components/PasswordContainer.js Целия файл

1
-import PropTypes from 'prop-types';
2
-import React, { Component } from 'react';
3
-
4
-import { translate } from '../../base/i18n';
5
-import { LOCKED_LOCALLY } from '../../room-lock';
6
-
7
-import AddPasswordForm from './AddPasswordForm';
8
-import LockStatePanel from './LockStatePanel';
9
-import RemovePasswordForm from './RemovePasswordForm';
10
-
11
-/**
12
- * React {@code Component} for displaying the current room lock state as well as
13
- * exposing features to modify the room lock.
14
- */
15
-class PasswordContainer extends Component {
16
-    /**
17
-     * {@code PasswordContainer}'s property types.
18
-     *
19
-     * @static
20
-     */
21
-    static propTypes = {
22
-        /**
23
-         * The JitsiConference for which to display a lock state and change the
24
-         * password.
25
-         *
26
-         * @type {JitsiConference}
27
-         */
28
-        conference: PropTypes.object,
29
-
30
-        /**
31
-         * The value for how the conference is locked (or undefined if not
32
-         * locked) as defined by room-lock constants.
33
-         */
34
-        locked: PropTypes.string,
35
-
36
-        /**
37
-         * The current known password for the JitsiConference.
38
-         */
39
-        password: PropTypes.string,
40
-
41
-        /**
42
-         * Whether or not the password editing components should be displayed.
43
-         */
44
-        showPasswordEdit: PropTypes.bool,
45
-
46
-        /**
47
-         * Invoked to obtain translated strings.
48
-         */
49
-        t: PropTypes.func
50
-    };
51
-
52
-    /**
53
-     * Initializes a new {@code PasswordContainer} instance.
54
-     *
55
-     * @param {Object} props - The read-only properties with which the new
56
-     * instance is to be initialized.
57
-     */
58
-    constructor(props) {
59
-        super(props);
60
-
61
-        this.state = {
62
-            /**
63
-             * Whether or not the form to edit the password should display. If
64
-             * true, the form should display.
65
-             *
66
-             * @type {boolean}
67
-             */
68
-            isEditingPassword: false
69
-        };
70
-
71
-        // Bind event handlers so they are only bound once for every instance.
72
-        this._onTogglePasswordEdit = this._onTogglePasswordEdit.bind(this);
73
-    }
74
-
75
-    /**
76
-     * Implements React's {@link Component#render()}.
77
-     *
78
-     * @inheritdoc
79
-     * @returns {ReactElement}
80
-     */
81
-    render() {
82
-        return (
83
-            <div className = 'password-overview'>
84
-                <div className = 'password-overview-status'>
85
-                    <LockStatePanel locked = { Boolean(this.props.locked) } />
86
-                    { this._renderShowPasswordLink() }
87
-                </div>
88
-                { this._renderPasswordEdit() }
89
-            </div>
90
-        );
91
-    }
92
-
93
-    /**
94
-     * Toggles the display of the ReactElements used to edit the password.
95
-     *
96
-     * @private
97
-     * @returns {void}
98
-     */
99
-    _onTogglePasswordEdit() {
100
-        this.setState({
101
-            isEditingPassword: !this.state.isEditingPassword
102
-        });
103
-    }
104
-
105
-    /**
106
-     * Creates a ReactElement used for setting or removing a password.
107
-     *
108
-     * @private
109
-     * @returns {ReactElement|null}
110
-     */
111
-    _renderPasswordEdit() {
112
-        if (!this.state.isEditingPassword) {
113
-            return null;
114
-        }
115
-
116
-        return (
117
-            this.props.locked
118
-                ? <RemovePasswordForm
119
-                    conference = { this.props.conference }
120
-                    lockedLocally = { this.props.locked === LOCKED_LOCALLY }
121
-                    password = { this.props.password } />
122
-                : <AddPasswordForm conference = { this.props.conference } />
123
-        );
124
-    }
125
-
126
-    /**
127
-     * Creates a ReactElement that toggles displaying password edit components.
128
-     *
129
-     * @private
130
-     * @returns {ReactElement|null}
131
-     */
132
-    _renderShowPasswordLink() {
133
-        if (!this.props.showPasswordEdit) {
134
-            return null;
135
-        }
136
-
137
-        let toggleStatusKey;
138
-
139
-        if (this.state.isEditingPassword) {
140
-            toggleStatusKey = 'invite.hidePassword';
141
-        } else if (this.props.locked) {
142
-            toggleStatusKey = 'invite.showPassword';
143
-        } else {
144
-            toggleStatusKey = 'invite.addPassword';
145
-        }
146
-
147
-        return (
148
-            <a
149
-                className = 'password-overview-toggle-edit'
150
-                onClick = { this._onTogglePasswordEdit }>
151
-                { this.props.t(toggleStatusKey) }
152
-            </a>
153
-        );
154
-    }
155
-}
156
-
157
-export default translate(PasswordContainer);

+ 0
- 119
react/features/invite/components/RemovePasswordForm.js Целия файл

1
-import PropTypes from 'prop-types';
2
-import React, { Component } from 'react';
3
-import { connect } from 'react-redux';
4
-
5
-import { setPassword } from '../../base/conference';
6
-import { translate } from '../../base/i18n';
7
-
8
-/**
9
- * A React {@code Component} for removing a lock from a JitsiConference.
10
- */
11
-class RemovePasswordForm extends Component {
12
-    /**
13
-     * {@code RemovePasswordForm}'s property types.
14
-     *
15
-     * @static
16
-     */
17
-    static propTypes = {
18
-        /**
19
-         * The JitsiConference on which remove a lock.
20
-         *
21
-         * @type {JitsiConference}
22
-         */
23
-        conference: PropTypes.object,
24
-
25
-        /**
26
-         * Invoked to send a password removal request.
27
-         */
28
-        dispatch: PropTypes.func,
29
-
30
-        /**
31
-         * Whether or not the room lock, if any, was set by the local user.
32
-         */
33
-        lockedLocally: PropTypes.bool,
34
-
35
-        /**
36
-         * The current known password for the JitsiConference.
37
-         */
38
-        password: PropTypes.string,
39
-
40
-        /**
41
-         * Invoked to obtain translated strings.
42
-         */
43
-        t: PropTypes.func
44
-    };
45
-
46
-    /**
47
-     * Initializes a new {@code RemovePasswordForm} instance.
48
-     *
49
-     * @param {Object} props - The read-only properties with which the new
50
-     * instance is to be initialized.
51
-     */
52
-    constructor(props) {
53
-        super(props);
54
-
55
-        // Bind event handlers so they are only bound once for every instance.
56
-        this._onClick = this._onClick.bind(this);
57
-    }
58
-
59
-    /**
60
-     * Implements React's {@link Component#render()}.
61
-     *
62
-     * @private
63
-     * @returns {ReactElement}
64
-     */
65
-    render() {
66
-        return (
67
-            <div className = 'remove-password'>
68
-                <div className = 'remove-password-description'>
69
-                    { this._getPasswordPreviewText() }
70
-                </div>
71
-                <a
72
-                    className = 'remove-password-link'
73
-                    id = 'inviteDialogRemovePassword'
74
-                    onClick = { this._onClick }>
75
-                    { this.props.t('dialog.removePassword') }
76
-                </a>
77
-            </div>
78
-        );
79
-    }
80
-
81
-    /**
82
-     * Creates a ReactElement for displaying the current password.
83
-     *
84
-     * @private
85
-     * @returns {ReactElement}
86
-     */
87
-    _getPasswordPreviewText() {
88
-        const { lockedLocally, password, t } = this.props;
89
-
90
-        return (
91
-            <span>
92
-                <span>
93
-                    { `${t('dialog.currentPassword')} ` }
94
-                </span>
95
-                <span className = 'remove-password-current'>
96
-                    { lockedLocally ? password : t('passwordSetRemotely') }
97
-                </span>
98
-            </span>
99
-        );
100
-    }
101
-
102
-    /**
103
-     * Dispatches a request to remove any set password on the JitsiConference.
104
-     *
105
-     * @private
106
-     * @returns {void}
107
-     */
108
-    _onClick() {
109
-        const { conference } = this.props;
110
-
111
-        this.props.dispatch(setPassword(
112
-            conference,
113
-            conference.lock,
114
-            ''
115
-        ));
116
-    }
117
-}
118
-
119
-export default translate(connect()(RemovePasswordForm));

+ 0
- 140
react/features/invite/components/ShareLinkForm.js Целия файл

1
-import Button from '@atlaskit/button';
2
-import { FieldTextStateless as TextField } from '@atlaskit/field-text';
3
-import PropTypes from 'prop-types';
4
-import React, { Component } from 'react';
5
-
6
-import { translate } from '../../base/i18n';
7
-
8
-const logger = require('jitsi-meet-logger').getLogger(__filename);
9
-
10
-/**
11
- * A React {@code Component} for displaying a value with a copy button to copy
12
- * the value into the clipboard.
13
- */
14
-class ShareLinkForm extends Component {
15
-    /**
16
-     * {@code ShareLinkForm}'s property types.
17
-     *
18
-     * @static
19
-     */
20
-    static propTypes = {
21
-        /**
22
-         * Invoked to obtain translated strings.
23
-         */
24
-        t: PropTypes.func,
25
-
26
-        /**
27
-         * The value to be displayed and copied into the clipboard.
28
-         */
29
-        toCopy: PropTypes.string
30
-    };
31
-
32
-    /**
33
-     * Initializes a new {@code ShareLinkForm} instance.
34
-     *
35
-     * @param {Object} props - The read-only properties with which the new
36
-     * instance is to be initialized.
37
-     */
38
-    constructor(props) {
39
-        super(props);
40
-
41
-        /**
42
-         * The internal reference to the React {@code component} for display
43
-         * the meeting link in an input element.
44
-         *
45
-         * @private
46
-         * @type {ReactComponent}
47
-         */
48
-        this._inputComponent = null;
49
-
50
-        // Bind event handlers so they are only bound once for every instance.
51
-        this._onClick = this._onClick.bind(this);
52
-        this._onDropdownTriggerInputChange
53
-            = this._onDropdownTriggerInputChange.bind(this);
54
-        this._setInput = this._setInput.bind(this);
55
-    }
56
-
57
-    /**
58
-     * Implements React's {@link Component#render()}.
59
-     *
60
-     * @inheritdoc
61
-     * @returns {ReactElement}
62
-     */
63
-    render() {
64
-        const { t } = this.props;
65
-        const inputValue = this.props.toCopy || t('inviteUrlDefaultMsg');
66
-
67
-        return (
68
-            <div className = 'form-control'>
69
-                <label className = 'form-control__label'>
70
-                    { t('dialog.shareLink') }
71
-                </label>
72
-                <div className = 'form-control__container'>
73
-                    <div className = 'form-control__input-container'>
74
-                        <TextField
75
-                            id = 'inviteLinkRef'
76
-                            isLabelHidden = { true }
77
-                            isReadOnly = { true }
78
-                            label = 'invite link'
79
-                            onChange = { this._onDropdownTriggerInputChange }
80
-                            ref = { this._setInput }
81
-                            shouldFitContainer = { true }
82
-                            type = 'text'
83
-                            value = { inputValue } />
84
-                    </div>
85
-                    <Button
86
-                        appearance = 'default'
87
-                        onClick = { this._onClick }
88
-                        type = 'button'>
89
-                        { t('dialog.copy') }
90
-                    </Button>
91
-                </div>
92
-            </div>
93
-        );
94
-    }
95
-
96
-    /**
97
-     * Copies the passed in value to the clipboard.
98
-     *
99
-     * @private
100
-     * @returns {void}
101
-     */
102
-    _onClick() {
103
-        try {
104
-            const { input } = this._inputComponent;
105
-
106
-            input.select();
107
-            document.execCommand('copy');
108
-            input.blur();
109
-        } catch (err) {
110
-            logger.error('error when copying the text', err);
111
-        }
112
-    }
113
-
114
-    /**
115
-     * This is a no-op function used to stub out TextField's onChange in order
116
-     * to prevent TextField from printing prop type validation errors. TextField
117
-     * is used as a trigger for the dropdown in {@code ShareLinkForm} to get the
118
-     * desired AtlasKit input look for the UI.
119
-     *
120
-     * @returns {void}
121
-     */
122
-    _onDropdownTriggerInputChange() {
123
-        // Intentionally left empty.
124
-    }
125
-
126
-    /**
127
-     * Sets the internal reference to the React Component wrapping the input
128
-     * with id {@code inviteLinkRef}.
129
-     *
130
-     * @param {ReactComponent} inputComponent - React Component for displaying
131
-     * an input for displaying the meeting link.
132
-     * @private
133
-     * @returns {void}
134
-     */
135
-    _setInput(inputComponent) {
136
-        this._inputComponent = inputComponent;
137
-    }
138
-}
139
-
140
-export default translate(ShareLinkForm);

+ 1
- 1
react/features/invite/components/dial-in-info-page/DialInInfoPage.web.js Целия файл

104
         if (loading) {
104
         if (loading) {
105
             contents = '';
105
             contents = '';
106
         } else if (numbersEnabled === false) {
106
         } else if (numbersEnabled === false) {
107
-            contents = this.props.t('invite.disabled');
107
+            contents = this.props.t('info.dialInNotSupported');
108
         } else if (error) {
108
         } else if (error) {
109
             contents = error;
109
             contents = error;
110
         } else {
110
         } else {

+ 0
- 1
react/features/invite/components/index.js Целия файл

1
 export { default as AddPeopleDialog } from './AddPeopleDialog';
1
 export { default as AddPeopleDialog } from './AddPeopleDialog';
2
 export { default as InfoDialogButton } from './InfoDialogButton';
2
 export { default as InfoDialogButton } from './InfoDialogButton';
3
 export { default as InviteButton } from './InviteButton';
3
 export { default as InviteButton } from './InviteButton';
4
-export { default as InviteDialog } from './InviteDialog';

+ 1
- 1
react/features/invite/components/info-dialog/InfoDialog.web.js Целия файл

411
         } else {
411
         } else {
412
             className = 'add-password';
412
             className = 'add-password';
413
             onClick = this._onTogglePasswordEditState;
413
             onClick = this._onTogglePasswordEditState;
414
-            textKey = 'invite.addPassword';
414
+            textKey = 'info.addPassword';
415
         }
415
         }
416
 
416
 
417
         return className && onClick && textKey
417
         return className && onClick && textKey

+ 1
- 17
react/features/toolbox/defaultToolbarButtons.web.js Целия файл

12
 } from '../analytics';
12
 } from '../analytics';
13
 import { ParticipantCounter } from '../contact-list';
13
 import { ParticipantCounter } from '../contact-list';
14
 import { openDeviceSelectionDialog } from '../device-selection';
14
 import { openDeviceSelectionDialog } from '../device-selection';
15
-import { InfoDialogButton, openInviteDialog } from '../invite';
15
+import { InfoDialogButton } from '../invite';
16
 import UIEvents from '../../../service/UI/UIEvents';
16
 import UIEvents from '../../../service/UI/UIEvents';
17
 import { VideoQualityButton } from '../video-quality';
17
 import { VideoQualityButton } from '../video-quality';
18
 
18
 
307
             component: InfoDialogButton
307
             component: InfoDialogButton
308
         },
308
         },
309
 
309
 
310
-        /**
311
-         * The descriptor of the toolbar button which shows the invite user
312
-         * dialog.
313
-         */
314
-        invite: {
315
-            classNames: [ 'button', 'icon-link' ],
316
-            enabled: true,
317
-            id: 'toolbar_button_link',
318
-            onClick(dispatch: Function) {
319
-                sendAnalytics(createToolbarEvent('invite'));
320
-
321
-                dispatch(openInviteDialog());
322
-            },
323
-            tooltipKey: 'toolbar.invite'
324
-        },
325
-
326
         /**
310
         /**
327
          * The descriptor of the microphone toolbar button.
311
          * The descriptor of the microphone toolbar button.
328
          */
312
          */

Loading…
Отказ
Запис