Merge pull request #3396 from nikvaessen/pr_independend_subtitles_cherry
independently display subtitles based on participants choice
This commit is contained in:
commit
b8179102c5
|
@ -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');
|
||||||
|
|
|
@ -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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
export { default as TranscriptionSubtitles } from './TranscriptionSubtitles';
|
export { default as TranscriptionSubtitles } from './TranscriptionSubtitles';
|
||||||
|
export { default as ClosedCaptionButton } from './ClosedCaptionButton';
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
export { default as TranscribingLabel } from './TranscribingLabel';
|
export { default as TranscribingLabel } from './TranscribingLabel';
|
||||||
export { default as ClosedCaptionButton } from './ClosedCaptionButton';
|
|
||||||
|
|
Loading…
Reference in New Issue