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

View File

@ -12,7 +12,12 @@ type Props = {
/**
* 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}
*/
render() {
if (!this.props._requestingSubtitles
|| !this.props._transcriptMessages) {
return null;
}
const paragraphs = [];
for (const [ transcriptMessageID, transcriptMessage ]
@ -73,8 +83,14 @@ class TranscriptionSubtitles extends Component<Props> {
* }}
*/
function _mapStateToProps(state) {
const {
_transcriptMessages,
_requestingSubtitles
} = state['features/subtitles'];
return {
_transcriptMessages: state['features/subtitles'].transcriptMessages
_transcriptMessages,
_requestingSubtitles
};
}
export default connect(_mapStateToProps)(TranscriptionSubtitles);

View File

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

View File

@ -2,7 +2,10 @@
import { MiddlewareRegistry } from '../base/redux';
import { ENDPOINT_MESSAGE_RECEIVED } from './actionTypes';
import {
ENDPOINT_MESSAGE_RECEIVED,
TOGGLE_REQUESTING_SUBTITLES
} from './actionTypes';
import {
removeTranscriptMessage,
updateTranscriptMessage
@ -28,6 +31,12 @@ const JSON_TYPE_TRANSLATION_RESULT = 'translation-result';
*/
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.
*/
@ -41,15 +50,33 @@ const REMOVE_AFTER_MS = 3000;
* @returns {Function}
*/
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case ENDPOINT_MESSAGE_RECEIVED:
return _endpointMessageReceived(store, next, action);
case TOGGLE_REQUESTING_SUBTITLES:
_requestingSubtitlesToggled(store);
break;
}
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
* {@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
// exist in the map.
const newTranscriptMessage
= { ...getState()['features/subtitles'].transcriptMessages
= { ...getState()['features/subtitles']._transcriptMessages
.get(transcriptMessageID) || { participantName } };
setClearerOnTranscriptMessage(dispatch,
@ -120,6 +147,7 @@ function _endpointMessageReceived({ dispatch, getState }, next, action) {
if (!isInterim) {
newTranscriptMessage.final = text;
dispatch(updateTranscriptMessage(transcriptMessageID,
newTranscriptMessage));
} else if (stability > 0.85) {
@ -130,6 +158,7 @@ function _endpointMessageReceived({ dispatch, getState }, next, action) {
newTranscriptMessage.stable = text;
newTranscriptMessage.unstable = undefined;
dispatch(updateTranscriptMessage(transcriptMessageID,
newTranscriptMessage));
} else {

View File

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

View File

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

View File

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