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:
parent
b64260e554
commit
ed5351d250
|
@ -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",
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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')}
|
||||||
|
<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));
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue