mirror of
https://github.com/mattermost/mattermost.git
synced 2026-05-28 04:35:04 -04:00
Merge 3e9d017a61 into cfafefe58c
This commit is contained in:
commit
7296f28e66
8 changed files with 253 additions and 4 deletions
|
|
@ -813,6 +813,35 @@ func (a *App) buildIdLoadedPushNotificationMessage(rctx request.CTX, channel *mo
|
|||
return msg
|
||||
}
|
||||
|
||||
func PriorityNotificationTitle(priority *model.PostPriority, rootID string, channelType model.ChannelType, channelName string, userLocale i18n.TranslateFunc) string {
|
||||
if rootID != "" || priority == nil || priority.Priority == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch *priority.Priority {
|
||||
case model.PostPriorityImportant:
|
||||
switch channelType {
|
||||
case model.ChannelTypeDirect:
|
||||
return userLocale("api.push_notification.title.important_dm")
|
||||
case model.ChannelTypeGroup:
|
||||
return userLocale("api.push_notification.title.important_gm")
|
||||
default:
|
||||
return userLocale("api.push_notification.title.important_channel", map[string]any{"channelName": channelName})
|
||||
}
|
||||
case model.PostPriorityUrgent:
|
||||
switch channelType {
|
||||
case model.ChannelTypeDirect:
|
||||
return userLocale("api.push_notification.title.urgent_dm")
|
||||
case model.ChannelTypeGroup:
|
||||
return userLocale("api.push_notification.title.urgent_gm")
|
||||
default:
|
||||
return userLocale("api.push_notification.title.urgent_channel", map[string]any{"channelName": channelName})
|
||||
}
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) buildFullPushNotificationMessage(rctx request.CTX, contentsConfig string, post *model.Post, user *model.User, channel *model.Channel, channelName string, senderName string,
|
||||
explicitMention bool, channelWideMention bool, replyToThreadType string,
|
||||
) *model.PushNotification {
|
||||
|
|
@ -833,6 +862,9 @@ func (a *App) buildFullPushNotificationMessage(rctx request.CTX, contentsConfig
|
|||
cfg := a.Config()
|
||||
if contentsConfig != model.GenericNoChannelNotification || channel.Type == model.ChannelTypeDirect {
|
||||
msg.ChannelName = channelName
|
||||
if priorityTitle := PriorityNotificationTitle(post.GetPriority(), post.RootId, channel.Type, channelName, userLocale); priorityTitle != "" {
|
||||
msg.ChannelName = priorityTitle
|
||||
}
|
||||
}
|
||||
|
||||
if a.IsCRTEnabledForUser(rctx, user.Id) {
|
||||
|
|
|
|||
|
|
@ -1083,6 +1083,98 @@ func TestBuildPushNotificationMessageMentions(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBuildFullPushNotificationMessagePriorityTitles(t *testing.T) {
|
||||
mainHelper.Parallel(t)
|
||||
th := Setup(t)
|
||||
|
||||
for name, tc := range map[string]struct {
|
||||
priority string
|
||||
channelType model.ChannelType
|
||||
channelName string
|
||||
rootID string
|
||||
contentsConfig string
|
||||
expectedTitle string
|
||||
}{
|
||||
"urgent channel root post": {
|
||||
priority: model.PostPriorityUrgent,
|
||||
channelType: model.ChannelTypeOpen,
|
||||
channelName: "Town Square",
|
||||
expectedTitle: "URGENT message in Town Square",
|
||||
},
|
||||
"urgent direct message root post": {
|
||||
priority: model.PostPriorityUrgent,
|
||||
channelType: model.ChannelTypeDirect,
|
||||
channelName: "@sender",
|
||||
expectedTitle: "URGENT Direct Message",
|
||||
},
|
||||
"urgent group message root post": {
|
||||
priority: model.PostPriorityUrgent,
|
||||
channelType: model.ChannelTypeGroup,
|
||||
channelName: "sender, receiver",
|
||||
expectedTitle: "URGENT Group Message",
|
||||
},
|
||||
"important channel root post": {
|
||||
priority: model.PostPriorityImportant,
|
||||
channelType: model.ChannelTypeOpen,
|
||||
channelName: "Town Square",
|
||||
expectedTitle: "IMPORTANT message in Town Square",
|
||||
},
|
||||
"important direct message root post": {
|
||||
priority: model.PostPriorityImportant,
|
||||
channelType: model.ChannelTypeDirect,
|
||||
channelName: "@sender",
|
||||
expectedTitle: "IMPORTANT Direct Message",
|
||||
},
|
||||
"important group message root post": {
|
||||
priority: model.PostPriorityImportant,
|
||||
channelType: model.ChannelTypeGroup,
|
||||
channelName: "sender, receiver",
|
||||
expectedTitle: "IMPORTANT Group Message",
|
||||
},
|
||||
"priority reply keeps channel title": {
|
||||
priority: model.PostPriorityUrgent,
|
||||
channelType: model.ChannelTypeOpen,
|
||||
channelName: "Town Square",
|
||||
rootID: model.NewId(),
|
||||
expectedTitle: "Reply in Town Square",
|
||||
},
|
||||
"generic no channel keeps channel title hidden": {
|
||||
priority: model.PostPriorityUrgent,
|
||||
channelType: model.ChannelTypeOpen,
|
||||
channelName: "Town Square",
|
||||
contentsConfig: model.GenericNoChannelNotification,
|
||||
expectedTitle: "",
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
contentsConfig := tc.contentsConfig
|
||||
if contentsConfig == "" {
|
||||
contentsConfig = model.FullNotification
|
||||
}
|
||||
|
||||
post := &model.Post{
|
||||
Id: model.NewId(),
|
||||
UserId: model.NewId(),
|
||||
RootId: tc.rootID,
|
||||
Message: "hello",
|
||||
Metadata: &model.PostMetadata{
|
||||
Priority: &model.PostPriority{
|
||||
Priority: model.NewPointer(tc.priority),
|
||||
},
|
||||
},
|
||||
}
|
||||
channel := &model.Channel{
|
||||
Id: model.NewId(),
|
||||
Type: tc.channelType,
|
||||
}
|
||||
user := &model.User{Locale: "en"}
|
||||
|
||||
msg := th.App.buildFullPushNotificationMessage(th.Context, contentsConfig, post, user, channel, tc.channelName, "sender", false, false, "")
|
||||
assert.Equal(t, tc.expectedTitle, msg.ChannelName)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendPushNotifications(t *testing.T) {
|
||||
mainHelper.Parallel(t)
|
||||
th := Setup(t).InitBasic(t)
|
||||
|
|
|
|||
|
|
@ -326,6 +326,11 @@ func (a *App) sendPersistentNotifications(post *model.Post, channel *model.Chann
|
|||
Sender: sender,
|
||||
}
|
||||
|
||||
if post.GetPriority() == nil {
|
||||
post = a.PreparePostForClient(request.EmptyContext(a.Log()), post, &model.PreparePostForClientOpts{IncludePriority: true})
|
||||
notification.Post = post
|
||||
}
|
||||
|
||||
if int64(len(mentionedUsersList)) > *a.Config().TeamSettings.MaxNotificationsPerChannel {
|
||||
return errors.Errorf("mentioned users: %d are more than allowed users: %d", len(mentionedUsersList), *a.Config().TeamSettings.MaxNotificationsPerChannel)
|
||||
}
|
||||
|
|
@ -372,7 +377,6 @@ func (a *App) sendPersistentNotifications(post *model.Post, channel *model.Chann
|
|||
}
|
||||
|
||||
if len(desktopUsers) != 0 {
|
||||
post = a.PreparePostForClient(request.EmptyContext(a.Log()), post, &model.PreparePostForClientOpts{IncludePriority: true})
|
||||
postJSON, jsonErr := post.ToJSON()
|
||||
if jsonErr != nil {
|
||||
return errors.Wrapf(jsonErr, "failed to encode post to JSON")
|
||||
|
|
|
|||
|
|
@ -3330,6 +3330,30 @@
|
|||
"id": "api.push_notification.title.collapsed_threads_dm",
|
||||
"translation": "Reply in Direct Message"
|
||||
},
|
||||
{
|
||||
"id": "api.push_notification.title.important_channel",
|
||||
"translation": "IMPORTANT message in {{.channelName}}"
|
||||
},
|
||||
{
|
||||
"id": "api.push_notification.title.important_dm",
|
||||
"translation": "IMPORTANT Direct Message"
|
||||
},
|
||||
{
|
||||
"id": "api.push_notification.title.important_gm",
|
||||
"translation": "IMPORTANT Group Message"
|
||||
},
|
||||
{
|
||||
"id": "api.push_notification.title.urgent_channel",
|
||||
"translation": "URGENT message in {{.channelName}}"
|
||||
},
|
||||
{
|
||||
"id": "api.push_notification.title.urgent_dm",
|
||||
"translation": "URGENT Direct Message"
|
||||
},
|
||||
{
|
||||
"id": "api.push_notification.title.urgent_gm",
|
||||
"translation": "URGENT Group Message"
|
||||
},
|
||||
{
|
||||
"id": "api.push_notifications.message.parse.app_error",
|
||||
"translation": "An error occurred building the push notification message."
|
||||
|
|
|
|||
|
|
@ -110,7 +110,8 @@ const (
|
|||
PostPropsSharedChannelState = "shared_channel_state"
|
||||
PostPropsSharedChannelWorkspaceName = "workspace_name"
|
||||
|
||||
PostPriorityUrgent = "urgent"
|
||||
PostPriorityImportant = "important"
|
||||
PostPriorityUrgent = "urgent"
|
||||
|
||||
DefaultExpirySeconds = 60 * 60 * 24 * 7 // 7 days
|
||||
DefaultReadDurationSeconds = 10 * 60 // 10 minutes
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {PostPriority} from '@mattermost/types/posts';
|
||||
|
||||
import {MarkUnread} from 'mattermost-redux/constants/channels';
|
||||
|
||||
import testConfigureStore from 'tests/test_store';
|
||||
|
|
@ -223,6 +225,59 @@ describe('notification_actions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test.each([
|
||||
['urgent channel message', 'channel_id', Constants.OPEN_CHANNEL, PostPriority.URGENT, 'URGENT message in Utopia'],
|
||||
['urgent direct message', 'channel_id', Constants.DM_CHANNEL, PostPriority.URGENT, 'URGENT Direct Message'],
|
||||
['urgent group message', 'gm_channel', Constants.GM_CHANNEL, PostPriority.URGENT, 'URGENT Group Message'],
|
||||
['important channel message', 'channel_id', Constants.OPEN_CHANNEL, PostPriority.IMPORTANT, 'IMPORTANT message in Utopia'],
|
||||
['important direct message', 'channel_id', Constants.DM_CHANNEL, PostPriority.IMPORTANT, 'IMPORTANT Direct Message'],
|
||||
['important group message', 'gm_channel', Constants.GM_CHANNEL, PostPriority.IMPORTANT, 'IMPORTANT Group Message'],
|
||||
])('should notify user with priority title for %s', async (_name, channelId, channelType, priority, expectedTitle) => {
|
||||
post = {
|
||||
...post,
|
||||
root_id: '',
|
||||
channel_id: channelId,
|
||||
metadata: {
|
||||
priority: {
|
||||
priority,
|
||||
},
|
||||
},
|
||||
};
|
||||
msgProps = {
|
||||
...msgProps,
|
||||
post: JSON.stringify(post),
|
||||
channel_type: channelType,
|
||||
};
|
||||
baseState.entities.channels.channels[channelId].type = channelType;
|
||||
|
||||
const store = testConfigureStore(baseState);
|
||||
|
||||
return store.dispatch(sendDesktopNotification(post, msgProps)).then(() => {
|
||||
expect(spy).toHaveBeenCalledWith(expect.objectContaining({
|
||||
title: expectedTitle,
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
test('should not use priority title for thread reply notifications', async () => {
|
||||
post = {
|
||||
...post,
|
||||
metadata: {
|
||||
priority: {
|
||||
priority: PostPriority.URGENT,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const store = testConfigureStore(baseState);
|
||||
|
||||
return store.dispatch(sendDesktopNotification(post, msgProps)).then(() => {
|
||||
expect(spy).toHaveBeenCalledWith(expect.objectContaining({
|
||||
title: 'Utopia',
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
test('should not notify user when tab and channel are active', async () => {
|
||||
const store = testConfigureStore(baseState);
|
||||
baseState.views.browser.focused = true;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import type {Channel, ChannelMembership} from '@mattermost/types/channels';
|
|||
import type {ServerError} from '@mattermost/types/errors';
|
||||
import {isMessageAttachmentArray} from '@mattermost/types/message_attachments';
|
||||
import type {Post} from '@mattermost/types/posts';
|
||||
import {PostPriority} from '@mattermost/types/posts';
|
||||
import type {UserProfile} from '@mattermost/types/users';
|
||||
|
||||
import {logError} from 'mattermost-redux/actions/errors';
|
||||
|
|
@ -134,7 +135,7 @@ export function sendDesktopNotification(post: Post, msgProps: NewPostMessageProp
|
|||
return {data: skipNotificationReason};
|
||||
}
|
||||
|
||||
const title = getNotificationTitle(channel, msgProps, isCrtReply);
|
||||
const title = getNotificationTitle(channel, msgProps, isCrtReply, post);
|
||||
const body = getNotificationBody(state, post, msgProps);
|
||||
|
||||
//Play a sound if explicitly set in settings
|
||||
|
|
@ -174,7 +175,37 @@ export function sendDesktopNotification(post: Post, msgProps: NewPostMessageProp
|
|||
};
|
||||
}
|
||||
|
||||
const getNotificationTitle = (channel: Pick<Channel, 'type' | 'display_name'>, msgProps: NewPostMessageProps, isCrtReply: boolean) => {
|
||||
const getPriorityNotificationTitle = (priority: PostPriority | '' | undefined, channelType: Channel['type'] | undefined, channelTitle: string) => {
|
||||
if (priority === PostPriority.IMPORTANT) {
|
||||
if (channelType === Constants.DM_CHANNEL) {
|
||||
return Utils.localizeMessage({id: 'notification.priority.important.dm', defaultMessage: 'IMPORTANT Direct Message'});
|
||||
} else if (channelType === Constants.GM_CHANNEL) {
|
||||
return Utils.localizeMessage({id: 'notification.priority.important.gm', defaultMessage: 'IMPORTANT Group Message'});
|
||||
}
|
||||
|
||||
return Utils.localizeMessage(
|
||||
{id: 'notification.priority.important.channel', defaultMessage: 'IMPORTANT message in {channelName}'},
|
||||
{channelName: channelTitle},
|
||||
);
|
||||
}
|
||||
|
||||
if (priority === PostPriority.URGENT) {
|
||||
if (channelType === Constants.DM_CHANNEL) {
|
||||
return Utils.localizeMessage({id: 'notification.priority.urgent.dm', defaultMessage: 'URGENT Direct Message'});
|
||||
} else if (channelType === Constants.GM_CHANNEL) {
|
||||
return Utils.localizeMessage({id: 'notification.priority.urgent.gm', defaultMessage: 'URGENT Group Message'});
|
||||
}
|
||||
|
||||
return Utils.localizeMessage(
|
||||
{id: 'notification.priority.urgent.channel', defaultMessage: 'URGENT message in {channelName}'},
|
||||
{channelName: channelTitle},
|
||||
);
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
const getNotificationTitle = (channel: Pick<Channel, 'type' | 'display_name'>, msgProps: NewPostMessageProps, isCrtReply: boolean, post: Post) => {
|
||||
let title = Utils.localizeMessage({id: 'channel_loader.title', defaultMessage: 'Posted'});
|
||||
if (channel.type === Constants.DM_CHANNEL) {
|
||||
title = Utils.localizeMessage({id: 'notification.dm', defaultMessage: 'Direct Message'});
|
||||
|
|
@ -194,6 +225,10 @@ const getNotificationTitle = (channel: Pick<Channel, 'type' | 'display_name'>, m
|
|||
title = Utils.localizeMessage({id: 'notification.crt', defaultMessage: 'Reply in {title}'}, {title});
|
||||
}
|
||||
|
||||
if (!isCrtReply && !post.root_id) {
|
||||
title = getPriorityNotificationTitle(post.metadata?.priority?.priority, channel.type || msgProps.channel_type, title) || title;
|
||||
}
|
||||
|
||||
return title;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5816,6 +5816,12 @@
|
|||
"no_results.user_groups.title": "No groups yet",
|
||||
"notification.crt": "Reply in {title}",
|
||||
"notification.dm": "Direct Message",
|
||||
"notification.priority.important.channel": "IMPORTANT message in {channelName}",
|
||||
"notification.priority.important.dm": "IMPORTANT Direct Message",
|
||||
"notification.priority.important.gm": "IMPORTANT Group Message",
|
||||
"notification.priority.urgent.channel": "URGENT message in {channelName}",
|
||||
"notification.priority.urgent.dm": "URGENT Direct Message",
|
||||
"notification.priority.urgent.gm": "URGENT Group Message",
|
||||
"notify_admin_to_upgrade_cta.notify-admin.already_notified": "Already notified!",
|
||||
"notify_admin_to_upgrade_cta.notify-admin.failed": "Try again later!",
|
||||
"notify_admin_to_upgrade_cta.notify-admin.notified": "Admin notified!",
|
||||
|
|
|
|||
Loading…
Reference in a new issue