From 0f07a934ff6b5e56984e82770e885fae7bdb2d30 Mon Sep 17 00:00:00 2001 From: Ashish Bhate Date: Thu, 29 Jul 2021 14:47:28 +0530 Subject: [PATCH] [MM-37118] Don't mark channel as read for reply posts with CRT on (#17965) Summary With CRT on, posting a reply to a thread should NOT mark the channel containing the the thread as read Ticket Link https://mattermost.atlassian.net/browse/MM-37118 --- app/post.go | 9 ++++-- app/post_test.go | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/app/post.go b/app/post.go index b8a80eabb3..563101f638 100644 --- a/app/post.go +++ b/app/post.go @@ -86,11 +86,14 @@ func (a *App) CreatePostAsUser(c *request.Context, post *model.Post, currentSess return nil, err } - // Update the LastViewAt only if the post does not have from_webhook prop set (e.g. Zapier app), - // or if it does not have from_bot set (e.g. from discovering the user is a bot within CreatePost). + // Update the Channel LastViewAt only if: + // the post does NOT have from_webhook prop set (e.g. Zapier app), and + // the post does NOT have from_bot set (e.g. from discovering the user is a bot within CreatePost), and + // the post is NOT a reply post with CRT enabled _, fromWebhook := post.GetProps()["from_webhook"] _, fromBot := post.GetProps()["from_bot"] - if !fromWebhook && !fromBot { + isCRTReply := post.RootId != "" && a.isCRTEnabledForUser(post.UserId) + if !fromWebhook && !fromBot && !isCRTReply { if _, err := a.MarkChannelsAsViewed([]string{post.ChannelId}, post.UserId, currentSessionId, true); err != nil { mlog.Warn( "Encountered error updating last viewed", diff --git a/app/post_test.go b/app/post_test.go index 6f359d098d..0f5506a14b 100644 --- a/app/post_test.go +++ b/app/post_test.go @@ -964,6 +964,77 @@ func TestCreatePostAsUser(t *testing.T) { testlib.AssertNoLog(t, th.LogBuffer, mlog.LevelWarn, "Failed to get membership") }) + + t.Run("marks channel as viewed for reply post when CRT is off", func(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.ServiceSettings.CollapsedThreads = model.CollapsedThreadsDefaultOff + }) + + post := &model.Post{ + ChannelId: th.BasicChannel.Id, + Message: "test", + UserId: th.BasicUser2.Id, + } + rootPost, appErr := th.App.CreatePostAsUser(th.Context, post, "", true) + require.Nil(t, appErr) + + channelMemberBefore, nErr := th.App.Srv().Store.Channel().GetMember(context.Background(), th.BasicChannel.Id, th.BasicUser.Id) + require.NoError(t, nErr) + + time.Sleep(1 * time.Millisecond) + replyPost := &model.Post{ + ChannelId: th.BasicChannel.Id, + Message: "test reply", + UserId: th.BasicUser.Id, + RootId: rootPost.Id, + } + _, appErr = th.App.CreatePostAsUser(th.Context, replyPost, "", true) + require.Nil(t, appErr) + + channelMemberAfter, nErr := th.App.Srv().Store.Channel().GetMember(context.Background(), th.BasicChannel.Id, th.BasicUser.Id) + require.NoError(t, nErr) + + require.NotEqual(t, channelMemberAfter.LastViewedAt, channelMemberBefore.LastViewedAt) + }) + + t.Run("does not mark channel as viewed for reply post when CRT is on", func(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.ServiceSettings.ThreadAutoFollow = true + *cfg.ServiceSettings.CollapsedThreads = model.CollapsedThreadsDefaultOn + }) + + post := &model.Post{ + ChannelId: th.BasicChannel.Id, + Message: "test", + UserId: th.BasicUser2.Id, + } + rootPost, appErr := th.App.CreatePostAsUser(th.Context, post, "", true) + require.Nil(t, appErr) + + channelMemberBefore, nErr := th.App.Srv().Store.Channel().GetMember(context.Background(), th.BasicChannel.Id, th.BasicUser.Id) + require.NoError(t, nErr) + + time.Sleep(1 * time.Millisecond) + replyPost := &model.Post{ + ChannelId: th.BasicChannel.Id, + Message: "test reply", + UserId: th.BasicUser.Id, + RootId: rootPost.Id, + } + _, appErr = th.App.CreatePostAsUser(th.Context, replyPost, "", true) + require.Nil(t, appErr) + + channelMemberAfter, nErr := th.App.Srv().Store.Channel().GetMember(context.Background(), th.BasicChannel.Id, th.BasicUser.Id) + require.NoError(t, nErr) + + require.Equal(t, channelMemberAfter.LastViewedAt, channelMemberBefore.LastViewedAt) + }) } func TestPatchPostInArchivedChannel(t *testing.T) {