[MM-58108] Posts missing channel_id in handleThreadReadChanged, handleAllThreadsInChannelMarkedRead, getThreadItemsInChannel (#27006)

Этот коммит содержится в:
M-ZubairAhmed
2024-05-22 14:08:41 +00:00
коммит произвёл GitHub
родитель f0110e361e
Коммит 7d7b203567
5 изменённых файлов: 78 добавлений и 71 удалений

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

@@ -1632,9 +1632,9 @@ function handleThreadReadChanged(msg) {
), ),
); );
} else if (msg.broadcast.channel_id) { } else if (msg.broadcast.channel_id) {
handleAllThreadsInChannelMarkedRead(doDispatch, doGetState, msg.broadcast.channel_id, msg.data.timestamp); doDispatch(handleAllThreadsInChannelMarkedRead(msg.broadcast.channel_id, msg.data.timestamp));
} else { } else {
handleAllMarkedRead(doDispatch, msg.broadcast.team_id); doDispatch(handleAllMarkedRead(msg.broadcast.team_id));
} }
}; };
} }

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

@@ -16,7 +16,7 @@ import {getChannel} from 'mattermost-redux/selectors/entities/channels';
import {makeGetPostsForThread} from 'mattermost-redux/selectors/entities/posts'; import {makeGetPostsForThread} from 'mattermost-redux/selectors/entities/posts';
import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getThread as getThreadSelector, getThreadItemsInChannel} from 'mattermost-redux/selectors/entities/threads'; import {getThread as getThreadSelector, getThreadsInChannel} from 'mattermost-redux/selectors/entities/threads';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc, GetStateFunc, ActionFunc, ActionFuncAsync} from 'mattermost-redux/types/actions'; import type {DispatchFunc, GetStateFunc, ActionFunc, ActionFuncAsync} from 'mattermost-redux/types/actions';
@@ -248,13 +248,13 @@ export function getThread(userId: string, teamId: string, threadId: string, exte
}; };
} }
export function handleAllMarkedRead(dispatch: DispatchFunc, teamId: string) { export function handleAllMarkedRead(teamId: string) {
dispatch({ return {
type: ThreadTypes.ALL_TEAM_THREADS_READ, type: ThreadTypes.ALL_TEAM_THREADS_READ,
data: { data: {
team_id: teamId, team_id: teamId,
}, },
}); };
} }
export function markAllThreadsInTeamRead(userId: string, teamId: string): ActionFuncAsync { export function markAllThreadsInTeamRead(userId: string, teamId: string): ActionFuncAsync {
@@ -267,7 +267,7 @@ export function markAllThreadsInTeamRead(userId: string, teamId: string): Action
return {error}; return {error};
} }
handleAllMarkedRead(dispatch, teamId); dispatch(handleAllMarkedRead(teamId));
return {}; return {};
}; };
@@ -395,32 +395,38 @@ export function setThreadFollow(userId: string, teamId: string, threadId: string
}; };
} }
export function handleAllThreadsInChannelMarkedRead(dispatch: DispatchFunc, getState: GetStateFunc, channelId: string, lastViewedAt: number) { export function handleAllThreadsInChannelMarkedRead(channelId: string, lastViewedAt: number): ActionFunc<boolean> {
const state = getState(); return (dispatch, getState) => {
const threadsInChannel = getThreadItemsInChannel(state, channelId); const state = getState();
const channel = getChannel(state, channelId);
if (channel == null) {
return;
}
const teamId = channel.team_id;
const actions = [];
for (const thread of threadsInChannel) { const channel = getChannel(state, channelId);
actions.push({ if (channel == null) {
type: ThreadTypes.READ_CHANGED_THREAD, return {data: false};
data: { }
id: thread.id,
channelId,
teamId,
lastViewedAt,
newUnreadMentions: 0,
newUnreadReplies: 0,
isUrgent: thread.is_urgent,
},
});
}
dispatch(batchActions(actions)); const teamId = channel.team_id;
const threadsInChannel = getThreadsInChannel(state, channelId);
const actions = [];
for (const thread of threadsInChannel) {
actions.push({
type: ThreadTypes.READ_CHANGED_THREAD,
data: {
id: thread.id,
channelId,
teamId,
lastViewedAt,
newUnreadMentions: 0,
newUnreadReplies: 0,
isUrgent: thread.is_urgent,
},
});
}
dispatch(batchActions(actions));
return {data: true};
};
} }
export function decrementThreadCounts(post: ExtendedPost): ActionFunc { export function decrementThreadCounts(post: ExtendedPost): ActionFunc {

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

@@ -189,6 +189,10 @@ describe('Selectors.Threads.getThreadsInChannel', () => {
it('should return threads in channel', () => { it('should return threads in channel', () => {
const user = TestHelper.fakeUserWithId(); const user = TestHelper.fakeUserWithId();
const thread1 = TestHelper.fakeThread(user.id, channel1.id);
const thread2 = TestHelper.fakeThread(user.id, channel1.id);
const thread3 = TestHelper.fakeThread(user.id, channel2.id);
const thread4 = TestHelper.fakeThread(user.id, channel3.id);
const profiles = { const profiles = {
[user.id]: user, [user.id]: user,
@@ -205,36 +209,20 @@ describe('Selectors.Threads.getThreadsInChannel', () => {
}, },
threads: { threads: {
threads: { threads: {
a: { [thread1.id]: thread1,
post: { [thread2.id]: thread2,
channel_id: channel1.id, [thread3.id]: thread3,
}, [thread4.id]: thread4,
},
b: {
post: {
channel_id: channel1.id,
},
},
c: {
post: {
channel_id: channel2.id,
},
},
d: {
post: {
channel_id: channel3.id,
},
},
}, },
threadsInTeam: { threadsInTeam: {
[team1.id]: ['a', 'b', 'c'], [team1.id]: [thread1.id, thread2.id, thread3.id],
[team2.id]: ['d'], [team2.id]: [thread4.id],
}, },
}, },
}, },
}); });
expect(Selectors.getThreadsInChannel(testState, channel1.id)).toEqual(['a', 'b']); expect(Selectors.getThreadsInChannel(testState, channel1.id)).toEqual([thread1, thread2]);
}); });
}); });

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

@@ -176,25 +176,20 @@ function sortByLastReply(ids: Array<UserThread['id']>, threads: ReturnType<typeo
export const getThreadsInChannel: ( export const getThreadsInChannel: (
state: GlobalState, state: GlobalState,
channelID: string, channelID: string,
) => Array<UserThread['id']> = createSelector( ) => UserThread[] = createSelector(
'getThreadsInChannel', 'getThreadsInChannel',
getThreads, getThreads,
(state: GlobalState, channelID: string) => channelID, (_: GlobalState, channelID: string) => channelID,
(allThreads: IDMappedObjects<UserThread>, channelID: string) => { (threads: IDMappedObjects<UserThread>, channelID: Channel['id']) => {
return Object.keys(allThreads).filter((id) => allThreads[id].post.channel_id === channelID); const allThreads = Object.values(threads);
},
);
export const getThreadItemsInChannel: ( const threadsInChannel: UserThread[] = [];
state: GlobalState, for (const thread of allThreads) {
channelID: string, if (thread && thread.post && thread.post.channel_id && thread.post.channel_id === channelID) {
) => UserThread[] = createSelector( threadsInChannel.push(thread);
'getThreadItemsInChannel', }
getThreads, }
(state: GlobalState, channelID: string) => channelID,
(allThreads: IDMappedObjects<UserThread>, channelID: Channel['id']) => { return threadsInChannel;
return Object.keys(allThreads).
map((id) => allThreads[id]).
filter((item) => item.post.channel_id === channelID);
}, },
); );

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

@@ -16,6 +16,7 @@ import type {Reaction} from '@mattermost/types/reactions';
import type {Role} from '@mattermost/types/roles'; import type {Role} from '@mattermost/types/roles';
import type {Scheme} from '@mattermost/types/schemes'; import type {Scheme} from '@mattermost/types/schemes';
import type {Team, TeamMembership} from '@mattermost/types/teams'; import type {Team, TeamMembership} from '@mattermost/types/teams';
import type {UserThread} from '@mattermost/types/threads';
import type {UserProfile, UserNotifyProps} from '@mattermost/types/users'; import type {UserProfile, UserNotifyProps} from '@mattermost/types/users';
export const DEFAULT_SERVER = 'http://localhost:8065'; export const DEFAULT_SERVER = 'http://localhost:8065';
@@ -553,6 +554,23 @@ class TestHelper {
}; };
}; };
fakeThread = (userId: string, channelId: string, override?: Partial<UserThread>): UserThread => {
return {
id: this.generateId(),
reply_count: 0,
last_reply_at: 0,
last_viewed_at: 0,
participants: [],
unread_replies: 0,
unread_mentions: 0,
is_following: true,
post: {
channel_id: channelId,
user_id: userId,
},
...override,
};
};
getFileInfoMock = (override: Partial<FileInfo>): FileInfo => { getFileInfoMock = (override: Partial<FileInfo>): FileInfo => {
return { return {
id: '', id: '',