feat(notifications) reset same type notification timeout

This commit is contained in:
Tudor D. Pop 2022-02-03 15:17:34 +02:00 committed by GitHub
parent 2a8d0b6e33
commit b9f3448379
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 97 additions and 92 deletions

View File

@ -603,7 +603,6 @@ function _raiseHandUpdated({ dispatch, getState }, conference, participantId, ne
titleKey: 'notify.somebody', titleKey: 'notify.somebody',
title: notificationTitle, title: notificationTitle,
descriptionKey: 'notify.raisedHand', descriptionKey: 'notify.raisedHand',
raiseHandNotification: true,
concatText: true, concatText: true,
uid: RAISE_HAND_NOTIFICATION_ID, uid: RAISE_HAND_NOTIFICATION_ID,
...action ...action

View File

@ -45,13 +45,3 @@ export const SHOW_NOTIFICATION = 'SHOW_NOTIFICATION';
* } * }
*/ */
export const SET_NOTIFICATIONS_ENABLED = 'SET_NOTIFICATIONS_ENABLED'; export const SET_NOTIFICATIONS_ENABLED = 'SET_NOTIFICATIONS_ENABLED';
/**
* The type of (redux) action which signals that raise hand notifications
* should be dismissed.
*
* {
* type: HIDE_RAISE_HAND_NOTIFICATIONS
* }
*/
export const HIDE_RAISE_HAND_NOTIFICATIONS = 'HIDE_RAISE_HAND_NOTIFICATIONS';

View File

@ -9,7 +9,6 @@ import { getParticipantCount } from '../base/participants/functions';
import { import {
CLEAR_NOTIFICATIONS, CLEAR_NOTIFICATIONS,
HIDE_NOTIFICATION, HIDE_NOTIFICATION,
HIDE_RAISE_HAND_NOTIFICATIONS,
SET_NOTIFICATIONS_ENABLED, SET_NOTIFICATIONS_ENABLED,
SHOW_NOTIFICATION SHOW_NOTIFICATION
} from './actionTypes'; } from './actionTypes';
@ -71,19 +70,6 @@ export function hideNotification(uid: string) {
}; };
} }
/**
* Removes the raise hand notifications.
*
* @returns {{
* type: HIDE_RAISE_HAND_NOTIFICATIONS
* }}
*/
export function hideRaiseHandNotifications() {
return {
type: HIDE_RAISE_HAND_NOTIFICATIONS
};
}
/** /**
* Stops notifications from being displayed. * Stops notifications from being displayed.
* *

View File

@ -104,7 +104,7 @@ class NotificationsContainer extends Component<Props> {
if (notification !== previousNotification) { if (notification !== previousNotification) {
this._clearNotificationDismissTimeout(); this._clearNotificationDismissTimeout();
if (notification && notification.timeout && notification.props.isDismissAllowed !== false) { if (notification && notification.timeout) {
const { const {
timeout, timeout,
uid uid

View File

@ -147,24 +147,6 @@ class NotificationsContainer extends Component<Props> {
}; };
} }
/**
* Sets a timeout for each notification, where applicable.
*
* @inheritdoc
*/
componentDidMount() {
this._updateTimeouts();
}
/**
* Sets a timeout for each notification, where applicable.
*
* @inheritdoc
*/
componentDidUpdate() {
this._updateTimeouts();
}
/** /**
* Implements React's {@link Component#render()}. * Implements React's {@link Component#render()}.
* *
@ -249,31 +231,6 @@ class NotificationsContainer extends Component<Props> {
); );
}); });
} }
/**
* Updates the timeouts for every notification.
*
* @returns {void}
*/
_updateTimeouts() {
const { _notifications } = this.props;
for (const notification of _notifications) {
if (notification.timeout
&& notification.props.isDismissAllowed !== false
&& !this._timeouts.has(notification.uid)) {
const {
timeout,
uid
} = notification;
const timerID = setTimeout(() => {
this._onDismissed(uid);
}, timeout);
this._timeouts.set(uid, timerID);
}
}
}
} }
/** /**

View File

@ -13,15 +13,65 @@ import {
import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux'; import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
import { PARTICIPANTS_PANE_OPEN } from '../participants-pane/actionTypes'; import { PARTICIPANTS_PANE_OPEN } from '../participants-pane/actionTypes';
import {
CLEAR_NOTIFICATIONS,
HIDE_NOTIFICATION,
SHOW_NOTIFICATION
} from './actionTypes';
import { import {
clearNotifications, clearNotifications,
hideRaiseHandNotifications, hideNotification,
showNotification, showNotification,
showParticipantJoinedNotification, showParticipantJoinedNotification,
showParticipantLeftNotification showParticipantLeftNotification
} from './actions'; } from './actions';
import { NOTIFICATION_TIMEOUT_TYPE } from './constants'; import {
import { joinLeaveNotificationsDisabled } from './functions'; NOTIFICATION_TIMEOUT_TYPE,
RAISE_HAND_NOTIFICATION_ID
} from './constants';
import { areThereNotifications, joinLeaveNotificationsDisabled } from './functions';
/**
* Map of timers.
*
* @type {Map}
*/
const timers = new Map();
/**
* Function that creates a timeout id for specific notification.
*
* @param {Object} notification - Notification for which we want to create a timeout.
* @param {Function} dispatch - The Redux dispatch function.
* @returns {void}
*/
const createTimeoutId = (notification, dispatch) => {
const {
timeout,
uid
} = notification;
if (timeout) {
const timerID = setTimeout(() => {
dispatch(hideNotification(uid));
}, timeout);
timers.set(uid, timerID);
}
};
/**
* Returns notifications state.
*
* @param {Object} state - Global state.
* @returns {Array<Object>} - Notifications state.
*/
const getNotifications = state => {
const _visible = areThereNotifications(state);
const { notifications } = state['features/notifications'];
return _visible ? notifications : [];
};
/** /**
* Middleware that captures actions to display notifications. * Middleware that captures actions to display notifications.
@ -30,12 +80,52 @@ import { joinLeaveNotificationsDisabled } from './functions';
* @returns {Function} * @returns {Function}
*/ */
MiddlewareRegistry.register(store => next => action => { MiddlewareRegistry.register(store => next => action => {
const { dispatch, getState } = store;
const state = getState();
switch (action.type) { switch (action.type) {
case CLEAR_NOTIFICATIONS: {
if (navigator.product !== 'ReactNative') {
const _notifications = getNotifications(state);
for (const notification of _notifications) {
if (timers.has(notification.uid)) {
const timeout = timers.get(notification.uid);
clearTimeout(timeout);
timers.delete(notification.uid);
}
}
timers.clear();
}
break;
}
case SHOW_NOTIFICATION: {
if (navigator.product !== 'ReactNative') {
if (timers.has(action.uid)) {
const timer = timers.get(action.uid);
clearTimeout(timer);
timers.delete(action.uid);
}
createTimeoutId(action, dispatch);
}
break;
}
case HIDE_NOTIFICATION: {
if (navigator.product !== 'ReactNative') {
const timer = timers.get(action.uid);
clearTimeout(timer);
timers.delete(action.uid);
}
break;
}
case PARTICIPANT_JOINED: { case PARTICIPANT_JOINED: {
const result = next(action); const result = next(action);
const { participant: p } = action; const { participant: p } = action;
const { dispatch, getState } = store;
const state = getState();
const { conference } = state['features/base/conference']; const { conference } = state['features/base/conference'];
if (conference && !p.local && !joinLeaveNotificationsDisabled() && !p.isReplacing) { if (conference && !p.local && !joinLeaveNotificationsDisabled() && !p.isReplacing) {
@ -48,8 +138,6 @@ MiddlewareRegistry.register(store => next => action => {
} }
case PARTICIPANT_LEFT: { case PARTICIPANT_LEFT: {
if (!joinLeaveNotificationsDisabled()) { if (!joinLeaveNotificationsDisabled()) {
const { dispatch, getState } = store;
const state = getState();
const participant = getParticipantById( const participant = getParticipantById(
store.getState(), store.getState(),
action.participant.id action.participant.id
@ -65,7 +153,6 @@ MiddlewareRegistry.register(store => next => action => {
return next(action); return next(action);
} }
case PARTICIPANT_UPDATED: { case PARTICIPANT_UPDATED: {
const state = store.getState();
const { disableModeratorIndicator } = state['features/base/config']; const { disableModeratorIndicator } = state['features/base/config'];
if (disableModeratorIndicator) { if (disableModeratorIndicator) {
@ -93,7 +180,7 @@ MiddlewareRegistry.register(store => next => action => {
return next(action); return next(action);
} }
case PARTICIPANTS_PANE_OPEN: { case PARTICIPANTS_PANE_OPEN: {
store.dispatch(hideRaiseHandNotifications()); store.dispatch(hideNotification(RAISE_HAND_NOTIFICATION_ID));
break; break;
} }
} }

View File

@ -5,7 +5,6 @@ import { ReducerRegistry } from '../base/redux';
import { import {
CLEAR_NOTIFICATIONS, CLEAR_NOTIFICATIONS,
HIDE_NOTIFICATION, HIDE_NOTIFICATION,
HIDE_RAISE_HAND_NOTIFICATIONS,
SET_NOTIFICATIONS_ENABLED, SET_NOTIFICATIONS_ENABLED,
SHOW_NOTIFICATION SHOW_NOTIFICATION
} from './actionTypes'; } from './actionTypes';
@ -44,14 +43,6 @@ ReducerRegistry.register('features/notifications',
notification => notification.uid !== action.uid) notification => notification.uid !== action.uid)
}; };
case HIDE_RAISE_HAND_NOTIFICATIONS:
return {
...state,
notifications: state.notifications.filter(
notification => !notification.props.raiseHandNotification
)
};
case SET_NOTIFICATIONS_ENABLED: case SET_NOTIFICATIONS_ENABLED:
return { return {
...state, ...state,

View File

@ -96,7 +96,6 @@ export function showPendingRecordingNotification(streamType: string) {
titleKey: 'dialog.recording' titleKey: 'dialog.recording'
}; };
const notification = await dispatch(showNotification({ const notification = await dispatch(showNotification({
isDismissAllowed: false,
...dialogProps ...dialogProps
}, NOTIFICATION_TIMEOUT_TYPE.MEDIUM)); }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
@ -172,7 +171,6 @@ export function showStartedRecordingNotification(
let dialogProps = { let dialogProps = {
descriptionKey: participantName ? 'liveStreaming.onBy' : 'liveStreaming.on', descriptionKey: participantName ? 'liveStreaming.onBy' : 'liveStreaming.on',
descriptionArguments: { name: participantName }, descriptionArguments: { name: participantName },
isDismissAllowed: true,
titleKey: 'dialog.liveStreaming' titleKey: 'dialog.liveStreaming'
}; };
@ -185,7 +183,6 @@ export function showStartedRecordingNotification(
customActionNameKey: undefined, customActionNameKey: undefined,
descriptionKey: participantName ? 'recording.onBy' : 'recording.on', descriptionKey: participantName ? 'recording.onBy' : 'recording.on',
descriptionArguments: { name: participantName }, descriptionArguments: { name: participantName },
isDismissAllowed: true,
titleKey: 'dialog.recording' titleKey: 'dialog.recording'
}; };
@ -210,7 +207,6 @@ export function showStartedRecordingNotification(
dialogProps.customActionHandler = [ () => copyText(link) ]; dialogProps.customActionHandler = [ () => copyText(link) ];
dialogProps.titleKey = 'recording.on'; dialogProps.titleKey = 'recording.on';
dialogProps.descriptionKey = 'recording.linkGenerated'; dialogProps.descriptionKey = 'recording.linkGenerated';
dialogProps.isDismissAllowed = false;
} catch (err) { } catch (err) {
dispatch(showErrorNotification({ dispatch(showErrorNotification({
titleKey: 'recording.errorFetchingLink' titleKey: 'recording.errorFetchingLink'

View File

@ -72,7 +72,6 @@ export function showPendingTranscribingNotification() {
return async (dispatch: Function) => { return async (dispatch: Function) => {
const notification = await dispatch(showNotification({ const notification = await dispatch(showNotification({
descriptionKey: 'transcribing.pending', descriptionKey: 'transcribing.pending',
isDismissAllowed: false,
titleKey: 'dialog.transcribing' titleKey: 'dialog.transcribing'
}, NOTIFICATION_TIMEOUT_TYPE.LONG)); }, NOTIFICATION_TIMEOUT_TYPE.LONG));