Merge pull request #7682 from mattermost/gm_conversion_on_reconnect_handler
[MM-55463] GM conversion reconnect handler
This commit is contained in:
commit
9ff24a8551
2 changed files with 53 additions and 14 deletions
|
|
@ -19,7 +19,7 @@ import {selectDefaultTeam} from '@helpers/api/team';
|
|||
import {DEFAULT_LOCALE} from '@i18n';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {getDeviceToken} from '@queries/app/global';
|
||||
import {queryAllChannelsForTeam, queryChannelsById} from '@queries/servers/channel';
|
||||
import {getChannelById, queryAllChannelsForTeam, queryChannelsById} from '@queries/servers/channel';
|
||||
import {prepareModels, truncateCrtRelatedTables} from '@queries/servers/entry';
|
||||
import {getHasCRTChanged} from '@queries/servers/preference';
|
||||
import {getConfig, getCurrentChannelId, getCurrentTeamId, getIsDataRetentionEnabled, getPushVerificationStatus, getWebSocketLastDisconnected, setCurrentTeamAndChannelId} from '@queries/servers/system';
|
||||
|
|
@ -42,6 +42,8 @@ export type AppEntryData = {
|
|||
removeTeamIds?: string[];
|
||||
removeChannelIds?: string[];
|
||||
isCRTEnabled: boolean;
|
||||
initialChannelId?: string;
|
||||
gmConverted: boolean;
|
||||
}
|
||||
|
||||
export type AppEntryError = {
|
||||
|
|
@ -56,6 +58,7 @@ export type EntryResponse = {
|
|||
teamData: MyTeamsRequest;
|
||||
chData?: MyChannelsRequest;
|
||||
meData?: MyUserRequest;
|
||||
gmConverted: boolean;
|
||||
} | {
|
||||
error: unknown;
|
||||
}
|
||||
|
|
@ -123,12 +126,12 @@ const entryRest = async (serverUrl: string, teamId?: string, channelId?: string,
|
|||
|
||||
const lastDisconnectedAt = since || await getWebSocketLastDisconnected(database);
|
||||
|
||||
const fetchedData = await fetchAppEntryData(serverUrl, lastDisconnectedAt, teamId);
|
||||
const fetchedData = await fetchAppEntryData(serverUrl, lastDisconnectedAt, teamId, channelId);
|
||||
if ('error' in fetchedData) {
|
||||
return {error: fetchedData.error};
|
||||
}
|
||||
|
||||
const {initialTeamId, teamData, chData, prefData, meData, removeTeamIds, removeChannelIds, isCRTEnabled} = fetchedData;
|
||||
const {initialTeamId, initialChannelId: fetchedChannelId, teamData, chData, prefData, meData, removeTeamIds, removeChannelIds, isCRTEnabled, gmConverted} = fetchedData;
|
||||
const chError = chData?.error;
|
||||
if (isErrorWithStatusCode(chError) && chError.status_code === 403) {
|
||||
// if the user does not have appropriate permissions, which means the user those not belong to the team,
|
||||
|
|
@ -142,7 +145,7 @@ const entryRest = async (serverUrl: string, teamId?: string, channelId?: string,
|
|||
|
||||
const rolesData = await fetchRoles(serverUrl, teamData.memberships, chData?.memberships, meData.user, true);
|
||||
|
||||
const initialChannelId = await entryInitialChannelId(database, channelId, teamId, initialTeamId, meData?.user?.locale || '', chData?.channels, chData?.memberships);
|
||||
const initialChannelId = await entryInitialChannelId(database, fetchedChannelId, teamId, initialTeamId, meData?.user?.locale || '', chData?.channels, chData?.memberships);
|
||||
|
||||
const removeTeams = await teamsToRemove(serverUrl, removeTeamIds);
|
||||
|
||||
|
|
@ -158,10 +161,10 @@ const entryRest = async (serverUrl: string, teamId?: string, channelId?: string,
|
|||
|
||||
const models = await Promise.all(modelPromises);
|
||||
|
||||
return {models: models.flat(), initialChannelId, initialTeamId, prefData, teamData, chData, meData};
|
||||
return {models: models.flat(), initialChannelId, initialTeamId, prefData, teamData, chData, meData, gmConverted};
|
||||
};
|
||||
|
||||
const fetchAppEntryData = async (serverUrl: string, sinceArg: number, initialTeamId = ''): Promise<AppEntryData | AppEntryError> => {
|
||||
const fetchAppEntryData = async (serverUrl: string, sinceArg: number, onLoadTeamId = '', channelId?: string): Promise<AppEntryData | AppEntryError> => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
|
|
@ -188,16 +191,45 @@ const fetchAppEntryData = async (serverUrl: string, sinceArg: number, initialTea
|
|||
}
|
||||
}
|
||||
|
||||
// Fetch in parallel teams / team membership / channels for current team / user preferences / user
|
||||
const promises: [Promise<MyTeamsRequest>, Promise<MyChannelsRequest | undefined>, Promise<MyUserRequest>] = [
|
||||
// Fetch in parallel teams / team membership / user preferences / user
|
||||
const promises: [Promise<MyTeamsRequest>, Promise<MyUserRequest>] = [
|
||||
fetchMyTeams(serverUrl, fetchOnly),
|
||||
initialTeamId ? fetchMyChannelsForTeam(serverUrl, initialTeamId, includeDeletedChannels, since, fetchOnly, false, isCRTEnabled) : Promise.resolve(undefined),
|
||||
fetchMe(serverUrl, fetchOnly),
|
||||
];
|
||||
|
||||
const resolution = await Promise.all(promises);
|
||||
const [teamData, , meData] = resolution;
|
||||
let [, chData] = resolution;
|
||||
const [teamData, meData] = resolution;
|
||||
let chData;
|
||||
|
||||
let initialTeamId = onLoadTeamId;
|
||||
let initialChannelId = channelId;
|
||||
let gmConverted = false;
|
||||
|
||||
if (channelId) {
|
||||
const existingChannel = await getChannelById(database, channelId);
|
||||
if (existingChannel && existingChannel.type === General.GM_CHANNEL) {
|
||||
// Okay, so now we know the channel existsin in mobile app's database as a GM.
|
||||
// We now need to also check if channel on server is actually a private channel,
|
||||
// and if so, which team does it belong to now. That team will become the
|
||||
// active team on mobile app after this point.
|
||||
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const serverChannel = await client.getChannel(channelId);
|
||||
|
||||
// Although yon can convert GM only to a pirvate channel, a private channel can furthur be converted to a public channel.
|
||||
// So between the mobile app being on the GM and reconnecting,
|
||||
// it may have become either a public or a private channel. So we need to check for both.
|
||||
if (serverChannel.type === General.PRIVATE_CHANNEL || serverChannel.type === General.OPEN_CHANNEL) {
|
||||
initialTeamId = serverChannel.team_id;
|
||||
initialChannelId = channelId;
|
||||
gmConverted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (initialTeamId) {
|
||||
chData = await fetchMyChannelsForTeam(serverUrl, initialTeamId, includeDeletedChannels, since, fetchOnly, false, isCRTEnabled);
|
||||
}
|
||||
|
||||
if (!initialTeamId && teamData.teams?.length && teamData.memberships?.length) {
|
||||
// If no initial team was set in the database but got teams in the response
|
||||
|
|
@ -221,6 +253,8 @@ const fetchAppEntryData = async (serverUrl: string, sinceArg: number, initialTea
|
|||
meData,
|
||||
removeTeamIds,
|
||||
isCRTEnabled,
|
||||
initialChannelId,
|
||||
gmConverted,
|
||||
};
|
||||
|
||||
if (teamData.teams?.length === 0 && !teamData.error) {
|
||||
|
|
@ -438,6 +472,7 @@ export async function handleEntryAfterLoadNavigation(
|
|||
currentChannelId: string,
|
||||
initialTeamId: string,
|
||||
initialChannelId: string,
|
||||
gmConverted: boolean,
|
||||
) {
|
||||
try {
|
||||
const {operator, database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
|
@ -462,7 +497,11 @@ export async function handleEntryAfterLoadNavigation(
|
|||
await handleKickFromTeam(serverUrl, currentTeamIdAfterLoad);
|
||||
}
|
||||
} else if (currentTeamIdAfterLoad !== initialTeamId) {
|
||||
await handleKickFromTeam(serverUrl, currentTeamIdAfterLoad);
|
||||
if (gmConverted) {
|
||||
await setCurrentTeamAndChannelId(operator, initialTeamId, currentChannelId);
|
||||
} else {
|
||||
await handleKickFromTeam(serverUrl, currentTeamIdAfterLoad);
|
||||
}
|
||||
} else if (currentChannelIdAfterLoad !== currentChannelId) {
|
||||
// Switched channels while loading
|
||||
if (!channelMembers.find((m) => m.channel_id === currentChannelIdAfterLoad)) {
|
||||
|
|
|
|||
|
|
@ -159,9 +159,9 @@ async function doReconnect(serverUrl: string) {
|
|||
setTeamLoading(serverUrl, false);
|
||||
return entryData.error;
|
||||
}
|
||||
const {models, initialTeamId, initialChannelId, prefData, teamData, chData} = entryData;
|
||||
const {models, initialTeamId, initialChannelId, prefData, teamData, chData, gmConverted} = entryData;
|
||||
|
||||
await handleEntryAfterLoadNavigation(serverUrl, teamData.memberships || [], chData?.memberships || [], currentTeamId || '', currentChannelId || '', initialTeamId, initialChannelId);
|
||||
await handleEntryAfterLoadNavigation(serverUrl, teamData.memberships || [], chData?.memberships || [], currentTeamId || '', currentChannelId || '', initialTeamId, initialChannelId, gmConverted);
|
||||
|
||||
const dt = Date.now();
|
||||
if (models?.length) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue