Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(external_api) include transcription state in recordingStatusChanged #14859

Merged
merged 2 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions modules/API/API.js
Original file line number Diff line number Diff line change
Expand Up @@ -1917,14 +1917,16 @@ class API {
* @param {boolean} on - True if recording is on, false otherwise.
* @param {string} mode - Stream or file or local.
* @param {string} error - Error type or null if success.
* @param {boolean} transcription - True if a transcription is being recorded, false otherwise.
* @returns {void}
*/
notifyRecordingStatusChanged(on, mode, error) {
notifyRecordingStatusChanged(on, mode, error, transcription) {
this._sendEvent({
name: 'recording-status-changed',
on,
mode,
error
error,
transcription
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import React, { useCallback } from 'react';
import { TouchableOpacity } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';

import { IReduxState } from '../../../app/types';
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
import { openHighlightDialog } from '../../../recording/actions.native';
import HighlightButton from '../../../recording/components/Recording/native/HighlightButton';
import RecordingLabel from '../../../recording/components/native/RecordingLabel';
import { getActiveSession } from '../../../recording/functions';
import { isLiveStreamingRunning } from '../../../recording/functions';
import VisitorsCountLabel from '../../../visitors/components/native/VisitorsCountLabel';

import RaisedHandsCountLabel from './RaisedHandsCountLabel';
Expand All @@ -30,8 +29,7 @@ interface IProps {

const AlwaysOnLabels = ({ createOnPress }: IProps) => {
const dispatch = useDispatch();
const isStreaming = useSelector((state: IReduxState) =>
Boolean(getActiveSession(state, JitsiRecordingConstants.mode.STREAM)));
const isStreaming = useSelector(isLiveStreamingRunning);
const openHighlightDialogCallback = useCallback(() =>
dispatch(openHighlightDialog()), [ dispatch ]);

Expand Down
6 changes: 3 additions & 3 deletions react/features/recording/components/AbstractRecordingLabel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { IReduxState } from '../../app/types';
import { JitsiRecordingConstants } from '../../base/lib-jitsi-meet';
import { isRecorderTranscriptionsRunning } from '../../transcribing/functions';
import {
getActiveSession,
getSessionStatusToShow,
isLiveStreamingRunning,
isRecordingRunning,
isRemoteParticipantRecordingLocally
} from '../functions';
Expand Down Expand Up @@ -81,9 +81,9 @@ export function _mapStateToProps(state: IReduxState, ownProps: any) {
const { mode } = ownProps;
const isLiveStreamingLabel = mode === JitsiRecordingConstants.mode.STREAM;
const _isTranscribing = isRecorderTranscriptionsRunning(state);
const isLivestreamingRunning = Boolean(getActiveSession(state, JitsiRecordingConstants.mode.STREAM));
const _isLivestreamingRunning = isLiveStreamingRunning(state);
const _isVisible = isLiveStreamingLabel
? isLivestreamingRunning // this is the livestreaming label
? _isLivestreamingRunning // this is the livestreaming label
: isRecordingRunning(state) || isRemoteParticipantRecordingLocally(state)
|| _isTranscribing; // this is the recording label

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ import { IReduxState } from '../../../app/types';
import { IconSites } from '../../../base/icons/svg';
import { MEET_FEATURES } from '../../../base/jwt/constants';
import { isJwtFeatureEnabled } from '../../../base/jwt/functions';
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
import { isLocalParticipantModerator } from '../../../base/participants/functions';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
import { maybeShowPremiumFeatureDialog } from '../../../jaas/actions';
import { isRecorderTranscriptionsRunning } from '../../../transcribing/functions';
import { getActiveSession, isCloudRecordingRunning, isLiveStreamingButtonVisible } from '../../functions';
import { isCloudRecordingRunning, isLiveStreamingButtonVisible, isLiveStreamingRunning } from '../../functions';

import { getLiveStreaming } from './functions';

Expand Down Expand Up @@ -154,7 +153,7 @@ export function _mapStateToProps(state: IReduxState, ownProps: IProps) {

return {
_disabled,
_isLiveStreamRunning: Boolean(getActiveSession(state, JitsiRecordingConstants.mode.STREAM)),
_isLiveStreamRunning: isLiveStreamingRunning(state),
_tooltip,
visible
};
Expand Down
12 changes: 11 additions & 1 deletion react/features/recording/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,16 @@ export function isCloudRecordingRunning(state: IReduxState) {
return Boolean(getActiveSession(state, JitsiRecordingConstants.mode.FILE));
}

/**
* Returns true if there is a live streaming running.
*
* @param {IReduxState} state - The redux state to search in.
* @returns {boolean}
*/
export function isLiveStreamingRunning(state: IReduxState) {
return Boolean(getActiveSession(state, JitsiRecordingConstants.mode.STREAM));
}

/**
* Returns true if there is a recording session running.
*
Expand Down Expand Up @@ -262,7 +272,7 @@ export function getRecordButtonProps(state: IReduxState) {
}

// disable the button if the livestreaming is running.
if (visible && getActiveSession(state, JitsiRecordingConstants.mode.STREAM)) {
if (visible && isLiveStreamingRunning(state)) {
disabled = true;
tooltip = 'dialog.recordingDisabledBecauseOfActiveLiveStreamingTooltip';
}
Expand Down
28 changes: 17 additions & 11 deletions react/features/recording/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => async action =>
(recorderSession: any) => {
if (recorderSession) {
recorderSession.getID() && dispatch(updateRecordingSessionData(recorderSession));
recorderSession.getError() && _showRecordingErrorNotification(recorderSession, dispatch);
recorderSession.getError() && _showRecordingErrorNotification(recorderSession, dispatch, getState);
}

return;
Expand Down Expand Up @@ -133,7 +133,8 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => async action =>
dispatch(updateLocalRecordingStatus(true, onlySelf));
sendAnalytics(createRecordingEvent('started', `local${onlySelf ? '.self' : ''}`));
if (typeof APP !== 'undefined') {
APP.API.notifyRecordingStatusChanged(true, 'local');
APP.API.notifyRecordingStatusChanged(
true, 'local', undefined, isRecorderTranscriptionsRunning(getState()));
}
} catch (err: any) {
logger.error('Capture failed', err);
Expand All @@ -154,7 +155,8 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => async action =>
};

if (typeof APP !== 'undefined') {
APP.API.notifyRecordingStatusChanged(false, 'local', err.message);
APP.API.notifyRecordingStatusChanged(
false, 'local', err.message, isRecorderTranscriptionsRunning(getState()));
}

dispatch(showErrorNotification(props, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
Expand All @@ -172,7 +174,8 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => async action =>
dispatch(playSound(RECORDING_OFF_SOUND_ID));
}
if (typeof APP !== 'undefined') {
APP.API.notifyRecordingStatusChanged(false, 'local');
APP.API.notifyRecordingStatusChanged(
false, 'local', undefined, isRecorderTranscriptionsRunning(getState()));
}
}
break;
Expand Down Expand Up @@ -237,7 +240,8 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => async action =>
}

if (typeof APP !== 'undefined') {
APP.API.notifyRecordingStatusChanged(true, mode);
APP.API.notifyRecordingStatusChanged(
true, mode, undefined, isRecorderTranscriptionsRunning(state));
}
}
} else if (updatedSessionData?.status === OFF && oldSessionData?.status !== OFF) {
Expand Down Expand Up @@ -269,7 +273,8 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => async action =>
}

if (typeof APP !== 'undefined') {
APP.API.notifyRecordingStatusChanged(false, mode);
APP.API.notifyRecordingStatusChanged(
false, mode, undefined, isRecorderTranscriptionsRunning(state));
}
}
}
Expand Down Expand Up @@ -312,14 +317,15 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => async action =>
* in recording session.
*
* @private
* @param {Object} recorderSession - The recorder session model from the
* @param {Object} session - The recorder session model from the
* lib.
* @param {Dispatch} dispatch - The Redux Dispatch function.
* @param {Function} getState - The Redux getState function.
* @returns {void}
*/
function _showRecordingErrorNotification(recorderSession: any, dispatch: IStore['dispatch']) {
const mode = recorderSession.getMode();
const error = recorderSession.getError();
function _showRecordingErrorNotification(session: any, dispatch: IStore['dispatch'], getState: IStore['getState']) {
const mode = session.getMode();
const error = session.getError();
const isStreamMode = mode === JitsiMeetJS.constants.recording.mode.STREAM;

switch (error) {
Expand Down Expand Up @@ -367,6 +373,6 @@ function _showRecordingErrorNotification(recorderSession: any, dispatch: IStore[
}

if (typeof APP !== 'undefined') {
APP.API.notifyRecordingStatusChanged(false, mode, error);
APP.API.notifyRecordingStatusChanged(false, mode, error, isRecorderTranscriptionsRunning(getState()));
}
}
14 changes: 11 additions & 3 deletions react/features/transcribing/subscriber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { playSound } from '../base/sounds/actions';
import { showNotification } from '../notifications/actions';
import { NOTIFICATION_TIMEOUT_TYPE } from '../notifications/constants';
import { RECORDING_OFF_SOUND_ID, RECORDING_ON_SOUND_ID } from '../recording/constants';
import { isLiveStreamingRunning, isRecordingRunning } from '../recording/functions';

import { isRecorderTranscriptionsRunning } from './functions';

Expand All @@ -17,10 +18,10 @@ StateListenerRegistry.register(
/* selector */ isRecorderTranscriptionsRunning,
/* listener */ (isRecorderTranscriptionsRunningValue, { getState, dispatch }) => {
if (isRecorderTranscriptionsRunningValue) {
notifyTranscribingStatusChanged(true);
notifyTranscribingStatusChanged(getState, true);
maybeEmitRecordingNotification(dispatch, getState, true);
} else {
notifyTranscribingStatusChanged(false);
notifyTranscribingStatusChanged(getState, false);
maybeEmitRecordingNotification(dispatch, getState, false);
}
}
Expand Down Expand Up @@ -58,11 +59,18 @@ function maybeEmitRecordingNotification(dispatch: IStore['dispatch'], getState:
/**
* Notify external application (if API is enabled) that transcribing has started or stopped.
*
* @param {Function} getState - The Redux state.
* @param {boolean} on - True if transcribing is on, false otherwise.
* @returns {void}
*/
function notifyTranscribingStatusChanged(on: boolean) {
function notifyTranscribingStatusChanged(getState: IStore['getState'], on: boolean) {
if (typeof APP !== 'undefined') {
const state = getState();
const isRecording = isRecordingRunning(state);
const isStreaming = isLiveStreamingRunning(state);
const mode = isRecording ? JitsiRecordingConstants.mode.FILE : JitsiRecordingConstants.mode.STREAM;

APP.API.notifyRecordingStatusChanged(isRecording || isStreaming, mode, undefined, on);
APP.API.notifyTranscribingStatusChanged(on);
}
}