Merge pull request #3396 from nikvaessen/pr_independend_subtitles_cherry

independently display subtitles based on participants choice
This commit is contained in:
bgrozev 2018-08-24 12:38:11 -05:00 committed by GitHub
commit b8179102c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 102 additions and 45 deletions

View File

@ -33,3 +33,15 @@ export const REMOVE_TRANSCRIPT_MESSAGE = Symbol('REMOVE_TRANSCRIPT_MESSAGE');
* } * }
*/ */
export const UPDATE_TRANSCRIPT_MESSAGE = Symbol('UPDATE_TRANSCRIPT_MESSAGE'); export const UPDATE_TRANSCRIPT_MESSAGE = Symbol('UPDATE_TRANSCRIPT_MESSAGE');
/**
* The type of (redux) action which indicates that the user pressed the
* ClosedCaption button, to either enable or disable subtitles based on the
* current state.
*
* {
* type: TOGGLE_REQUESTING_SUBTITLES
* }
*/
export const TOGGLE_REQUESTING_SUBTITLES
= Symbol('TOGGLE_REQUESTING_SUBTITLES');

View File

@ -3,6 +3,7 @@
import { import {
ENDPOINT_MESSAGE_RECEIVED, ENDPOINT_MESSAGE_RECEIVED,
REMOVE_TRANSCRIPT_MESSAGE, REMOVE_TRANSCRIPT_MESSAGE,
TOGGLE_REQUESTING_SUBTITLES,
UPDATE_TRANSCRIPT_MESSAGE UPDATE_TRANSCRIPT_MESSAGE
} from './actionTypes'; } from './actionTypes';
@ -61,3 +62,16 @@ export function updateTranscriptMessage(transcriptMessageID: string,
newTranscriptMessage newTranscriptMessage
}; };
} }
/**
* Signals that the local user has toggled the ClosedCaption button.
*
* @returns {{
* type: TOGGLE_REQUESTING_SUBTITLES
* }}
*/
export function toggleRequestingSubtitles() {
return {
type: TOGGLE_REQUESTING_SUBTITLES
};
}

View File

@ -6,7 +6,7 @@ import { translate } from '../../base/i18n/index';
import { ToolbarButton } from '../../toolbox/'; import { ToolbarButton } from '../../toolbox/';
import { dialTranscriber, stopTranscribing } from '../actions'; import { toggleRequestingSubtitles } from '../actions';
import { createToolbarEvent, sendAnalytics } from '../../analytics'; import { createToolbarEvent, sendAnalytics } from '../../analytics';
@ -26,14 +26,9 @@ type Props = {
dispatch: Function, dispatch: Function,
/** /**
* Boolean value indicating current transcribing status * Whether the local participant is currently requesting subtitles.
*/ */
_transcribing: boolean, _requestingSubtitles: Boolean
/**
* Boolean value indicating current dialing status
*/
_dialing: boolean
}; };
/** /**
@ -64,8 +59,8 @@ class ClosedCaptionButton extends Component<Props> {
* @returns {ReactElement} * @returns {ReactElement}
*/ */
render() { render() {
const { _dialing, _transcribing, t } = this.props; const { _requestingSubtitles, t } = this.props;
const iconClass = `icon-closed_caption ${_dialing || _transcribing const iconClass = `icon-closed_caption ${_requestingSubtitles
? 'toggled' : ''}`; ? 'toggled' : ''}`;
return ( return (
@ -88,24 +83,14 @@ class ClosedCaptionButton extends Component<Props> {
* @returns {void} * @returns {void}
*/ */
_onToggleButton() { _onToggleButton() {
const { _transcribing, _dialing, dispatch } = this.props; const { _requestingSubtitles, dispatch } = this.props;
sendAnalytics(createToolbarEvent( sendAnalytics(createToolbarEvent('transcribing.ccButton',
'transcribing.ccButton',
{ {
'is_transcribing': Boolean(_transcribing), 'requesting_subtitles': Boolean(_requestingSubtitles)
'is_dialing': Boolean(_dialing)
})); }));
if (_dialing) { dispatch(toggleRequestingSubtitles());
return;
}
if (_transcribing) {
dispatch(stopTranscribing());
} else {
dispatch(dialTranscriber());
}
} }
} }
@ -120,11 +105,10 @@ class ClosedCaptionButton extends Component<Props> {
* }} * }}
*/ */
function _mapStateToProps(state) { function _mapStateToProps(state) {
const { isTranscribing, isDialing } = state['features/transcribing']; const { _requestingSubtitles } = state['features/subtitles'];
return { return {
_transcribing: isTranscribing, _requestingSubtitles
_dialing: isDialing
}; };
} }

View File

@ -12,7 +12,12 @@ type Props = {
/** /**
* Map of transcriptMessageID's with corresponding transcriptMessage. * Map of transcriptMessageID's with corresponding transcriptMessage.
*/ */
_transcriptMessages: Map<string, Object> _transcriptMessages: Map<string, Object>,
/**
* Whether local participant is requesting to see subtitles
*/
_requestingSubtitles: Boolean
}; };
/** /**
@ -28,6 +33,11 @@ class TranscriptionSubtitles extends Component<Props> {
* @returns {ReactElement} * @returns {ReactElement}
*/ */
render() { render() {
if (!this.props._requestingSubtitles
|| !this.props._transcriptMessages) {
return null;
}
const paragraphs = []; const paragraphs = [];
for (const [ transcriptMessageID, transcriptMessage ] for (const [ transcriptMessageID, transcriptMessage ]
@ -73,8 +83,14 @@ class TranscriptionSubtitles extends Component<Props> {
* }} * }}
*/ */
function _mapStateToProps(state) { function _mapStateToProps(state) {
const {
_transcriptMessages,
_requestingSubtitles
} = state['features/subtitles'];
return { return {
_transcriptMessages: state['features/subtitles'].transcriptMessages _transcriptMessages,
_requestingSubtitles
}; };
} }
export default connect(_mapStateToProps)(TranscriptionSubtitles); export default connect(_mapStateToProps)(TranscriptionSubtitles);

View File

@ -1 +1,2 @@
export { default as TranscriptionSubtitles } from './TranscriptionSubtitles'; export { default as TranscriptionSubtitles } from './TranscriptionSubtitles';
export { default as ClosedCaptionButton } from './ClosedCaptionButton';

View File

@ -2,7 +2,10 @@
import { MiddlewareRegistry } from '../base/redux'; import { MiddlewareRegistry } from '../base/redux';
import { ENDPOINT_MESSAGE_RECEIVED } from './actionTypes'; import {
ENDPOINT_MESSAGE_RECEIVED,
TOGGLE_REQUESTING_SUBTITLES
} from './actionTypes';
import { import {
removeTranscriptMessage, removeTranscriptMessage,
updateTranscriptMessage updateTranscriptMessage
@ -28,6 +31,12 @@ const JSON_TYPE_TRANSLATION_RESULT = 'translation-result';
*/ */
const P_NAME_TRANSLATION_LANGUAGE = 'translation_language'; const P_NAME_TRANSLATION_LANGUAGE = 'translation_language';
/**
* The local participant property which is used to set whether the local
* participant wants to have a transcriber in the room.
*/
const P_NAME_REQUESTING_TRANSCRIPTION = 'requestingTranscription';
/** /**
* Time after which the rendered subtitles will be removed. * Time after which the rendered subtitles will be removed.
*/ */
@ -41,15 +50,33 @@ const REMOVE_AFTER_MS = 3000;
* @returns {Function} * @returns {Function}
*/ */
MiddlewareRegistry.register(store => next => action => { MiddlewareRegistry.register(store => next => action => {
switch (action.type) { switch (action.type) {
case ENDPOINT_MESSAGE_RECEIVED: case ENDPOINT_MESSAGE_RECEIVED:
return _endpointMessageReceived(store, next, action); return _endpointMessageReceived(store, next, action);
case TOGGLE_REQUESTING_SUBTITLES:
_requestingSubtitlesToggled(store);
break;
} }
return next(action); return next(action);
}); });
/**
* Toggle the local property 'requestingTranscription'. This will cause Jicofo
* and Jigasi to decide whether the transcriber needs to be in the room.
*
* @param {Store} store - The redux store.
* @private
* @returns {void}
*/
function _requestingSubtitlesToggled({ getState }) {
const { _requestingSubtitles } = getState()['features/subtitles'];
const { conference } = getState()['features/base/conference'];
conference.setLocalParticipantProperty(P_NAME_REQUESTING_TRANSCRIPTION,
!_requestingSubtitles);
}
/** /**
* Notifies the feature transcription that the action * Notifies the feature transcription that the action
* {@code ENDPOINT_MESSAGE_RECEIVED} is being dispatched within a specific redux * {@code ENDPOINT_MESSAGE_RECEIVED} is being dispatched within a specific redux
@ -109,7 +136,7 @@ function _endpointMessageReceived({ dispatch, getState }, next, action) {
// message ID or adds a new transcript message if it does not // message ID or adds a new transcript message if it does not
// exist in the map. // exist in the map.
const newTranscriptMessage const newTranscriptMessage
= { ...getState()['features/subtitles'].transcriptMessages = { ...getState()['features/subtitles']._transcriptMessages
.get(transcriptMessageID) || { participantName } }; .get(transcriptMessageID) || { participantName } };
setClearerOnTranscriptMessage(dispatch, setClearerOnTranscriptMessage(dispatch,
@ -120,6 +147,7 @@ function _endpointMessageReceived({ dispatch, getState }, next, action) {
if (!isInterim) { if (!isInterim) {
newTranscriptMessage.final = text; newTranscriptMessage.final = text;
dispatch(updateTranscriptMessage(transcriptMessageID, dispatch(updateTranscriptMessage(transcriptMessageID,
newTranscriptMessage)); newTranscriptMessage));
} else if (stability > 0.85) { } else if (stability > 0.85) {
@ -130,6 +158,7 @@ function _endpointMessageReceived({ dispatch, getState }, next, action) {
newTranscriptMessage.stable = text; newTranscriptMessage.stable = text;
newTranscriptMessage.unstable = undefined; newTranscriptMessage.unstable = undefined;
dispatch(updateTranscriptMessage(transcriptMessageID, dispatch(updateTranscriptMessage(transcriptMessageID,
newTranscriptMessage)); newTranscriptMessage));
} else { } else {

View File

@ -1,7 +1,7 @@
import { ReducerRegistry } from '../base/redux'; import { ReducerRegistry } from '../base/redux';
import { import {
REMOVE_TRANSCRIPT_MESSAGE, REMOVE_TRANSCRIPT_MESSAGE, TOGGLE_REQUESTING_SUBTITLES,
UPDATE_TRANSCRIPT_MESSAGE UPDATE_TRANSCRIPT_MESSAGE
} from './actionTypes'; } from './actionTypes';
@ -9,7 +9,8 @@ import {
* Default State for 'features/transcription' feature * Default State for 'features/transcription' feature
*/ */
const defaultState = { const defaultState = {
transcriptMessages: new Map() _transcriptMessages: new Map(),
_requestingSubtitles: false
}; };
/** /**
@ -21,9 +22,14 @@ ReducerRegistry.register('features/subtitles', (
switch (action.type) { switch (action.type) {
case REMOVE_TRANSCRIPT_MESSAGE: case REMOVE_TRANSCRIPT_MESSAGE:
return _removeTranscriptMessage(state, action); return _removeTranscriptMessage(state, action);
case UPDATE_TRANSCRIPT_MESSAGE: case UPDATE_TRANSCRIPT_MESSAGE:
return _updateTranscriptMessage(state, action); return _updateTranscriptMessage(state, action);
case TOGGLE_REQUESTING_SUBTITLES:
return {
...state,
_requestingSubtitles: !state._requestingSubtitles
};
} }
return state; return state;
@ -46,7 +52,7 @@ function _removeTranscriptMessage(state, { transcriptMessageID }) {
return { return {
...state, ...state,
transcriptMessages: newTranscriptMessages _transcriptMessages: newTranscriptMessages
}; };
} }
@ -68,6 +74,6 @@ function _updateTranscriptMessage(state,
return { return {
...state, ...state,
transcriptMessages: newTranscriptMessages _transcriptMessages: newTranscriptMessages
}; };
} }

View File

@ -14,8 +14,7 @@ import { translate } from '../../../base/i18n';
import { import {
getLocalParticipant, getLocalParticipant,
getParticipants, getParticipants,
participantUpdated, participantUpdated
isLocalParticipantModerator
} from '../../../base/participants'; } from '../../../base/participants';
import { getLocalVideoTrack, toggleScreensharing } from '../../../base/tracks'; import { getLocalVideoTrack, toggleScreensharing } from '../../../base/tracks';
import { ChatCounter } from '../../../chat'; import { ChatCounter } from '../../../chat';
@ -64,7 +63,7 @@ import ToolbarButton from './ToolbarButton';
import VideoMuteButton from '../VideoMuteButton'; import VideoMuteButton from '../VideoMuteButton';
import { import {
ClosedCaptionButton ClosedCaptionButton
} from '../../../transcribing'; } from '../../../subtitles';
/** /**
* The type of the React {@code Component} props of {@link Toolbox}. * The type of the React {@code Component} props of {@link Toolbox}.
@ -1040,7 +1039,7 @@ function _mapStateToProps(state) {
callStatsID, callStatsID,
iAmRecorder iAmRecorder
} = state['features/base/config']; } = state['features/base/config'];
let { const {
transcribingEnabled transcribingEnabled
} = state['features/base/config']; } = state['features/base/config'];
const sharedVideoStatus = state['features/shared-video'].status; const sharedVideoStatus = state['features/shared-video'].status;
@ -1060,9 +1059,6 @@ function _mapStateToProps(state) {
let desktopSharingDisabledTooltipKey; let desktopSharingDisabledTooltipKey;
transcribingEnabled
= isLocalParticipantModerator(state) && transcribingEnabled;
if (state['features/base/config'].enableFeaturesBasedOnToken) { if (state['features/base/config'].enableFeaturesBasedOnToken) {
// we enable desktop sharing if any participant already have this // we enable desktop sharing if any participant already have this
// feature enabled // feature enabled

View File

@ -1,2 +1 @@
export { default as TranscribingLabel } from './TranscribingLabel'; export { default as TranscribingLabel } from './TranscribingLabel';
export { default as ClosedCaptionButton } from './ClosedCaptionButton';