Merge pull request #8377 from jitsi/tavram/notifications
feat(external_api) allow notifications to be configured
This commit is contained in:
commit
1ab0f1993a
59
config.js
59
config.js
|
@ -695,6 +695,65 @@ var config = {
|
||||||
ignoreStartMuted
|
ignoreStartMuted
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
Use this array to configure which notifications will be shown to the user
|
||||||
|
The items correspond to the title or description key of that notification
|
||||||
|
Some of these notifications also depend on some other internal logic to be displayed or not,
|
||||||
|
so adding them here will not ensure they will always be displayed
|
||||||
|
|
||||||
|
A falsy value for this prop will result in having all notifications enabled (e.g null, undefined, false)
|
||||||
|
*/
|
||||||
|
// notifications: [
|
||||||
|
// 'connection.CONNFAIL', // shown when the connection fails,
|
||||||
|
// 'dialog.cameraNotSendingData', // shown when there's no feed from user's camera
|
||||||
|
// 'dialog.kickTitle', // shown when user has been kicked
|
||||||
|
// 'dialog.liveStreaming', // livestreaming notifications (pending, on, off, limits)
|
||||||
|
// 'dialog.lockTitle', // shown when setting conference password fails
|
||||||
|
// 'dialog.maxUsersLimitReached', // shown when maximmum users limit has been reached
|
||||||
|
// 'dialog.micNotSendingData', // shown when user's mic is not sending any audio
|
||||||
|
// 'dialog.passwordNotSupportedTitle', // shown when setting conference password fails due to password format
|
||||||
|
// 'dialog.recording', // recording notifications (pending, on, off, limits)
|
||||||
|
// 'dialog.remoteControlTitle', // remote control notifications (allowed, denied, start, stop, error)
|
||||||
|
// 'dialog.reservationError',
|
||||||
|
// 'dialog.serviceUnavailable', // shown when server is not reachable
|
||||||
|
// 'dialog.sessTerminated', // shown when there is a failed conference session
|
||||||
|
// 'dialog.tokenAuthFailed', // show when an invalid jwt is used
|
||||||
|
// 'dialog.transcribing', // transcribing notifications (pending, off)
|
||||||
|
// 'dialOut.statusMessage', // shown when dial out status is updated.
|
||||||
|
// 'liveStreaming.busy', // shown when livestreaming service is busy
|
||||||
|
// 'liveStreaming.failedToStart', // shown when livestreaming fails to start
|
||||||
|
// 'liveStreaming.unavailableTitle', // shown when livestreaming service is not reachable
|
||||||
|
// 'lobby.joinRejectedMessage', // shown when while in a lobby, user's request to join is rejected
|
||||||
|
// 'lobby.notificationTitle', // shown when lobby is toggled and when join requests are allowed / denied
|
||||||
|
// 'localRecording.localRecording', // shown when a local recording is started
|
||||||
|
// 'notify.disconnected', // shown when a participant has left
|
||||||
|
// 'notify.grantedTo', // shown when moderator rights were granted to a participant
|
||||||
|
// 'notify.invitedOneMember', // shown when 1 participant has been invited
|
||||||
|
// 'notify.invitedThreePlusMembers', // shown when 3+ participants have been invited
|
||||||
|
// 'notify.invitedTwoMembers', // shown when 2 participants have been invited
|
||||||
|
// 'notify.kickParticipant', // shown when a participant is kicked
|
||||||
|
// 'notify.mutedRemotelyTitle', // shown when user is muted by a remote party
|
||||||
|
// 'notify.mutedTitle', // shown when user has been muted upon joining,
|
||||||
|
// 'notify.newDeviceAudioTitle', // prompts the user to use a newly detected audio device
|
||||||
|
// 'notify.newDeviceCameraTitle', // prompts the user to use a newly detected camera
|
||||||
|
// 'notify.passwordRemovedRemotely', // shown when a password has been removed remotely
|
||||||
|
// 'notify.passwordSetRemotely', // shown when a password has been set remotely
|
||||||
|
// 'notify.raisedHand', // shown when a partcipant used raise hand,
|
||||||
|
// 'notify.startSilentTitle', // shown when user joined with no audio
|
||||||
|
// 'prejoin.errorDialOut',
|
||||||
|
// 'prejoin.errorDialOutDisconnected',
|
||||||
|
// 'prejoin.errorDialOutFailed',
|
||||||
|
// 'prejoin.errorDialOutStatus',
|
||||||
|
// 'prejoin.errorStatusCode',
|
||||||
|
// 'prejoin.errorValidation',
|
||||||
|
// 'recording.busy', // shown when recording service is busy
|
||||||
|
// 'recording.failedToStart', // shown when recording fails to start
|
||||||
|
// 'recording.unavailableTitle', // shown when recording service is not reachable
|
||||||
|
// 'toolbar.noAudioSignalTitle', // shown when a broken mic is detected
|
||||||
|
// 'toolbar.noisyAudioInputTitle', // shown when noise is detected for the current microphone
|
||||||
|
// 'toolbar.talkWhileMutedPopup', // shown when user tries to speak while muted
|
||||||
|
// 'transcribing.failedToStart' // shown when transcribing fails to start
|
||||||
|
// ]
|
||||||
|
|
||||||
// Allow all above example options to include a trailing comma and
|
// Allow all above example options to include a trailing comma and
|
||||||
// prevent fear when commenting out the last value.
|
// prevent fear when commenting out the last value.
|
||||||
|
|
|
@ -132,6 +132,7 @@ export default [
|
||||||
'liveStreamingEnabled',
|
'liveStreamingEnabled',
|
||||||
'localRecording',
|
'localRecording',
|
||||||
'maxFullResolutionParticipants',
|
'maxFullResolutionParticipants',
|
||||||
|
'notifications',
|
||||||
'openBridgeChannel',
|
'openBridgeChannel',
|
||||||
'openSharedDocumentOnJoin',
|
'openSharedDocumentOnJoin',
|
||||||
'opusMaxAverageBitrate',
|
'opusMaxAverageBitrate',
|
||||||
|
|
|
@ -46,14 +46,14 @@ MiddlewareRegistry.register(({ getState, dispatch }) => next => action => {
|
||||||
|
|
||||||
recordingController.onWarning = (messageKey, messageParams) => {
|
recordingController.onWarning = (messageKey, messageParams) => {
|
||||||
dispatch(showNotification({
|
dispatch(showNotification({
|
||||||
title: i18next.t('localRecording.localRecording'),
|
titleKey: 'localRecording.localRecording',
|
||||||
description: i18next.t(messageKey, messageParams)
|
description: i18next.t(messageKey, messageParams)
|
||||||
}, 10000));
|
}, 10000));
|
||||||
};
|
};
|
||||||
|
|
||||||
recordingController.onNotify = (messageKey, messageParams) => {
|
recordingController.onNotify = (messageKey, messageParams) => {
|
||||||
dispatch(showNotification({
|
dispatch(showNotification({
|
||||||
title: i18next.t('localRecording.localRecording'),
|
titleKey: 'localRecording.localRecording',
|
||||||
description: i18next.t(messageKey, messageParams)
|
description: i18next.t(messageKey, messageParams)
|
||||||
}, 10000));
|
}, 10000));
|
||||||
};
|
};
|
||||||
|
|
|
@ -108,20 +108,20 @@ async function _handleNoAudioSignalNotification({ dispatch, getState }, action)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const notification = showNotification({
|
const notification = await dispatch(showNotification({
|
||||||
titleKey: 'toolbar.noAudioSignalTitle',
|
titleKey: 'toolbar.noAudioSignalTitle',
|
||||||
description: <DialInLink />,
|
description: <DialInLink />,
|
||||||
descriptionKey,
|
descriptionKey,
|
||||||
customActionNameKey,
|
customActionNameKey,
|
||||||
customActionHandler
|
customActionHandler
|
||||||
});
|
}));
|
||||||
|
|
||||||
dispatch(notification);
|
|
||||||
|
|
||||||
dispatch(playSound(NO_AUDIO_SIGNAL_SOUND_ID));
|
dispatch(playSound(NO_AUDIO_SIGNAL_SOUND_ID));
|
||||||
|
|
||||||
|
if (notification) {
|
||||||
// Store the current notification uid so we can check for this state and hide it in case
|
// Store the current notification uid so we can check for this state and hide it in case
|
||||||
// a new track was added, thus changing the context of the notification
|
// a new track was added, thus changing the context of the notification
|
||||||
dispatch(setNoAudioSignalNotificationUid(notification.uid));
|
dispatch(setNoAudioSignalNotificationUid(notification.uid));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,17 +37,18 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
conference.on(
|
conference.on(
|
||||||
JitsiConferenceEvents.NOISY_MIC, () => {
|
JitsiConferenceEvents.NOISY_MIC, async () => {
|
||||||
const notification = showNotification({
|
const notification = await dispatch(showNotification({
|
||||||
titleKey: 'toolbar.noisyAudioInputTitle',
|
titleKey: 'toolbar.noisyAudioInputTitle',
|
||||||
descriptionKey: 'toolbar.noisyAudioInputDesc'
|
descriptionKey: 'toolbar.noisyAudioInputDesc'
|
||||||
});
|
}));
|
||||||
|
|
||||||
dispatch(notification);
|
|
||||||
dispatch(playSound(NOISY_AUDIO_INPUT_SOUND_ID));
|
dispatch(playSound(NOISY_AUDIO_INPUT_SOUND_ID));
|
||||||
|
|
||||||
|
if (notification) {
|
||||||
// we store the last notification id so we can hide it if the mic is muted
|
// we store the last notification id so we can hide it if the mic is muted
|
||||||
dispatch(setNoisyAudioInputNotificationUid(notification.uid));
|
dispatch(setNoisyAudioInputNotificationUid(notification.uid));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,19 +76,23 @@ export function showErrorNotification(props: Object) {
|
||||||
* @param {Object} props - The props needed to show the notification component.
|
* @param {Object} props - The props needed to show the notification component.
|
||||||
* @param {number} timeout - How long the notification should display before
|
* @param {number} timeout - How long the notification should display before
|
||||||
* automatically being hidden.
|
* automatically being hidden.
|
||||||
* @returns {{
|
* @returns {Function}
|
||||||
* type: SHOW_NOTIFICATION,
|
|
||||||
* props: Object,
|
|
||||||
* timeout: number,
|
|
||||||
* uid: number
|
|
||||||
* }}
|
|
||||||
*/
|
*/
|
||||||
export function showNotification(props: Object = {}, timeout: ?number) {
|
export function showNotification(props: Object = {}, timeout: ?number) {
|
||||||
return {
|
return function(dispatch: Function, getState: Function) {
|
||||||
|
const { notifications } = getState()['features/base/config'];
|
||||||
|
const shouldDisplay = !notifications
|
||||||
|
|| notifications.includes(props.descriptionKey)
|
||||||
|
|| notifications.includes(props.titleKey);
|
||||||
|
|
||||||
|
if (shouldDisplay) {
|
||||||
|
return dispatch({
|
||||||
type: SHOW_NOTIFICATION,
|
type: SHOW_NOTIFICATION,
|
||||||
props,
|
props,
|
||||||
timeout,
|
timeout,
|
||||||
uid: window.Date.now()
|
uid: window.Date.now()
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ export function setLiveStreamKey(streamKey: string) {
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
export function showPendingRecordingNotification(streamType: string) {
|
export function showPendingRecordingNotification(streamType: string) {
|
||||||
return (dispatch: Function) => {
|
return async (dispatch: Function) => {
|
||||||
const isLiveStreaming
|
const isLiveStreaming
|
||||||
= streamType === JitsiMeetJS.constants.recording.mode.STREAM;
|
= streamType === JitsiMeetJS.constants.recording.mode.STREAM;
|
||||||
const dialogProps = isLiveStreaming ? {
|
const dialogProps = isLiveStreaming ? {
|
||||||
|
@ -85,15 +85,14 @@ export function showPendingRecordingNotification(streamType: string) {
|
||||||
descriptionKey: 'recording.pending',
|
descriptionKey: 'recording.pending',
|
||||||
titleKey: 'dialog.recording'
|
titleKey: 'dialog.recording'
|
||||||
};
|
};
|
||||||
const showNotificationAction = showNotification({
|
const notification = await dispatch(showNotification({
|
||||||
isDismissAllowed: false,
|
isDismissAllowed: false,
|
||||||
...dialogProps
|
...dialogProps
|
||||||
});
|
}));
|
||||||
|
|
||||||
dispatch(showNotificationAction);
|
if (notification) {
|
||||||
|
dispatch(_setPendingRecordingNotificationUid(notification.uid, streamType));
|
||||||
dispatch(_setPendingRecordingNotificationUid(
|
}
|
||||||
showNotificationAction.uid, streamType));
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,20 +40,20 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
conference.on(
|
conference.on(
|
||||||
JitsiConferenceEvents.TALK_WHILE_MUTED, () => {
|
JitsiConferenceEvents.TALK_WHILE_MUTED, async () => {
|
||||||
const notification = showNotification({
|
const notification = await dispatch(showNotification({
|
||||||
titleKey: 'toolbar.talkWhileMutedPopup',
|
titleKey: 'toolbar.talkWhileMutedPopup',
|
||||||
customActionNameKey: 'notify.unmute',
|
customActionNameKey: 'notify.unmute',
|
||||||
customActionHandler: () => dispatch(setAudioMuted(false))
|
customActionHandler: () => dispatch(setAudioMuted(false))
|
||||||
});
|
}));
|
||||||
|
|
||||||
dispatch(notification);
|
|
||||||
|
|
||||||
dispatch(playSound(TALK_WHILE_MUTED_SOUND_ID));
|
dispatch(playSound(TALK_WHILE_MUTED_SOUND_ID));
|
||||||
|
|
||||||
|
if (notification) {
|
||||||
// we store the last start muted notification id that we showed,
|
// we store the last start muted notification id that we showed,
|
||||||
// so we can hide it when unmuted mic is detected
|
// so we can hide it when unmuted mic is detected
|
||||||
dispatch(setCurrentNotificationUid(notification.uid));
|
dispatch(setCurrentNotificationUid(notification.uid));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,17 +69,16 @@ export function potentialTranscriberJoined(participantId: string) {
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
export function showPendingTranscribingNotification() {
|
export function showPendingTranscribingNotification() {
|
||||||
return (dispatch: Function) => {
|
return async (dispatch: Function) => {
|
||||||
const showNotificationAction = showNotification({
|
const notification = await dispatch(showNotification({
|
||||||
descriptionKey: 'transcribing.pending',
|
descriptionKey: 'transcribing.pending',
|
||||||
isDismissAllowed: false,
|
isDismissAllowed: false,
|
||||||
titleKey: 'dialog.transcribing'
|
titleKey: 'dialog.transcribing'
|
||||||
});
|
}));
|
||||||
|
|
||||||
dispatch(showNotificationAction);
|
if (notification) {
|
||||||
|
dispatch(setPendingTranscribingNotificationUid(notification.uid));
|
||||||
dispatch(setPendingTranscribingNotificationUid(
|
}
|
||||||
showNotificationAction.uid));
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue