* Make GM behave as DM

* Fix lint

* Add desktop notification special behavior

* Change notification preferences menu

* Make changes to the GM channel intro

* Fix tests

* Fix i18n and style lint

* Add system notice and update style

* Fix style and fix tests

* Fix tests

* Handle push notifications as desktop notifications

* Fix tests

* Add test and default GMs to none when user level config is none

* Fix test

* Update only for mentions text

* Add tests

* Fix lint

* Fix lint
Этот коммит содержится в:
Daniel Espino García
2023-09-19 15:29:57 +02:00
коммит произвёл GitHub
родитель 39d6cb8008
Коммит 88d043a971
40 изменённых файлов: 1824 добавлений и 511 удалений

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

@@ -50,8 +50,8 @@ func TestGetPreferences(t *testing.T) {
prefs, _, err := client.GetPreferences(context.Background(), user1.Id)
require.NoError(t, err)
// 5 because we have 2 initial preferences tutorial_step and recommended_next_steps added when creating a new user
require.Equal(t, len(prefs), 5, "received the wrong number of preferences")
// 6 because we have 3 initial preferences tutorial_step, recommended_next_steps and system_notification are added when creating a new user
require.Equal(t, len(prefs), 6, "received the wrong number of preferences")
for _, preference := range prefs {
require.Equal(t, preference.UserId, th.BasicUser.Id, "user id does not match")

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

@@ -387,7 +387,9 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
status = &model.Status{UserId: id, Status: model.StatusOffline, Manual: false, LastActivityAt: 0, ActiveChannel: ""}
}
if ShouldSendPushNotification(profileMap[id], channelMemberNotifyPropsMap[id], true, status, post) {
isExplicitlyMentioned := mentions.Mentions[id] > GMMention
isGM := channel.Type == model.ChannelTypeGroup
if ShouldSendPushNotification(profileMap[id], channelMemberNotifyPropsMap[id], isExplicitlyMentioned, status, post, isGM) {
mentionType := mentions.Mentions[id]
replyToThreadType := ""
@@ -428,7 +430,8 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
status = &model.Status{UserId: id, Status: model.StatusOffline, Manual: false, LastActivityAt: 0, ActiveChannel: ""}
}
if ShouldSendPushNotification(profileMap[id], channelMemberNotifyPropsMap[id], false, status, post) {
isGM := channel.Type == model.ChannelTypeGroup
if ShouldSendPushNotification(profileMap[id], channelMemberNotifyPropsMap[id], false, status, post, isGM) {
a.sendPushNotification(
notification,
profileMap[id],
@@ -770,6 +773,14 @@ func (a *App) getExplicitMentionsAndKeywords(c request.CTX, post *model.Post, ch
keywords = a.getMentionKeywordsInChannel(profileMap, allowChannelMentions, channelMemberNotifyPropsMap)
mentions = getExplicitMentions(post, keywords, groups)
// Add a GM mention to all members of a GM channel
if channel.Type == model.ChannelTypeGroup {
for id := range channelMemberNotifyPropsMap {
mentions.addMention(id, GMMention)
}
}
// Add an implicit mention when a user is added to a channel
// even if the user has set 'username mentions' to false in account settings.
if post.Type == model.PostTypeAddToChannel {
@@ -1063,6 +1074,9 @@ const (
// A placeholder that should never be used in practice
NoMention MentionType = iota
// The post is in a GM
GMMention
// The post is in a thread that the user has commented on
ThreadMention

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

@@ -512,12 +512,12 @@ func (a *App) getMobileAppSessions(userID string) ([]*model.Session, *model.AppE
return sessions, nil
}
func ShouldSendPushNotification(user *model.User, channelNotifyProps model.StringMap, wasMentioned bool, status *model.Status, post *model.Post) bool {
return DoesNotifyPropsAllowPushNotification(user, channelNotifyProps, post, wasMentioned) &&
func ShouldSendPushNotification(user *model.User, channelNotifyProps model.StringMap, wasMentioned bool, status *model.Status, post *model.Post, isGM bool) bool {
return DoesNotifyPropsAllowPushNotification(user, channelNotifyProps, post, wasMentioned, isGM) &&
DoesStatusAllowPushNotification(user.NotifyProps, status, post.ChannelId)
}
func DoesNotifyPropsAllowPushNotification(user *model.User, channelNotifyProps model.StringMap, post *model.Post, wasMentioned bool) bool {
func DoesNotifyPropsAllowPushNotification(user *model.User, channelNotifyProps model.StringMap, post *model.Post, wasMentioned, isGM bool) bool {
userNotifyProps := user.NotifyProps
userNotify := userNotifyProps[model.PushNotifyProp]
channelNotify, ok := channelNotifyProps[model.PushNotifyProp]
@@ -525,6 +525,14 @@ func DoesNotifyPropsAllowPushNotification(user *model.User, channelNotifyProps m
channelNotify = model.ChannelNotifyDefault
}
notify := channelNotify
if channelNotify == model.ChannelNotifyDefault {
notify = userNotify
if isGM && userNotify == model.UserNotifyMention {
notify = model.ChannelNotifyAll
}
}
// If the channel is muted do not send push notifications
if channelNotifyProps[model.MarkUnreadNotifyProp] == model.ChannelMarkUnreadMention {
return false
@@ -534,28 +542,19 @@ func DoesNotifyPropsAllowPushNotification(user *model.User, channelNotifyProps m
return false
}
if channelNotify == model.UserNotifyNone {
if notify == model.ChannelNotifyNone {
return false
}
if channelNotify == model.ChannelNotifyMention && !wasMentioned {
if notify == model.ChannelNotifyMention && !wasMentioned {
return false
}
if userNotify == model.UserNotifyMention && channelNotify == model.ChannelNotifyDefault && !wasMentioned {
return false
}
if (userNotify == model.UserNotifyAll || channelNotify == model.ChannelNotifyAll) &&
if (notify == model.ChannelNotifyAll) &&
(post.UserId != user.Id || post.GetProp("from_webhook") == "true") {
return true
}
if userNotify == model.UserNotifyNone &&
channelNotify == model.ChannelNotifyDefault {
return false
}
return true
}

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

@@ -36,6 +36,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned bool
isMuted bool
expected bool
isGM bool
}{
{
name: "When post is a System Message and has no mentions",
@@ -45,6 +46,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When post is a System Message and has mentions",
@@ -54,6 +56,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is ALL, no channel props is set and has no mentions",
@@ -63,6 +66,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is ALL, no channel props is set and has mentions",
@@ -72,6 +76,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is MENTION, no channel props is set and has no mentions",
@@ -81,6 +86,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is MENTION, no channel props is set and has mentions",
@@ -90,6 +96,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is NONE, no channel props is set and has no mentions",
@@ -99,6 +106,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is NONE, no channel props is set and has mentions",
@@ -108,6 +116,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is ALL, channel is DEFAULT and has no mentions",
@@ -117,6 +126,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is ALL, channel is DEFAULT and has mentions",
@@ -126,6 +136,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is MENTION, channel is DEFAULT and has no mentions",
@@ -135,6 +146,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is MENTION, channel is DEFAULT and has mentions",
@@ -144,6 +156,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is NONE, channel is DEFAULT and has no mentions",
@@ -153,6 +166,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is NONE, channel is DEFAULT and has mentions",
@@ -162,6 +176,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is ALL, channel is ALL and has no mentions",
@@ -171,6 +186,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is ALL, channel is ALL and has mentions",
@@ -180,6 +196,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is MENTION, channel is ALL and has no mentions",
@@ -189,6 +206,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is MENTION, channel is ALL and has mentions",
@@ -198,6 +216,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is NONE, channel is ALL and has no mentions",
@@ -207,6 +226,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is NONE, channel is ALL and has mentions",
@@ -216,6 +236,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is ALL, channel is MENTION and has no mentions",
@@ -225,6 +246,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is ALL, channel is MENTION and has mentions",
@@ -234,6 +256,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is MENTION, channel is MENTION and has no mentions",
@@ -243,6 +266,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is MENTION, channel is MENTION and has mentions",
@@ -252,6 +276,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is NONE, channel is MENTION and has no mentions",
@@ -261,6 +286,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is NONE, channel is MENTION and has mentions",
@@ -270,6 +296,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: true,
isGM: false,
},
{
name: "When default is ALL, channel is NONE and has no mentions",
@@ -279,6 +306,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is ALL, channel is NONE and has mentions",
@@ -288,6 +316,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is MENTION, channel is NONE and has no mentions",
@@ -297,6 +326,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is MENTION, channel is NONE and has mentions",
@@ -306,6 +336,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is NONE, channel is NONE and has no mentions",
@@ -315,6 +346,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is NONE, channel is NONE and has mentions",
@@ -324,6 +356,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: true,
isMuted: false,
expected: false,
isGM: false,
},
{
name: "When default is ALL, and channel is MUTED",
@@ -333,6 +366,47 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
wasMentioned: false,
isMuted: true,
expected: false,
isGM: false,
},
{
name: "For GM default for NONE is NONE",
userNotifySetting: model.UserNotifyNone,
channelNotifySetting: model.ChannelNotifyDefault,
withSystemPost: false,
wasMentioned: false,
isMuted: false,
expected: false,
isGM: true,
},
{
name: "For GM, mentioned is only called if explicitly mentioned",
userNotifySetting: model.UserNotifyNone,
channelNotifySetting: model.ChannelNotifyMention,
withSystemPost: false,
wasMentioned: true,
isMuted: false,
expected: true,
isGM: true,
},
{
name: "For GM default for MENTION is ALL",
userNotifySetting: model.UserNotifyMention,
channelNotifySetting: model.ChannelNotifyDefault,
withSystemPost: false,
wasMentioned: false,
isMuted: false,
expected: true,
isGM: true,
},
{
name: "For GM, mentioned is only called if explicitly mentioned",
userNotifySetting: model.UserNotifyNone,
channelNotifySetting: model.ChannelNotifyMention,
withSystemPost: false,
wasMentioned: false,
isMuted: false,
expected: false,
isGM: true,
},
}
@@ -352,7 +426,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
if tc.isMuted {
channelNotifyProps[model.MarkUnreadNotifyProp] = model.ChannelMarkUnreadMention
}
assert.Equal(t, tc.expected, DoesNotifyPropsAllowPushNotification(user, channelNotifyProps, post, tc.wasMentioned))
assert.Equal(t, tc.expected, DoesNotifyPropsAllowPushNotification(user, channelNotifyProps, post, tc.wasMentioned, tc.isGM))
})
}
}

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

@@ -38,19 +38,21 @@ func TestSendNotifications(t *testing.T) {
th.App.AddUserToChannel(th.Context, th.BasicUser2, th.BasicChannel, false)
post1, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
post1, createPostErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: "@" + th.BasicUser2.Username,
Type: model.PostTypeAddToChannel,
Props: map[string]any{model.PostPropsAddedUserId: "junk"},
}, true, true)
require.Nil(t, appErr)
require.Nil(t, createPostErr)
mentions, err := th.App.SendNotifications(th.Context, post1, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true)
require.NoError(t, err)
require.NotNil(t, mentions)
require.True(t, pUtils.Contains(mentions, th.BasicUser2.Id), "mentions", mentions)
t.Run("Basic channel", func(t *testing.T) {
mentions, err := th.App.SendNotifications(th.Context, post1, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true)
require.NoError(t, err)
require.NotNil(t, mentions)
require.True(t, pUtils.Contains(mentions, th.BasicUser2.Id), "mentions", mentions)
})
t.Run("license is required for group mention", func(t *testing.T) {
group := th.CreateGroup()
@@ -70,7 +72,7 @@ func TestSendNotifications(t *testing.T) {
groupMentionPost, createPostErr := th.App.CreatePost(th.Context, groupMentionPost, th.BasicChannel, false, true)
require.Nil(t, createPostErr)
mentions, err = th.App.SendNotifications(th.Context, groupMentionPost, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true)
mentions, err := th.App.SendNotifications(th.Context, groupMentionPost, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true)
require.NoError(t, err)
require.NotNil(t, mentions)
require.Len(t, mentions, 0)
@@ -83,40 +85,83 @@ func TestSendNotifications(t *testing.T) {
require.Len(t, mentions, 1)
})
dm, appErr := th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, th.BasicUser2.Id)
require.Nil(t, appErr)
t.Run("message in DM generate mention", func(t *testing.T) {
dm, appErr := th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, th.BasicUser2.Id)
require.Nil(t, appErr)
post2, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: dm.Id,
Message: "dm message",
}, true, true)
require.Nil(t, appErr)
post2, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: dm.Id,
Message: "dm message",
}, true, true)
require.Nil(t, appErr)
mentions, err = th.App.SendNotifications(th.Context, post2, th.BasicTeam, dm, th.BasicUser, nil, true)
require.NoError(t, err)
require.NotNil(t, mentions)
mentions, err := th.App.SendNotifications(th.Context, post2, th.BasicTeam, dm, th.BasicUser, nil, true)
require.NoError(t, err)
require.NotNil(t, mentions)
_, appErr = th.App.UpdateActive(th.Context, th.BasicUser2, false)
require.Nil(t, appErr)
appErr = th.App.Srv().InvalidateAllCaches()
require.Nil(t, appErr)
_, appErr = th.App.UpdateActive(th.Context, th.BasicUser2, false)
require.Nil(t, appErr)
appErr = th.App.Srv().InvalidateAllCaches()
require.Nil(t, appErr)
post3, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: dm.Id,
Message: "dm message",
}, true, true)
require.Nil(t, appErr)
post3, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: dm.Id,
Message: "dm message",
}, true, true)
require.Nil(t, appErr)
mentions, err = th.App.SendNotifications(th.Context, post3, th.BasicTeam, dm, th.BasicUser, nil, true)
require.NoError(t, err)
require.NotNil(t, mentions)
mentions, err = th.App.SendNotifications(th.Context, post3, th.BasicTeam, dm, th.BasicUser, nil, true)
require.NoError(t, err)
require.NotNil(t, mentions)
th.BasicChannel.DeleteAt = 1
mentions, err = th.App.SendNotifications(th.Context, post1, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true)
require.NoError(t, err)
require.Empty(t, mentions)
th.BasicChannel.DeleteAt = 1
mentions, err = th.App.SendNotifications(th.Context, post1, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true)
require.NoError(t, err)
require.Empty(t, mentions)
})
t.Run("message in GM generate mention", func(t *testing.T) {
users := []*model.User{}
for i := 0; i < 2; i++ {
user := th.CreateUser()
users = append(users, user)
}
channel := th.CreateGroupChannel(th.Context, users[0], users[1])
post2, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: users[0].Id,
ChannelId: channel.Id,
Message: "gm message",
}, true, true)
require.Nil(t, appErr)
mentions, err := th.App.SendNotifications(th.Context, post2, th.BasicTeam, channel, users[0], nil, true)
require.NoError(t, err)
require.NotNil(t, mentions)
_, appErr = th.App.UpdateActive(th.Context, users[1], false)
require.Nil(t, appErr)
appErr = th.App.Srv().InvalidateAllCaches()
require.Nil(t, appErr)
post3, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: users[0].Id,
ChannelId: channel.Id,
Message: "gm message",
}, true, true)
require.Nil(t, appErr)
mentions, err = th.App.SendNotifications(th.Context, post3, th.BasicTeam, channel, users[0], nil, true)
require.NoError(t, err)
require.NotNil(t, mentions)
th.BasicChannel.DeleteAt = 1
mentions, err = th.App.SendNotifications(th.Context, post1, th.BasicTeam, th.BasicChannel, users[0], nil, true)
require.NoError(t, err)
require.Empty(t, mentions)
})
t.Run("replies to post created by OAuth bot should not notify user", func(t *testing.T) {
th := Setup(t).InitBasic()
@@ -129,7 +174,7 @@ func TestSendNotifications(t *testing.T) {
Props: model.StringInterface{"from_webhook": "true", "override_username": "a bot"},
}
rootPost, appErr = th.App.CreatePostMissingChannel(th.Context, rootPost, false, true)
rootPost, appErr := th.App.CreatePostMissingChannel(th.Context, rootPost, false, true)
require.Nil(t, appErr)
childPost := &model.Post{
@@ -145,11 +190,12 @@ func TestSendNotifications(t *testing.T) {
Order: []string{rootPost.Id, childPost.Id},
Posts: map[string]*model.Post{rootPost.Id: rootPost, childPost.Id: childPost},
}
mentions, err = th.App.SendNotifications(th.Context, childPost, th.BasicTeam, th.BasicChannel, th.BasicUser2, &postList, true)
mentions, err := th.App.SendNotifications(th.Context, childPost, th.BasicTeam, th.BasicChannel, th.BasicUser2, &postList, true)
require.NoError(t, err)
require.False(t, pUtils.Contains(mentions, user.Id))
}
var appErr *model.AppError
th.BasicUser.NotifyProps[model.CommentsNotifyProp] = model.CommentsNotifyAny
th.BasicUser, appErr = th.App.UpdateUser(th.Context, th.BasicUser, false)
require.Nil(t, appErr)

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

@@ -179,17 +179,19 @@ func TestPluginAPIGetUserPreferences(t *testing.T) {
preferences, err := api.GetPreferencesForUser(user1.Id)
require.Nil(t, err)
assert.Equal(t, 2, len(preferences))
assert.Equal(t, 3, len(preferences))
assert.Equal(t, user1.Id, preferences[0].UserId)
assert.Equal(t, model.PreferenceRecommendedNextSteps, preferences[0].Category)
assert.Equal(t, "hide", preferences[0].Name)
assert.Equal(t, "false", preferences[0].Value)
assert.Equal(t, user1.Id, preferences[1].UserId)
assert.Equal(t, model.PreferenceCategoryTutorialSteps, preferences[1].Category)
assert.Equal(t, user1.Id, preferences[1].Name)
assert.Equal(t, "0", preferences[1].Value)
assert.Equal(t, model.PreferenceCategorySystemNotice, preferences[1].Category)
assert.Equal(t, user1.Id, preferences[2].UserId)
assert.Equal(t, model.PreferenceCategoryTutorialSteps, preferences[2].Category)
assert.Equal(t, user1.Id, preferences[2].Name)
assert.Equal(t, "0", preferences[2].Value)
}
func TestPluginAPIDeleteUserPreferences(t *testing.T) {
@@ -207,7 +209,7 @@ func TestPluginAPIDeleteUserPreferences(t *testing.T) {
preferences, err := api.GetPreferencesForUser(user1.Id)
require.Nil(t, err)
assert.Equal(t, 2, len(preferences))
assert.Equal(t, 3, len(preferences))
err = api.DeletePreferencesForUser(user1.Id, preferences)
require.Nil(t, err)
@@ -234,16 +236,16 @@ func TestPluginAPIDeleteUserPreferences(t *testing.T) {
preferences, err = api.GetPreferencesForUser(user2.Id)
require.Nil(t, err)
assert.Equal(t, 3, len(preferences))
assert.Equal(t, 4, len(preferences))
err = api.DeletePreferencesForUser(user2.Id, []model.Preference{preference})
require.Nil(t, err)
preferences, err = api.GetPreferencesForUser(user2.Id)
require.Nil(t, err)
assert.Equal(t, 2, len(preferences))
assert.Equal(t, 3, len(preferences))
assert.ElementsMatch(t,
[]string{model.PreferenceRecommendedNextSteps, model.PreferenceCategoryTutorialSteps},
[]string{preferences[0].Category, preferences[1].Category},
[]string{model.PreferenceRecommendedNextSteps, model.PreferenceCategoryTutorialSteps, model.PreferenceCategorySystemNotice},
[]string{preferences[0].Category, preferences[1].Category, preferences[2].Category},
)
}
@@ -262,16 +264,17 @@ func TestPluginAPIUpdateUserPreferences(t *testing.T) {
preferences, err := api.GetPreferencesForUser(user1.Id)
require.Nil(t, err)
assert.Equal(t, 2, len(preferences))
assert.Equal(t, 3, len(preferences))
assert.Equal(t, user1.Id, preferences[0].UserId)
assert.Equal(t, model.PreferenceRecommendedNextSteps, preferences[0].Category)
assert.Equal(t, "hide", preferences[0].Name)
assert.Equal(t, "false", preferences[0].Value)
assert.Equal(t, user1.Id, preferences[1].UserId)
assert.Equal(t, model.PreferenceCategoryTutorialSteps, preferences[1].Category)
assert.Equal(t, user1.Id, preferences[1].Name)
assert.Equal(t, "0", preferences[1].Value)
assert.Equal(t, model.PreferenceCategorySystemNotice, preferences[1].Category)
assert.Equal(t, user1.Id, preferences[2].UserId)
assert.Equal(t, model.PreferenceCategoryTutorialSteps, preferences[2].Category)
assert.Equal(t, user1.Id, preferences[2].Name)
assert.Equal(t, "0", preferences[2].Value)
preference := model.Preference{
Name: user1.Id,
@@ -286,8 +289,8 @@ func TestPluginAPIUpdateUserPreferences(t *testing.T) {
preferences, err = api.GetPreferencesForUser(user1.Id)
require.Nil(t, err)
assert.Equal(t, 3, len(preferences))
expectedCategories := []string{model.PreferenceCategoryTutorialSteps, model.PreferenceCategoryTheme, model.PreferenceRecommendedNextSteps}
assert.Equal(t, 4, len(preferences))
expectedCategories := []string{model.PreferenceCategoryTutorialSteps, model.PreferenceCategoryTheme, model.PreferenceRecommendedNextSteps, model.PreferenceCategorySystemNotice}
for _, pref := range preferences {
assert.Contains(t, expectedCategories, pref.Category)
assert.Equal(t, user1.Id, pref.UserId)

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

@@ -275,9 +275,9 @@ func (a *App) channelTeamMapsForPosts(posts []*model.Post) (map[string]*model.Ch
func (a *App) sendPersistentNotifications(post *model.Post, channel *model.Channel, team *model.Team, mentions *ExplicitMentions, profileMap model.UserMap, channelNotifyProps map[string]map[string]model.StringMap) error {
mentionedUsersList := make(model.StringArray, 0, len(mentions.Mentions))
for id := range mentions.Mentions {
// Don't send notification to post owner
if id != post.UserId {
for id, v := range mentions.Mentions {
// Don't send notification to post owner nor GM mentions
if id != post.UserId && v > GMMention {
mentionedUsersList = append(mentionedUsersList, id)
}
}
@@ -307,7 +307,8 @@ func (a *App) sendPersistentNotifications(post *model.Post, channel *model.Chann
status = &model.Status{UserId: userID, Status: model.StatusOffline, Manual: false, LastActivityAt: 0, ActiveChannel: ""}
}
if ShouldSendPushNotification(profileMap[userID], channelNotifyProps[channel.Id][userID], true, status, post) {
isGM := channel.Type == model.ChannelTypeGroup
if ShouldSendPushNotification(profileMap[userID], channelNotifyProps[channel.Id][userID], true, status, post, isGM) {
a.sendPushNotification(
notification,
user,

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

@@ -282,8 +282,9 @@ func (a *App) createUserOrGuest(c request.CTX, user *model.User, guest bool) (*m
recommendedNextStepsPref := model.Preference{UserId: ruser.Id, Category: model.PreferenceRecommendedNextSteps, Name: "hide", Value: "false"}
tutorialStepPref := model.Preference{UserId: ruser.Id, Category: model.PreferenceCategoryTutorialSteps, Name: ruser.Id, Value: "0"}
gmASdmPref := model.Preference{UserId: ruser.Id, Category: model.PreferenceCategorySystemNotice, Name: "GMasDM", Value: "true"}
preferences := model.Preferences{recommendedNextStepsPref, tutorialStepPref}
preferences := model.Preferences{recommendedNextStepsPref, tutorialStepPref, gmASdmPref}
if err := a.Srv().Store().Preference().Save(preferences); err != nil {
c.Logger().Warn("Encountered error saving user preferences", mlog.Err(err))
}

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

@@ -1825,6 +1825,11 @@ func TestCreateUserWithInitialPreferences(t *testing.T) {
assert.Equal(t, model.PreferenceRecommendedNextSteps, recommendedNextStepsPref[0].Category)
assert.Equal(t, "hide", recommendedNextStepsPref[0].Name)
assert.Equal(t, "false", recommendedNextStepsPref[0].Value)
gmASdmNoticeViewedPref, appErr := th.App.GetPreferenceByCategoryAndNameForUser(testUser.Id, model.PreferenceCategorySystemNotice, "GMasDM")
require.Nil(t, appErr)
assert.Equal(t, "GMasDM", gmASdmNoticeViewedPref.Name)
assert.Equal(t, "true", gmASdmNoticeViewedPref.Value)
})
t.Run("successfully create a guest user with initial tutorial and recommended steps preferences", func(t *testing.T) {
@@ -1842,6 +1847,11 @@ func TestCreateUserWithInitialPreferences(t *testing.T) {
assert.Equal(t, model.PreferenceRecommendedNextSteps, recommendedNextStepsPref[0].Category)
assert.Equal(t, "hide", recommendedNextStepsPref[0].Name)
assert.Equal(t, "false", recommendedNextStepsPref[0].Value)
gmASdmNoticeViewedPref, appErr := th.App.GetPreferenceByCategoryAndNameForUser(testUser.Id, model.PreferenceCategorySystemNotice, "GMasDM")
require.Nil(t, appErr)
assert.Equal(t, "GMasDM", gmASdmNoticeViewedPref.Name)
assert.Equal(t, "true", gmASdmNoticeViewedPref.Value)
})
}

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

@@ -31,6 +31,8 @@ const (
PreferenceNameUseMilitaryTime = "use_military_time"
PreferenceRecommendedNextSteps = "recommended_next_steps"
PreferenceCategorySystemNotice = "system_notice"
PreferenceCategoryTheme = "theme"
// the name for theme props is the team id