Add dial-in link to no audio notification (#5026)

* Add dial-in link to no audio notification

* refactor react link component

* fix tests
This commit is contained in:
Andrei Gavrilescu 2020-02-05 20:10:57 +02:00 committed by GitHub
parent b64260e554
commit ed5351d250
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 130 additions and 25 deletions

View File

@ -635,8 +635,10 @@
"moreActions": "More actions", "moreActions": "More actions",
"mute": "Mute / Unmute", "mute": "Mute / Unmute",
"noAudioSignalTitle": "There is no input coming from your mic!", "noAudioSignalTitle": "There is no input coming from your mic!",
"noAudioSignalDesc": "If you did not purposely mute it from system settings or hardware, consider changing the device.", "noAudioSignalDesc": "If you did not purposely mute it from system settings or hardware, consider switching the device.",
"noAudioSignalDescSuggestion": "If you did not purposely mute it from system settings or hardware, consider using the following device:", "noAudioSignalDescSuggestion": "If you did not purposely mute it from system settings or hardware, consider switching to the suggested device.",
"noAudioSignalDialInDesc": "You can also dial-in using:",
"noAudioSignalDialInLinkDesc" : "Dial-in numbers",
"noisyAudioInputTitle": "Your microphone appears to be noisy!", "noisyAudioInputTitle": "Your microphone appears to be noisy!",
"noisyAudioInputDesc": "Jitsi has detected noise coming from your microphone, please consider muting or changing the device.", "noisyAudioInputDesc": "Jitsi has detected noise coming from your microphone, please consider muting or changing the device.",
"openChat": "Open chat", "openChat": "Open chat",

View File

@ -17,7 +17,8 @@ import {
import { import {
_decodeRoomURI, _decodeRoomURI,
_getDefaultPhoneNumber, _getDefaultPhoneNumber,
getDialInfoPageURL getDialInfoPageURL,
shouldDisplayDialIn
} from '../../../functions'; } from '../../../functions';
import logger from '../../../logger'; import logger from '../../../logger';
import DialInNumber from './DialInNumber'; import DialInNumber from './DialInNumber';
@ -316,7 +317,6 @@ class InfoDialog extends Component<Props, State> {
*/ */
_getTextToCopy() { _getTextToCopy() {
const { _localParticipant, liveStreamViewURL, t } = this.props; const { _localParticipant, liveStreamViewURL, t } = this.props;
const shouldDisplayDialIn = this._shouldDisplayDialIn();
const _inviteURL = _decodeRoomURI(this.props._inviteURL); const _inviteURL = _decodeRoomURI(this.props._inviteURL);
let invite = _localParticipant && _localParticipant.name let invite = _localParticipant && _localParticipant.name
@ -335,7 +335,7 @@ class InfoDialog extends Component<Props, State> {
invite = `${invite}\n${liveStream}`; invite = `${invite}\n${liveStream}`;
} }
if (shouldDisplayDialIn) { if (shouldDisplayDialIn(this.props.dialIn)) {
const dial = t('info.invitePhone', { const dial = t('info.invitePhone', {
number: this.state.phoneNumber, number: this.state.phoneNumber,
conferenceID: this.props.dialIn.conferenceID conferenceID: this.props.dialIn.conferenceID
@ -480,7 +480,7 @@ class InfoDialog extends Component<Props, State> {
* @returns {null|ReactElement} * @returns {null|ReactElement}
*/ */
_renderDialInDisplay() { _renderDialInDisplay() {
if (!this._shouldDisplayDialIn()) { if (!shouldDisplayDialIn(this.props.dialIn)) {
return null; return null;
} }
@ -571,23 +571,6 @@ class InfoDialog extends Component<Props, State> {
); );
} }
/**
* Returns whether or not dial-in related UI should be displayed.
*
* @private
* @returns {boolean}
*/
_shouldDisplayDialIn() {
const { conferenceID, numbers, numbersEnabled } = this.props.dialIn;
const { phoneNumber } = this.state;
return Boolean(
conferenceID
&& numbers
&& numbersEnabled
&& phoneNumber);
}
_setCopyElement: () => void; _setCopyElement: () => void;
/** /**

View File

@ -524,6 +524,23 @@ export function getDialInfoPageURLForURIString(
return `${protocol}//${host}${contextRoot}static/dialInInfo.html?room=${room}`; return `${protocol}//${host}${contextRoot}static/dialInInfo.html?room=${room}`;
} }
/**
* Returns whether or not dial-in related UI should be displayed.
*
* @param {Object} dialIn - Dial in information.
* @returns {boolean}
*/
export function shouldDisplayDialIn(dialIn: Object) {
const { conferenceID, numbers, numbersEnabled } = dialIn;
const phoneNumber = _getDefaultPhoneNumber(numbers);
return Boolean(
conferenceID
&& numbers
&& numbersEnabled
&& phoneNumber);
}
/** /**
* Sets the internal state of which dial-in number to display. * Sets the internal state of which dial-in number to display.
* *
@ -533,7 +550,11 @@ export function getDialInfoPageURLForURIString(
* @returns {string|null} * @returns {string|null}
*/ */
export function _getDefaultPhoneNumber( export function _getDefaultPhoneNumber(
dialInNumbers: Object): ?string { dialInNumbers: ?Object): ?string {
if (!dialInNumbers) {
return null;
}
if (Array.isArray(dialInNumbers)) { if (Array.isArray(dialInNumbers)) {
// new syntax follows // new syntax follows

View File

@ -0,0 +1,95 @@
// @flow
import React, { Component } from 'react';
import { connect } from '../../base/redux';
import { translate } from '../../base/i18n';
import { getDialInfoPageURL, shouldDisplayDialIn } from '../../invite';
/**
* The type of the React {@code Component} props of {@link DialInLink}.
*/
type Props = {
/**
* The name of the current conference.
*/
_room: string,
/**
* The current location url of the conference.
*/
_locationURL: string,
/**
* The redux state representing the dial-in numbers feature.
*/
_dialIn: Object,
/**
* Invoked to obtain translated strings.
*/
t: Function
};
/**
* React {@code Component} responsible for displaying a telephone number and
* conference ID for dialing into a conference.
*
* @extends Component
*/
class DialInLink extends Component<Props> {
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
const { _room, _locationURL, _dialIn, t } = this.props;
if (!shouldDisplayDialIn(_dialIn)) {
return null;
}
return (
<div>{t('toolbar.noAudioSignalDialInDesc')}&nbsp;
<a
href = {
getDialInfoPageURL(
_room,
_locationURL
)
}
rel = 'noopener noreferrer'
target = '_blank'>
{t('toolbar.noAudioSignalDialInLinkDesc')}
</a>
</div>
);
}
}
/**
* Maps (parts of) the Redux state to the associated props for the
* {@code DialInLink} component.
*
* @param {Object} state - The Redux state.
* @private
* @returns {{
* _room: string,
* _locationURL: string,
* _dialIn: Object,
* }}
*/
function _mapStateToProps(state) {
return {
_room: state['features/base/conference'].room,
_locationURL: state['features/base/connection'].locationURL,
_dialIn: state['features/invite']
};
}
export default translate(connect(_mapStateToProps)(DialInLink));

View File

@ -1,5 +1,7 @@
// @flow // @flow
import React from 'react';
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app'; import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
import { CONFERENCE_JOINED } from '../base/conference'; import { CONFERENCE_JOINED } from '../base/conference';
import { import {
@ -13,6 +15,7 @@ import { playSound, registerSound, unregisterSound } from '../base/sounds';
import { hideNotification, showNotification } from '../notifications'; import { hideNotification, showNotification } from '../notifications';
import { setNoAudioSignalNotificationUid } from './actions'; import { setNoAudioSignalNotificationUid } from './actions';
import DialInLink from './components/DialInLink';
import { NO_AUDIO_SIGNAL_SOUND_ID } from './constants'; import { NO_AUDIO_SIGNAL_SOUND_ID } from './constants';
import { NO_AUDIO_SIGNAL_SOUND_FILE } from './sounds'; import { NO_AUDIO_SIGNAL_SOUND_FILE } from './sounds';
@ -91,7 +94,7 @@ async function _handleNoAudioSignalNotification({ dispatch, getState }, action)
// at the point of the implementation the showNotification function only supports doing that for // at the point of the implementation the showNotification function only supports doing that for
// the description. // the description.
// TODO Add support for arguments to showNotification title and customAction strings. // TODO Add support for arguments to showNotification title and customAction strings.
customActionNameKey = `Use ${formatDeviceLabel(activeDevice.deviceLabel)}`; customActionNameKey = `Switch to ${formatDeviceLabel(activeDevice.deviceLabel)}`;
customActionHandler = () => { customActionHandler = () => {
// Select device callback // Select device callback
dispatch( dispatch(
@ -107,6 +110,7 @@ async function _handleNoAudioSignalNotification({ dispatch, getState }, action)
const notification = showNotification({ const notification = showNotification({
titleKey: 'toolbar.noAudioSignalTitle', titleKey: 'toolbar.noAudioSignalTitle',
description: <DialInLink />,
descriptionKey, descriptionKey,
customActionNameKey, customActionNameKey,
customActionHandler customActionHandler