Outgoing call ringtones (#2949)
* fix(PresenceLabel): Use translated strings for the presence label. * feat(sounds): Implements loop and stop functionality. * feat(invite): Add ringtones. * fix(invite): Code style issues.
This commit is contained in:
parent
ee74f11c3d
commit
c344a83376
|
@ -577,5 +577,15 @@
|
||||||
"appNotInstalled": "You need the __app__ mobile app to join this meeting on your phone.",
|
"appNotInstalled": "You need the __app__ mobile app to join this meeting on your phone.",
|
||||||
"downloadApp": "Download the app",
|
"downloadApp": "Download the app",
|
||||||
"openApp": "Continue to the app"
|
"openApp": "Continue to the app"
|
||||||
|
},
|
||||||
|
"presenceStatus": {
|
||||||
|
"invited": "Invited",
|
||||||
|
"ringing": "Ringing",
|
||||||
|
"calling": "Calling",
|
||||||
|
"connected": "Connected",
|
||||||
|
"connecting": "Connecting",
|
||||||
|
"busy": "Busy",
|
||||||
|
"rejected": "Rejected",
|
||||||
|
"ignored": "Ignored"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
/* eslint-disable no-unused-vars */
|
/* eslint-disable no-unused-vars */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
import { I18nextProvider } from 'react-i18next';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
|
|
||||||
|
import { i18next } from '../../../react/features/base/i18n';
|
||||||
import { PresenceLabel } from '../../../react/features/presence-status';
|
import { PresenceLabel } from '../../../react/features/presence-status';
|
||||||
/* eslint-enable no-unused-vars */
|
/* eslint-enable no-unused-vars */
|
||||||
|
|
||||||
|
@ -456,7 +458,9 @@ export default class LargeVideoManager {
|
||||||
if (presenceLabelContainer.length) {
|
if (presenceLabelContainer.length) {
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Provider store = { APP.store }>
|
<Provider store = { APP.store }>
|
||||||
<PresenceLabel participantID = { id } />
|
<I18nextProvider i18n = { i18next }>
|
||||||
|
<PresenceLabel participantID = { id } />
|
||||||
|
</I18nextProvider>
|
||||||
</Provider>,
|
</Provider>,
|
||||||
presenceLabelContainer.get(0));
|
presenceLabelContainer.get(0));
|
||||||
}
|
}
|
||||||
|
|
|
@ -609,7 +609,9 @@ RemoteVideo.prototype.addPresenceLabel = function() {
|
||||||
if (presenceLabelContainer) {
|
if (presenceLabelContainer) {
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Provider store = { APP.store }>
|
<Provider store = { APP.store }>
|
||||||
<PresenceLabel participantID = { this.id } />
|
<I18nextProvider i18n = { i18next }>
|
||||||
|
<PresenceLabel participantID = { this.id } />
|
||||||
|
</I18nextProvider>
|
||||||
</Provider>,
|
</Provider>,
|
||||||
presenceLabelContainer);
|
presenceLabelContainer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { Component } from 'react';
|
||||||
* playback.
|
* playback.
|
||||||
*/
|
*/
|
||||||
export type AudioElement = {
|
export type AudioElement = {
|
||||||
|
currentTime?: number,
|
||||||
pause: () => void,
|
pause: () => void,
|
||||||
play: () => void,
|
play: () => void,
|
||||||
setSinkId?: string => void
|
setSinkId?: string => void
|
||||||
|
@ -32,7 +33,8 @@ type Props = {
|
||||||
* @type {Object | string}
|
* @type {Object | string}
|
||||||
*/
|
*/
|
||||||
src: Object | string,
|
src: Object | string,
|
||||||
stream: Object
|
stream: Object,
|
||||||
|
loop?: ?boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -74,4 +74,17 @@ export default class Audio extends AbstractAudio {
|
||||||
// writing to not render anything.
|
// writing to not render anything.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the sound if it's currently playing.
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
stop() {
|
||||||
|
// Currently not implemented for mobile. If needed, a possible
|
||||||
|
// implementation is:
|
||||||
|
// if (this._sound) {
|
||||||
|
// this._sound.stop();
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,11 @@ export default class Audio extends AbstractAudio {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
|
const loop = this.props.loop ? 'true' : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<audio
|
<audio
|
||||||
|
loop = { loop }
|
||||||
onCanPlayThrough = { this._onCanPlayThrough }
|
onCanPlayThrough = { this._onCanPlayThrough }
|
||||||
preload = 'auto'
|
preload = 'auto'
|
||||||
|
|
||||||
|
@ -52,6 +55,20 @@ export default class Audio extends AbstractAudio {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the audio HTML element.
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
stop() {
|
||||||
|
if (this._ref) {
|
||||||
|
this._ref.pause();
|
||||||
|
|
||||||
|
// $FlowFixMe
|
||||||
|
this._ref.currentTime = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If audio element reference has been set and the file has been
|
* If audio element reference has been set and the file has been
|
||||||
* loaded then {@link setAudioElementImpl} will be called to eventually add
|
* loaded then {@link setAudioElementImpl} will be called to eventually add
|
||||||
|
|
|
@ -42,6 +42,16 @@ export const PLAY_SOUND = Symbol('PLAY_SOUND');
|
||||||
*/
|
*/
|
||||||
export const REGISTER_SOUND = Symbol('REGISTER_SOUND');
|
export const REGISTER_SOUND = Symbol('REGISTER_SOUND');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of (redux) action to stop a sound from the sounds collection.
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* type: STOP_SOUND,
|
||||||
|
* soundId: string
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export const STOP_SOUND = Symbol('STOP_SOUND');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of (redux) action to unregister an existing sound from the sounds
|
* The type of (redux) action to unregister an existing sound from the sounds
|
||||||
* collection.
|
* collection.
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
_REMOVE_AUDIO_ELEMENT,
|
_REMOVE_AUDIO_ELEMENT,
|
||||||
PLAY_SOUND,
|
PLAY_SOUND,
|
||||||
REGISTER_SOUND,
|
REGISTER_SOUND,
|
||||||
|
STOP_SOUND,
|
||||||
UNREGISTER_SOUND
|
UNREGISTER_SOUND
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
import { getSoundsPath } from './functions';
|
import { getSoundsPath } from './functions';
|
||||||
|
@ -84,17 +85,41 @@ export function playSound(soundId: string): Object {
|
||||||
* created for given source object.
|
* created for given source object.
|
||||||
* @param {string} soundName - The name of bundled audio file that will be
|
* @param {string} soundName - The name of bundled audio file that will be
|
||||||
* associated with the given {@code soundId}.
|
* associated with the given {@code soundId}.
|
||||||
|
* @param {Object} options - Optional paramaters.
|
||||||
|
* @param {boolean} options.loop - True in order to loop the sound.
|
||||||
* @returns {{
|
* @returns {{
|
||||||
* type: REGISTER_SOUND,
|
* type: REGISTER_SOUND,
|
||||||
* soundId: string,
|
* soundId: string,
|
||||||
* src: string
|
* src: string,
|
||||||
|
* options: {
|
||||||
|
* loop: boolean
|
||||||
|
* }
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
export function registerSound(soundId: string, soundName: string): Object {
|
export function registerSound(
|
||||||
|
soundId: string, soundName: string, options: Object = {}): Object {
|
||||||
return {
|
return {
|
||||||
type: REGISTER_SOUND,
|
type: REGISTER_SOUND,
|
||||||
soundId,
|
soundId,
|
||||||
src: `${getSoundsPath()}/${soundName}`
|
src: `${getSoundsPath()}/${soundName}`,
|
||||||
|
options
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops playback of the sound identified by the given sound id.
|
||||||
|
*
|
||||||
|
* @param {string} soundId - The id of the sound to be stopped (the same one
|
||||||
|
* which was used in {@link registerSound} to register the sound).
|
||||||
|
* @returns {{
|
||||||
|
* type: STOP_SOUND,
|
||||||
|
* soundId: string
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
export function stopSound(soundId: string): Object {
|
||||||
|
return {
|
||||||
|
type: STOP_SOUND,
|
||||||
|
soundId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,12 +55,15 @@ class SoundCollection extends Component<Props> {
|
||||||
const sounds = [];
|
const sounds = [];
|
||||||
|
|
||||||
for (const [ soundId, sound ] of this.props._sounds.entries()) {
|
for (const [ soundId, sound ] of this.props._sounds.entries()) {
|
||||||
|
const { options, src } = sound;
|
||||||
|
|
||||||
sounds.push(
|
sounds.push(
|
||||||
React.createElement(
|
React.createElement(
|
||||||
Audio, {
|
Audio, {
|
||||||
key,
|
key,
|
||||||
setRef: this._setRef.bind(this, soundId),
|
setRef: this._setRef.bind(this, soundId),
|
||||||
src: sound.src
|
src,
|
||||||
|
loop: options.loop
|
||||||
}));
|
}));
|
||||||
key += 1;
|
key += 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import { MiddlewareRegistry } from '../redux';
|
import { MiddlewareRegistry } from '../redux';
|
||||||
|
|
||||||
import { PLAY_SOUND } from './actionTypes';
|
import { PLAY_SOUND, STOP_SOUND } from './actionTypes';
|
||||||
|
|
||||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||||
|
|
||||||
|
@ -17,6 +17,9 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
case PLAY_SOUND:
|
case PLAY_SOUND:
|
||||||
_playSound(store, action.soundId);
|
_playSound(store, action.soundId);
|
||||||
break;
|
break;
|
||||||
|
case STOP_SOUND:
|
||||||
|
_stopSound(store, action.soundId);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return next(action);
|
return next(action);
|
||||||
|
@ -44,3 +47,28 @@ function _playSound({ getState }, soundId) {
|
||||||
logger.warn(`PLAY_SOUND: no sound found for id: ${soundId}`);
|
logger.warn(`PLAY_SOUND: no sound found for id: ${soundId}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop sound from audio element registered in the Redux store.
|
||||||
|
*
|
||||||
|
* @param {Store} store - The Redux store instance.
|
||||||
|
* @param {string} soundId - Audio element identifier.
|
||||||
|
* @private
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function _stopSound({ getState }, soundId) {
|
||||||
|
const sounds = getState()['features/base/sounds'];
|
||||||
|
const sound = sounds.get(soundId);
|
||||||
|
|
||||||
|
if (sound) {
|
||||||
|
const { audioElement } = sound;
|
||||||
|
|
||||||
|
if (audioElement) {
|
||||||
|
audioElement.stop();
|
||||||
|
} else {
|
||||||
|
logger.warn(`STOP_SOUND: sound not loaded yet for id: ${soundId}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warn(`STOP_SOUND: no sound found for id: ${soundId}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -29,7 +29,12 @@ export type Sound = {
|
||||||
* can be either a path to the file or an object depending on the platform
|
* can be either a path to the file or an object depending on the platform
|
||||||
* (native vs web).
|
* (native vs web).
|
||||||
*/
|
*/
|
||||||
src: Object | string
|
src: Object | string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This field is container for all optional parameters related to the sound.
|
||||||
|
*/
|
||||||
|
options: Object
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -115,7 +120,8 @@ function _registerSound(state, action) {
|
||||||
const nextState = new Map(state);
|
const nextState = new Map(state);
|
||||||
|
|
||||||
nextState.set(action.soundId, {
|
nextState.set(action.soundId, {
|
||||||
src: action.src
|
src: action.src,
|
||||||
|
options: action.options
|
||||||
});
|
});
|
||||||
|
|
||||||
return nextState;
|
return nextState;
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
/**
|
||||||
|
* The identifier of the sound to be played when the status of an outgoing call
|
||||||
|
* is ringing.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const OUTGOING_CALL_RINGING_SOUND_ID = 'OUTGOING_CALL_RINGING_SOUND_ID';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The identifier of the sound to be played when outgoing call is started.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const OUTGOING_CALL_START_SOUND_ID = 'OUTGOING_CALL_START_SOUND_ID';
|
|
@ -1,11 +1,38 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
|
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app';
|
||||||
|
import {
|
||||||
|
getParticipantById,
|
||||||
|
PARTICIPANT_UPDATED,
|
||||||
|
PARTICIPANT_LEFT
|
||||||
|
} from '../base/participants';
|
||||||
import { MiddlewareRegistry } from '../base/redux';
|
import { MiddlewareRegistry } from '../base/redux';
|
||||||
|
import {
|
||||||
|
playSound,
|
||||||
|
registerSound,
|
||||||
|
stopSound,
|
||||||
|
unregisterSound
|
||||||
|
} from '../base/sounds';
|
||||||
|
import {
|
||||||
|
CALLING,
|
||||||
|
INVITED,
|
||||||
|
RINGING
|
||||||
|
} from '../presence-status';
|
||||||
|
|
||||||
import { UPDATE_DIAL_IN_NUMBERS_FAILED } from './actionTypes';
|
import { UPDATE_DIAL_IN_NUMBERS_FAILED } from './actionTypes';
|
||||||
|
import {
|
||||||
|
OUTGOING_CALL_START_SOUND_ID,
|
||||||
|
OUTGOING_CALL_RINGING_SOUND_ID
|
||||||
|
} from './constants';
|
||||||
|
import {
|
||||||
|
OUTGOING_CALL_START_FILE,
|
||||||
|
OUTGOING_CALL_RINGING_FILE
|
||||||
|
} from './sounds';
|
||||||
|
|
||||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||||
|
|
||||||
|
declare var interfaceConfig: Object;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The middleware of the feature invite common to mobile/react-native and
|
* The middleware of the feature invite common to mobile/react-native and
|
||||||
* Web/React.
|
* Web/React.
|
||||||
|
@ -13,11 +40,66 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||||
* @param {Store} store - The redux store.
|
* @param {Store} store - The redux store.
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
MiddlewareRegistry.register(store => next => action => {
|
MiddlewareRegistry.register(store => next => action => {
|
||||||
|
let oldParticipantPresence;
|
||||||
|
|
||||||
|
if (action.type === PARTICIPANT_UPDATED
|
||||||
|
|| action.type === PARTICIPANT_LEFT) {
|
||||||
|
oldParticipantPresence
|
||||||
|
= _getParticipantPresence(store.getState(), action.participant.id);
|
||||||
|
}
|
||||||
|
|
||||||
const result = next(action);
|
const result = next(action);
|
||||||
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case APP_WILL_MOUNT:
|
||||||
|
store.dispatch(
|
||||||
|
registerSound(
|
||||||
|
OUTGOING_CALL_START_SOUND_ID,
|
||||||
|
OUTGOING_CALL_START_FILE));
|
||||||
|
|
||||||
|
store.dispatch(
|
||||||
|
registerSound(
|
||||||
|
OUTGOING_CALL_RINGING_SOUND_ID,
|
||||||
|
OUTGOING_CALL_RINGING_FILE,
|
||||||
|
{ loop: true }));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case APP_WILL_UNMOUNT:
|
||||||
|
store.dispatch(unregisterSound(OUTGOING_CALL_START_SOUND_ID));
|
||||||
|
store.dispatch(unregisterSound(OUTGOING_CALL_RINGING_SOUND_ID));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PARTICIPANT_LEFT:
|
||||||
|
case PARTICIPANT_UPDATED: {
|
||||||
|
const newParticipantPresence
|
||||||
|
= _getParticipantPresence(store.getState(), action.participant.id);
|
||||||
|
|
||||||
|
if (oldParticipantPresence === newParticipantPresence) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (oldParticipantPresence) {
|
||||||
|
case CALLING:
|
||||||
|
case INVITED:
|
||||||
|
store.dispatch(stopSound(OUTGOING_CALL_START_SOUND_ID));
|
||||||
|
break;
|
||||||
|
case RINGING:
|
||||||
|
store.dispatch(stopSound(OUTGOING_CALL_RINGING_SOUND_ID));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (newParticipantPresence) {
|
||||||
|
case CALLING:
|
||||||
|
case INVITED:
|
||||||
|
store.dispatch(playSound(OUTGOING_CALL_START_SOUND_ID));
|
||||||
|
break;
|
||||||
|
case RINGING:
|
||||||
|
store.dispatch(playSound(OUTGOING_CALL_RINGING_SOUND_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case UPDATE_DIAL_IN_NUMBERS_FAILED:
|
case UPDATE_DIAL_IN_NUMBERS_FAILED:
|
||||||
logger.error(
|
logger.error(
|
||||||
'Error encountered while fetching dial-in numbers:',
|
'Error encountered while fetching dial-in numbers:',
|
||||||
|
@ -27,3 +109,24 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the presence status of a participant associated with the passed id.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The redux state.
|
||||||
|
* @param {string} id - The id of the participant.
|
||||||
|
* @returns {string} - The presence status.
|
||||||
|
*/
|
||||||
|
function _getParticipantPresence(state, id) {
|
||||||
|
if (!id) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const participants = state['features/base/participants'];
|
||||||
|
const participantById = getParticipantById(participants, id);
|
||||||
|
|
||||||
|
if (!participantById) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return participantById.presence;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
/**
|
||||||
|
* The name of the sound file which will be played when the status of an
|
||||||
|
* outgoing call is ringing.
|
||||||
|
*/
|
||||||
|
export const OUTGOING_CALL_RINGING_FILE = 'outgoingRinging.wav';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the sound file which will be played when outgoing call is
|
||||||
|
* started.
|
||||||
|
*/
|
||||||
|
export const OUTGOING_CALL_START_FILE = 'outgoingStart.wav';
|
|
@ -2,8 +2,11 @@ import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import { translate } from '../../base/i18n';
|
||||||
import { getParticipantById } from '../../base/participants';
|
import { getParticipantById } from '../../base/participants';
|
||||||
|
|
||||||
|
import { STATUS_TO_I18N_KEY } from '../constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* React {@code Component} for displaying the current presence status of a
|
* React {@code Component} for displaying the current presence status of a
|
||||||
* participant.
|
* participant.
|
||||||
|
@ -35,7 +38,12 @@ class PresenceLabel extends Component {
|
||||||
/**
|
/**
|
||||||
* The ID of the participant whose presence status shoul display.
|
* The ID of the participant whose presence status shoul display.
|
||||||
*/
|
*/
|
||||||
participantID: PropTypes.string
|
participantID: PropTypes.string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked to obtain translated strings.
|
||||||
|
*/
|
||||||
|
t: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,10 +59,31 @@ class PresenceLabel extends Component {
|
||||||
<div
|
<div
|
||||||
className
|
className
|
||||||
= { `presence-label ${_presence ? '' : 'no-presence'}` }>
|
= { `presence-label ${_presence ? '' : 'no-presence'}` }>
|
||||||
{ _presence }
|
{ this._getPresenceText() }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the text associated with the current presence status.
|
||||||
|
*
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
_getPresenceText() {
|
||||||
|
const { _presence, t } = this.props;
|
||||||
|
|
||||||
|
if (!_presence) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const i18nKey = STATUS_TO_I18N_KEY[_presence];
|
||||||
|
|
||||||
|
if (!i18nKey) { // fallback to status value
|
||||||
|
return _presence;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t(i18nKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,4 +108,4 @@ function _mapStateToProps(state, ownProps) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(_mapStateToProps)(PresenceLabel);
|
export default translate(connect(_mapStateToProps)(PresenceLabel));
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
/**
|
||||||
|
* Тhe status for a participant when it's invited to a conference.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const INVITED = 'Invited';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тhe status for a participant when a call has been initiated.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const CALLING = 'Calling';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тhe status for a participant when the invite is received and its device(s)
|
||||||
|
* are ringing.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const RINGING = 'Ringing';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A status for a participant that indicates the call is connected.
|
||||||
|
* NOTE: Currently used for phone numbers only.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const CONNECTED = 'Connected';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A status for a participant that indicates the call is in process of
|
||||||
|
* connecting.
|
||||||
|
* NOTE: Currently used for phone numbers only.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const CONNECTING = 'Connecting';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The status for a participant when the invitation is received but the user
|
||||||
|
* has responded with busy message.
|
||||||
|
*/
|
||||||
|
export const BUSY = 'Busy';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The status for a participant when the invitation is rejected.
|
||||||
|
*/
|
||||||
|
export const REJECTED = 'Rejected';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The status for a participant when the invitation is ignored.
|
||||||
|
*/
|
||||||
|
export const IGNORED = 'Ignored';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps the presence status values to i18n translation keys.
|
||||||
|
*
|
||||||
|
* @type {Object<String, String>}
|
||||||
|
*/
|
||||||
|
export const STATUS_TO_I18N_KEY = {
|
||||||
|
'Invited': 'presenceStatus.invited',
|
||||||
|
'Ringing': 'presenceStatus.ringing',
|
||||||
|
'Calling': 'presenceStatus.calling',
|
||||||
|
'Connected': 'presenceStatus.connected',
|
||||||
|
'Connecting': 'presenceStatus.connecting',
|
||||||
|
'Busy': 'presenceStatus.busy',
|
||||||
|
'Rejected': 'presenceStatus.rejected',
|
||||||
|
'Ignored': 'presenceStatus.ignored'
|
||||||
|
};
|
|
@ -1 +1,2 @@
|
||||||
export * from './components';
|
export * from './components';
|
||||||
|
export * from './constants';
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue