From cfbdbd478357d2fe7e672d2ab5d69b877c17b7bd Mon Sep 17 00:00:00 2001 From: Calinteodor Date: Wed, 5 Mar 2025 09:52:22 +0200 Subject: [PATCH] feat(base/config): notify user on conference destruction option (#15697) Notify user about conference destruction using a new config option. --- conference.js | 6 ++++-- config.js | 3 +++ react/features/base/conference/middleware.native.ts | 12 +++++++++++- react/features/base/conference/middleware.web.ts | 4 +++- react/features/base/config/configType.ts | 1 + react/features/base/config/configWhitelist.ts | 1 + react/features/base/connection/actions.web.ts | 6 ++++-- react/features/conference/middleware.native.ts | 2 +- react/features/conference/middleware.web.ts | 3 ++- 9 files changed, 30 insertions(+), 8 deletions(-) diff --git a/conference.js b/conference.js index cbd964a265..662598c0d6 100644 --- a/conference.js +++ b/conference.js @@ -2278,8 +2278,10 @@ export default { * @param {boolean} [requestFeedback=false] if user feedback should be * @param {string} [hangupReason] the reason for leaving the meeting * requested + * @param {boolean} [notifyOnConferenceTermination] whether to notify + * the user on conference termination */ - hangup(requestFeedback = false, hangupReason) { + hangup(requestFeedback = false, hangupReason, notifyOnConferenceTermination) { APP.store.dispatch(disableReceiver()); this._stopProxyConnection(); @@ -2298,7 +2300,7 @@ export default { if (requestFeedback) { const feedbackDialogClosed = (feedbackResult = {}) => { - if (!feedbackResult.wasDialogShown && hangupReason) { + if (!feedbackResult.wasDialogShown && hangupReason && notifyOnConferenceTermination) { return APP.store.dispatch( openLeaveReasonDialog(hangupReason)).then(() => feedbackResult); } diff --git a/config.js b/config.js index 82c1b84e5f..0d0fc84614 100644 --- a/config.js +++ b/config.js @@ -755,6 +755,9 @@ var config = { // and microsoftApiApplicationClientID // enableCalendarIntegration: false, + // Whether to notify when the conference is terminated because it was destroyed. + // notifyOnConferenceDestruction: true, + // The client id for the google APIs used for the calendar integration, youtube livestreaming, etc. // googleApiApplicationClientID: '', diff --git a/react/features/base/conference/middleware.native.ts b/react/features/base/conference/middleware.native.ts index ad33a2046d..ffde497098 100644 --- a/react/features/base/conference/middleware.native.ts +++ b/react/features/base/conference/middleware.native.ts @@ -4,7 +4,7 @@ import { JitsiConferenceErrors } from '../lib-jitsi-meet'; import MiddlewareRegistry from '../redux/MiddlewareRegistry'; import { CONFERENCE_FAILED } from './actionTypes'; -import { conferenceLeft } from './actions'; +import { conferenceLeft } from './actions.native'; import { TRIGGER_READY_TO_CLOSE_REASONS } from './constants'; import './middleware.any'; @@ -15,10 +15,20 @@ MiddlewareRegistry.register(store => next => action => { switch (action.type) { case CONFERENCE_FAILED: { + const { getState } = store; + const state = getState(); + const { notifyOnConferenceDestruction = true } = state['features/base/config']; + if (error?.name !== JitsiConferenceErrors.CONFERENCE_DESTROYED) { break; } + if (!notifyOnConferenceDestruction) { + dispatch(conferenceLeft(action.conference)); + dispatch(appNavigate(undefined)); + break; + } + const [ reason ] = error.params; const reasonKey = Object.keys(TRIGGER_READY_TO_CLOSE_REASONS)[ diff --git a/react/features/base/conference/middleware.web.ts b/react/features/base/conference/middleware.web.ts index 3fd90623af..f343049936 100644 --- a/react/features/base/conference/middleware.web.ts +++ b/react/features/base/conference/middleware.web.ts @@ -122,12 +122,14 @@ MiddlewareRegistry.register(store => next => action => { } if (errorName === JitsiConferenceErrors.CONFERENCE_DESTROYED) { + const state = getState(); + const { notifyOnConferenceDestruction = true } = state['features/base/config']; const [ reason ] = action.error.params; const titlekey = Object.keys(TRIGGER_READY_TO_CLOSE_REASONS)[ Object.values(TRIGGER_READY_TO_CLOSE_REASONS).indexOf(reason) ]; - dispatch(hangup(true, i18next.t(titlekey) || reason)); + dispatch(hangup(true, i18next.t(titlekey) || reason, notifyOnConferenceDestruction)); } releaseScreenLock(); diff --git a/react/features/base/config/configType.ts b/react/features/base/config/configType.ts index db683dbab3..40eb339d31 100644 --- a/react/features/base/config/configType.ts +++ b/react/features/base/config/configType.ts @@ -486,6 +486,7 @@ export interface IConfig { short?: number; }; notifications?: Array; + notifyOnConferenceDestruction?: boolean; openSharedDocumentOnJoin?: boolean; opusMaxAverageBitrate?: number; p2p?: { diff --git a/react/features/base/config/configWhitelist.ts b/react/features/base/config/configWhitelist.ts index dd2014c15e..b919ffb38e 100644 --- a/react/features/base/config/configWhitelist.ts +++ b/react/features/base/config/configWhitelist.ts @@ -182,6 +182,7 @@ export default [ 'mouseMoveCallbackInterval', 'notifications', 'notificationTimeouts', + 'notifyOnConferenceDestruction', 'openSharedDocumentOnJoin', 'opusMaxAverageBitrate', 'p2p.backToP2PDelay', diff --git a/react/features/base/connection/actions.web.ts b/react/features/base/connection/actions.web.ts index acf9af4327..2c997af642 100644 --- a/react/features/base/connection/actions.web.ts +++ b/react/features/base/connection/actions.web.ts @@ -62,9 +62,11 @@ export function connect(id?: string, password?: string) { * @param {boolean} [requestFeedback] - Whether to attempt showing a * request for call feedback. * @param {string} [feedbackTitle] - The feedback title. + * @param {boolean} [notifyOnConferenceTermination] - Whether to notify + * the user on conference termination. * @returns {Function} */ -export function hangup(requestFeedback = false, feedbackTitle?: string) { +export function hangup(requestFeedback = false, feedbackTitle?: string, notifyOnConferenceTermination?: boolean) { // XXX For web based version we use conference hanging up logic from the old app. return async (dispatch: IStore['dispatch']) => { if (LocalRecordingManager.isRecordingLocally()) { @@ -80,6 +82,6 @@ export function hangup(requestFeedback = false, feedbackTitle?: string) { }); } - return APP.conference.hangup(requestFeedback, feedbackTitle); + return APP.conference.hangup(requestFeedback, feedbackTitle, notifyOnConferenceTermination); }; } diff --git a/react/features/conference/middleware.native.ts b/react/features/conference/middleware.native.ts index 4e6fe67c39..c49f4fad8b 100644 --- a/react/features/conference/middleware.native.ts +++ b/react/features/conference/middleware.native.ts @@ -1,6 +1,6 @@ import { appNavigate } from '../app/actions.native'; import { KICKED_OUT } from '../base/conference/actionTypes'; -import { conferenceLeft } from '../base/conference/actions'; +import { conferenceLeft } from '../base/conference/actions.native'; import MiddlewareRegistry from '../base/redux/MiddlewareRegistry'; import { notifyKickedOut } from './actions.native'; diff --git a/react/features/conference/middleware.web.ts b/react/features/conference/middleware.web.ts index 1a6e06ce9d..02ba6eea10 100644 --- a/react/features/conference/middleware.web.ts +++ b/react/features/conference/middleware.web.ts @@ -35,7 +35,8 @@ MiddlewareRegistry.register(store => next => action => { dispatch(hangup(true, participantDisplayName ? i18next.t('dialog.kickTitle', { participantDisplayName }) - : i18next.t('dialog.kickSystemTitle'))); + : i18next.t('dialog.kickSystemTitle'), + true)); return result; }