MM-41349: CRT, fix LastUpdated semantics (#19523)
* deadcode: remove UpdateChannelLastViewedAt * deadcode: remove ThreadStore.(Save(Multiple)|Update|Delete) * deadcode: followThead in App.MarkChannelAsUnreadFromPost * document ThreadMembership, Thread structs * maintain LastUpdated consistently Whenever we touch a `ThreadMembership` record, we should be setting `LastUpdated` to the current timestamp. The mobile client relies on this to detect changes to these records. * simplify: never updateThreads from `App.MarkChannelAsUnreadFromPost` Change all invocations of `ChannelStore.UpdateLastViewedAtPost` from `App.MarkChannelAsUnreadFromPost` to pass `updateThreads` as `false`. When `ChannelStore.UpdateLastViewedAtPost` was invoked with `updateThreads` as `true`, it would in turn call `ThreadStore.UpdateUnreadsByChannel` but pass `updateViewedTimestamp` as `false`. This effectively updated the `LastUpdated` field of the corresponding thread memberships but never touched any of the actual data (such as `LastViewed`). The overall CRT feature continued to work, because `App.MarkChannelAsUnreadFromPost` directly updates the relevant thread memberships via `ThreadStore.MaintainMembership`. * deadcode: updateThreads in ChannelStore.UpdateLastViewedAtPost * simplify: never updateThreads from App.SendNotifications Change all invocations of `ChannelStore.IncrementMentionCount` from `App.SendNotifications` to pass `updateThreads` as `false`. When `ChannelStore.IncrementMentionCount` was invoked with `updateThreads` as `true`, it would in turn call `ThreadStore.UpdateUnreadsByChannel` but pass `updateViewedTimestamp` as `false`. This effectively updated the `LastUpdated` field of the corresponding thread memberships but never touched any of the actual data (such as `UnreadMentions`). The overall CRT feature continued to work, because `App.SendNotifications` directly updates the relevant thread memberships mention counts via `ThreadStore.MaintainMembership`. * deadcode: updateThreads in ChannelStore.IncrementMentionCount * fix & rename ThreadStore.UpdateUnreadsByChannel Rename `ThreadStore.UpdateUnreadsByChannel` to `ThreadStore.UpdateLastViewedByThreadIds`, making it unconditionally set the `LastViewed` for the given threads (as well as `LastUpdated`). All previous invocations of this method that passed `updateViewedTimestamp` have been previously removed. * unrelated gofmt -w -s changes to satisfy linter * always set LastUpdated to model.GetMillis() * deadcode: ThreadStore.SaveMembership * fix TestMarkUnreadWithThreads * GetMasterX
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
cc900149c6
Коммит
6757edc4e2
@@ -223,7 +223,7 @@ type AppIface interface {
|
||||
// MakeAuditRecord creates a audit record pre-populated with defaults.
|
||||
MakeAuditRecord(event string, initialStatus string) *audit.Record
|
||||
// MarkChanelAsUnreadFromPost will take a post and set the channel as unread from that one.
|
||||
MarkChannelAsUnreadFromPost(postID string, userID string, collapsedThreadsSupported, followThread bool) (*model.ChannelUnreadAt, *model.AppError)
|
||||
MarkChannelAsUnreadFromPost(postID string, userID string, collapsedThreadsSupported bool) (*model.ChannelUnreadAt, *model.AppError)
|
||||
// MentionsToPublicChannels returns all the mentions to public channels,
|
||||
// linking them to their channels
|
||||
MentionsToPublicChannels(message, teamID string) model.ChannelMentionMap
|
||||
@@ -1035,7 +1035,6 @@ type AppIface interface {
|
||||
TriggerWebhook(c *request.Context, payload *model.OutgoingWebhookPayload, hook *model.OutgoingWebhook, post *model.Post, channel *model.Channel)
|
||||
UnregisterPluginCommand(pluginID, teamID, trigger string)
|
||||
UpdateActive(c *request.Context, user *model.User, active bool) (*model.User, *model.AppError)
|
||||
UpdateChannelLastViewedAt(channelIDs []string, userID string) *model.AppError
|
||||
UpdateChannelMemberNotifyProps(data map[string]string, channelID string, userID string) (*model.ChannelMember, *model.AppError)
|
||||
UpdateChannelMemberRoles(channelID string, userID string, newRoles string) (*model.ChannelMember, *model.AppError)
|
||||
UpdateChannelMemberSchemeRoles(channelID string, userID string, isSchemeGuest bool, isSchemeUser bool, isSchemeAdmin bool) (*model.ChannelMember, *model.AppError)
|
||||
|
||||
@@ -2486,28 +2486,6 @@ func (a *App) SetActiveChannel(userID string, channelID string) *model.AppError
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) UpdateChannelLastViewedAt(channelIDs []string, userID string) *model.AppError {
|
||||
if _, err := a.Srv().Store.Channel().UpdateLastViewedAt(channelIDs, userID, *a.Config().ServiceSettings.ThreadAutoFollow); err != nil {
|
||||
var invErr *store.ErrInvalidInput
|
||||
switch {
|
||||
case errors.As(err, &invErr):
|
||||
return model.NewAppError("UpdateChannelLastViewedAt", "app.channel.update_last_viewed_at.app_error", nil, invErr.Error(), http.StatusBadRequest)
|
||||
default:
|
||||
return model.NewAppError("UpdateChannelLastViewedAt", "app.channel.update_last_viewed_at.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
if *a.Config().ServiceSettings.EnableChannelViewedMessages {
|
||||
for _, channelID := range channelIDs {
|
||||
message := model.NewWebSocketEvent(model.WebsocketEventChannelViewed, "", "", userID, nil)
|
||||
message.Add("channel_id", channelID)
|
||||
a.Publish(message)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) IsCRTEnabledForUser(userID string) bool {
|
||||
if *a.Config().ServiceSettings.CollapsedThreads == model.CollapsedThreadsDisabled {
|
||||
return false
|
||||
@@ -2521,7 +2499,7 @@ func (a *App) IsCRTEnabledForUser(userID string) bool {
|
||||
}
|
||||
|
||||
// MarkChanelAsUnreadFromPost will take a post and set the channel as unread from that one.
|
||||
func (a *App) MarkChannelAsUnreadFromPost(postID string, userID string, collapsedThreadsSupported, followThread bool) (*model.ChannelUnreadAt, *model.AppError) {
|
||||
func (a *App) MarkChannelAsUnreadFromPost(postID string, userID string, collapsedThreadsSupported bool) (*model.ChannelUnreadAt, *model.AppError) {
|
||||
if !collapsedThreadsSupported || !a.IsCRTEnabledForUser(userID) {
|
||||
return a.markChannelAsUnreadFromPostCRTUnsupported(postID, userID)
|
||||
}
|
||||
@@ -2553,23 +2531,15 @@ func (a *App) MarkChannelAsUnreadFromPost(postID string, userID string, collapse
|
||||
if storeErr != nil && !errors.As(storeErr, &nfErr) {
|
||||
return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, storeErr.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
var opts store.ThreadMembershipOpts
|
||||
// if this post was not followed before, create thread membership and update mention count
|
||||
if threadMembership == nil {
|
||||
opts = store.ThreadMembershipOpts{
|
||||
Following: followThread,
|
||||
opts := store.ThreadMembershipOpts{
|
||||
Following: false,
|
||||
IncrementMentions: false,
|
||||
UpdateFollowing: true,
|
||||
UpdateViewedTimestamp: true,
|
||||
UpdateParticipants: false,
|
||||
}
|
||||
} else if !threadMembership.Following && followThread {
|
||||
opts = store.ThreadMembershipOpts{
|
||||
Following: true,
|
||||
UpdateFollowing: true,
|
||||
}
|
||||
}
|
||||
if opts.UpdateFollowing || threadMembership == nil {
|
||||
threadMembership, storeErr = a.Srv().Store.Thread().MaintainMembership(user.Id, threadId, opts)
|
||||
if storeErr != nil && !errors.As(storeErr, &nfErr) {
|
||||
return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, storeErr.Error(), http.StatusInternalServerError)
|
||||
@@ -2608,7 +2578,7 @@ func (a *App) MarkChannelAsUnreadFromPost(postID string, userID string, collapse
|
||||
}
|
||||
}
|
||||
|
||||
channelUnread, nErr := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, unreadMentionsRoot, *a.Config().ServiceSettings.ThreadAutoFollow, true)
|
||||
channelUnread, nErr := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, unreadMentionsRoot, true)
|
||||
if nErr != nil {
|
||||
return channelUnread, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
@@ -2644,7 +2614,7 @@ func (a *App) markChannelAsUnreadFromPostCRTUnsupported(postID string, userID st
|
||||
// In CRT Supported Client: badge on channel only sums mentions in root posts including and below the post that was marked.
|
||||
// In CRT Unsupported Client: badge on channel sums mentions in all posts (root & replies) including and below the post that was marked unread.
|
||||
if post.RootId == "" {
|
||||
channelUnread, nErr := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, unreadMentionsRoot, false, true)
|
||||
channelUnread, nErr := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, unreadMentionsRoot, true)
|
||||
if nErr != nil {
|
||||
return channelUnread, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
@@ -2718,7 +2688,7 @@ func (a *App) markChannelAsUnreadFromPostCRTUnsupported(postID string, userID st
|
||||
}
|
||||
}
|
||||
|
||||
channelUnread, nErr := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, 0, false, false)
|
||||
channelUnread, nErr := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, 0, false)
|
||||
if nErr != nil {
|
||||
return channelUnread, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
@@ -1274,16 +1274,16 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
|
||||
unread, err = th.App.GetChannelUnread(c1.Id, u2.Id)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, int64(4), unread.MsgCount)
|
||||
err = th.App.UpdateChannelLastViewedAt([]string{c1.Id, pc1.Id}, u1.Id)
|
||||
_, err = th.App.MarkChannelsAsViewed([]string{c1.Id, pc1.Id}, u1.Id, "", false)
|
||||
require.Nil(t, err)
|
||||
err = th.App.UpdateChannelLastViewedAt([]string{c1.Id, pc1.Id}, u2.Id)
|
||||
_, err = th.App.MarkChannelsAsViewed([]string{c1.Id, pc1.Id}, u2.Id, "", false)
|
||||
require.Nil(t, err)
|
||||
unread, err = th.App.GetChannelUnread(c1.Id, u2.Id)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, int64(0), unread.MsgCount)
|
||||
|
||||
t.Run("Unread but last one", func(t *testing.T) {
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost(p2.Id, u1.Id, true, true)
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost(p2.Id, u1.Id, true)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, response)
|
||||
assert.Equal(t, int64(2), response.MsgCount)
|
||||
@@ -1294,7 +1294,7 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Unread last one", func(t *testing.T) {
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost(p3.Id, u1.Id, true, true)
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost(p3.Id, u1.Id, true)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, response)
|
||||
assert.Equal(t, int64(3), response.MsgCount)
|
||||
@@ -1305,7 +1305,7 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Unread first one", func(t *testing.T) {
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost(p1.Id, u1.Id, true, true)
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost(p1.Id, u1.Id, true)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, response)
|
||||
assert.Equal(t, int64(1), response.MsgCount)
|
||||
@@ -1322,7 +1322,7 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Unread on a private channel", func(t *testing.T) {
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost(pp1.Id, u1.Id, true, true)
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost(pp1.Id, u1.Id, true)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, response)
|
||||
assert.Equal(t, int64(0), response.MsgCount)
|
||||
@@ -1331,7 +1331,7 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
|
||||
assert.Equal(t, int64(2), unread.MsgCount)
|
||||
assert.Equal(t, pp1.CreateAt-1, response.LastViewedAt)
|
||||
|
||||
response, err = th.App.MarkChannelAsUnreadFromPost(pp2.Id, u1.Id, true, true)
|
||||
response, err = th.App.MarkChannelAsUnreadFromPost(pp2.Id, u1.Id, true)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int64(1), response.MsgCount)
|
||||
unread, err = th.App.GetChannelUnread(pc1.Id, u1.Id)
|
||||
@@ -1360,7 +1360,7 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
|
||||
Message: "@" + u1.Username,
|
||||
}, c2, false, true)
|
||||
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost(p4.Id, u1.Id, true, true)
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost(p4.Id, u1.Id, true)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int64(1), response.MsgCount)
|
||||
assert.Equal(t, int64(2), response.MentionCount)
|
||||
@@ -1383,7 +1383,7 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
|
||||
_, err := th.App.CreatePost(th.Context, &model.Post{ChannelId: dc.Id, UserId: th.BasicUser.Id, Message: "testReply", RootId: dm1.Id}, dc, false, false)
|
||||
assert.Nil(t, err)
|
||||
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost(dm1.Id, u2.Id, true, true)
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost(dm1.Id, u2.Id, true)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int64(0), response.MsgCount)
|
||||
assert.Equal(t, int64(4), response.MentionCount)
|
||||
@@ -1397,7 +1397,7 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Can't unread an imaginary post", func(t *testing.T) {
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost("invalid4ofngungryquinj976y", u1.Id, true, true)
|
||||
response, err := th.App.MarkChannelAsUnreadFromPost("invalid4ofngungryquinj976y", u1.Id, true)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, response)
|
||||
})
|
||||
@@ -2070,7 +2070,7 @@ func TestMarkChannelAsUnreadFromPostPanic(t *testing.T) {
|
||||
})
|
||||
|
||||
require.NotPanics(t, func() {
|
||||
th.App.MarkChannelAsUnreadFromPost("postID", "userID", true, true)
|
||||
th.App.MarkChannelAsUnreadFromPost("postID", "userID", true)
|
||||
}, "unexpected panic from MarkChannelAsUnreadFromPost")
|
||||
}
|
||||
|
||||
@@ -2246,7 +2246,7 @@ func TestMarkChannelAsUnreadFromPostCollapsedThreadsTurnedOff(t *testing.T) {
|
||||
require.Nil(t, appErr)
|
||||
|
||||
t.Run("Mark reply post as unread", func(t *testing.T) {
|
||||
_, err := th.App.MarkChannelAsUnreadFromPost(replyPost1.Id, th.BasicUser.Id, true, true)
|
||||
_, err := th.App.MarkChannelAsUnreadFromPost(replyPost1.Id, th.BasicUser.Id, true)
|
||||
require.Nil(t, err)
|
||||
// Get channel unreads
|
||||
// Easier to reason with ChannelUnread now, than channelUnreadAt from the previous call
|
||||
@@ -2270,7 +2270,7 @@ func TestMarkChannelAsUnreadFromPostCollapsedThreadsTurnedOff(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Mark root post as unread", func(t *testing.T) {
|
||||
_, err := th.App.MarkChannelAsUnreadFromPost(rootPost1.Id, th.BasicUser.Id, true, true)
|
||||
_, err := th.App.MarkChannelAsUnreadFromPost(rootPost1.Id, th.BasicUser.Id, true)
|
||||
require.Nil(t, err)
|
||||
// Get channel unreads
|
||||
// Easier to reason with ChannelUnread now, than channelUnreadAt from the previous call
|
||||
@@ -2285,6 +2285,14 @@ func TestMarkChannelAsUnreadFromPostCollapsedThreadsTurnedOff(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
// TestMarkUnreadWithThreads asserts the behaviour of App.MarkChannelAsUnreadFromPost, but was
|
||||
// originally written when that API accepted a followThread parameter. While tested, that parameter
|
||||
// was never actually called as true, resulting in deadcode.
|
||||
//
|
||||
// When removing the parameter, one of the following tests failed, as it covered behaviour that
|
||||
// was unused and now unsupported. The test has since been updated to reflect the new reality,
|
||||
// but a careful examination of MarkChannelAsUnreadFromPost should be conducted as it's unclear
|
||||
// why that API tries to manipulate thread memberships at all. Fixing that is left to another task.
|
||||
func TestMarkUnreadWithThreads(t *testing.T) {
|
||||
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
|
||||
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
|
||||
@@ -2295,47 +2303,11 @@ func TestMarkUnreadWithThreads(t *testing.T) {
|
||||
*cfg.ServiceSettings.CollapsedThreads = model.CollapsedThreadsDefaultOn
|
||||
})
|
||||
|
||||
t.Run("Follow threads only if specified", func(t *testing.T) {
|
||||
rootPost, appErr := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hi"}, th.BasicChannel, false, false)
|
||||
require.Nil(t, appErr)
|
||||
replyPost, appErr := th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hi"}, th.BasicChannel, false, false)
|
||||
require.Nil(t, appErr)
|
||||
threads, appErr := th.App.GetThreadsForUser(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{})
|
||||
require.Nil(t, appErr)
|
||||
require.Zero(t, threads.Total)
|
||||
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(replyPost.Id, th.BasicUser.Id, true, true)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
threads, appErr = th.App.GetThreadsForUser(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{})
|
||||
require.Nil(t, appErr)
|
||||
require.NotZero(t, threads.Total)
|
||||
|
||||
threadMembership, appErr := th.App.GetThreadMembershipForUser(th.BasicUser.Id, replyPost.RootId)
|
||||
require.Nil(t, appErr)
|
||||
require.NotNil(t, threadMembership)
|
||||
assert.True(t, threadMembership.Following)
|
||||
|
||||
// Create a new thread
|
||||
rootPost, appErr = th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hi2"}, th.BasicChannel, false, false)
|
||||
require.Nil(t, appErr)
|
||||
replyPost, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hi2"}, th.BasicChannel, false, false)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(replyPost.Id, th.BasicUser.Id, true, false)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
threadMembership, appErr = th.App.GetThreadMembershipForUser(th.BasicUser.Id, replyPost.RootId)
|
||||
require.Nil(t, appErr)
|
||||
require.NotNil(t, threadMembership)
|
||||
assert.False(t, threadMembership.Following)
|
||||
})
|
||||
|
||||
t.Run("Set unread mentions correctly", func(t *testing.T) {
|
||||
t.Run("Never followed root post with no replies or mentions", func(t *testing.T) {
|
||||
rootPost, appErr := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hi"}, th.BasicChannel, false, false)
|
||||
require.Nil(t, appErr)
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(rootPost.Id, th.BasicUser.Id, true, true)
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(rootPost.Id, th.BasicUser.Id, true)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
threadMembership, appErr := th.App.GetThreadMembershipForUser(th.BasicUser.Id, rootPost.Id)
|
||||
@@ -2349,7 +2321,7 @@ func TestMarkUnreadWithThreads(t *testing.T) {
|
||||
require.Nil(t, appErr)
|
||||
_, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hi"}, th.BasicChannel, false, false)
|
||||
require.Nil(t, appErr)
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(rootPost.Id, th.BasicUser.Id, true, true)
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(rootPost.Id, th.BasicUser.Id, true)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
threadMembership, appErr := th.App.GetThreadMembershipForUser(th.BasicUser.Id, rootPost.Id)
|
||||
@@ -2363,7 +2335,7 @@ func TestMarkUnreadWithThreads(t *testing.T) {
|
||||
require.Nil(t, appErr)
|
||||
_, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hi @" + th.BasicUser.Username}, th.BasicChannel, false, false)
|
||||
require.Nil(t, appErr)
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(rootPost.Id, th.BasicUser.Id, true, true)
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(rootPost.Id, th.BasicUser.Id, true)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
threadMembership, appErr := th.App.GetThreadMembershipForUser(th.BasicUser.Id, rootPost.Id)
|
||||
@@ -2380,7 +2352,7 @@ func TestMarkUnreadWithThreads(t *testing.T) {
|
||||
appErr = th.App.UpdateThreadFollowForUser(th.BasicUser.Id, th.BasicTeam.Id, rootPost.Id, false)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(rootPost.Id, th.BasicUser.Id, true, true)
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(rootPost.Id, th.BasicUser.Id, true)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
threadMembership, appErr := th.App.GetThreadMembershipForUser(th.BasicUser.Id, rootPost.Id)
|
||||
@@ -2399,7 +2371,7 @@ func TestMarkUnreadWithThreads(t *testing.T) {
|
||||
appErr = th.App.UpdateThreadFollowForUser(th.BasicUser.Id, th.BasicTeam.Id, rootPost.Id, false)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(rootPost.Id, th.BasicUser.Id, true, true)
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(rootPost.Id, th.BasicUser.Id, true)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
threadMembership, appErr := th.App.GetThreadMembershipForUser(th.BasicUser.Id, rootPost.Id)
|
||||
@@ -2418,13 +2390,13 @@ func TestMarkUnreadWithThreads(t *testing.T) {
|
||||
appErr = th.App.UpdateThreadFollowForUser(th.BasicUser.Id, th.BasicTeam.Id, rootPost.Id, false)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(rootPost.Id, th.BasicUser.Id, true, true)
|
||||
_, appErr = th.App.MarkChannelAsUnreadFromPost(rootPost.Id, th.BasicUser.Id, true)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
threadMembership, appErr := th.App.GetThreadMembershipForUser(th.BasicUser.Id, rootPost.Id)
|
||||
require.Nil(t, appErr)
|
||||
require.NotNil(t, threadMembership)
|
||||
assert.Equal(t, int64(1), threadMembership.UnreadMentions)
|
||||
assert.Zero(t, threadMembership.UnreadMentions)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod
|
||||
umc := make(chan *model.AppError, 1)
|
||||
go func(userID string) {
|
||||
defer close(umc)
|
||||
nErr := a.Srv().Store.Channel().IncrementMentionCount(post.ChannelId, userID, *a.Config().ServiceSettings.ThreadAutoFollow, post.RootId == "")
|
||||
nErr := a.Srv().Store.Channel().IncrementMentionCount(post.ChannelId, userID, post.RootId == "")
|
||||
if nErr != nil {
|
||||
umc <- model.NewAppError("SendNotifications", "app.channel.increment_mention_count.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
|
||||
@@ -11579,7 +11579,7 @@ func (a *OpenTracingAppLayer) MakePermissionError(s *model.Session, permissions
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) MarkChannelAsUnreadFromPost(postID string, userID string, collapsedThreadsSupported bool, followThread bool) (*model.ChannelUnreadAt, *model.AppError) {
|
||||
func (a *OpenTracingAppLayer) MarkChannelAsUnreadFromPost(postID string, userID string, collapsedThreadsSupported bool) (*model.ChannelUnreadAt, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.MarkChannelAsUnreadFromPost")
|
||||
|
||||
@@ -11591,7 +11591,7 @@ func (a *OpenTracingAppLayer) MarkChannelAsUnreadFromPost(postID string, userID
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0, resultVar1 := a.app.MarkChannelAsUnreadFromPost(postID, userID, collapsedThreadsSupported, followThread)
|
||||
resultVar0, resultVar1 := a.app.MarkChannelAsUnreadFromPost(postID, userID, collapsedThreadsSupported)
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
@@ -15973,28 +15973,6 @@ func (a *OpenTracingAppLayer) UpdateChannel(channel *model.Channel) (*model.Chan
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) UpdateChannelLastViewedAt(channelIDs []string, userID string) *model.AppError {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateChannelLastViewedAt")
|
||||
|
||||
a.ctx = newCtx
|
||||
a.app.Srv().Store.SetContext(newCtx)
|
||||
defer func() {
|
||||
a.app.Srv().Store.SetContext(origCtx)
|
||||
a.ctx = origCtx
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0 := a.app.UpdateChannelLastViewedAt(channelIDs, userID)
|
||||
|
||||
if resultVar0 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar0))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) UpdateChannelMemberNotifyProps(data map[string]string, channelID string, userID string) (*model.ChannelMember, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateChannelMemberNotifyProps")
|
||||
|
||||
@@ -2314,7 +2314,7 @@ func TestCollapsedThreadFetch(t *testing.T) {
|
||||
thread, nErr := th.App.Srv().Store.Thread().Get(postRoot.Id)
|
||||
require.NoError(t, nErr)
|
||||
require.Len(t, thread.Participants, 1)
|
||||
th.App.MarkChannelAsUnreadFromPost(postRoot.Id, user1.Id, true, true)
|
||||
th.App.MarkChannelAsUnreadFromPost(postRoot.Id, user1.Id, true)
|
||||
l, err := th.App.GetPostsForChannelAroundLastUnread(channel.Id, user1.Id, 10, 10, true, true, false)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, l.Order, 1)
|
||||
|
||||
Ссылка в новой задаче
Block a user