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
This commit is contained in:
parent
2412239206
commit
2f23f8e400
|
@ -38,7 +38,7 @@
|
|||
.info-dialog-copy-element {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
-webkit-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
|
@ -56,11 +56,11 @@
|
|||
}
|
||||
|
||||
.info-dialog-conference-url {
|
||||
max-width: 250px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
user-select: text;
|
||||
white-space: nowrap;
|
||||
width: max-content;
|
||||
width: -moz-max-content;
|
||||
width: -webkit-max-content;
|
||||
word-break: break-all;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.info-dialog-dial-in {
|
||||
|
@ -82,14 +82,18 @@
|
|||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.info-password,
|
||||
.info-dialog-password,
|
||||
.info-password,
|
||||
.info-password-form {
|
||||
align-items: baseline;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.info-password-field {
|
||||
margin-left: 2px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
@ -110,10 +114,6 @@
|
|||
.info-password-local {
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.conference-id {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.dial-in-page {
|
||||
|
@ -125,10 +125,6 @@
|
|||
justify-content: center;
|
||||
width: 100%;
|
||||
|
||||
* {
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.dial-in-numbers-list {
|
||||
font-size: 24px;
|
||||
margin-top: 20px;
|
||||
|
@ -139,3 +135,12 @@
|
|||
width: 30%;
|
||||
}
|
||||
}
|
||||
|
||||
.info-dialog,
|
||||
.dial-in-page {
|
||||
* {
|
||||
user-select: text;
|
||||
-moz-user-select: text;
|
||||
-webkit-user-select: text;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -516,11 +516,11 @@
|
|||
"info": {
|
||||
"addPassword": "Add password",
|
||||
"cancelPassword": "Cancel password",
|
||||
"conferenceURL": "Link: __url__",
|
||||
"conferenceURL": "Link:",
|
||||
"country": "Country",
|
||||
"dialANumber": "To join your meeting, dial one of these numbers and then enter this PIN: __conferenceID__#",
|
||||
"dialInNumber": "Dial-in: __phoneNumber__",
|
||||
"dialInConferenceID": "PIN: __conferenceID__#",
|
||||
"dialInNumber": "Dial-in:",
|
||||
"dialInConferenceID": "PIN:",
|
||||
"dialInNotSupported": "Sorry, dialing in is currently not suppported.",
|
||||
"genericError": "Whoops, something went wrong.",
|
||||
"invitePhone": "To join by phone, dial __number__ and enter this PIN: __conferenceID__#",
|
||||
|
@ -532,7 +532,7 @@
|
|||
"noRoom": "No room was specified to dial-in into.",
|
||||
"numbers": "Dial-in Numbers",
|
||||
"password": "Password:",
|
||||
"title": "Call info",
|
||||
"title": "Share",
|
||||
"tooltip": "Get access info about the meeting"
|
||||
},
|
||||
"settingsView": {
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
/**
|
||||
* The type of the action which signals a request to display the inline
|
||||
* conference info dialog.
|
||||
*
|
||||
* {
|
||||
* type: SET_INFO_DIALOG_VISIBILITY,
|
||||
* visible: boolean
|
||||
* }
|
||||
*/
|
||||
export const SET_INFO_DIALOG_VISIBILITY = Symbol('SET_INFO_DIALOG_VISIBILITY');
|
||||
|
||||
/**
|
||||
* The type of the action which signals an error occurred while requesting dial-
|
||||
* in numbers.
|
||||
|
|
|
@ -1,34 +1,11 @@
|
|||
// @flow
|
||||
|
||||
import {
|
||||
SET_INFO_DIALOG_VISIBILITY,
|
||||
UPDATE_DIAL_IN_NUMBERS_FAILED,
|
||||
UPDATE_DIAL_IN_NUMBERS_SUCCESS
|
||||
} from './actionTypes';
|
||||
import { getDialInConferenceID, getDialInNumbers } from './functions';
|
||||
|
||||
/**
|
||||
* Opens the inline conference info dialog.
|
||||
*
|
||||
* @param {boolean} visible - Whether or not the dialog should be displayed.
|
||||
* @param {boolean} autoClose - Whether or not the dialog should automatically
|
||||
* close after a set period of time.
|
||||
* @returns {{
|
||||
* type: SET_INFO_DIALOG_VISIBILITY,
|
||||
* autoClose: boolean,
|
||||
* visible: boolean
|
||||
* }}
|
||||
*/
|
||||
export function setInfoDialogVisibility(
|
||||
visible: boolean,
|
||||
autoClose: boolean = false) {
|
||||
return {
|
||||
type: SET_INFO_DIALOG_VISIBILITY,
|
||||
autoClose,
|
||||
visible
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends AJAX requests for dial-in numbers and conference ID.
|
||||
*
|
||||
|
|
|
@ -7,16 +7,16 @@ import { connect } from 'react-redux';
|
|||
|
||||
import { createToolbarEvent, sendAnalytics } from '../../analytics';
|
||||
import { translate } from '../../base/i18n';
|
||||
import { getParticipantCount } from '../../base/participants';
|
||||
import {
|
||||
ToolbarButton,
|
||||
ToolbarButtonV2,
|
||||
TOOLTIP_TO_POPUP_POSITION
|
||||
} from '../../toolbox';
|
||||
|
||||
import { setInfoDialogVisibility, updateDialInNumbers } from '../actions';
|
||||
import { InfoDialog } from './info-dialog';
|
||||
import { updateDialInNumbers } from '../actions';
|
||||
|
||||
const { INITIAL_TOOLBAR_TIMEOUT } = interfaceConfig;
|
||||
import { InfoDialog } from './info-dialog';
|
||||
|
||||
/**
|
||||
* A configuration object to describe how {@code ToolbarButton} should render
|
||||
|
@ -32,6 +32,14 @@ const DEFAULT_BUTTON_CONFIGURATION = {
|
|||
tooltipKey: 'info.tooltip'
|
||||
};
|
||||
|
||||
/**
|
||||
* The amount of time, in milliseconds, to wait until automatically showing
|
||||
* the {@code InfoDialog}. This is essentially a hack as automatic showing
|
||||
* should happen in a lonely call and some time is needed to populate
|
||||
* participants already in the call.
|
||||
*/
|
||||
const INFO_DIALOG_AUTO_SHOW_TIMEOUT = 1500;
|
||||
|
||||
/**
|
||||
* A React Component for displaying a button which opens a dialog with
|
||||
* information about the conference and with ways to invite people.
|
||||
|
@ -55,15 +63,16 @@ class InfoDialogButton extends Component {
|
|||
]),
|
||||
|
||||
/**
|
||||
* Whether or not the {@code InfoDialog} should close by itself after a
|
||||
* a timeout.
|
||||
* Whether or not the {@code InfoDialog} should display automatically
|
||||
* after {@link INFO_DIALOG_AUTO_SHOW_TIMEOUT}.
|
||||
*/
|
||||
_shouldAutoClose: PropTypes.bool,
|
||||
_disableAutoShow: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* Whether or not {@code InfoDialog} should be displayed.
|
||||
* The number of real participants in the call. If in a lonely call,
|
||||
* the {@code InfoDialog} will be automatically shown.
|
||||
*/
|
||||
_showDialog: PropTypes.bool,
|
||||
_participantCount: PropTypes.number,
|
||||
|
||||
/**
|
||||
* Whether or not the toolbox, in which this component exists, are
|
||||
|
@ -98,16 +107,23 @@ class InfoDialogButton extends Component {
|
|||
super(props);
|
||||
|
||||
/**
|
||||
* The timeout to automatically hide the {@code InfoDialog} if it has
|
||||
* not been interacted with.
|
||||
* The timeout to automatically show the {@code InfoDialog} if it has
|
||||
* not been shown yet in a lonely call.
|
||||
*
|
||||
* @type {timeoutID}
|
||||
*/
|
||||
this._autoHideDialogTimeout = null;
|
||||
this._autoShowTimeout = null;
|
||||
|
||||
|
||||
this.state = {
|
||||
/**
|
||||
* Whether or not {@code InfoDialog} should be visible.
|
||||
*/
|
||||
showDialog: false
|
||||
};
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
this._onDialogClose = this._onDialogClose.bind(this);
|
||||
this._onDialogMouseOver = this._onDialogMouseOver.bind(this);
|
||||
this._onDialogToggle = this._onDialogToggle.bind(this);
|
||||
}
|
||||
|
||||
|
@ -117,30 +133,15 @@ class InfoDialogButton extends Component {
|
|||
* @inheritdoc
|
||||
*/
|
||||
componentDidMount() {
|
||||
if (this.props._shouldAutoClose) {
|
||||
this._setAutoCloseTimeout();
|
||||
}
|
||||
this._autoShowTimeout = setTimeout(() => {
|
||||
this._maybeAutoShowDialog();
|
||||
}, INFO_DIALOG_AUTO_SHOW_TIMEOUT);
|
||||
|
||||
if (!this.props._dialInNumbers) {
|
||||
this.props.dispatch(updateDialInNumbers());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or clear the timeout to automatically hide the {@code InfoDialog}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
componentDidUpdate(prevProps) {
|
||||
// If the _shouldAutoClose flag has been updated to be true then make
|
||||
// sure to set _autoHideDialogTimeout.
|
||||
if (this.props._shouldAutoClose && !prevProps._shouldAutoClose) {
|
||||
this._setAutoCloseTimeout();
|
||||
} else {
|
||||
this._clearAutoCloseTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the visibility of the {@code InfoDialog}.
|
||||
*
|
||||
|
@ -148,7 +149,7 @@ class InfoDialogButton extends Component {
|
|||
*/
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// Ensure the dialog is closed when the toolbox becomes hidden.
|
||||
if (nextProps._showDialog && !nextProps._toolboxVisible) {
|
||||
if (this.state.showDialog && !nextProps._toolboxVisible) {
|
||||
this._onDialogClose();
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +160,7 @@ class InfoDialogButton extends Component {
|
|||
* @inheritdoc
|
||||
*/
|
||||
componentWillUnmount() {
|
||||
this._clearAutoCloseTimeout();
|
||||
clearTimeout(this._autoShowTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,14 +176,16 @@ class InfoDialogButton extends Component {
|
|||
}
|
||||
|
||||
/**
|
||||
* Cancels the timeout to automatically hide the {@code InfoDialog}.
|
||||
* Callback invoked after a timeout to trigger display of the
|
||||
* {@code InfoDialog} if certain conditions are met.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_clearAutoCloseTimeout() {
|
||||
clearTimeout(this._autoHideDialogTimeout);
|
||||
this._autoHideDialogTimeout = null;
|
||||
_maybeAutoShowDialog() {
|
||||
if (this.props._participantCount < 2 && !this.props._disableAutoShow) {
|
||||
this.setState({ showDialog: true });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -192,17 +195,7 @@ class InfoDialogButton extends Component {
|
|||
* @returns {void}
|
||||
*/
|
||||
_onDialogClose() {
|
||||
this.props.dispatch(setInfoDialogVisibility(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the timeout to automatically hide the {@code InfoDialog}.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onDialogMouseOver() {
|
||||
this._clearAutoCloseTimeout();
|
||||
this.setState({ showDialog: false });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -214,7 +207,7 @@ class InfoDialogButton extends Component {
|
|||
_onDialogToggle() {
|
||||
sendAnalytics(createToolbarEvent('info'));
|
||||
|
||||
this.props.dispatch(setInfoDialogVisibility(!this.props._showDialog));
|
||||
this.setState({ showDialog: !this.state.showDialog });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -225,22 +218,21 @@ class InfoDialogButton extends Component {
|
|||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderOldToolbarButton() {
|
||||
const { _showDialog, _toolboxVisible, tooltipPosition } = this.props;
|
||||
const { tooltipPosition } = this.props;
|
||||
const { showDialog } = this.state;
|
||||
|
||||
const buttonConfiguration = {
|
||||
...DEFAULT_BUTTON_CONFIGURATION,
|
||||
classNames: [
|
||||
...DEFAULT_BUTTON_CONFIGURATION.classNames,
|
||||
_showDialog ? 'toggled button-active' : ''
|
||||
showDialog ? 'toggled button-active' : ''
|
||||
]
|
||||
};
|
||||
|
||||
return (
|
||||
<InlineDialog
|
||||
content = { <InfoDialog
|
||||
autoUpdateNumbers = { false }
|
||||
onClose = { this._onDialogClose }
|
||||
onMouseOver = { this._onDialogMouseOver } /> }
|
||||
isOpen = { _toolboxVisible && _showDialog }
|
||||
content = { <InfoDialog onClose = { this._onDialogClose } /> }
|
||||
isOpen = { showDialog }
|
||||
onClose = { this._onDialogClose }
|
||||
position = { TOOLTIP_TO_POPUP_POSITION[tooltipPosition] }>
|
||||
<ToolbarButton
|
||||
|
@ -259,17 +251,16 @@ class InfoDialogButton extends Component {
|
|||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderNewToolbarButton() {
|
||||
const { _showDialog, _toolboxVisible, t } = this.props;
|
||||
const iconClass = `icon-info ${_showDialog ? 'toggled' : ''}`;
|
||||
const { t } = this.props;
|
||||
const { showDialog } = this.state;
|
||||
const iconClass = `icon-info ${showDialog ? 'toggled' : ''}`;
|
||||
|
||||
return (
|
||||
<div className = 'toolbox-button-wth-dialog'>
|
||||
<InlineDialog
|
||||
content = { <InfoDialog
|
||||
autoUpdateNumbers = { false }
|
||||
onClose = { this._onDialogClose }
|
||||
onMouseOver = { this._onDialogMouseOver } /> }
|
||||
isOpen = { _toolboxVisible && _showDialog }
|
||||
content = {
|
||||
<InfoDialog onClose = { this._onDialogClose } /> }
|
||||
isOpen = { showDialog }
|
||||
onClose = { this._onDialogClose }
|
||||
position = { 'top right' }>
|
||||
<ToolbarButtonV2
|
||||
|
@ -281,22 +272,6 @@ class InfoDialogButton extends Component {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a timeout to automatically hide the {@code InfoDialog}.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setAutoCloseTimeout() {
|
||||
this._clearAutoCloseTimeout();
|
||||
|
||||
this._autoHideDialogTimeout = setTimeout(() => {
|
||||
if (this.props._showDialog) {
|
||||
this._onDialogClose();
|
||||
}
|
||||
}, INITIAL_TOOLBAR_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -307,22 +282,17 @@ class InfoDialogButton extends Component {
|
|||
* @private
|
||||
* @returns {{
|
||||
* _dialInNumbers: Array,
|
||||
* _shouldAutoClose: boolean,
|
||||
* _showDialog: boolean,
|
||||
* _disableAutoShow: bolean,
|
||||
* _participantCount: number,
|
||||
* _toolboxVisible: boolean
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
const {
|
||||
infoDialogVisible,
|
||||
infoDialogWillAutoClose,
|
||||
numbers
|
||||
} = state['features/invite'];
|
||||
|
||||
return {
|
||||
_dialInNumbers: numbers,
|
||||
_shouldAutoClose: infoDialogWillAutoClose,
|
||||
_showDialog: infoDialogVisible,
|
||||
_dialInNumbers: state['features/invite'].numbers,
|
||||
_disableAutoShow: state['features/base/config'].iAmRecorder,
|
||||
_participantCount:
|
||||
getParticipantCount(state['features/base/participants']),
|
||||
_toolboxVisible: state['features/toolbox'].visible
|
||||
};
|
||||
}
|
||||
|
|
|
@ -41,16 +41,28 @@ class DialInNumber extends Component {
|
|||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const { conferenceID, phoneNumber } = this.props;
|
||||
const { conferenceID, phoneNumber, t } = this.props;
|
||||
|
||||
return (
|
||||
<div className = 'dial-in-number'>
|
||||
<span className = 'phone-number'>
|
||||
{ this.props.t('info.dialInNumber', { phoneNumber }) }
|
||||
<span className = 'info-label'>
|
||||
{ t('info.dialInNumber') }
|
||||
</span>
|
||||
<span className = 'spacer'> </span>
|
||||
<span className = 'info-value'>
|
||||
{ phoneNumber }
|
||||
</span>
|
||||
</span>
|
||||
<span className = 'spacer'> </span>
|
||||
<span className = 'conference-id'>
|
||||
{ this.props.t(
|
||||
'info.dialInConferenceID', { conferenceID }) }
|
||||
<span className = 'info-label'>
|
||||
{ t('info.dialInConferenceID') }
|
||||
</span>
|
||||
<span className = 'spacer'> </span>
|
||||
<span className = 'info-value'>
|
||||
{ `${conferenceID}#` }
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -214,14 +214,13 @@ class InfoDialog extends Component {
|
|||
{ t('info.title') }
|
||||
</div>
|
||||
<div className = 'info-dialog-conference-url'>
|
||||
{ t('info.conferenceURL',
|
||||
{ url: this._getURLToDisplay() }) }
|
||||
<textarea
|
||||
className = 'info-dialog-copy-element'
|
||||
readOnly = { true }
|
||||
ref = { this._setCopyElement }
|
||||
tabIndex = '-1'
|
||||
value = { this._getTextToCopy() } />
|
||||
<span className = 'info-label'>
|
||||
{ t('info.conferenceURL') }
|
||||
</span>
|
||||
<span className = 'spacer'> </span>
|
||||
<span className = 'info-value'>
|
||||
{ this._getURLToDisplay() }
|
||||
</span>
|
||||
</div>
|
||||
<div className = 'info-dialog-dial-in'>
|
||||
{ this._renderDialInDisplay() }
|
||||
|
@ -244,6 +243,12 @@ class InfoDialog extends Component {
|
|||
{ this._renderPasswordAction() }
|
||||
</div>
|
||||
</div>
|
||||
<textarea
|
||||
className = 'info-dialog-copy-element'
|
||||
readOnly = { true }
|
||||
ref = { this._setCopyElement }
|
||||
tabIndex = '-1'
|
||||
value = { this._getTextToCopy() } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -94,10 +94,13 @@ class PasswordForm extends Component {
|
|||
|
||||
return (
|
||||
<div className = 'info-password'>
|
||||
<div>{ t('info.password') }</div>
|
||||
<div className = 'info-password-field'>
|
||||
<span className = 'info-label'>
|
||||
{ t('info.password') }
|
||||
</span>
|
||||
<span className = 'spacer'> </span>
|
||||
<span className = 'info-password-field info-value'>
|
||||
{ this._renderPasswordField() }
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import { CONFERENCE_JOINED } from '../base/conference';
|
||||
import { MiddlewareRegistry } from '../base/redux';
|
||||
|
||||
import { setInfoDialogVisibility } from './actions';
|
||||
import { UPDATE_DIAL_IN_NUMBERS_FAILED } from './actionTypes';
|
||||
|
||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
|
@ -17,13 +15,6 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
const result = next(action);
|
||||
|
||||
switch (action.type) {
|
||||
case CONFERENCE_JOINED:
|
||||
// we do not want to show call info in iAmRecorder mode
|
||||
if (store.getState()['features/base/config'].iAmRecorder) {
|
||||
return result;
|
||||
}
|
||||
store.dispatch(setInfoDialogVisibility(true, true));
|
||||
break;
|
||||
|
||||
case UPDATE_DIAL_IN_NUMBERS_FAILED:
|
||||
logger.error(
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { ReducerRegistry } from '../base/redux';
|
||||
|
||||
import {
|
||||
SET_INFO_DIALOG_VISIBILITY,
|
||||
UPDATE_DIAL_IN_NUMBERS_FAILED,
|
||||
UPDATE_DIAL_IN_NUMBERS_SUCCESS
|
||||
} from './actionTypes';
|
||||
|
@ -12,13 +11,6 @@ const DEFAULT_STATE = {
|
|||
|
||||
ReducerRegistry.register('features/invite', (state = DEFAULT_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case SET_INFO_DIALOG_VISIBILITY:
|
||||
return {
|
||||
...state,
|
||||
infoDialogVisible: action.visible,
|
||||
infoDialogWillAutoClose: action.autoClose
|
||||
};
|
||||
|
||||
case UPDATE_DIAL_IN_NUMBERS_FAILED:
|
||||
return {
|
||||
...state,
|
||||
|
|
Loading…
Reference in New Issue