From cddaf46840d24afef9a9423f4c14773ecb6e619e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Thu, 11 Jan 2024 16:15:34 +0100 Subject: [PATCH 1/6] fix(transcribing) remove unused state properties --- react/features/transcribing/reducer.ts | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/react/features/transcribing/reducer.ts b/react/features/transcribing/reducer.ts index e619c9946454..323f5ba0dbcd 100644 --- a/react/features/transcribing/reducer.ts +++ b/react/features/transcribing/reducer.ts @@ -12,7 +12,6 @@ import { * * @returns {{ * isTranscribing: boolean, - * isDialing: boolean, * transcriberJID: null, * potentialTranscriberJIDs: Array * }} @@ -28,20 +27,6 @@ function _getInitialState() { */ isTranscribing: false, - /** - * Indicates whether the transcriber has been dialed into the room and - * we're currently awaiting successful joining or failure of joining. - * - * @type {boolean} - */ - isDialing: false, - - /** - * Indicates whether the transcribing feature is in the process of - * terminating; the transcriber has been told to leave. - */ - isTerminating: false, - /** * The JID of the active transcriber. * @@ -59,8 +44,6 @@ function _getInitialState() { } export interface ITranscribingState { - isDialing: boolean; - isTerminating: boolean; isTranscribing: boolean; pendingNotificationUid?: string; potentialTranscriberJIDs: string[]; @@ -77,13 +60,11 @@ ReducerRegistry.register('features/transcribing', return { ...state, isTranscribing: true, - isDialing: false, transcriberJID: action.transcriberJID }; case _TRANSCRIBER_LEFT: return { ...state, - isTerminating: false, isTranscribing: false, transcriberJID: undefined, potentialTranscriberJIDs: [] From 7d93089feac8c9fbec96a15f20c9fe20bba58fd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Thu, 11 Jan 2024 17:05:10 +0100 Subject: [PATCH 2/6] fix(transcribing) simplified code --- react/features/transcribing/reducer.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/react/features/transcribing/reducer.ts b/react/features/transcribing/reducer.ts index 323f5ba0dbcd..481f842849a9 100644 --- a/react/features/transcribing/reducer.ts +++ b/react/features/transcribing/reducer.ts @@ -72,9 +72,7 @@ ReducerRegistry.register('features/transcribing', case _POTENTIAL_TRANSCRIBER_JOINED: return { ...state, - potentialTranscriberJIDs: - [ action.transcriberJID ] - .concat(state.potentialTranscriberJIDs) + potentialTranscriberJIDs: [ action.transcriberJID, ...state.potentialTranscriberJIDs ] }; case SET_PENDING_TRANSCRIBING_NOTIFICATION_UID: return { From b498d93c4f419d6260de560aee783a8ee72c174d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Thu, 11 Jan 2024 17:08:20 +0100 Subject: [PATCH 3/6] fix(transcribing) show pending notification while transcriber joins --- react/features/transcribing/middleware.ts | 52 ++++++++++++++--------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/react/features/transcribing/middleware.ts b/react/features/transcribing/middleware.ts index 0122afa20123..61dfb04058be 100644 --- a/react/features/transcribing/middleware.ts +++ b/react/features/transcribing/middleware.ts @@ -6,6 +6,7 @@ import { PARTICIPANT_UPDATED } from '../base/participants/actionTypes'; import MiddlewareRegistry from '../base/redux/MiddlewareRegistry'; +import { SET_REQUESTING_SUBTITLES } from '../subtitles/actionTypes'; import { toggleRequestingSubtitles } from '../subtitles/actions.any'; import { @@ -15,6 +16,7 @@ import { import { hidePendingTranscribingNotification, potentialTranscriberJoined, + showPendingTranscribingNotification, showStoppedTranscribingNotification, transcriberJoined, transcriberLeft @@ -29,61 +31,69 @@ const TRANSCRIBER_DISPLAY_NAME = 'Transcriber'; * @returns {Function} */ // eslint-disable-next-line no-unused-vars -MiddlewareRegistry.register(store => next => action => { +MiddlewareRegistry.register(({ dispatch, getState }) => next => action => { const { + isTranscribing, transcriberJID, potentialTranscriberJIDs - } = store.getState()['features/transcribing']; + } = getState()['features/transcribing']; switch (action.type) { + case _TRANSCRIBER_JOINED: { + const state = getState(); + const { transcription } = state['features/base/config']; + const { _requestingSubtitles } = state['features/subtitles']; + + if (!_requestingSubtitles && !transcription?.disableStartForAll) { + dispatch(toggleRequestingSubtitles()); + } + break; + } case _TRANSCRIBER_LEFT: { - store.dispatch(showStoppedTranscribingNotification()); - const state = store.getState(); + dispatch(showStoppedTranscribingNotification()); + + const state = getState(); const { transcription } = state['features/base/config']; const { _requestingSubtitles } = state['features/subtitles']; if (_requestingSubtitles && !transcription?.disableStartForAll) { - store.dispatch(toggleRequestingSubtitles()); + dispatch(toggleRequestingSubtitles()); } break; } case HIDDEN_PARTICIPANT_JOINED: - if (action.displayName - && action.displayName === TRANSCRIBER_DISPLAY_NAME) { - store.dispatch(transcriberJoined(action.id)); + if (action.displayName === TRANSCRIBER_DISPLAY_NAME) { + dispatch(transcriberJoined(action.id)); } else { - store.dispatch(potentialTranscriberJoined(action.id)); + dispatch(potentialTranscriberJoined(action.id)); } break; case HIDDEN_PARTICIPANT_LEFT: if (action.id === transcriberJID) { - store.dispatch(transcriberLeft(action.id)); + dispatch(transcriberLeft(action.id)); } break; case PARTICIPANT_UPDATED: { const { participant } = action; - if (potentialTranscriberJIDs.includes(participant.id) - && participant.name === TRANSCRIBER_DISPLAY_NAME) { + if (potentialTranscriberJIDs.includes(participant.id) && participant.name === TRANSCRIBER_DISPLAY_NAME) { batch(() => { - store.dispatch(transcriberJoined(participant.id)); - store.dispatch(hidePendingTranscribingNotification()); + dispatch(transcriberJoined(participant.id)); + dispatch(hidePendingTranscribingNotification()); }); } break; } - case _TRANSCRIBER_JOINED: { - const state = store.getState(); - const { transcription } = state['features/base/config']; - const { _requestingSubtitles } = state['features/subtitles']; - if (!_requestingSubtitles && !transcription?.disableStartForAll) { - store.dispatch(toggleRequestingSubtitles()); + case SET_REQUESTING_SUBTITLES: + if (action.enabled && !isTranscribing) { + dispatch(showPendingTranscribingNotification()); } + break; - } + } return next(action); From f099c3de809d37f68611578ed49aa046acb2ff8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Thu, 11 Jan 2024 17:15:04 +0100 Subject: [PATCH 4/6] fix(transcribing) refactor notification handling The current notification system allows us to replce notifications easily as long as we use a consistent UID. --- react/features/notifications/constants.ts | 7 +++ react/features/transcribing/actionTypes.ts | 14 ----- react/features/transcribing/actions.ts | 67 +++++----------------- react/features/transcribing/middleware.ts | 8 +-- react/features/transcribing/reducer.ts | 7 --- 5 files changed, 23 insertions(+), 80 deletions(-) diff --git a/react/features/notifications/constants.ts b/react/features/notifications/constants.ts index 0d7a838fcf0c..996a601c2381 100644 --- a/react/features/notifications/constants.ts +++ b/react/features/notifications/constants.ts @@ -112,3 +112,10 @@ export const SILENT_JOIN_THRESHOLD = 30; * Amount of participants beyond which no left notification will be emitted. */ export const SILENT_LEFT_THRESHOLD = 30; + +/** + * The identifier for the transcriber notifications. + * + * @type {string} + */ +export const TRANSCRIBING_NOTIFICATION_ID = 'TRANSCRIBING_NOTIFICATION'; diff --git a/react/features/transcribing/actionTypes.ts b/react/features/transcribing/actionTypes.ts index df2346f441a5..f777d233670d 100644 --- a/react/features/transcribing/actionTypes.ts +++ b/react/features/transcribing/actionTypes.ts @@ -32,17 +32,3 @@ export const _TRANSCRIBER_LEFT = 'TRANSCRIBER_LEFT'; */ export const _POTENTIAL_TRANSCRIBER_JOINED = 'POTENTIAL_TRANSCRIBER_JOINED'; - -/** - * The type of Redux action which sets the pending transcribing notification UID - * to use it for when hiding the notification is necessary, or unsets it when - * undefined (or no param) is passed. - * - * { - * type: SET_PENDING_TRANSCRIBING_NOTIFICATION_UID, - * uid: ?number - * } - * @public - */ -export const SET_PENDING_TRANSCRIBING_NOTIFICATION_UID - = 'SET_PENDING_TRANSCRIBING_NOTIFICATION_UID'; diff --git a/react/features/transcribing/actions.ts b/react/features/transcribing/actions.ts index db4e8828e6a3..965157ca85d9 100644 --- a/react/features/transcribing/actions.ts +++ b/react/features/transcribing/actions.ts @@ -1,9 +1,10 @@ -import { IStore } from '../app/types'; -import { hideNotification, showErrorNotification, showNotification } from '../notifications/actions'; -import { NOTIFICATION_TIMEOUT_TYPE } from '../notifications/constants'; +import { showErrorNotification, showNotification } from '../notifications/actions'; +import { + NOTIFICATION_TIMEOUT_TYPE, + TRANSCRIBING_NOTIFICATION_ID +} from '../notifications/constants'; import { - SET_PENDING_TRANSCRIBING_NOTIFICATION_UID, _POTENTIAL_TRANSCRIBER_JOINED, _TRANSCRIBER_JOINED, _TRANSCRIBER_LEFT @@ -61,54 +62,14 @@ export function potentialTranscriberJoined(participantId: string) { * Signals that the pending transcribing notification should be shown on the * screen. * - * @returns {Function} + * @returns {showNotification} */ export function showPendingTranscribingNotification() { - return async (dispatch: IStore['dispatch']) => { - const notification = await dispatch(showNotification({ - descriptionKey: 'transcribing.pending', - titleKey: 'dialog.transcribing' - }, NOTIFICATION_TIMEOUT_TYPE.LONG)); - - if (notification) { - dispatch(setPendingTranscribingNotificationUid(notification.uid)); - } - }; -} - -/** - * Sets UID of the the pending transcribing notification to use it when hiding - * the notification is necessary, or unsets it when undefined (or no param) is - * passed. - * - * @param {?number} uid - The UID of the notification. - * @returns {{ - * type: SET_PENDING_TRANSCRIBING_NOTIFICATION_UID, - * uid: number - * }} - */ -export function setPendingTranscribingNotificationUid(uid?: string) { - return { - type: SET_PENDING_TRANSCRIBING_NOTIFICATION_UID, - uid - }; -} - -/** - * Signals that the pending transcribing notification should be removed from the - * screen. - * - * @returns {Function} - */ -export function hidePendingTranscribingNotification() { - return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { - const { pendingNotificationUid } = getState()['features/transcribing']; - - if (pendingNotificationUid) { - dispatch(hideNotification(pendingNotificationUid)); - dispatch(setPendingTranscribingNotificationUid()); - } - }; + return showNotification({ + descriptionKey: 'transcribing.pending', + titleKey: 'dialog.transcribing', + uid: TRANSCRIBING_NOTIFICATION_ID + }, NOTIFICATION_TIMEOUT_TYPE.LONG); } /** @@ -120,7 +81,8 @@ export function hidePendingTranscribingNotification() { export function showStoppedTranscribingNotification() { return showNotification({ descriptionKey: 'transcribing.off', - titleKey: 'dialog.transcribing' + titleKey: 'dialog.transcribing', + uid: TRANSCRIBING_NOTIFICATION_ID }, NOTIFICATION_TIMEOUT_TYPE.SHORT); } @@ -133,6 +95,7 @@ export function showStoppedTranscribingNotification() { export function showTranscribingError() { return showErrorNotification({ descriptionKey: 'transcribing.error', - titleKey: 'transcribing.failedToStart' + titleKey: 'transcribing.failedToStart', + uid: TRANSCRIBING_NOTIFICATION_ID }, NOTIFICATION_TIMEOUT_TYPE.LONG); } diff --git a/react/features/transcribing/middleware.ts b/react/features/transcribing/middleware.ts index 61dfb04058be..e57ddfed5ed3 100644 --- a/react/features/transcribing/middleware.ts +++ b/react/features/transcribing/middleware.ts @@ -1,5 +1,3 @@ -import { batch } from 'react-redux'; - import { HIDDEN_PARTICIPANT_JOINED, HIDDEN_PARTICIPANT_LEFT, @@ -14,7 +12,6 @@ import { _TRANSCRIBER_LEFT } from './actionTypes'; import { - hidePendingTranscribingNotification, potentialTranscriberJoined, showPendingTranscribingNotification, showStoppedTranscribingNotification, @@ -78,10 +75,7 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => { const { participant } = action; if (potentialTranscriberJIDs.includes(participant.id) && participant.name === TRANSCRIBER_DISPLAY_NAME) { - batch(() => { - dispatch(transcriberJoined(participant.id)); - dispatch(hidePendingTranscribingNotification()); - }); + dispatch(transcriberJoined(participant.id)); } break; diff --git a/react/features/transcribing/reducer.ts b/react/features/transcribing/reducer.ts index 481f842849a9..c219590b6375 100644 --- a/react/features/transcribing/reducer.ts +++ b/react/features/transcribing/reducer.ts @@ -1,7 +1,6 @@ import ReducerRegistry from '../base/redux/ReducerRegistry'; import { - SET_PENDING_TRANSCRIBING_NOTIFICATION_UID, _POTENTIAL_TRANSCRIBER_JOINED, _TRANSCRIBER_JOINED, _TRANSCRIBER_LEFT @@ -45,7 +44,6 @@ function _getInitialState() { export interface ITranscribingState { isTranscribing: boolean; - pendingNotificationUid?: string; potentialTranscriberJIDs: string[]; transcriberJID?: string | null; } @@ -74,11 +72,6 @@ ReducerRegistry.register('features/transcribing', ...state, potentialTranscriberJIDs: [ action.transcriberJID, ...state.potentialTranscriberJIDs ] }; - case SET_PENDING_TRANSCRIBING_NOTIFICATION_UID: - return { - ...state, - pendingNotificationUid: action.uid - }; default: return state; } From 6128292161eedd5d06a2421e15bb7192c0fb8e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Fri, 12 Jan 2024 09:40:58 +0100 Subject: [PATCH 5/6] feat(transcribing) add notification when transcribing starts --- lang/main.json | 1 + react/features/transcribing/actions.ts | 14 ++++++++++++++ react/features/transcribing/middleware.ts | 3 +++ 3 files changed, 18 insertions(+) diff --git a/lang/main.json b/lang/main.json index b9be2e6c6ad6..2e852358e1e4 100644 --- a/lang/main.json +++ b/lang/main.json @@ -1360,6 +1360,7 @@ "failedToStart": "Transcribing failed to start", "labelToolTip": "The meeting is being transcribed", "off": "Transcribing stopped", + "on": "Transcribing started", "pending": "Preparing to transcribe the meeting...", "sourceLanguageDesc": "Currently the meeting language is set to {{sourceLanguage}}.
You can change it from ", "sourceLanguageHere": "here", diff --git a/react/features/transcribing/actions.ts b/react/features/transcribing/actions.ts index 965157ca85d9..1569829bb285 100644 --- a/react/features/transcribing/actions.ts +++ b/react/features/transcribing/actions.ts @@ -72,6 +72,20 @@ export function showPendingTranscribingNotification() { }, NOTIFICATION_TIMEOUT_TYPE.LONG); } +/** + * Signals that the started transcribing notification should be shown on the + * screen. + * + * @returns {showNotification} + */ +export function showStartedTranscribingNotification() { + return showNotification({ + descriptionKey: 'transcribing.on', + titleKey: 'dialog.transcribing', + uid: TRANSCRIBING_NOTIFICATION_ID + }, NOTIFICATION_TIMEOUT_TYPE.SHORT); +} + /** * Signals that the stopped transcribing notification should be shown on the * screen. diff --git a/react/features/transcribing/middleware.ts b/react/features/transcribing/middleware.ts index e57ddfed5ed3..49acf03785ae 100644 --- a/react/features/transcribing/middleware.ts +++ b/react/features/transcribing/middleware.ts @@ -14,6 +14,7 @@ import { import { potentialTranscriberJoined, showPendingTranscribingNotification, + showStartedTranscribingNotification, showStoppedTranscribingNotification, transcriberJoined, transcriberLeft @@ -37,6 +38,8 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => { switch (action.type) { case _TRANSCRIBER_JOINED: { + dispatch(showStartedTranscribingNotification()); + const state = getState(); const { transcription } = state['features/base/config']; const { _requestingSubtitles } = state['features/subtitles']; From 72ff1c101535e6831b917ea0c9b23c603ade5b4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Fri, 12 Jan 2024 11:15:47 +0100 Subject: [PATCH 6/6] feat(external-api) add transcribingStatusChanged event --- modules/API/API.js | 13 +++++++++++++ modules/API/external/external_api.js | 1 + react/features/transcribing/middleware.ts | 15 ++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/modules/API/API.js b/modules/API/API.js index 77a77c15d36f..c784369fff48 100644 --- a/modules/API/API.js +++ b/modules/API/API.js @@ -1975,6 +1975,19 @@ class API { }); } + /** + * Notify external application (if API is enabled) that transcribing has started or stopped. + * + * @param {boolean} on - True if transcribing is on, false otherwise. + * @returns {void} + */ + notifyTranscribingStatusChanged(on) { + this._sendEvent({ + name: 'transcribing-status-changed', + on + }); + } + /** * Notify external application (if API is enabled) that the user received * a transcription chunk. diff --git a/modules/API/external/external_api.js b/modules/API/external/external_api.js index 002fc0742537..ce9807021837 100644 --- a/modules/API/external/external_api.js +++ b/modules/API/external/external_api.js @@ -160,6 +160,7 @@ const events = { 'suspend-detected': 'suspendDetected', 'tile-view-changed': 'tileViewChanged', 'toolbar-button-clicked': 'toolbarButtonClicked', + 'transcribing-status-changed': 'transcribingStatusChanged', 'transcription-chunk-received': 'transcriptionChunkReceived', 'whiteboard-status-changed': 'whiteboardStatusChanged' }; diff --git a/react/features/transcribing/middleware.ts b/react/features/transcribing/middleware.ts index 49acf03785ae..1638b8253745 100644 --- a/react/features/transcribing/middleware.ts +++ b/react/features/transcribing/middleware.ts @@ -38,6 +38,7 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => { switch (action.type) { case _TRANSCRIBER_JOINED: { + notifyTranscribingStatusChanged(true); dispatch(showStartedTranscribingNotification()); const state = getState(); @@ -50,6 +51,7 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => { break; } case _TRANSCRIBER_LEFT: { + notifyTranscribingStatusChanged(false); dispatch(showStoppedTranscribingNotification()); const state = getState(); @@ -83,7 +85,6 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => { break; } - case SET_REQUESTING_SUBTITLES: if (action.enabled && !isTranscribing) { dispatch(showPendingTranscribingNotification()); @@ -95,3 +96,15 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => { return next(action); }); + +/** + * Notify external application (if API is enabled) that transcribing has started or stopped. + * + * @param {boolean} on - True if transcribing is on, false otherwise. + * @returns {void} + */ +function notifyTranscribingStatusChanged(on: boolean) { + if (typeof APP !== 'undefined') { + APP.API.notifyTranscribingStatusChanged(on); + } +}