PLT-2074 Refactor desktop notification settings UI and add setting for duration (#3883)

* Refactor desktop notification settings UI and add setting for duration

* Update en.json

* Update desktop_notification_settings.jsx
Этот коммит содержится в:
Joram Wilander
2016-08-29 09:52:59 -04:00
коммит произвёл Christopher Speller
родитель d252e61c66
Коммит a76db5b84f
8 изменённых файлов: 542 добавлений и 271 удалений

Просмотреть файл

@@ -81,4 +81,4 @@ function onThemeSaved(teamId, theme, onSuccess) {
}); });
onSuccess(); onSuccess();
} }

Просмотреть файл

@@ -33,7 +33,7 @@ export default class SettingItemMin extends React.Component {
> >
<li className='col-sm-9 section-title'>{this.props.title}</li> <li className='col-sm-9 section-title'>{this.props.title}</li>
{editButton} {editButton}
<li className='col-sm-10 section-describe'>{this.props.describe}</li> <li className='col-sm-12 section-describe'>{this.props.describe}</li>
</ul> </ul>
); );
} }

Просмотреть файл

@@ -0,0 +1,454 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import SettingItemMin from 'components/setting_item_min.jsx';
import SettingItemMax from 'components/setting_item_max.jsx';
import * as Utils from 'utils/utils.jsx';
import * as UserAgent from 'utils/user_agent.jsx';
import React from 'react';
import {FormattedMessage} from 'react-intl';
export default class DesktopNotificationSettings extends React.Component {
constructor(props) {
super(props);
this.buildMaximizedSetting = this.buildMaximizedSetting.bind(this);
this.buildMinimizedSetting = this.buildMinimizedSetting.bind(this);
this.state = {};
}
buildMaximizedSetting() {
let inputs = [];
let extraInfo = null;
const activityRadio = [false, false, false];
if (this.props.activity === 'mention') {
activityRadio[1] = true;
} else if (this.props.activity === 'none') {
activityRadio[2] = true;
} else {
activityRadio[0] = true;
}
let soundSection;
let durationSection;
if (this.props.activity !== 'none') {
const soundRadio = [false, false];
if (this.props.sound === 'false') {
soundRadio[1] = true;
} else {
soundRadio[0] = true;
}
if (UserAgent.isFirefox()) {
soundSection = (
<div>
<hr/>
<label>
<FormattedMessage
id='user.settings.notifications.desktop.sound'
defaultMessage='Notification sound'
/>
</label>
<br/>
<FormattedMessage
id='user.settings.notifications.soundConfig'
defaultMessage='Please configure notification sounds in your browser settings'
/>
</div>
);
} else {
soundSection = (
<div>
<hr/>
<label>
<FormattedMessage
id='user.settings.notifications.desktop.sound'
defaultMessage='Notification sound'
/>
</label>
<br/>
<div className='radio'>
<label>
<input
type='radio'
name='notificationSounds'
checked={soundRadio[0]}
onChange={() => this.props.setParentState('desktopSound', 'true')}
/>
<FormattedMessage
id='user.settings.notifications.on'
defaultMessage='On'
/>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
name='notificationSounds'
checked={soundRadio[1]}
onChange={() => this.props.setParentState('desktopSound', 'false')}
/>
<FormattedMessage
id='user.settings.notifications.off'
defaultMessage='Off'
/>
</label>
<br/>
</div>
<br/>
<span>
<FormattedMessage
id='user.settings.notifications.sounds_info'
defaultMessage='Notification sounds are available on IE11, Edge, Safari and Chrome.'
/>
</span>
</div>
);
}
const durationRadio = [false, false, false, false];
if (this.props.duration === '3') {
durationRadio[0] = true;
} else if (this.props.duration === '10') {
durationRadio[2] = true;
} else if (this.props.duration === '0') {
durationRadio[3] = true;
} else {
durationRadio[1] = true;
}
durationSection = (
<div>
<hr/>
<label>
<FormattedMessage
id='user.settings.notifications.desktop.duration'
defaultMessage='Notification duration'
/>
</label>
<br/>
<div className='radio'>
<label>
<input
type='radio'
name='desktopDuration'
checked={durationRadio[0]}
onChange={() => this.props.setParentState('desktopDuration', '3')}
/>
<FormattedMessage
id='user.settings.notifications.desktop.seconds'
defaultMessage='{seconds} seconds'
values={{
seconds: '3'
}}
/>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
name='desktopDuration'
checked={durationRadio[1]}
onChange={() => this.props.setParentState('desktopDuration', '5')}
/>
<FormattedMessage
id='user.settings.notifications.desktop.seconds'
defaultMessage='{seconds} seconds'
values={{
seconds: '5'
}}
/>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
name='desktopDuration'
checked={durationRadio[2]}
onChange={() => this.props.setParentState('desktopDuration', '10')}
/>
<FormattedMessage
id='user.settings.notifications.desktop.seconds'
defaultMessage='{seconds} seconds'
values={{
seconds: '10'
}}
/>
</label>
</div>
<div className='radio'>
<label>
<input
type='radio'
name='desktopDuration'
checked={durationRadio[3]}
onChange={() => this.props.setParentState('desktopDuration', '0')}
/>
<FormattedMessage
id='user.settings.notifications.desktop.unlimited'
defaultMessage='Unlimited'
/>
</label>
</div>
</div>
);
extraInfo = (
<span>
<FormattedMessage
id='user.settings.notifications.desktop.durationInfo'
defaultMessage='Sets how long desktop notifications will remain on screen.'
/>
</span>
);
}
inputs.push(
<div key='userNotificationLevelOption'>
<label>
<FormattedMessage
id='user.settings.notifications.desktop'
defaultMessage='Send desktop notifications'
/>
</label>
<br/>
<div className='radio'>
<label>
<input
type='radio'
name='desktopNotificationLevel'
checked={activityRadio[0]}
onChange={() => this.props.setParentState('desktopActivity', 'all')}
/>
<FormattedMessage
id='user.settings.notifications.allActivity'
defaultMessage='For all activity'
/>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
name='desktopNotificationLevel'
checked={activityRadio[1]}
onChange={() => this.props.setParentState('desktopActivity', 'mention')}
/>
<FormattedMessage
id='user.settings.notifications.onlyMentions'
defaultMessage='Only for mentions and direct messages'
/>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
name='desktopNotificationLevel'
checked={activityRadio[2]}
onChange={() => this.props.setParentState('desktopActivity', 'none')}
/>
<FormattedMessage
id='user.settings.notifications.never'
defaultMessage='Never'
/>
</label>
</div>
<br/>
<span>
<FormattedMessage
id='user.settings.notifications.info'
defaultMessage='Desktop notifications are available on Firefox, Safari, and Chrome.'
/>
</span>
{soundSection}
{durationSection}
</div>
);
return (
<SettingItemMax
title={Utils.localizeMessage('user.settings.notifications.desktop.title', 'Desktop notifications')}
extraInfo={extraInfo}
inputs={inputs}
submit={this.props.submit}
server_error={this.props.error}
updateSection={this.props.cancel}
/>
);
}
buildMinimizedSetting() {
let describe = '';
if (this.props.activity === 'mention') {
if (UserAgent.isFirefox()) {
if (this.props.duration === '0') {
describe = (
<FormattedMessage
id='user.settings.notifications.desktop.mentionsFirefoxForever'
defaultMessage='For mentions and direct messages, shown indefinitely'
/>
);
} else {
describe = (
<FormattedMessage
id='user.settings.notifications.desktop.mentionsFirefoxTimed'
defaultMessage='For mentions and direct messages, shown for {seconds} seconds'
values={{
seconds: this.props.duration
}}
/>
);
}
} else if (this.props.sound === 'false') {
if (this.props.duration === '0') {
describe = (
<FormattedMessage
id='user.settings.notifications.desktop.mentionsNoSoundForever'
defaultMessage='For mentions and direct messages, without sound, shown indefinitely'
/>
);
} else {
describe = (
<FormattedMessage
id='user.settings.notifications.desktop.mentionsNoSoundTimed'
defaultMessage='For mentions and direct messages, without sound, shown for {seconds} seconds'
values={{
seconds: this.props.duration
}}
/>
);
}
} else {
if (this.props.duration === '0') { //eslint-disable-line no-lonely-if
describe = (
<FormattedMessage
id='user.settings.notifications.desktop.mentionsSoundForever'
defaultMessage='For mentions and direct messages, with sound, shown indefinitely'
/>
);
} else {
describe = (
<FormattedMessage
id='user.settings.notifications.desktop.mentionsSoundTimed'
defaultMessage='For mentions and direct messages, with sound, shown for {seconds} seconds'
values={{
seconds: this.props.duration
}}
/>
);
}
}
} else if (this.props.activity === 'none') {
describe = (
<FormattedMessage
id='user.settings.notifications.off'
defaultMessage='Off'
/>
);
} else {
if (UserAgent.isFirefox()) { //eslint-disable-line no-lonely-if
if (this.props.duration === '0') {
describe = (
<FormattedMessage
id='user.settings.notifications.desktop.allFirefoxForever'
defaultMessage='For all activity, shown indefinitely'
/>
);
} else {
describe = (
<FormattedMessage
id='user.settings.notifications.desktop.allFirefoxTimed'
defaultMessage='For all activity, shown for {seconds} seconds'
values={{
seconds: this.props.duration
}}
/>
);
}
} else if (this.props.sound === 'false') {
if (this.props.duration === '0') {
describe = (
<FormattedMessage
id='user.settings.notifications.desktop.allNoSoundForever'
defaultMessage='For all activity, without sound, shown indefinitely'
/>
);
} else {
describe = (
<FormattedMessage
id='user.settings.notifications.desktop.allNoSoundTimed'
defaultMessage='For all activity, without sound, shown for {seconds} seconds'
values={{
seconds: this.props.duration
}}
/>
);
}
} else {
if (this.props.duration === '0') { //eslint-disable-line no-lonely-if
describe = (
<FormattedMessage
id='user.settings.notifications.desktop.allSoundForever'
defaultMessage='For all activity, with sound, shown indefinitely'
/>
);
} else {
describe = (
<FormattedMessage
id='user.settings.notifications.desktop.allSoundTimed'
defaultMessage='For all activity, with sound, shown for {seconds} seconds'
values={{
seconds: this.props.duration
}}
/>
);
}
}
}
const handleUpdateDesktopSection = function updateDesktopSection() {
this.props.updateSection('desktop');
}.bind(this);
return (
<SettingItemMin
title={Utils.localizeMessage('user.settings.notifications.desktop.title', 'Desktop notifications')}
describe={describe}
updateSection={handleUpdateDesktopSection}
/>
);
}
render() {
if (this.props.active) {
return this.buildMaximizedSetting();
}
return this.buildMinimizedSetting();
}
}
DesktopNotificationSettings.propTypes = {
activity: React.PropTypes.string.isRequired,
sound: React.PropTypes.string.isRequired,
duration: React.PropTypes.string.isRequired,
updateSection: React.PropTypes.func,
setParentState: React.PropTypes.func,
submit: React.PropTypes.func,
cancel: React.PropTypes.func,
error: React.PropTypes.string,
active: React.PropTypes.bool
};

Просмотреть файл

@@ -4,12 +4,12 @@
import $ from 'jquery'; import $ from 'jquery';
import SettingItemMin from 'components/setting_item_min.jsx'; import SettingItemMin from 'components/setting_item_min.jsx';
import SettingItemMax from 'components/setting_item_max.jsx'; import SettingItemMax from 'components/setting_item_max.jsx';
import DesktopNotificationSettings from './desktop_notification_settings.jsx';
import UserStore from 'stores/user_store.jsx'; import UserStore from 'stores/user_store.jsx';
import Client from 'client/web_client.jsx'; import Client from 'client/web_client.jsx';
import * as AsyncClient from 'utils/async_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx';
import * as UserAgent from 'utils/user_agent.jsx';
import * as Utils from 'utils/utils.jsx'; import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx'; import Constants from 'utils/constants.jsx';
@@ -18,21 +18,24 @@ import {FormattedMessage} from 'react-intl';
function getNotificationsStateFromStores() { function getNotificationsStateFromStores() {
const user = UserStore.getCurrentUser(); const user = UserStore.getCurrentUser();
const soundNeeded = !UserAgent.isFirefox();
let sound = 'true';
let desktop = 'default'; let desktop = 'default';
let sound = 'true';
let desktopDuration = '5';
let comments = 'never'; let comments = 'never';
let enableEmail = 'true'; let enableEmail = 'true';
let pushActivity = 'mention'; let pushActivity = 'mention';
let pushStatus = Constants.UserStatuses.ONLINE; let pushStatus = Constants.UserStatuses.ONLINE;
if (user.notify_props) { if (user.notify_props) {
if (user.notify_props.desktop) {
desktop = user.notify_props.desktop;
}
if (user.notify_props.desktop_sound) { if (user.notify_props.desktop_sound) {
sound = user.notify_props.desktop_sound; sound = user.notify_props.desktop_sound;
} }
if (user.notify_props.desktop) { if (user.notify_props.desktop_duration) {
desktop = user.notify_props.desktop; desktopDuration = user.notify_props.desktop_duration;
} }
if (user.notify_props.comments) { if (user.notify_props.comments) {
comments = user.notify_props.comments; comments = user.notify_props.comments;
@@ -85,12 +88,12 @@ function getNotificationsStateFromStores() {
} }
return { return {
notifyLevel: desktop, desktopActivity: desktop,
desktopDuration,
enableEmail, enableEmail,
pushActivity, pushActivity,
pushStatus, pushStatus,
soundNeeded, desktopSound: sound,
enableSound: sound,
usernameKey, usernameKey,
mentionKey, mentionKey,
customKeys, customKeys,
@@ -110,16 +113,15 @@ export default class NotificationsTab extends React.Component {
this.handleSubmit = this.handleSubmit.bind(this); this.handleSubmit = this.handleSubmit.bind(this);
this.handleCancel = this.handleCancel.bind(this); this.handleCancel = this.handleCancel.bind(this);
this.updateSection = this.updateSection.bind(this); this.updateSection = this.updateSection.bind(this);
this.updateState = this.updateState.bind(this); this.setStateValue = this.setStateValue.bind(this);
this.onListenerChange = this.onListenerChange.bind(this); this.onListenerChange = this.onListenerChange.bind(this);
this.handleNotifyRadio = this.handleNotifyRadio.bind(this);
this.handleEmailRadio = this.handleEmailRadio.bind(this); this.handleEmailRadio = this.handleEmailRadio.bind(this);
this.handleSoundRadio = this.handleSoundRadio.bind(this);
this.updateUsernameKey = this.updateUsernameKey.bind(this); this.updateUsernameKey = this.updateUsernameKey.bind(this);
this.updateMentionKey = this.updateMentionKey.bind(this); this.updateMentionKey = this.updateMentionKey.bind(this);
this.updateFirstNameKey = this.updateFirstNameKey.bind(this); this.updateFirstNameKey = this.updateFirstNameKey.bind(this);
this.updateChannelKey = this.updateChannelKey.bind(this); this.updateChannelKey = this.updateChannelKey.bind(this);
this.updateCustomMentionKeys = this.updateCustomMentionKeys.bind(this); this.updateCustomMentionKeys = this.updateCustomMentionKeys.bind(this);
this.updateState = this.updateState.bind(this);
this.onCustomChange = this.onCustomChange.bind(this); this.onCustomChange = this.onCustomChange.bind(this);
this.createPushNotificationSection = this.createPushNotificationSection.bind(this); this.createPushNotificationSection = this.createPushNotificationSection.bind(this);
@@ -130,8 +132,9 @@ export default class NotificationsTab extends React.Component {
var data = {}; var data = {};
data.user_id = this.props.user.id; data.user_id = this.props.user.id;
data.email = this.state.enableEmail; data.email = this.state.enableEmail;
data.desktop_sound = this.state.enableSound; data.desktop_sound = this.state.desktopSound;
data.desktop = this.state.notifyLevel; data.desktop = this.state.desktopActivity;
data.desktop_duration = this.state.desktopDuration;
data.push = this.state.pushActivity; data.push = this.state.pushActivity;
data.push_status = this.state.pushStatus; data.push_status = this.state.pushStatus;
data.comments = this.state.notifyCommentsLevel; data.comments = this.state.notifyCommentsLevel;
@@ -166,12 +169,18 @@ export default class NotificationsTab extends React.Component {
} }
handleCancel(e) { handleCancel(e) {
e.preventDefault();
this.updateState(); this.updateState();
this.props.updateSection(''); this.props.updateSection('');
e.preventDefault();
$('.settings-modal .modal-body').scrollTop(0).perfectScrollbar('update'); $('.settings-modal .modal-body').scrollTop(0).perfectScrollbar('update');
} }
setStateValue(key, value) {
const data = {};
data[key] = value;
this.setState(data);
}
updateSection(section) { updateSection(section) {
this.updateState(); this.updateState();
this.props.updateSection(section); this.props.updateSection(section);
@@ -196,11 +205,6 @@ export default class NotificationsTab extends React.Component {
this.updateState(); this.updateState();
} }
handleNotifyRadio(notifyLevel) {
this.setState({notifyLevel});
this.refs.wrapper.focus();
}
handleNotifyCommentsRadio(notifyCommentsLevel) { handleNotifyCommentsRadio(notifyCommentsLevel) {
this.setState({notifyCommentsLevel}); this.setState({notifyCommentsLevel});
this.refs.wrapper.focus(); this.refs.wrapper.focus();
@@ -221,11 +225,6 @@ export default class NotificationsTab extends React.Component {
this.refs.wrapper.focus(); this.refs.wrapper.focus();
} }
handleSoundRadio(enableSound) {
this.setState({enableSound});
this.refs.wrapper.focus();
}
updateUsernameKey(val) { updateUsernameKey(val) {
this.setState({usernameKey: val}); this.setState({usernameKey: val});
} }
@@ -261,7 +260,7 @@ export default class NotificationsTab extends React.Component {
} }
createPushNotificationSection() { createPushNotificationSection() {
let handleUpdateDesktopSection; let handleUpdatePushSection;
if (this.props.activeSection === 'push') { if (this.props.activeSection === 'push') {
let inputs = []; let inputs = [];
let extraInfo = null; let extraInfo = null;
@@ -495,7 +494,7 @@ export default class NotificationsTab extends React.Component {
} }
} }
handleUpdateDesktopSection = function updateDesktopSection() { handleUpdatePushSection = function updateDesktopSection() {
this.props.updateSection('push'); this.props.updateSection('push');
}.bind(this); }.bind(this);
@@ -503,240 +502,14 @@ export default class NotificationsTab extends React.Component {
<SettingItemMin <SettingItemMin
title={Utils.localizeMessage('user.settings.notifications.push', 'Send mobile push notifications')} title={Utils.localizeMessage('user.settings.notifications.push', 'Send mobile push notifications')}
describe={describe} describe={describe}
updateSection={handleUpdateDesktopSection} updateSection={handleUpdatePushSection}
/> />
); );
} }
render() { render() {
const serverError = this.state.serverError; const serverError = this.state.serverError;
const user = this.props.user;
var user = this.props.user;
var desktopSection;
var handleUpdateDesktopSection;
if (this.props.activeSection === 'desktop') {
var notifyActive = [false, false, false];
if (this.state.notifyLevel === 'mention') {
notifyActive[1] = true;
} else if (this.state.notifyLevel === 'none') {
notifyActive[2] = true;
} else {
notifyActive[0] = true;
}
let inputs = [];
inputs.push(
<div key='userNotificationLevelOption'>
<div className='radio'>
<label>
<input
type='radio'
name='desktopNotificationLevel'
checked={notifyActive[0]}
onChange={this.handleNotifyRadio.bind(this, 'all')}
/>
<FormattedMessage
id='user.settings.notifications.allActivity'
defaultMessage='For all activity'
/>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
name='desktopNotificationLevel'
checked={notifyActive[1]}
onChange={this.handleNotifyRadio.bind(this, 'mention')}
/>
<FormattedMessage
id='user.settings.notifications.onlyMentions'
defaultMessage='Only for mentions and direct messages'
/>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
name='desktopNotificationLevel'
checked={notifyActive[2]}
onChange={this.handleNotifyRadio.bind(this, 'none')}
/>
<FormattedMessage
id='user.settings.notifications.never'
defaultMessage='Never'
/>
</label>
</div>
</div>
);
const extraInfo = (
<span>
<FormattedMessage
id='user.settings.notifications.info'
defaultMessage='Desktop notifications are available on Firefox, Safari, Chrome, Internet Explorer, and Edge.'
/>
</span>
);
desktopSection = (
<SettingItemMax
title={Utils.localizeMessage('user.settings.notifications.desktop', 'Send desktop notifications')}
extraInfo={extraInfo}
inputs={inputs}
submit={this.handleSubmit}
server_error={serverError}
updateSection={this.handleCancel}
/>
);
} else {
let describe = '';
if (this.state.notifyLevel === 'mention') {
describe = (
<FormattedMessage
id='user.settings.notifications.onlyMentions'
defaultMessage='Only for mentions and direct messages'
/>
);
} else if (this.state.notifyLevel === 'none') {
describe = (
<FormattedMessage
id='user.settings.notifications.never'
defaultMessage='Never'
/>
);
} else {
describe = (
<FormattedMessage
id='user.settings.notification.allActivity'
defaultMessage='For all activity'
/>
);
}
handleUpdateDesktopSection = function updateDesktopSection() {
this.props.updateSection('desktop');
}.bind(this);
desktopSection = (
<SettingItemMin
title={Utils.localizeMessage('user.settings.notifications.desktop', 'Send desktop notifications')}
describe={describe}
updateSection={handleUpdateDesktopSection}
/>
);
}
var soundSection;
var handleUpdateSoundSection;
if (this.props.activeSection === 'sound' && this.state.soundNeeded) {
var soundActive = [false, false];
if (this.state.enableSound === 'false') {
soundActive[1] = true;
} else {
soundActive[0] = true;
}
let inputs = [];
inputs.push(
<div key='userNotificationSoundOptions'>
<div className='radio'>
<label>
<input
type='radio'
name='notificationSounds'
checked={soundActive[0]}
onChange={this.handleSoundRadio.bind(this, 'true')}
/>
<FormattedMessage
id='user.settings.notifications.on'
defaultMessage='On'
/>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
name='notificationSounds'
checked={soundActive[1]}
onChange={this.handleSoundRadio.bind(this, 'false')}
/>
<FormattedMessage
id='user.settings.notifications.off'
defaultMessage='Off'
/>
</label>
<br/>
</div>
</div>
);
const extraInfo = (
<span>
<FormattedMessage
id='user.settings.notifications.sounds_info'
defaultMessage='Desktop notifications sounds are available on Firefox, Safari, Chrome, Internet Explorer, and Edge.'
/>
</span>
);
soundSection = (
<SettingItemMax
title={Utils.localizeMessage('user.settings.notifications.desktopSounds', 'Desktop notification sounds')}
extraInfo={extraInfo}
inputs={inputs}
submit={this.handleSubmit}
server_error={serverError}
updateSection={this.handleCancel}
/>
);
} else {
let describe = '';
if (!this.state.soundNeeded) {
describe = (
<FormattedMessage
id='user.settings.notifications.soundConfig'
defaultMessage='Please configure notification sounds in your browser settings'
/>
);
} else if (this.state.enableSound === 'false') {
describe = (
<FormattedMessage
id='user.settings.notifications.off'
defaultMessage='Off'
/>
);
} else {
describe = (
<FormattedMessage
id='user.settings.notifications.on'
defaultMessage='On'
/>
);
}
handleUpdateSoundSection = function updateSoundSection() {
this.props.updateSection('sound');
}.bind(this);
soundSection = (
<SettingItemMin
title={Utils.localizeMessage('user.settings.notifications.desktopSounds', 'Desktop notification sounds')}
describe={describe}
updateSection={handleUpdateSoundSection}
disableOpen={!this.state.soundNeeded}
/>
);
}
var keysSection; var keysSection;
var handleUpdateKeysSection; var handleUpdateKeysSection;
@@ -1089,9 +862,17 @@ export default class NotificationsTab extends React.Component {
/> />
</h3> </h3>
<div className='divider-dark first'/> <div className='divider-dark first'/>
{desktopSection} <DesktopNotificationSettings
<div className='divider-light'/> activity={this.state.desktopActivity}
{soundSection} sound={this.state.desktopSound}
duration={this.state.desktopDuration}
updateSection={this.updateSection}
setParentState={this.setStateValue}
submit={this.handleSubmit}
cancel={this.handleCancel}
error={this.state.serverError}
active={this.props.activeSection === 'desktop'}
/>
<div className='divider-light'/> <div className='divider-light'/>
<EmailNotificationSetting <EmailNotificationSetting
activeSection={this.props.activeSection} activeSection={this.props.activeSection}

Просмотреть файл

@@ -1865,6 +1865,24 @@
"user.settings.notifications.commentsNever": "No mentions for comments", "user.settings.notifications.commentsNever": "No mentions for comments",
"user.settings.notifications.commentsRoot": "Mention any comments on your post", "user.settings.notifications.commentsRoot": "Mention any comments on your post",
"user.settings.notifications.desktop": "Send desktop notifications", "user.settings.notifications.desktop": "Send desktop notifications",
"user.settings.notifications.desktop.mentionsFirefoxForever": "For mentions and direct messages, shown indefinitely",
"user.settings.notifications.desktop.mentionsFirefoxTimed": "For mentions and direct messages, shown for {seconds} seconds",
"user.settings.notifications.desktop.mentionsNoSoundForever": "For mentions and direct messages, without sound, shown indefinitely",
"user.settings.notifications.desktop.mentionsNoSoundTimed": "For mentions and direct messages, without sound, shown for {seconds} seconds",
"user.settings.notifications.desktop.mentionsSoundForever": "For mentions and direct messages, with sound, shown indefinitely",
"user.settings.notifications.desktop.mentionsSoundTimed": "For mentions and direct messages, with sound, shown for {seconds} seconds",
"user.settings.notifications.desktop.allFirefoxForever": "For all activity, shown indefinitely",
"user.settings.notifications.desktop.allFirefoxTimed": "For all activity, shown for {seconds} seconds",
"user.settings.notifications.desktop.allNoSoundForever": "For all activity, without sound, shown indefinitely",
"user.settings.notifications.desktop.allNoSoundTimed": "For all activity, without sound, shown for {seconds} seconds",
"user.settings.notifications.desktop.allSoundForever": "For all activity, with sound, shown indefinitely",
"user.settings.notifications.desktop.allSoundTimed": "For all activity, with sound, shown for {seconds} seconds",
"user.settings.notifications.desktop.title": "Desktop notifications",
"user.settings.notifications.desktop.unlimited": "Unlimited",
"user.settings.notifications.desktop.seconds": "{seconds} seconds",
"user.settings.notifications.desktop.durationInfo": "Sets how long desktop notifications will remain on screen.",
"user.settings.notifications.desktop.duration": "Notification duration",
"user.settings.notifications.desktop.sound": "Notification sound",
"user.settings.notifications.desktopSounds": "Desktop notification sounds", "user.settings.notifications.desktopSounds": "Desktop notification sounds",
"user.settings.notifications.emailBatchingInfo": "Notifications are combined into a single email and sent at the maximum frequency selected here.", "user.settings.notifications.emailBatchingInfo": "Notifications are combined into a single email and sent at the maximum frequency selected here.",
"user.settings.notifications.emailInfo": "Email notifications that are sent for mentions and direct messages when you are offline or away from {siteName} for more than 5 minutes.", "user.settings.notifications.emailInfo": "Email notifications that are sent for mentions and direct messages when you are offline or away from {siteName} for more than 5 minutes.",
@@ -1873,7 +1891,7 @@
"user.settings.notifications.everyXMinutes": "Every {count, plural, one {minute} other {{count, number} minutes}}", "user.settings.notifications.everyXMinutes": "Every {count, plural, one {minute} other {{count, number} minutes}}",
"user.settings.notifications.header": "Notifications", "user.settings.notifications.header": "Notifications",
"user.settings.notifications.immediately": "Immediately", "user.settings.notifications.immediately": "Immediately",
"user.settings.notifications.info": "Desktop notifications are available on Firefox, Safari, Chrome, Internet Explorer, and Edge.", "user.settings.notifications.info": "Desktop notifications are available on Firefox, Safari, and Chrome.",
"user.settings.notifications.never": "Never", "user.settings.notifications.never": "Never",
"user.settings.notifications.noWords": "No words configured", "user.settings.notifications.noWords": "No words configured",
"user.settings.notifications.off": "Off", "user.settings.notifications.off": "Off",
@@ -1884,7 +1902,7 @@
"user.settings.notifications.sensitiveUsername": "Your non-case sensitive username \"{username}\"", "user.settings.notifications.sensitiveUsername": "Your non-case sensitive username \"{username}\"",
"user.settings.notifications.sensitiveWords": "Other non-case sensitive words, separated by commas:", "user.settings.notifications.sensitiveWords": "Other non-case sensitive words, separated by commas:",
"user.settings.notifications.soundConfig": "Please configure notification sounds in your browser settings", "user.settings.notifications.soundConfig": "Please configure notification sounds in your browser settings",
"user.settings.notifications.sounds_info": "Desktop notifications sounds are available on Firefox, Safari, Chrome, Internet Explorer, and Edge.", "user.settings.notifications.sounds_info": "Notification sounds are available on IE11, Edge, Safari and Chrome.",
"user.settings.notifications.teamWide": "Team-wide mentions \"@all\"", "user.settings.notifications.teamWide": "Team-wide mentions \"@all\"",
"user.settings.notifications.title": "Notification Settings", "user.settings.notifications.title": "Notification Settings",
"user.settings.notifications.usernameMention": "Your username mentioned \"@{username}\"", "user.settings.notifications.usernameMention": "Your username mentioned \"@{username}\"",

Просмотреть файл

@@ -79,17 +79,26 @@ class NotificationStoreClass extends EventEmitter {
notifyText = notifyText.substring(0, 49) + '...'; notifyText = notifyText.substring(0, 49) + '...';
} }
let body = '';
if (notifyText.length === 0) { if (notifyText.length === 0) {
if (msgProps.image) { if (msgProps.image) {
Utils.notifyMe(title, username + Utils.localizeMessage('channel_loader.uploadedImage', ' uploaded an image'), channel, teamId); body = username + Utils.localizeMessage('channel_loader.uploadedImage', ' uploaded an image');
} else if (msgProps.otherFile) { } else if (msgProps.otherFile) {
Utils.notifyMe(title, username + Utils.localizeMessage('channel_loader.uploadedFile', ' uploaded a file'), channel, teamId); body = Utils.localizeMessage('channel_loader.uploadedFile', ' uploaded a file');
} else { } else {
Utils.notifyMe(title, username + Utils.localizeMessage('channel_loader.something', ' did something new'), channel, teamId); body = username + Utils.localizeMessage('channel_loader.something', ' did something new');
} }
} else { } else {
Utils.notifyMe(title, username + Utils.localizeMessage('channel_loader.wrote', ' wrote: ') + notifyText, channel, teamId); body = username + Utils.localizeMessage('channel_loader.wrote', ' wrote: ') + notifyText;
} }
let duration = Constants.DEFAULT_NOTIFICATION_DURATION;
if (user.notify_props && user.notify_props.desktop_duration) {
duration = parseInt(user.notify_props.desktop_duration, 10) * 1000;
}
Utils.notifyMe(title, body, channel, teamId, duration);
if (!user.notify_props || user.notify_props.desktop_sound === 'true') { if (!user.notify_props || user.notify_props.desktop_sound === 'true') {
Utils.ding(); Utils.ding();
} }

Просмотреть файл

@@ -809,7 +809,8 @@ export const Constants = {
PERMISSIONS_SYSTEM_ADMIN: 'system_admin', PERMISSIONS_SYSTEM_ADMIN: 'system_admin',
MENTION_MEMBERS: 'mention.members', MENTION_MEMBERS: 'mention.members',
MENTION_NONMEMBERS: 'mention.nonmembers', MENTION_NONMEMBERS: 'mention.nonmembers',
MENTION_SPECIAL: 'mention.special' MENTION_SPECIAL: 'mention.special',
DEFAULT_NOTIFICATION_DURATION: 5000
}; };
export default Constants; export default Constants;

Просмотреть файл

@@ -86,18 +86,23 @@ export function getCookie(name) {
var requestedNotificationPermission = false; var requestedNotificationPermission = false;
export function notifyMe(title, body, channel, teamId) { export function notifyMe(title, body, channel, teamId, duration) {
if (!('Notification' in window)) { if (!('Notification' in window)) {
return; return;
} }
let notificationDuration = Constants.DEFAULT_NOTIFICATION_DURATION;
if (duration != null) {
notificationDuration = duration;
}
if (Notification.permission === 'granted' || (Notification.permission === 'default' && !requestedNotificationPermission)) { if (Notification.permission === 'granted' || (Notification.permission === 'default' && !requestedNotificationPermission)) {
requestedNotificationPermission = true; requestedNotificationPermission = true;
Notification.requestPermission((permission) => { Notification.requestPermission((permission) => {
if (permission === 'granted') { if (permission === 'granted') {
try { try {
var notification = new Notification(title, {body, tag: body, icon: icon50}); var notification = new Notification(title, {body, tag: body, icon: icon50, requireInteraction: notificationDuration === 0});
notification.onclick = () => { notification.onclick = () => {
window.focus(); window.focus();
if (channel) { if (channel) {
@@ -108,9 +113,12 @@ export function notifyMe(title, body, channel, teamId) {
browserHistory.push(TeamStore.getCurrentTeamUrl() + '/channels/town-square'); browserHistory.push(TeamStore.getCurrentTeamUrl() + '/channels/town-square');
} }
}; };
setTimeout(() => {
notification.close(); if (notificationDuration > 0) {
}, 5000); setTimeout(() => {
notification.close();
}, notificationDuration);
}
} catch (e) { } catch (e) {
console.error(e); //eslint-disable-line no-console console.error(e); //eslint-disable-line no-console
} }