Fix browser notification permission request logic (#13543)
* Add notification permission handling code * Request notification permission when enabling any notification setting * Add badge to notification settings when permissions insufficient * Disable alerts by default, requesting permission and enable them on onboarding
This commit is contained in:
@ -4,6 +4,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import ClearColumnButton from './clear_column_button';
|
||||
import SettingToggle from './setting_toggle';
|
||||
import Icon from 'mastodon/components/icon';
|
||||
|
||||
export default class ColumnSettings extends React.PureComponent {
|
||||
|
||||
@ -12,6 +13,10 @@ export default class ColumnSettings extends React.PureComponent {
|
||||
pushSettings: ImmutablePropTypes.map.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onClear: PropTypes.func.isRequired,
|
||||
onRequestNotificationPermission: PropTypes.func.isRequired,
|
||||
alertsEnabled: PropTypes.bool,
|
||||
browserSupport: PropTypes.bool,
|
||||
browserPermission: PropTypes.bool,
|
||||
};
|
||||
|
||||
onPushChange = (path, checked) => {
|
||||
@ -19,7 +24,7 @@ export default class ColumnSettings extends React.PureComponent {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { settings, pushSettings, onChange, onClear } = this.props;
|
||||
const { settings, pushSettings, onChange, onClear, onRequestNotificationPermission, alertsEnabled, browserSupport, browserPermission } = this.props;
|
||||
|
||||
const filterShowStr = <FormattedMessage id='notifications.column_settings.filter_bar.show' defaultMessage='Show' />;
|
||||
const filterAdvancedStr = <FormattedMessage id='notifications.column_settings.filter_bar.advanced' defaultMessage='Display all categories' />;
|
||||
@ -30,8 +35,40 @@ export default class ColumnSettings extends React.PureComponent {
|
||||
const showPushSettings = pushSettings.get('browserSupport') && pushSettings.get('isSubscribed');
|
||||
const pushStr = showPushSettings && <FormattedMessage id='notifications.column_settings.push' defaultMessage='Push notifications' />;
|
||||
|
||||
const settingsIssues = [];
|
||||
|
||||
if (alertsEnabled && browserSupport && browserPermission !== 'granted') {
|
||||
if (browserPermission === 'denied') {
|
||||
settingsIssues.push(
|
||||
<button
|
||||
className='text-btn column-header__issue-btn'
|
||||
tabIndex='0'
|
||||
onClick={onRequestNotificationPermission}
|
||||
>
|
||||
<Icon id='exclamation-circle' /> <FormattedMessage id='notifications.permission_denied' defaultMessage='Mastodon cannot show notifications because the permission has been denied' />
|
||||
</button>
|
||||
);
|
||||
} else if (browserPermission === 'default') {
|
||||
settingsIssues.push(
|
||||
<button
|
||||
className='text-btn column-header__issue-btn'
|
||||
tabIndex='0'
|
||||
onClick={onRequestNotificationPermission}
|
||||
>
|
||||
<Icon id='exclamation-circle' /> <FormattedMessage id='notifications.request_permission' defaultMessage='Enable browser notifications' />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{settingsIssues && (
|
||||
<div className='column-settings__row'>
|
||||
{settingsIssues}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className='column-settings__row'>
|
||||
<ClearColumnButton onClick={onClear} />
|
||||
</div>
|
||||
|
@ -3,28 +3,55 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ColumnSettings from '../components/column_settings';
|
||||
import { changeSetting } from '../../../actions/settings';
|
||||
import { setFilter } from '../../../actions/notifications';
|
||||
import { clearNotifications } from '../../../actions/notifications';
|
||||
import { clearNotifications, requestBrowserPermission } from '../../../actions/notifications';
|
||||
import { changeAlerts as changePushNotifications } from '../../../actions/push_notifications';
|
||||
import { openModal } from '../../../actions/modal';
|
||||
import { showAlert } from '../../../actions/alerts';
|
||||
|
||||
const messages = defineMessages({
|
||||
clearMessage: { id: 'notifications.clear_confirmation', defaultMessage: 'Are you sure you want to permanently clear all your notifications?' },
|
||||
clearConfirm: { id: 'notifications.clear', defaultMessage: 'Clear notifications' },
|
||||
permissionDenied: { id: 'notifications.permission_denied', defaultMessage: 'Cannot enable desktop notifications as permission has been denied.' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
settings: state.getIn(['settings', 'notifications']),
|
||||
pushSettings: state.get('push_notifications'),
|
||||
alertsEnabled: state.getIn(['settings', 'notifications', 'alerts']).includes(true),
|
||||
browserSupport: state.getIn(['notifications', 'browserSupport']),
|
||||
browserPermission: state.getIn(['notifications', 'browserPermission']),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||
|
||||
onChange (path, checked) {
|
||||
if (path[0] === 'push') {
|
||||
dispatch(changePushNotifications(path.slice(1), checked));
|
||||
if (checked && typeof window.Notification !== 'undefined' && Notification.permission !== 'granted') {
|
||||
dispatch(requestBrowserPermission((permission) => {
|
||||
if (permission === 'granted') {
|
||||
dispatch(changePushNotifications(path.slice(1), checked));
|
||||
} else {
|
||||
dispatch(showAlert(undefined, messages.permissionDenied));
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
dispatch(changePushNotifications(path.slice(1), checked));
|
||||
}
|
||||
} else if (path[0] === 'quickFilter') {
|
||||
dispatch(changeSetting(['notifications', ...path], checked));
|
||||
dispatch(setFilter('all'));
|
||||
} else if (path[0] === 'alerts' && checked && typeof window.Notification !== 'undefined' && Notification.permission !== 'granted') {
|
||||
if (checked && typeof window.Notification !== 'undefined' && Notification.permission !== 'granted') {
|
||||
dispatch(requestBrowserPermission((permission) => {
|
||||
if (permission === 'granted') {
|
||||
dispatch(changeSetting(['notifications', ...path], checked));
|
||||
} else {
|
||||
dispatch(showAlert(undefined, messages.permissionDenied));
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
dispatch(changeSetting(['notifications', ...path], checked));
|
||||
}
|
||||
} else {
|
||||
dispatch(changeSetting(['notifications', ...path], checked));
|
||||
}
|
||||
@ -38,6 +65,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||
}));
|
||||
},
|
||||
|
||||
onRequestNotificationPermission () {
|
||||
dispatch(requestBrowserPermission());
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ColumnSettings));
|
||||
|
@ -55,6 +55,7 @@ const mapStateToProps = state => ({
|
||||
numPending: state.getIn(['notifications', 'pendingItems'], ImmutableList()).size,
|
||||
lastReadId: state.getIn(['notifications', 'readMarkerId']),
|
||||
canMarkAsRead: state.getIn(['notifications', 'readMarkerId']) !== '0' && getNotifications(state).some(item => item !== null && compareId(item.get('id'), state.getIn(['notifications', 'readMarkerId'])) > 0),
|
||||
needsNotificationPermission: state.getIn(['settings', 'notifications', 'alerts']).includes(true) && state.getIn(['notifications', 'browserSupport']) && state.getIn(['notifications', 'browserPermission']) !== 'granted',
|
||||
});
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
@ -75,6 +76,7 @@ class Notifications extends React.PureComponent {
|
||||
numPending: PropTypes.number,
|
||||
lastReadId: PropTypes.string,
|
||||
canMarkAsRead: PropTypes.bool,
|
||||
needsNotificationPermission: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
@ -250,6 +252,7 @@ class Notifications extends React.PureComponent {
|
||||
pinned={pinned}
|
||||
multiColumn={multiColumn}
|
||||
extraButton={extraButton}
|
||||
collapseIssues={this.props.needsNotificationPermission}
|
||||
>
|
||||
<ColumnSettingsContainer />
|
||||
</ColumnHeader>
|
||||
|
Reference in New Issue
Block a user