PLT-2664 Split out push notifications from email notifications (#3049)

* Split out push and email notification logic, always send push notifications on mention

* Add user setting to control push notifications

* Minor changeto simplify code
Этот коммит содержится в:
Joram Wilander
2016-05-19 14:33:04 -04:00
родитель fd24902194
Коммит 1492d1a3cb
6 изменённых файлов: 379 добавлений и 191 удалений

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

@@ -465,39 +465,28 @@ func handleWebhookEvents(c *Context, post *model.Post, team *model.Team, channel
}
func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *model.Channel, profileMap map[string]*model.User, members []model.ChannelMember) {
var channelName string
var bodyText string
var subjectText string
var mentionedUsers []string
if post.IsSystemMessage() {
return
}
if _, ok := profileMap[post.UserId]; !ok {
l4g.Error(utils.T("api.post.send_notifications_and_forget.user_id.error"), post.UserId)
return
}
senderName := profileMap[post.UserId].Username
toEmailMap := make(map[string]bool)
mentionedUserIds := make(map[string]bool)
alwaysNotifyUserIds := []string{}
if channel.Type == model.CHANNEL_DIRECT {
var otherUserId string
if userIds := strings.Split(channel.Name, "__"); userIds[0] == post.UserId {
otherUserId = userIds[1]
channelName = profileMap[userIds[1]].Username
} else {
otherUserId = userIds[0]
channelName = profileMap[userIds[0]].Username
}
otherUser := profileMap[otherUserId]
sendEmail := true
if _, ok := otherUser.NotifyProps["email"]; ok && otherUser.NotifyProps["email"] == "false" {
sendEmail = false
}
if sendEmail && (otherUser.IsOffline() || otherUser.IsAway()) {
toEmailMap[otherUserId] = true
}
mentionedUserIds[otherUserId] = true
} else {
// Find out who is a member of the channel, only keep those profiles
@@ -534,6 +523,10 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
if profile.NotifyProps["channel"] == "true" {
keywordMap["@channel"] = append(keywordMap["@channel"], profile.Id)
}
if profile.NotifyProps["push"] == model.USER_NOTIFY_ALL && (post.UserId != profile.Id || post.Props["from_webhook"] == "true") {
alwaysNotifyUserIds = append(alwaysNotifyUserIds, profile.Id)
}
}
// Build a map as a list of unique user_ids that are mentioned in this post
@@ -576,179 +569,54 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
if post.UserId == userId && post.Props["from_webhook"] != "true" {
continue
}
sendEmail := true
if _, ok := profileMap[userId].NotifyProps["email"]; ok && profileMap[userId].NotifyProps["email"] == "false" {
sendEmail = false
}
if sendEmail && (profileMap[userId].IsAway() || profileMap[userId].IsOffline()) {
toEmailMap[userId] = true
} else {
toEmailMap[userId] = false
}
mentionedUserIds[userId] = true
}
}
for id := range toEmailMap {
for id := range mentionedUserIds {
go updateMentionCount(post.ChannelId, id)
}
}
if len(toEmailMap) != 0 {
mentionedUsers = make([]string, 0, len(toEmailMap))
for k := range toEmailMap {
mentionedUsers = append(mentionedUsers, k)
mentionedUsersList := make([]string, 0, len(mentionedUserIds))
senderName := profileMap[post.UserId].Username
for id := range mentionedUserIds {
mentionedUsersList = append(mentionedUsersList, id)
}
if utils.Cfg.EmailSettings.SendEmailNotifications {
for _, id := range mentionedUsersList {
userAllowsEmails := profileMap[id].NotifyProps["email"] != "false"
if userAllowsEmails && (profileMap[id].IsAway() || profileMap[id].IsOffline()) {
sendNotificationEmail(c, post, profileMap[id], channel, team, senderName)
}
}
}
teamURL := c.GetSiteURL() + "/" + team.Name
sendPushNotifications := false
if *utils.Cfg.EmailSettings.SendPushNotifications {
pushServer := *utils.Cfg.EmailSettings.PushNotificationServer
if pushServer == model.MHPNS && (!utils.IsLicensed || !*utils.License.Features.MHPNS) {
l4g.Warn(utils.T("api.post.send_notifications_and_forget.push_notification.mhpnsWarn"))
sendPushNotifications = false
} else {
sendPushNotifications = true
}
}
// Build and send the emails
tm := time.Unix(post.CreateAt/1000, 0)
for id, doSend := range toEmailMap {
if !doSend {
continue
if sendPushNotifications {
for _, id := range mentionedUsersList {
if profileMap[id].NotifyProps["push"] != "none" {
sendPushNotification(post, profileMap[id], channel, senderName, true)
}
// skip if inactive
if profileMap[id].DeleteAt > 0 {
continue
}
userLocale := utils.GetUserTranslations(profileMap[id].Locale)
if channel.Type == model.CHANNEL_DIRECT {
bodyText = userLocale("api.post.send_notifications_and_forget.message_body")
subjectText = userLocale("api.post.send_notifications_and_forget.message_subject")
} else {
bodyText = userLocale("api.post.send_notifications_and_forget.mention_body")
subjectText = userLocale("api.post.send_notifications_and_forget.mention_subject")
channelName = channel.DisplayName
}
month := userLocale(tm.Month().String())
day := fmt.Sprintf("%d", tm.Day())
year := fmt.Sprintf("%d", tm.Year())
zone, _ := tm.Zone()
subjectPage := utils.NewHTMLTemplate("post_subject", profileMap[id].Locale)
subjectPage.Props["Subject"] = userLocale("api.templates.post_subject",
map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName,
"Month": month[:3], "Day": day, "Year": year})
subjectPage.Props["SiteName"] = utils.Cfg.TeamSettings.SiteName
bodyPage := utils.NewHTMLTemplate("post_body", profileMap[id].Locale)
bodyPage.Props["SiteURL"] = c.GetSiteURL()
bodyPage.Props["PostMessage"] = model.ClearMentionTags(post.Message)
bodyPage.Props["TeamLink"] = teamURL + "/channels/" + channel.Name
bodyPage.Props["BodyText"] = bodyText
bodyPage.Props["Button"] = userLocale("api.templates.post_body.button")
bodyPage.Html["Info"] = template.HTML(userLocale("api.templates.post_body.info",
map[string]interface{}{"ChannelName": channelName, "SenderName": senderName,
"Hour": fmt.Sprintf("%02d", tm.Hour()), "Minute": fmt.Sprintf("%02d", tm.Minute()),
"TimeZone": zone, "Month": month, "Day": day}))
// attempt to fill in a message body if the post doesn't have any text
if len(strings.TrimSpace(bodyPage.Props["PostMessage"])) == 0 && len(post.Filenames) > 0 {
// extract the filenames from their paths and determine what type of files are attached
filenames := make([]string, len(post.Filenames))
onlyImages := true
for i, filename := range post.Filenames {
var err error
if filenames[i], err = url.QueryUnescape(filepath.Base(filename)); err != nil {
// this should never error since filepath was escaped using url.QueryEscape
filenames[i] = filepath.Base(filename)
}
ext := filepath.Ext(filename)
onlyImages = onlyImages && model.IsFileExtImage(ext)
}
filenamesString := strings.Join(filenames, ", ")
var attachmentPrefix string
if onlyImages {
attachmentPrefix = "Image"
} else {
attachmentPrefix = "File"
}
if len(post.Filenames) > 1 {
attachmentPrefix += "s"
}
bodyPage.Props["PostMessage"] = userLocale("api.post.send_notifications_and_forget.sent",
map[string]interface{}{"Prefix": attachmentPrefix, "Filenames": filenamesString})
}
if err := utils.SendMail(profileMap[id].Email, subjectPage.Render(), bodyPage.Render()); err != nil {
l4g.Error(utils.T("api.post.send_notifications_and_forget.send.error"), profileMap[id].Email, err)
}
if *utils.Cfg.EmailSettings.SendPushNotifications {
sessionChan := Srv.Store.Session().GetSessions(id)
if result := <-sessionChan; result.Err != nil {
l4g.Error(utils.T("api.post.send_notifications_and_forget.sessions.error"), id, result.Err)
} else {
sessions := result.Data.([]*model.Session)
alreadySeen := make(map[string]string)
pushServer := *utils.Cfg.EmailSettings.PushNotificationServer
if pushServer == model.MHPNS && (!utils.IsLicensed || !*utils.License.Features.MHPNS) {
l4g.Warn(utils.T("api.post.send_notifications_and_forget.push_notification.mhpnsWarn"))
} else {
for _, session := range sessions {
if len(session.DeviceId) > 0 && alreadySeen[session.DeviceId] == "" &&
(strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":") || strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":")) {
alreadySeen[session.DeviceId] = session.DeviceId
msg := model.PushNotification{}
if badge := <-Srv.Store.User().GetUnreadCount(id); badge.Err != nil {
msg.Badge = 1
l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), id, badge.Err)
} else {
msg.Badge = int(badge.Data.(int64))
}
msg.ServerId = utils.CfgDiagnosticId
msg.ChannelId = channel.Id
msg.ChannelName = channel.Name
if strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":") {
msg.Platform = model.PUSH_NOTIFY_APPLE
msg.DeviceId = strings.TrimPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":")
} else if strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":") {
msg.Platform = model.PUSH_NOTIFY_ANDROID
msg.DeviceId = strings.TrimPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":")
}
if *utils.Cfg.EmailSettings.PushNotificationContents == model.FULL_NOTIFICATION {
if channel.Type == model.CHANNEL_DIRECT {
msg.Category = model.CATEGORY_DM
msg.Message = "@" + senderName + ": " + model.ClearMentionTags(post.Message)
} else {
msg.Message = "@" + senderName + " @ " + channelName + ": " + model.ClearMentionTags(post.Message)
}
} else {
if channel.Type == model.CHANNEL_DIRECT {
msg.Category = model.CATEGORY_DM
msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_message")
} else {
msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention") + channelName
}
}
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
}
httpClient := &http.Client{Transport: tr}
request, _ := http.NewRequest("POST", pushServer+model.API_URL_SUFFIX_V1+"/send_push", strings.NewReader(msg.ToJson()))
l4g.Debug(utils.T("api.post.send_notifications_and_forget.push_notification.debug"), msg.DeviceId, msg.Message)
if _, err := httpClient.Do(request); err != nil {
l4g.Error(utils.T("api.post.send_notifications_and_forget.push_notification.error"), id, err)
}
}
}
}
}
}
for _, id := range alwaysNotifyUserIds {
if _, ok := mentionedUserIds[id]; !ok {
sendPushNotification(post, profileMap[id], channel, senderName, false)
}
}
}
@@ -756,6 +624,7 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
message := model.NewMessage(c.TeamId, post.ChannelId, post.UserId, model.ACTION_POSTED)
message.Add("post", post.ToJson())
message.Add("channel_type", channel.Type)
message.Add("sender_name", senderName)
if len(post.Filenames) != 0 {
message.Add("otherFile", "true")
@@ -769,13 +638,173 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
}
}
if len(mentionedUsers) != 0 {
message.Add("mentions", model.ArrayToJson(mentionedUsers))
if len(mentionedUsersList) != 0 {
message.Add("mentions", model.ArrayToJson(mentionedUsersList))
}
go Publish(message)
}
func sendNotificationEmail(c *Context, post *model.Post, user *model.User, channel *model.Channel, team *model.Team, senderName string) {
// skip if inactive
if user.DeleteAt > 0 {
return
}
var channelName string
var bodyText string
var subjectText string
teamURL := c.GetSiteURL() + "/" + team.Name
tm := time.Unix(post.CreateAt/1000, 0)
userLocale := utils.GetUserTranslations(user.Locale)
if channel.Type == model.CHANNEL_DIRECT {
bodyText = userLocale("api.post.send_notifications_and_forget.message_body")
subjectText = userLocale("api.post.send_notifications_and_forget.message_subject")
channelName = senderName
} else {
bodyText = userLocale("api.post.send_notifications_and_forget.mention_body")
subjectText = userLocale("api.post.send_notifications_and_forget.mention_subject")
channelName = channel.DisplayName
}
month := userLocale(tm.Month().String())
day := fmt.Sprintf("%d", tm.Day())
year := fmt.Sprintf("%d", tm.Year())
zone, _ := tm.Zone()
subjectPage := utils.NewHTMLTemplate("post_subject", user.Locale)
subjectPage.Props["Subject"] = userLocale("api.templates.post_subject",
map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName,
"Month": month[:3], "Day": day, "Year": year})
subjectPage.Props["SiteName"] = utils.Cfg.TeamSettings.SiteName
bodyPage := utils.NewHTMLTemplate("post_body", user.Locale)
bodyPage.Props["SiteURL"] = c.GetSiteURL()
bodyPage.Props["PostMessage"] = model.ClearMentionTags(post.Message)
bodyPage.Props["TeamLink"] = teamURL + "/channels/" + channel.Name
bodyPage.Props["BodyText"] = bodyText
bodyPage.Props["Button"] = userLocale("api.templates.post_body.button")
bodyPage.Html["Info"] = template.HTML(userLocale("api.templates.post_body.info",
map[string]interface{}{"ChannelName": channelName, "SenderName": senderName,
"Hour": fmt.Sprintf("%02d", tm.Hour()), "Minute": fmt.Sprintf("%02d", tm.Minute()),
"TimeZone": zone, "Month": month, "Day": day}))
// attempt to fill in a message body if the post doesn't have any text
if len(strings.TrimSpace(bodyPage.Props["PostMessage"])) == 0 && len(post.Filenames) > 0 {
// extract the filenames from their paths and determine what type of files are attached
filenames := make([]string, len(post.Filenames))
onlyImages := true
for i, filename := range post.Filenames {
var err error
if filenames[i], err = url.QueryUnescape(filepath.Base(filename)); err != nil {
// this should never error since filepath was escaped using url.QueryEscape
filenames[i] = filepath.Base(filename)
}
ext := filepath.Ext(filename)
onlyImages = onlyImages && model.IsFileExtImage(ext)
}
filenamesString := strings.Join(filenames, ", ")
var attachmentPrefix string
if onlyImages {
attachmentPrefix = "Image"
} else {
attachmentPrefix = "File"
}
if len(post.Filenames) > 1 {
attachmentPrefix += "s"
}
bodyPage.Props["PostMessage"] = userLocale("api.post.send_notifications_and_forget.sent",
map[string]interface{}{"Prefix": attachmentPrefix, "Filenames": filenamesString})
}
if err := utils.SendMail(user.Email, subjectPage.Render(), bodyPage.Render()); err != nil {
l4g.Error(utils.T("api.post.send_notifications_and_forget.send.error"), user.Email, err)
}
}
func sendPushNotification(post *model.Post, user *model.User, channel *model.Channel, senderName string, wasMentioned bool) {
var sessions []*model.Session
if result := <-Srv.Store.Session().GetSessions(user.Id); result.Err != nil {
l4g.Error(utils.T("api.post.send_notifications_and_forget.sessions.error"), user.Id, result.Err)
return
} else {
sessions = result.Data.([]*model.Session)
}
var channelName string
if channel.Type == model.CHANNEL_DIRECT {
channelName = senderName
} else {
channelName = channel.DisplayName
}
userLocale := utils.GetUserTranslations(user.Locale)
for _, session := range sessions {
if len(session.DeviceId) > 0 &&
(strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":") || strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":")) {
msg := model.PushNotification{}
if badge := <-Srv.Store.User().GetUnreadCount(user.Id); badge.Err != nil {
msg.Badge = 1
l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), user.Id, badge.Err)
} else {
msg.Badge = int(badge.Data.(int64))
}
msg.ServerId = utils.CfgDiagnosticId
msg.ChannelId = channel.Id
msg.ChannelName = channel.Name
if strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":") {
msg.Platform = model.PUSH_NOTIFY_APPLE
msg.DeviceId = strings.TrimPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":")
} else if strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":") {
msg.Platform = model.PUSH_NOTIFY_ANDROID
msg.DeviceId = strings.TrimPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":")
}
if *utils.Cfg.EmailSettings.PushNotificationContents == model.FULL_NOTIFICATION {
if channel.Type == model.CHANNEL_DIRECT {
msg.Category = model.CATEGORY_DM
msg.Message = "@" + senderName + ": " + model.ClearMentionTags(post.Message)
} else {
msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_in") + channelName + ": " + model.ClearMentionTags(post.Message)
}
} else {
if channel.Type == model.CHANNEL_DIRECT {
msg.Category = model.CATEGORY_DM
msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_message")
} else if wasMentioned {
msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention") + channelName
} else {
msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_non_mention") + channelName
}
}
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
}
httpClient := &http.Client{Transport: tr}
request, _ := http.NewRequest("POST", *utils.Cfg.EmailSettings.PushNotificationServer+model.API_URL_SUFFIX_V1+"/send_push", strings.NewReader(msg.ToJson()))
l4g.Debug(utils.T("api.post.send_notifications_and_forget.push_notification.debug"), msg.DeviceId, msg.Message)
if _, err := httpClient.Do(request); err != nil {
l4g.Error(utils.T("api.post.send_notifications_and_forget.push_notification.error"), user.Id, err)
}
// notification sent, don't need to check other sessions
break
}
}
}
func updateMentionCount(channelId, userId string) {
if result := <-Srv.Store.Channel().IncrementMentionCount(channelId, userId); result.Err != nil {
l4g.Error(utils.T("api.post.update_mention_count_and_forget.update_error"), userId, channelId, result.Err)

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

@@ -903,6 +903,14 @@
"id": "api.post.send_notifications_and_forget.push_mention",
"translation": " mentioned you in "
},
{
"id": "api.post.send_notifications_and_forget.push_in",
"translation": " in "
},
{
"id": "api.post.send_notifications_and_forget.push_non_mention",
"translation": " posted in "
},
{
"id": "api.post.send_notifications_and_forget.push_message",
"translation": " sent you a direct message"

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

@@ -191,6 +191,7 @@ func (u *User) PreUpdate() {
func (u *User) SetDefaultNotifications() {
u.NotifyProps = make(map[string]string)
u.NotifyProps["email"] = "true"
u.NotifyProps["push"] = USER_NOTIFY_MENTION
u.NotifyProps["desktop"] = USER_NOTIFY_ALL
u.NotifyProps["desktop_sound"] = "true"
u.NotifyProps["mention_keys"] = u.Username + ",@" + u.Username

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

@@ -219,6 +219,7 @@ func getClientConfig(c *model.Config) map[string]string {
props["EnableDeveloper"] = strconv.FormatBool(*c.ServiceSettings.EnableDeveloper)
props["SendEmailNotifications"] = strconv.FormatBool(c.EmailSettings.SendEmailNotifications)
props["SendPushNotifications"] = strconv.FormatBool(*c.EmailSettings.SendPushNotifications)
props["EnableSignUpWithEmail"] = strconv.FormatBool(c.EmailSettings.EnableSignUpWithEmail)
props["EnableSignInWithEmail"] = strconv.FormatBool(*c.EmailSettings.EnableSignInWithEmail)
props["EnableSignInWithUsername"] = strconv.FormatBool(*c.EmailSettings.EnableSignInWithUsername)

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

@@ -30,6 +30,10 @@ function getNotificationsStateFromStores() {
if (user.notify_props && user.notify_props.email) {
email = user.notify_props.email;
}
var push = 'mention';
if (user.notify_props && user.notify_props.push) {
push = user.notify_props.push;
}
var usernameKey = false;
var mentionKey = false;
@@ -72,9 +76,20 @@ function getNotificationsStateFromStores() {
}
}
return {notifyLevel: desktop, enableEmail: email, soundNeeded: soundNeeded, enableSound: sound,
usernameKey: usernameKey, mentionKey: mentionKey, customKeys: customKeys, customKeysChecked: customKeys.length > 0,
firstNameKey: firstNameKey, allKey: allKey, channelKey: channelKey};
return {
notifyLevel: desktop,
notifyPushLevel: push,
enableEmail: email,
soundNeeded,
enableSound: sound,
usernameKey,
mentionKey,
customKeys,
customKeysChecked: customKeys.length > 0,
firstNameKey,
allKey,
channelKey
};
}
const holders = defineMessages({
@@ -121,6 +136,7 @@ class NotificationsTab extends React.Component {
this.updateChannelKey = this.updateChannelKey.bind(this);
this.updateCustomMentionKeys = this.updateCustomMentionKeys.bind(this);
this.onCustomChange = this.onCustomChange.bind(this);
this.createPushNotificationSection = this.createPushNotificationSection.bind(this);
this.state = getNotificationsStateFromStores();
}
@@ -130,6 +146,7 @@ class NotificationsTab extends React.Component {
data.email = this.state.enableEmail;
data.desktop_sound = this.state.enableSound;
data.desktop = this.state.notifyLevel;
data.push = this.state.notifyPushLevel;
var mentionKeys = [];
if (this.state.usernameKey) {
@@ -185,15 +202,21 @@ class NotificationsTab extends React.Component {
this.updateState();
}
handleNotifyRadio(notifyLevel) {
this.setState({notifyLevel: notifyLevel});
this.setState({notifyLevel});
ReactDOM.findDOMNode(this.refs.wrapper).focus();
}
handlePushRadio(notifyPushLevel) {
this.setState({notifyPushLevel});
ReactDOM.findDOMNode(this.refs.wrapper).focus();
}
handleEmailRadio(enableEmail) {
this.setState({enableEmail: enableEmail});
this.setState({enableEmail});
ReactDOM.findDOMNode(this.refs.wrapper).focus();
}
handleSoundRadio(enableSound) {
this.setState({enableSound: enableSound});
this.setState({enableSound});
ReactDOM.findDOMNode(this.refs.wrapper).focus();
}
updateUsernameKey(val) {
@@ -227,12 +250,126 @@ class NotificationsTab extends React.Component {
ReactDOM.findDOMNode(this.refs.customcheck).checked = true;
this.updateCustomMentionKeys();
}
createPushNotificationSection() {
var handleUpdateDesktopSection;
if (this.props.activeSection === 'push') {
var notifyActive = [false, false, false];
if (this.state.notifyPushLevel === 'all') {
notifyActive[0] = true;
} else if (this.state.notifyPushLevel === 'none') {
notifyActive[2] = true;
} else {
notifyActive[1] = true;
}
let inputs = [];
inputs.push(
<div key='userNotificationLevelOption'>
<div className='radio'>
<label>
<input
type='radio'
checked={notifyActive[0]}
onChange={this.handlePushRadio.bind(this, 'all')}
/>
<FormattedMessage
id='user.settings.push_notification.allActivity'
defaultMessage='For all activity'
/>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
checked={notifyActive[1]}
onChange={this.handlePushRadio.bind(this, 'mention')}
/>
<FormattedMessage
id='user.settings.push_notifications.onlyMentions'
defaultMessage='For mentions and direct messages'
/>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
checked={notifyActive[2]}
onChange={this.handlePushRadio.bind(this, 'none')}
/>
<FormattedMessage
id='user.settings.push_notifications.off'
defaultMessage='Off'
/>
</label>
</div>
</div>
);
const extraInfo = (
<span>
<FormattedMessage
id='user.settings.push_notifications.info'
defaultMessage='Notification alerts are pushed to your mobile device when there is activity in Mattermost.'
/>
</span>
);
return (
<SettingItemMax
title={Utils.localizeMessage('user.settings.notifications.push', 'Mobile push notifications')}
extraInfo={extraInfo}
inputs={inputs}
submit={this.handleSubmit}
server_error={this.state.serverError}
updateSection={this.handleCancel}
/>
);
}
let describe = '';
if (this.state.notifyPushLevel === 'all') {
describe = (
<FormattedMessage
id='user.settings.push_notification.allActivity'
defaultMessage='For all activity'
/>
);
} else if (this.state.notifyPushLevel === 'none') {
describe = (
<FormattedMessage
id='user.settings.push_notifications.off'
defaultMessage='Off'
/>
);
} else {
describe = (
<FormattedMessage
id='user.settings.push_notifications.onlyMentions'
defaultMessage='For mentions and direct messages'
/>
);
}
handleUpdateDesktopSection = function updateDesktopSection() {
this.props.updateSection('push');
}.bind(this);
return (
<SettingItemMin
title={Utils.localizeMessage('user.settings.notifications.push', 'Mobile push notifications')}
describe={describe}
updateSection={handleUpdateDesktopSection}
/>
);
}
render() {
const {formatMessage} = this.props.intl;
var serverError = null;
if (this.state.serverError) {
serverError = this.state.serverError;
}
const serverError = this.state.serverError;
var user = this.props.user;
@@ -764,6 +901,11 @@ class NotificationsTab extends React.Component {
);
}
let pushNotificationSection;
if (global.window.mm_config.SendPushNotifications === 'true') {
pushNotificationSection = this.createPushNotificationSection();
}
return (
<div>
<div className='modal-header'>
@@ -809,6 +951,8 @@ class NotificationsTab extends React.Component {
<div className='divider-light'/>
{emailSection}
<div className='divider-light'/>
{pushNotificationSection}
<div className='divider-light'/>
{keysSection}
<div className='divider-dark'/>
</div>

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

@@ -1390,6 +1390,11 @@
"user.settings.modal.notifications": "Notifications",
"user.settings.modal.security": "Security",
"user.settings.modal.title": "Account Settings",
"user.settings.push_notification.off": "Off",
"user.settings.push_notification.onlyMentions": "For mentions and direct messages",
"user.settings.push_notification.allActivity": "For all activity",
"user.settings.push_notification.info": "Notification alerts are pushed to your mobile device when there is activity in Mattermost.",
"user.settings.notification.push": "Mobile push notifications",
"user.settings.notification.allActivity": "For all activity",
"user.settings.notification.soundConfig": "Please configure notification sounds in your browser settings",
"user.settings.notifications.channelWide": "Channel-wide mentions \"@channel\"",