[MM-54021][MM-58736] Remove limit on loading channel members on initial load, reload members on reconnect, separate loading of members from channels on initial load (#28310)
* [MM-54021][MM-58736] Remove limit on loading channel members on initial load, reload members on reconnect, separate loading of members from channels on initial load * PR feedback --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
2b7b4100d2
Коммит
ed4cab7aa2
@@ -31,6 +31,7 @@ import {
|
|||||||
getChannelStats,
|
getChannelStats,
|
||||||
markMultipleChannelsAsRead,
|
markMultipleChannelsAsRead,
|
||||||
getChannelMemberCountsByGroup,
|
getChannelMemberCountsByGroup,
|
||||||
|
fetchAllMyChannelMembers,
|
||||||
} from 'mattermost-redux/actions/channels';
|
} from 'mattermost-redux/actions/channels';
|
||||||
import {getCloudSubscription} from 'mattermost-redux/actions/cloud';
|
import {getCloudSubscription} from 'mattermost-redux/actions/cloud';
|
||||||
import {clearErrors, logError} from 'mattermost-redux/actions/errors';
|
import {clearErrors, logError} from 'mattermost-redux/actions/errors';
|
||||||
@@ -235,6 +236,7 @@ export function reconnect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch(loadChannelsForCurrentUser());
|
dispatch(loadChannelsForCurrentUser());
|
||||||
|
dispatch(fetchAllMyChannelMembers());
|
||||||
|
|
||||||
if (mostRecentPost) {
|
if (mostRecentPost) {
|
||||||
dispatch(syncPostsInChannel(currentChannelId, mostRecentPost.create_at));
|
dispatch(syncPostsInChannel(currentChannelId, mostRecentPost.create_at));
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ jest.mock('mattermost-redux/actions/users', () => ({
|
|||||||
|
|
||||||
jest.mock('mattermost-redux/actions/channels', () => ({
|
jest.mock('mattermost-redux/actions/channels', () => ({
|
||||||
getChannelStats: jest.fn(() => ({type: 'GET_CHANNEL_STATS'})),
|
getChannelStats: jest.fn(() => ({type: 'GET_CHANNEL_STATS'})),
|
||||||
|
fetchAllMyChannelMembers: jest.fn(() => ({type: 'FETCH_ALL_MY_CHANNEL_MEMBERS'})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('actions/post_actions', () => ({
|
jest.mock('actions/post_actions', () => ({
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import type {UserProfile} from '@mattermost/types/users';
|
|||||||
import type {RelationOneToOne} from '@mattermost/types/utilities';
|
import type {RelationOneToOne} from '@mattermost/types/utilities';
|
||||||
|
|
||||||
import {UserTypes} from 'mattermost-redux/action_types';
|
import {UserTypes} from 'mattermost-redux/action_types';
|
||||||
import {fetchAllMyTeamsChannelsAndChannelMembersREST, searchAllChannels} from 'mattermost-redux/actions/channels';
|
import {fetchAllMyTeamsChannels, searchAllChannels} from 'mattermost-redux/actions/channels';
|
||||||
import {logError} from 'mattermost-redux/actions/errors';
|
import {logError} from 'mattermost-redux/actions/errors';
|
||||||
import {Client4} from 'mattermost-redux/client';
|
import {Client4} from 'mattermost-redux/client';
|
||||||
import {Preferences} from 'mattermost-redux/constants';
|
import {Preferences} from 'mattermost-redux/constants';
|
||||||
@@ -838,12 +838,12 @@ export default class SwitchChannelProvider extends Provider {
|
|||||||
if (!teamId) {
|
if (!teamId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const channelsAsync = this.store.dispatch(fetchAllMyTeamsChannelsAndChannelMembersREST());
|
const channelsAsync = this.store.dispatch(fetchAllMyTeamsChannels());
|
||||||
let channels;
|
let channels;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const {data} = await channelsAsync;
|
const {data} = await channelsAsync;
|
||||||
channels = data.channels as Channel[];
|
channels = data as Channel[];
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.store.dispatch(logError(err));
|
this.store.dispatch(logError(err));
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {connect} from 'react-redux';
|
|||||||
import type {ConnectedProps} from 'react-redux';
|
import type {ConnectedProps} from 'react-redux';
|
||||||
import type {RouteComponentProps} from 'react-router-dom';
|
import type {RouteComponentProps} from 'react-router-dom';
|
||||||
|
|
||||||
import {fetchAllMyTeamsChannelsAndChannelMembersREST, fetchChannelsAndMembers, unsetActiveChannelOnServer} from 'mattermost-redux/actions/channels';
|
import {fetchAllMyTeamsChannels, fetchAllMyChannelMembers, fetchChannelsAndMembers, unsetActiveChannelOnServer} from 'mattermost-redux/actions/channels';
|
||||||
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
|
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
|
||||||
import {getLicense, getConfig} from 'mattermost-redux/selectors/entities/general';
|
import {getLicense, getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||||
import {getCurrentTeamId, getMyTeams} from 'mattermost-redux/selectors/entities/teams';
|
import {getCurrentTeamId, getMyTeams} from 'mattermost-redux/selectors/entities/teams';
|
||||||
@@ -53,7 +53,8 @@ function mapStateToProps(state: GlobalState, ownProps: OwnProps) {
|
|||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
fetchChannelsAndMembers,
|
fetchChannelsAndMembers,
|
||||||
fetchAllMyTeamsChannelsAndChannelMembersREST,
|
fetchAllMyTeamsChannels,
|
||||||
|
fetchAllMyChannelMembers,
|
||||||
markAsReadOnFocus,
|
markAsReadOnFocus,
|
||||||
initializeTeam,
|
initializeTeam,
|
||||||
joinTeam,
|
joinTeam,
|
||||||
|
|||||||
@@ -55,13 +55,14 @@ function TeamController(props: Props) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
InitialLoadingScreen.stop();
|
InitialLoadingScreen.stop();
|
||||||
async function fetchInitialChannels() {
|
async function fetchAllChannels() {
|
||||||
await props.fetchAllMyTeamsChannelsAndChannelMembersREST();
|
await props.fetchAllMyTeamsChannels();
|
||||||
|
|
||||||
setInitialChannelsLoaded(true);
|
setInitialChannelsLoaded(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchInitialChannels();
|
props.fetchAllMyChannelMembers();
|
||||||
|
fetchAllChannels();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -2088,4 +2088,27 @@ describe('Actions.Channels', () => {
|
|||||||
expect(channelMemberCounts['group-2'].channel_member_count).toEqual(999);
|
expect(channelMemberCounts['group-2'].channel_member_count).toEqual(999);
|
||||||
expect(channelMemberCounts['group-2'].channel_member_timezones_count).toEqual(131);
|
expect(channelMemberCounts['group-2'].channel_member_timezones_count).toEqual(131);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('fetchAllMyChannelMembers', async () => {
|
||||||
|
const store = configureStore({
|
||||||
|
entities: {
|
||||||
|
users: {
|
||||||
|
currentUserId: 'some-user-id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
nock(Client4.getBaseRoute()).get(
|
||||||
|
'/users/some-user-id/channel_members?page=0&per_page=200').
|
||||||
|
reply(200, [...Array(200).keys()].map((index) => ({channel_id: `channel-${index}`, user_id: 'some-user-id'})));
|
||||||
|
nock(Client4.getBaseRoute()).get(
|
||||||
|
'/users/some-user-id/channel_members?page=1&per_page=200').
|
||||||
|
reply(200, [...Array(200).keys()].map((index) => ({channel_id: `channel-${index + 200}`, user_id: 'some-user-id'})));
|
||||||
|
nock(Client4.getBaseRoute()).get(
|
||||||
|
'/users/some-user-id/channel_members?page=2&per_page=200').
|
||||||
|
reply(200, [...Array(100).keys()].map((index) => ({channel_id: `channel-${index + 400}`, user_id: 'some-user-id'})));
|
||||||
|
|
||||||
|
await store.dispatch(Actions.fetchAllMyChannelMembers());
|
||||||
|
expect(Object.keys(store.getState().entities.channels.myMembers).length).toBe(500);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -464,32 +464,43 @@ export function fetchChannelsAndMembers(teamId: string): ActionFuncAsync<{channe
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchAllMyTeamsChannelsAndChannelMembersREST(): ActionFuncAsync {
|
export function fetchAllMyChannelMembers(): ActionFuncAsync {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const {currentUserId} = state.entities.users;
|
const {currentUserId} = state.entities.users;
|
||||||
let channels;
|
|
||||||
let channelsMembers: ChannelMembership[] = [];
|
let channelsMembers: ChannelMembership[] = [];
|
||||||
let allMembers = true;
|
let hasMoreMembers = true;
|
||||||
let page = 0;
|
let page = 0;
|
||||||
do {
|
try {
|
||||||
try {
|
while (hasMoreMembers) {
|
||||||
|
// Expected to disable since we don't have number of pages, so we can't use Promise.all
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await Client4.getAllChannelsMembers(currentUserId, page, 200).then(
|
const data = await Client4.getAllChannelsMembers(currentUserId, page, 200);
|
||||||
// eslint-disable-next-line no-loop-func
|
channelsMembers = [...channelsMembers, ...data];
|
||||||
(data) => {
|
if (data.length < 200) {
|
||||||
channelsMembers = [...channelsMembers, ...data];
|
hasMoreMembers = false;
|
||||||
page++;
|
}
|
||||||
if (data.length < 200) {
|
page++;
|
||||||
allMembers = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
forceLogoutIfNecessary(error, dispatch, getState);
|
|
||||||
dispatch(logError(error));
|
|
||||||
return {error};
|
|
||||||
}
|
}
|
||||||
} while (allMembers && page <= 2);
|
} catch (error) {
|
||||||
|
forceLogoutIfNecessary(error, dispatch, getState);
|
||||||
|
dispatch(logError(error));
|
||||||
|
return {error};
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: ChannelTypes.RECEIVED_MY_CHANNEL_MEMBERS,
|
||||||
|
data: channelsMembers,
|
||||||
|
currentUserId,
|
||||||
|
});
|
||||||
|
return {data: channelsMembers};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fetchAllMyTeamsChannels(): ActionFuncAsync {
|
||||||
|
return async (dispatch, getState) => {
|
||||||
|
let channels;
|
||||||
try {
|
try {
|
||||||
channels = await Client4.getAllTeamsChannels();
|
channels = await Client4.getAllTeamsChannels();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -498,18 +509,11 @@ export function fetchAllMyTeamsChannelsAndChannelMembersREST(): ActionFuncAsync
|
|||||||
return {error};
|
return {error};
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(batchActions([
|
dispatch({
|
||||||
{
|
type: ChannelTypes.RECEIVED_ALL_CHANNELS,
|
||||||
type: ChannelTypes.RECEIVED_ALL_CHANNELS,
|
data: channels,
|
||||||
data: channels,
|
});
|
||||||
},
|
return {data: channels};
|
||||||
{
|
|
||||||
type: ChannelTypes.RECEIVED_MY_CHANNEL_MEMBERS,
|
|
||||||
data: channelsMembers,
|
|
||||||
currentUserId,
|
|
||||||
},
|
|
||||||
]));
|
|
||||||
return {data: {channels, channelsMembers}};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user