ref(notifications): replace NotificationWithToggle with Notification

It was decided along with the mute participant dialog reactification
that these types of warning messages should not be toggleable--that
they should simply always display because there is no undo action.
As such, the component NotificationWithToggle is no longer needed.
This commit is contained in:
Leonard Kim 2017-11-16 09:25:04 -08:00 committed by yanas
parent fe411398e3
commit ef813fbf71
9 changed files with 45 additions and 260 deletions

View File

@ -324,20 +324,17 @@
"stopRecordingWarning": "Are you sure you would like to stop the recording?",
"stopLiveStreaming": "Stop live streaming",
"stopRecording": "Stop recording",
"doNotShowWarningAgain": "Don't show this warning again",
"doNotShowMessageAgain": "Don't show this message again",
"permissionDenied": "Permission Denied",
"screenSharingFailedToInstall": "Oops! Your screen sharing extension failed to install.",
"screenSharingFailedToInstallTitle": "Screen sharing extension failed to install",
"screenSharingPermissionDeniedError": "Oops! Something went wrong with your screen sharing extension permissions. Please reload and try again.",
"micErrorPresent": "There was an error connecting to your microphone.",
"cameraErrorPresent": "There was an error connecting to your camera.",
"cameraUnsupportedResolutionError": "Your camera does not support required video resolution.",
"cameraUnknownError": "Cannot use camera for a unknown reason.",
"cameraUnknownError": "Cannot use camera for an unknown reason.",
"cameraPermissionDeniedError": "You have not granted permission to use your camera. You can still join the conference but others won't see you. Use the camera button in the address bar to fix this.",
"cameraNotFoundError": "Camera was not found.",
"cameraConstraintFailedError": "Your camera does not satisfy some of the required constraints.",
"micUnknownError": "Cannot use microphone for a unknown reason.",
"micUnknownError": "Cannot use microphone for an unknown reason.",
"micPermissionDeniedError": "You have not granted permission to use your microphone. You can still join the conference but others won't hear you. Use the camera button in the address bar to fix this.",
"micNotFoundError": "Microphone was not found.",
"micConstraintFailedError": "Your microphone does not satisfy some of the required constraints.",

View File

@ -31,8 +31,8 @@ import {
} from '../../react/features/base/participants';
import { openDisplayNamePrompt } from '../../react/features/display-name';
import {
maybeShowNotificationWithDoNotDisplay,
setNotificationsEnabled
setNotificationsEnabled,
showWarningNotification
} from '../../react/features/notifications';
import {
checkAutoEnableDesktopSharing,
@ -1155,8 +1155,6 @@ UI.showMicErrorNotification = function(micError) {
const { message, name } = micError;
const persistenceKey = `doNotShowErrorAgain-mic-${name}`;
const micJitsiTrackErrorMsg
= JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.microphone[name];
const micErrorMsg = micJitsiTrackErrorMsg
@ -1164,18 +1162,13 @@ UI.showMicErrorNotification = function(micError) {
.microphone[JitsiTrackErrors.GENERAL];
const additionalMicErrorMsg = micJitsiTrackErrorMsg ? null : message;
APP.store.dispatch(maybeShowNotificationWithDoNotDisplay(
persistenceKey,
{
additionalMessage: additionalMicErrorMsg,
messageKey: micErrorMsg,
showToggle: Boolean(micJitsiTrackErrorMsg),
subtitleKey: 'dialog.micErrorPresent',
titleKey: name === JitsiTrackErrors.PERMISSION_DENIED
? 'deviceError.microphonePermission'
: 'deviceError.microphoneError',
toggleLabelKey: 'dialog.doNotShowWarningAgain'
}));
APP.store.dispatch(showWarningNotification({
description: additionalMicErrorMsg,
descriptionKey: micErrorMsg,
titleKey: name === JitsiTrackErrors.PERMISSION_DENIED
? 'deviceError.microphonePermission'
: 'deviceError.microphoneError'
}));
};
/**
@ -1192,8 +1185,6 @@ UI.showCameraErrorNotification = function(cameraError) {
const { message, name } = cameraError;
const persistenceKey = `doNotShowErrorAgain-camera-${name}`;
const cameraJitsiTrackErrorMsg
= JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.camera[name];
const cameraErrorMsg = cameraJitsiTrackErrorMsg
@ -1201,17 +1192,12 @@ UI.showCameraErrorNotification = function(cameraError) {
.camera[JitsiTrackErrors.GENERAL];
const additionalCameraErrorMsg = cameraJitsiTrackErrorMsg ? null : message;
APP.store.dispatch(maybeShowNotificationWithDoNotDisplay(
persistenceKey,
{
additionalMessage: additionalCameraErrorMsg,
messageKey: cameraErrorMsg,
showToggle: Boolean(cameraJitsiTrackErrorMsg),
subtitleKey: 'dialog.cameraErrorPresent',
titleKey: name === JitsiTrackErrors.PERMISSION_DENIED
? 'deviceError.cameraPermission' : 'deviceError.cameraError',
toggleLabelKey: 'dialog.doNotShowWarningAgain'
}));
APP.store.dispatch(showWarningNotification({
description: additionalCameraErrorMsg,
descriptionKey: cameraErrorMsg,
titleKey: name === JitsiTrackErrors.PERMISSION_DENIED
? 'deviceError.cameraPermission' : 'deviceError.cameraError'
}));
};
/**

25
package-lock.json generated
View File

@ -533,31 +533,6 @@
"styled-components": "1.3.0"
}
},
"@atlaskit/toggle": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/@atlaskit/toggle/-/toggle-2.6.1.tgz",
"integrity": "sha1-I2R+VzTs9psaPb8VpVw0tlfim90=",
"requires": {
"@atlaskit/icon": "8.1.0",
"@atlaskit/theme": "2.2.0",
"babel-runtime": "6.26.0",
"prop-types": "15.6.0",
"styled-components": "1.3.0",
"uid": "0.0.2"
},
"dependencies": {
"@atlaskit/icon": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@atlaskit/icon/-/icon-8.1.0.tgz",
"integrity": "sha1-HeV48TixTcmMOFkYZbW2h+VYuDo=",
"requires": {
"babel-runtime": "6.26.0",
"prop-types": "15.6.0",
"styled-components": "1.3.0"
}
}
}
},
"@atlaskit/tooltip": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@atlaskit/tooltip/-/tooltip-6.0.0.tgz",

View File

@ -30,7 +30,6 @@
"@atlaskit/spinner": "4.0.0",
"@atlaskit/tabs": "4.0.1",
"@atlaskit/theme": "2.2.0",
"@atlaskit/toggle": "2.6.1",
"@atlaskit/tooltip": "6.0.0",
"@atlassian/aui": "6.0.6",
"autosize": "1.18.13",

View File

@ -1,14 +1,9 @@
import jitsiLocalStorage from '../../../modules/util/JitsiLocalStorage';
import {
HIDE_NOTIFICATION,
SET_NOTIFICATIONS_ENABLED,
SHOW_NOTIFICATION
} from './actionTypes';
import {
Notification,
NotificationWithToggle
} from './components';
import { Notification } from './components';
import { NOTIFICATION_TYPE } from './constants';
@ -96,33 +91,3 @@ export function showWarningNotification(props) {
appearance: NOTIFICATION_TYPE.WARNING
});
}
/**
* Displays a notification unless the passed in persistenceKey value exists in
* local storage and has been set to "true".
*
* @param {string} persistenceKey - The local storage key to look up for whether
* or not the notification should display.
* @param {Object} props - The props needed to show the notification component.
* @returns {Function}
*/
export function maybeShowNotificationWithDoNotDisplay(persistenceKey, props) {
return dispatch => {
if (jitsiLocalStorage.getItem(persistenceKey) === 'true') {
return;
}
const newProps = Object.assign({}, props, {
onToggleSubmit: isToggled => {
jitsiLocalStorage.setItem(persistenceKey, isToggled);
}
});
dispatch({
type: SHOW_NOTIFICATION,
component: NotificationWithToggle,
props: newProps,
uid: window.Date.now()
});
};
}

View File

@ -61,7 +61,8 @@ class Notification extends Component<*> {
defaultTitleKey: PropTypes.string,
/**
* The description string.
* A description string that can be used in addition to the prop
* descriptionKey.
*/
description: PropTypes.string,
@ -161,8 +162,7 @@ class Notification extends Component<*> {
<Flag
actions = { this._mapAppearanceToButtons(hideErrorSupportLink) }
appearance = { appearance }
description = { description
|| t(descriptionKey, descriptionArguments) }
description = { this._renderDescription() }
icon = { this._mapAppearanceToIcon() }
id = { uid }
isDismissAllowed = { isDismissAllowed }
@ -173,6 +173,30 @@ class Notification extends Component<*> {
_onDismissed: () => void;
/**
* Creates a {@code ReactElement} for displaying the contents of the
* notification.
*
* @private
* @returns {ReactElement}
*/
_renderDescription() {
const {
description,
descriptionArguments,
descriptionKey,
t
} = this.props;
return (
<div>
{ descriptionKey
? t(descriptionKey, descriptionArguments) : null }
{ description || null }
</div>
);
}
/**
* Calls back into {@code FlagGroup} to dismiss the notification.
*

View File

@ -1,160 +0,0 @@
import { ToggleStateless } from '@atlaskit/toggle';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { translate } from '../../base/i18n';
import { default as Notification } from './Notification';
import { NOTIFICATION_TYPE } from '../constants';
/**
* React {@code Component} for displaying a notification with a toggle element.
*
* @extends Component
*/
class NotificationWithToggle extends Component {
/**
* {@code NotificationWithToggle} component's property types.
*
* @static
*/
static propTypes = {
...Notification.propTypes,
/**
* Any additional text to display at the end of the notification message
* body.
*/
additionalMessage: PropTypes.string,
/**
* Optional callback to invoke when the notification is dismissed. The
* current value of the toggle element will be passed in.
*/
onToggleSubmit: PropTypes.func,
/**
* Whether or not the toggle element should be displayed.
*/
showToggle: PropTypes.bool,
/**
* Translation key for a message to display at the top of the
* notification body.
*/
subtitleKey: PropTypes.string,
/*
* The translation key to be used as a label describing what setting the
* toggle will change.
*/
toggleLabelKey: PropTypes.string
};
/**
* Initializes a new {@code NotificationWithToggle} instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props) {
super(props);
this.state = {
/**
* Whether or not the toggle element is active/checked/selected.
*
* @type {boolean}
*/
isToggleChecked: false
};
// Bind event handlers so they are only bound once for every instance.
this._onDismissed = this._onDismissed.bind(this);
this._onToggleChange = this._onToggleChange.bind(this);
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (
<Notification
appearance = { NOTIFICATION_TYPE.WARNING }
{ ...this.props }
description = { this._renderDescription() } />
);
}
/**
* Calls back into {@code FlagGroup} to dismiss the notification. Optionally
* will execute a passed in onToggleSubmit callback with the current state
* of the toggle element.
*
* @private
* @returns {void}
*/
_onDismissed() {
const { onDismissed, onToggleSubmit, showToggle, uid } = this.props;
if (showToggle && onToggleSubmit) {
onToggleSubmit(this.state.isToggleChecked);
}
onDismissed(uid);
}
/**
* Updates the current known state of the toggle selection.
*
* @param {Object} event - The DOM event from changing the toggle selection.
* @private
* @returns {void}
*/
_onToggleChange(event) {
this.setState({
isToggleChecked: event.target.checked
});
}
/**
* Creates a React Element for displaying the notification message as well
* as a toggle.
*
* @private
* @returns {ReactElement}
*/
_renderDescription() {
const {
additionalMessage,
descriptionKey,
showToggle,
subtitleKey,
t,
toggleLabelKey
} = this.props;
return (
<div className = 'notification-with-toggle'>
<div>{ t(subtitleKey) }</div>
{ descriptionKey ? <div>{ t(descriptionKey) }</div> : null }
{ additionalMessage ? <div>{ additionalMessage }</div>
: null }
{ showToggle
? <div>
{ t(toggleLabelKey) }
<ToggleStateless
isChecked
= { this.state.isToggleChecked }
onChange = { this._onToggleChange } />
</div>
: null }
</div>
);
}
}
export default translate(NotificationWithToggle);

View File

@ -1,3 +1,2 @@
export { default as Notification } from './Notification';
export { default as NotificationsContainer } from './NotificationsContainer';
export { default as NotificationWithToggle } from './NotificationWithToggle';