Unify entry functions (#6231)
* Unify entry functions * Handle switched to channel on websocket reconnect * Simplify global threads by moving it to switchByChannelId * Keep in mind team when changing to global threads view * Avoid unneeded channel switches on notification entry * Fix effects on home screen * Address feedback
This commit is contained in:
parent
fd2a8a36e8
commit
0464dd34ee
11 changed files with 298 additions and 444 deletions
|
|
@ -8,7 +8,7 @@ import DatabaseManager from '@database/manager';
|
|||
import {getTranslations, t} from '@i18n';
|
||||
import {getChannelById} from '@queries/servers/channel';
|
||||
import {getPostById} from '@queries/servers/post';
|
||||
import {getCurrentTeamId, getCurrentUserId, setCurrentChannelId} from '@queries/servers/system';
|
||||
import {getCurrentTeamId, getCurrentUserId, setCurrentTeamAndChannelId} from '@queries/servers/system';
|
||||
import {addChannelToTeamHistory} from '@queries/servers/team';
|
||||
import {getIsCRTEnabled, getThreadById, prepareThreadsFromReceivedPosts, queryThreadsInTeam} from '@queries/servers/thread';
|
||||
import {getCurrentUser} from '@queries/servers/user';
|
||||
|
|
@ -19,7 +19,7 @@ import {changeOpacity} from '@utils/theme';
|
|||
|
||||
import type Model from '@nozbe/watermelondb/Model';
|
||||
|
||||
export const switchToGlobalThreads = async (serverUrl: string, prepareRecordsOnly = false) => {
|
||||
export const switchToGlobalThreads = async (serverUrl: string, teamId?: string, prepareRecordsOnly = false) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
|
|
@ -27,10 +27,19 @@ export const switchToGlobalThreads = async (serverUrl: string, prepareRecordsOnl
|
|||
|
||||
const {database} = operator;
|
||||
const models: Model[] = [];
|
||||
|
||||
let teamIdToUse = teamId;
|
||||
if (!teamId) {
|
||||
teamIdToUse = await getCurrentTeamId(database);
|
||||
}
|
||||
|
||||
if (!teamIdToUse) {
|
||||
return {error: 'no team to switch to'};
|
||||
}
|
||||
|
||||
try {
|
||||
await setCurrentChannelId(operator, '');
|
||||
const currentTeamId = await getCurrentTeamId(database);
|
||||
const history = await addChannelToTeamHistory(operator, currentTeamId, Screens.GLOBAL_THREADS, true);
|
||||
await setCurrentTeamAndChannelId(operator, teamId, '');
|
||||
const history = await addChannelToTeamHistory(operator, teamIdToUse, Screens.GLOBAL_THREADS, true);
|
||||
models.push(...history);
|
||||
const isTabletDevice = await isTablet();
|
||||
if (isTabletDevice) {
|
||||
|
|
|
|||
|
|
@ -971,6 +971,10 @@ export async function getChannelTimezones(serverUrl: string, channelId: string)
|
|||
}
|
||||
|
||||
export async function switchToChannelById(serverUrl: string, channelId: string, teamId?: string, skipLastUnread = false) {
|
||||
if (channelId === Screens.GLOBAL_THREADS) {
|
||||
return switchToGlobalThreads(serverUrl, teamId);
|
||||
}
|
||||
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
|
|
@ -993,9 +997,6 @@ export async function switchToPenultimateChannel(serverUrl: string) {
|
|||
try {
|
||||
const currentTeam = await getCurrentTeamId(database);
|
||||
const channelId = await getNthLastChannelFromTeam(database, currentTeam, 1);
|
||||
if (channelId === Screens.GLOBAL_THREADS) {
|
||||
return switchToGlobalThreads(serverUrl);
|
||||
}
|
||||
return switchToChannelById(serverUrl, channelId);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
|
|
|
|||
|
|
@ -1,25 +1,15 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {switchToGlobalThreads} from '@actions/local/thread';
|
||||
import {switchToChannelById} from '@actions/remote/channel';
|
||||
import {fetchRoles} from '@actions/remote/role';
|
||||
import {fetchConfigAndLicense} from '@actions/remote/systems';
|
||||
import {Screens} from '@constants';
|
||||
import {SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
import {PUSH_PROXY_RESPONSE_NOT_AVAILABLE, PUSH_PROXY_RESPONSE_UNKNOWN, PUSH_PROXY_STATUS_NOT_AVAILABLE, PUSH_PROXY_STATUS_UNKNOWN, PUSH_PROXY_STATUS_VERIFIED} from '@constants/push_proxy';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {getDeviceToken} from '@queries/app/global';
|
||||
import {queryChannelsById, getDefaultChannelForTeam} from '@queries/servers/channel';
|
||||
import {prepareModels} from '@queries/servers/entry';
|
||||
import {prepareCommonSystemValues, getCommonSystemValues, getCurrentTeamId, getWebSocketLastDisconnected, setCurrentTeamAndChannelId, getPushVerificationStatus} from '@queries/servers/system';
|
||||
import {getNthLastChannelFromTeam} from '@queries/servers/team';
|
||||
import {prepareCommonSystemValues, getCommonSystemValues, getCurrentTeamId, getWebSocketLastDisconnected, setCurrentTeamAndChannelId, getCurrentChannelId} from '@queries/servers/system';
|
||||
import {getCurrentUser} from '@queries/servers/user';
|
||||
import {deleteV1Data} from '@utils/file';
|
||||
import {isTablet} from '@utils/helpers';
|
||||
|
||||
import {deferredAppEntryActions, fetchAppEntryData, registerDeviceToken, syncOtherServers, teamsToRemove} from './common';
|
||||
import {deferredAppEntryActions, entry, registerDeviceToken, syncOtherServers, verifyPushProxy} from './common';
|
||||
|
||||
export async function appEntry(serverUrl: string, since = 0) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
|
|
@ -41,58 +31,31 @@ export async function appEntry(serverUrl: string, since = 0) {
|
|||
|
||||
const tabletDevice = await isTablet();
|
||||
const currentTeamId = await getCurrentTeamId(database);
|
||||
const currentChannelId = await getCurrentChannelId(database);
|
||||
const lastDisconnectedAt = (await getWebSocketLastDisconnected(database)) || since;
|
||||
const fetchedData = await fetchAppEntryData(serverUrl, lastDisconnectedAt, currentTeamId);
|
||||
|
||||
if ('error' in fetchedData) {
|
||||
return {error: fetchedData.error};
|
||||
const entryData = await entry(serverUrl, currentTeamId, currentChannelId, since);
|
||||
if ('error' in entryData) {
|
||||
return {error: entryData.error};
|
||||
}
|
||||
const {models, initialTeamId, initialChannelId, prefData, teamData, chData} = entryData;
|
||||
|
||||
const {initialTeamId, teamData, chData, prefData, meData, removeTeamIds, removeChannelIds} = fetchedData;
|
||||
const rolesData = await fetchRoles(serverUrl, teamData?.memberships, chData?.memberships, meData?.user, true, true);
|
||||
let switchToChannel = false;
|
||||
|
||||
if (initialTeamId === currentTeamId) {
|
||||
if (tabletDevice) {
|
||||
const cId = await getNthLastChannelFromTeam(database, currentTeamId);
|
||||
if (cId === Screens.GLOBAL_THREADS) {
|
||||
switchToGlobalThreads(serverUrl);
|
||||
} else {
|
||||
switchToChannelById(serverUrl, cId, initialTeamId);
|
||||
}
|
||||
}
|
||||
// Immediately set the new team as the current team in the database so that the UI
|
||||
// renders the correct team.
|
||||
if (tabletDevice && initialChannelId) {
|
||||
switchToChannel = true;
|
||||
switchToChannelById(serverUrl, initialChannelId, initialTeamId);
|
||||
} else {
|
||||
// Immediately set the new team as the current team in the database so that the UI
|
||||
// renders the correct team.
|
||||
let channelId = '';
|
||||
if (tabletDevice) {
|
||||
const channel = await getDefaultChannelForTeam(database, initialTeamId);
|
||||
channelId = channel?.id || '';
|
||||
}
|
||||
if (channelId) {
|
||||
switchToChannelById(serverUrl, channelId, initialTeamId);
|
||||
} else {
|
||||
setCurrentTeamAndChannelId(operator, initialTeamId, channelId);
|
||||
}
|
||||
setCurrentTeamAndChannelId(operator, initialTeamId, initialChannelId);
|
||||
}
|
||||
|
||||
const removeTeams = await teamsToRemove(serverUrl, removeTeamIds);
|
||||
await operator.batchRecords(models);
|
||||
|
||||
let removeChannels;
|
||||
if (removeChannelIds?.length) {
|
||||
removeChannels = await queryChannelsById(database, removeChannelIds).fetch();
|
||||
}
|
||||
|
||||
const modelPromises = await prepareModels({operator, initialTeamId, removeTeams, removeChannels, teamData, chData, prefData, meData});
|
||||
if (rolesData.roles?.length) {
|
||||
modelPromises.push(operator.handleRole({roles: rolesData.roles, prepareRecordsOnly: true}));
|
||||
}
|
||||
|
||||
const models = await Promise.all(modelPromises);
|
||||
await operator.batchRecords(models.flat());
|
||||
|
||||
const {id: currentUserId, locale: currentUserLocale} = meData.user || (await getCurrentUser(database))!;
|
||||
const {id: currentUserId, locale: currentUserLocale} = (await getCurrentUser(database))!;
|
||||
const {config, license} = await getCommonSystemValues(database);
|
||||
await deferredAppEntryActions(serverUrl, lastDisconnectedAt, currentUserId, currentUserLocale, prefData.preferences, config, license, teamData, chData, initialTeamId);
|
||||
await deferredAppEntryActions(serverUrl, lastDisconnectedAt, currentUserId, currentUserLocale, prefData.preferences, config, license, teamData, chData, initialTeamId, switchToChannel ? initialChannelId : undefined);
|
||||
|
||||
if (!since) {
|
||||
// Load data from other servers
|
||||
|
|
@ -101,58 +64,7 @@ export async function appEntry(serverUrl: string, since = 0) {
|
|||
|
||||
verifyPushProxy(serverUrl);
|
||||
|
||||
const error = teamData.error || chData?.error || prefData.error || meData.error;
|
||||
return {error, userId: meData?.user?.id};
|
||||
}
|
||||
|
||||
export async function verifyPushProxy(serverUrl: string) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
const ppVerification = await getPushVerificationStatus(database);
|
||||
if (
|
||||
ppVerification !== PUSH_PROXY_STATUS_UNKNOWN &&
|
||||
ppVerification !== ''
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const appDatabase = DatabaseManager.appDatabase?.database;
|
||||
if (!appDatabase) {
|
||||
return;
|
||||
}
|
||||
|
||||
const deviceId = await getDeviceToken(appDatabase);
|
||||
if (!deviceId) {
|
||||
return;
|
||||
}
|
||||
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await client.ping(deviceId);
|
||||
const canReceiveNotifications = response?.data?.CanReceiveNotifications;
|
||||
switch (canReceiveNotifications) {
|
||||
case PUSH_PROXY_RESPONSE_NOT_AVAILABLE:
|
||||
operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.PUSH_VERIFICATION_STATUS, value: PUSH_PROXY_STATUS_NOT_AVAILABLE}], prepareRecordsOnly: false});
|
||||
return;
|
||||
case PUSH_PROXY_RESPONSE_UNKNOWN:
|
||||
return;
|
||||
default:
|
||||
operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.PUSH_VERIFICATION_STATUS, value: PUSH_PROXY_STATUS_VERIFIED}], prepareRecordsOnly: false});
|
||||
}
|
||||
} catch (err) {
|
||||
// Do nothing
|
||||
}
|
||||
return {userId: currentUserId};
|
||||
}
|
||||
|
||||
export async function upgradeEntry(serverUrl: string) {
|
||||
|
|
@ -164,12 +76,12 @@ export async function upgradeEntry(serverUrl: string) {
|
|||
|
||||
try {
|
||||
const configAndLicense = await fetchConfigAndLicense(serverUrl, false);
|
||||
const entry = await appEntry(serverUrl);
|
||||
const entryData = await appEntry(serverUrl);
|
||||
|
||||
const error = configAndLicense.error || entry.error;
|
||||
const error = configAndLicense.error || entryData.error;
|
||||
|
||||
if (!error) {
|
||||
const models = await prepareCommonSystemValues(operator, {currentUserId: entry.userId});
|
||||
const models = await prepareCommonSystemValues(operator, {currentUserId: entryData.userId});
|
||||
if (models?.length) {
|
||||
await operator.batchRecords(models);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,19 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {fetchChannelStats, fetchMissingSidebarInfo, fetchMyChannelsForTeam, markChannelAsRead, MyChannelsRequest} from '@actions/remote/channel';
|
||||
import {fetchPostsForChannel, fetchPostsForUnreadChannels} from '@actions/remote/post';
|
||||
import {Model} from '@nozbe/watermelondb';
|
||||
|
||||
import {fetchMissingSidebarInfo, fetchMyChannelsForTeam, MyChannelsRequest} from '@actions/remote/channel';
|
||||
import {fetchPostsForUnreadChannels} from '@actions/remote/post';
|
||||
import {MyPreferencesRequest, fetchMyPreferences} from '@actions/remote/preference';
|
||||
import {fetchRoles} from '@actions/remote/role';
|
||||
import {fetchConfigAndLicense} from '@actions/remote/systems';
|
||||
import {fetchAllTeams, fetchMyTeams, fetchTeamsChannelsAndUnreadPosts, MyTeamsRequest} from '@actions/remote/team';
|
||||
import {fetchNewThreads} from '@actions/remote/thread';
|
||||
import {fetchMe, MyUserRequest, updateAllUsersSince} from '@actions/remote/user';
|
||||
import {Preferences} from '@constants';
|
||||
import {SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
import {PUSH_PROXY_RESPONSE_NOT_AVAILABLE, PUSH_PROXY_RESPONSE_UNKNOWN, PUSH_PROXY_STATUS_NOT_AVAILABLE, PUSH_PROXY_STATUS_UNKNOWN, PUSH_PROXY_STATUS_VERIFIED} from '@constants/push_proxy';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import {getPreferenceValue, getTeammateNameDisplaySetting} from '@helpers/api/preference';
|
||||
import {selectDefaultTeam} from '@helpers/api/team';
|
||||
|
|
@ -15,14 +21,13 @@ import {DEFAULT_LOCALE} from '@i18n';
|
|||
import NetworkManager from '@managers/network_manager';
|
||||
import {getDeviceToken} from '@queries/app/global';
|
||||
import {queryAllServers} from '@queries/app/servers';
|
||||
import {queryAllChannelsForTeam} from '@queries/servers/channel';
|
||||
import {getConfig} from '@queries/servers/system';
|
||||
import {deleteMyTeams, getAvailableTeamIds, queryMyTeams, queryMyTeamsByIds, queryTeamsById} from '@queries/servers/team';
|
||||
import {queryAllChannelsForTeam, queryChannelsById} from '@queries/servers/channel';
|
||||
import {prepareModels} from '@queries/servers/entry';
|
||||
import {getConfig, getPushVerificationStatus, getWebSocketLastDisconnected} from '@queries/servers/system';
|
||||
import {deleteMyTeams, getAvailableTeamIds, getNthLastChannelFromTeam, queryMyTeams, queryMyTeamsByIds, queryTeamsById} from '@queries/servers/team';
|
||||
import {isDMorGM} from '@utils/channel';
|
||||
import {isCRTEnabled} from '@utils/thread';
|
||||
|
||||
import {fetchNewThreads} from '../thread';
|
||||
|
||||
import type ClientError from '@client/rest/error';
|
||||
|
||||
export type AppEntryData = {
|
||||
|
|
@ -60,7 +65,65 @@ export const teamsToRemove = async (serverUrl: string, removeTeamIds?: string[])
|
|||
return undefined;
|
||||
};
|
||||
|
||||
export const fetchAppEntryData = async (serverUrl: string, since: number, initialTeamId: string): Promise<AppEntryData | AppEntryError> => {
|
||||
export type EntryResponse = {
|
||||
models: Model[];
|
||||
initialTeamId: string;
|
||||
initialChannelId: string;
|
||||
prefData: MyPreferencesRequest;
|
||||
teamData: MyTeamsRequest;
|
||||
chData?: MyChannelsRequest;
|
||||
} | {
|
||||
error: unknown;
|
||||
}
|
||||
export const entry = async (serverUrl: string, teamId?: string, channelId?: string, since = 0): Promise<EntryResponse> => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
const lastDisconnectedAt = since || await getWebSocketLastDisconnected(database);
|
||||
|
||||
const fetchedData = await fetchAppEntryData(serverUrl, lastDisconnectedAt, teamId);
|
||||
if ('error' in fetchedData) {
|
||||
return {error: fetchedData.error};
|
||||
}
|
||||
|
||||
const {initialTeamId, teamData, chData, prefData, meData, removeTeamIds, removeChannelIds} = fetchedData;
|
||||
const error = teamData.error || chData?.error || prefData.error || meData.error;
|
||||
if (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
const rolesData = await fetchRoles(serverUrl, teamData.memberships, chData?.memberships, meData.user, true);
|
||||
|
||||
let initialChannelId = channelId;
|
||||
if (!chData?.channels?.find((c) => c.id === channelId)) {
|
||||
initialChannelId = '';
|
||||
}
|
||||
if (initialTeamId !== teamId || !initialChannelId) {
|
||||
initialChannelId = await getNthLastChannelFromTeam(database, initialTeamId);
|
||||
}
|
||||
|
||||
const removeTeams = await teamsToRemove(serverUrl, removeTeamIds);
|
||||
|
||||
let removeChannels;
|
||||
if (removeChannelIds?.length) {
|
||||
removeChannels = await queryChannelsById(database, removeChannelIds).fetch();
|
||||
}
|
||||
|
||||
const modelPromises = await prepareModels({operator, initialTeamId, removeTeams, removeChannels, teamData, chData, prefData, meData});
|
||||
if (rolesData.roles?.length) {
|
||||
modelPromises.push(operator.handleRole({roles: rolesData.roles, prepareRecordsOnly: true}));
|
||||
}
|
||||
|
||||
const models = await Promise.all(modelPromises);
|
||||
|
||||
return {models: models.flat(), initialChannelId, initialTeamId, prefData, teamData, chData};
|
||||
};
|
||||
|
||||
export const fetchAppEntryData = async (serverUrl: string, since: number, initialTeamId = ''): Promise<AppEntryData | AppEntryError> => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
|
|
@ -188,13 +251,6 @@ export async function deferredAppEntryActions(
|
|||
serverUrl: string, since: number, currentUserId: string, currentUserLocale: string, preferences: PreferenceType[] | undefined,
|
||||
config: ClientConfig, license: ClientLicense, teamData: MyTeamsRequest, chData: MyChannelsRequest | undefined,
|
||||
initialTeamId?: string, initialChannelId?: string) {
|
||||
// defer fetching posts for initial channel
|
||||
if (initialChannelId) {
|
||||
fetchPostsForChannel(serverUrl, initialChannelId);
|
||||
markChannelAsRead(serverUrl, initialChannelId);
|
||||
fetchChannelStats(serverUrl, initialChannelId);
|
||||
}
|
||||
|
||||
// defer sidebar DM & GM profiles
|
||||
if (chData?.channels?.length && chData.memberships?.length) {
|
||||
const directChannels = chData.channels.filter(isDMorGM);
|
||||
|
|
@ -288,3 +344,53 @@ const syncAllChannelMembers = async (serverUrl: string) => {
|
|||
// Do nothing
|
||||
}
|
||||
};
|
||||
|
||||
export async function verifyPushProxy(serverUrl: string) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
const ppVerification = await getPushVerificationStatus(database);
|
||||
if (
|
||||
ppVerification !== PUSH_PROXY_STATUS_UNKNOWN &&
|
||||
ppVerification !== ''
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const appDatabase = DatabaseManager.appDatabase?.database;
|
||||
if (!appDatabase) {
|
||||
return;
|
||||
}
|
||||
|
||||
const deviceId = await getDeviceToken(appDatabase);
|
||||
if (!deviceId) {
|
||||
return;
|
||||
}
|
||||
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await client.ping(deviceId);
|
||||
const canReceiveNotifications = response?.data?.CanReceiveNotifications;
|
||||
switch (canReceiveNotifications) {
|
||||
case PUSH_PROXY_RESPONSE_NOT_AVAILABLE:
|
||||
operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.PUSH_VERIFICATION_STATUS, value: PUSH_PROXY_STATUS_NOT_AVAILABLE}], prepareRecordsOnly: false});
|
||||
return;
|
||||
case PUSH_PROXY_RESPONSE_UNKNOWN:
|
||||
return;
|
||||
default:
|
||||
operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.PUSH_VERIFICATION_STATUS, value: PUSH_PROXY_STATUS_VERIFIED}], prepareRecordsOnly: false});
|
||||
}
|
||||
} catch (err) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,18 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {fetchMyChannelsForTeam, MyChannelsRequest} from '@actions/remote/channel';
|
||||
import {MyPreferencesRequest, fetchMyPreferences} from '@actions/remote/preference';
|
||||
import {fetchRolesIfNeeded, RolesRequest} from '@actions/remote/role';
|
||||
import {switchToChannelById} from '@actions/remote/channel';
|
||||
import {getSessions} from '@actions/remote/session';
|
||||
import {ConfigAndLicenseRequest, fetchConfigAndLicense} from '@actions/remote/systems';
|
||||
import {fetchMyTeams, MyTeamsRequest} from '@actions/remote/team';
|
||||
import {Preferences} from '@constants';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import {getPreferenceValue} from '@helpers/api/preference';
|
||||
import {selectDefaultTeam} from '@helpers/api/team';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {prepareModels} from '@queries/servers/entry';
|
||||
import {prepareCommonSystemValues} from '@queries/servers/system';
|
||||
import {addChannelToTeamHistory, addTeamToTeamHistory} from '@queries/servers/team';
|
||||
import {selectDefaultChannelForTeam} from '@utils/channel';
|
||||
import {prepareCommonSystemValues, setCurrentTeamAndChannelId} from '@queries/servers/system';
|
||||
import {isTablet} from '@utils/helpers';
|
||||
import {scheduleExpiredNotification} from '@utils/notification';
|
||||
|
||||
import {deferredAppEntryActions} from './common';
|
||||
import {deferredAppEntryActions, entry, EntryResponse} from './common';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type TeamModel from '@typings/database/models/servers/team';
|
||||
|
||||
type AfterLoginArgs = {
|
||||
serverUrl: string;
|
||||
|
|
@ -54,20 +44,18 @@ export async function loginEntry({serverUrl, user, deviceToken}: AfterLoginArgs)
|
|||
|
||||
try {
|
||||
const isTabletDevice = await isTablet();
|
||||
let initialTeam: Team|TeamModel|undefined;
|
||||
let initialChannel: Channel|undefined;
|
||||
let myTeams: Team[]|undefined;
|
||||
|
||||
// Fetch in parallel server config & license / user preferences / teams / team membership
|
||||
const promises: [Promise<ConfigAndLicenseRequest>, Promise<MyPreferencesRequest>, Promise<MyTeamsRequest>] = [
|
||||
const promises: [Promise<ConfigAndLicenseRequest>, Promise<EntryResponse>] = [
|
||||
fetchConfigAndLicense(serverUrl, true),
|
||||
fetchMyPreferences(serverUrl, true),
|
||||
fetchMyTeams(serverUrl, true),
|
||||
entry(serverUrl, '', ''),
|
||||
];
|
||||
|
||||
const [clData, prefData, teamData] = await Promise.all(promises);
|
||||
let chData: MyChannelsRequest|undefined;
|
||||
let rData: RolesRequest|undefined;
|
||||
const [clData, entryData] = await Promise.all(promises);
|
||||
|
||||
if ('error' in entryData) {
|
||||
return {error: entryData.error};
|
||||
}
|
||||
|
||||
// schedule local push notification if needed
|
||||
if (clData.config) {
|
||||
|
|
@ -91,89 +79,22 @@ export async function loginEntry({serverUrl, user, deviceToken}: AfterLoginArgs)
|
|||
}
|
||||
}
|
||||
|
||||
// select initial team
|
||||
if (!clData.error && !prefData.error && !teamData.error) {
|
||||
const teamOrderPreference = getPreferenceValue(prefData.preferences!, Preferences.TEAMS_ORDER, '', '') as string;
|
||||
const teamRoles: string[] = [];
|
||||
const teamMembers = new Set<string>();
|
||||
|
||||
teamData.memberships?.forEach((tm) => {
|
||||
teamRoles.push(...tm.roles.split(' '));
|
||||
teamMembers.add(tm.team_id);
|
||||
});
|
||||
|
||||
myTeams = teamData.teams!.filter((t) => teamMembers.has(t.id));
|
||||
initialTeam = selectDefaultTeam(myTeams, user.locale, teamOrderPreference, clData.config?.ExperimentalPrimaryTeam);
|
||||
|
||||
if (initialTeam) {
|
||||
const rolesToFetch = new Set<string>([...user.roles.split(' '), ...teamRoles]);
|
||||
|
||||
// fetch channels / channel membership for initial team
|
||||
chData = await fetchMyChannelsForTeam(serverUrl, initialTeam.id, false, 0, true);
|
||||
if (chData.channels?.length && chData.memberships?.length) {
|
||||
const {channels, memberships} = chData;
|
||||
const channelIds = new Set(channels?.map((c) => c.id));
|
||||
for (let i = 0; i < memberships!.length; i++) {
|
||||
const member = memberships[i];
|
||||
if (channelIds.has(member.channel_id)) {
|
||||
member.roles.split(' ').forEach(rolesToFetch.add, rolesToFetch);
|
||||
}
|
||||
}
|
||||
|
||||
// fetch user roles
|
||||
rData = await fetchRolesIfNeeded(serverUrl, Array.from(rolesToFetch), true);
|
||||
|
||||
// select initial channel only on Tablets
|
||||
if (isTabletDevice) {
|
||||
initialChannel = selectDefaultChannelForTeam(channels!, memberships!, initialTeam!.id, rData.roles, user.locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
let switchToChannel = false;
|
||||
const {models, initialTeamId, initialChannelId, prefData, teamData, chData} = entryData;
|
||||
if (initialChannelId && isTabletDevice) {
|
||||
switchToChannel = true;
|
||||
switchToChannelById(serverUrl, initialChannelId, initialTeamId);
|
||||
} else {
|
||||
setCurrentTeamAndChannelId(operator, initialTeamId, '');
|
||||
}
|
||||
|
||||
const modelPromises = await prepareModels({operator, teamData, chData, prefData, initialTeamId: initialTeam?.id});
|
||||
|
||||
const systemModels = prepareCommonSystemValues(
|
||||
operator,
|
||||
{
|
||||
config: clData.config || ({} as ClientConfig),
|
||||
license: clData.license || ({} as ClientLicense),
|
||||
currentTeamId: initialTeam?.id || '',
|
||||
currentChannelId: initialChannel?.id || '',
|
||||
},
|
||||
);
|
||||
if (systemModels) {
|
||||
modelPromises.push(systemModels);
|
||||
}
|
||||
|
||||
if (initialTeam) {
|
||||
const th = addTeamToTeamHistory(operator, initialTeam.id, true);
|
||||
modelPromises.push(th);
|
||||
}
|
||||
|
||||
if (initialTeam && initialChannel) {
|
||||
try {
|
||||
const tch = addChannelToTeamHistory(operator, initialTeam.id, initialChannel.id, true);
|
||||
modelPromises.push(tch);
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
if (rData?.roles?.length) {
|
||||
const roles = operator.handleRole({roles: rData.roles, prepareRecordsOnly: true});
|
||||
modelPromises.push(roles);
|
||||
}
|
||||
|
||||
const models = await Promise.all(modelPromises);
|
||||
await operator.batchRecords(models.flat());
|
||||
await operator.batchRecords(models);
|
||||
|
||||
const config = clData.config || {} as ClientConfig;
|
||||
const license = clData.license || {} as ClientLicense;
|
||||
deferredAppEntryActions(serverUrl, 0, user.id, user.locale, prefData.preferences, config, license, teamData, chData, initialTeam?.id, initialChannel?.id);
|
||||
deferredAppEntryActions(serverUrl, 0, user.id, user.locale, prefData.preferences, config, license, teamData, chData, initialTeamId, switchToChannel ? initialChannelId : undefined);
|
||||
|
||||
const error = clData.error || prefData.error || teamData.error || chData?.error;
|
||||
return {error, time: Date.now() - dt, hasTeams: Boolean((myTeams?.length || 0) > 0 && !teamData.error)};
|
||||
return {time: Date.now() - dt, hasTeams: Boolean(teamData.teams?.length)};
|
||||
} catch (error) {
|
||||
const systemModels = await prepareCommonSystemValues(operator, {
|
||||
config: ({} as ClientConfig),
|
||||
|
|
|
|||
|
|
@ -2,12 +2,10 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import {switchToChannel} from '@actions/local/channel';
|
||||
import {markChannelAsRead} from '@actions/remote/channel';
|
||||
import {fetchRoles} from '@actions/remote/role';
|
||||
import {markChannelAsRead, switchToChannelById} from '@actions/remote/channel';
|
||||
import {Screens} from '@constants';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import {queryChannelsById, getDefaultChannelForTeam, getMyChannel} from '@queries/servers/channel';
|
||||
import {prepareModels} from '@queries/servers/entry';
|
||||
import {getMyChannel} from '@queries/servers/channel';
|
||||
import {getCommonSystemValues, getCurrentTeamId, getWebSocketLastDisconnected, setCurrentTeamAndChannelId} from '@queries/servers/system';
|
||||
import {getMyTeamById} from '@queries/servers/team';
|
||||
import {getCurrentUser} from '@queries/servers/user';
|
||||
|
|
@ -15,7 +13,7 @@ import EphemeralStore from '@store/ephemeral_store';
|
|||
import {isTablet} from '@utils/helpers';
|
||||
import {emitNotificationError} from '@utils/notification';
|
||||
|
||||
import {deferredAppEntryActions, fetchAppEntryData, syncOtherServers, teamsToRemove} from './common';
|
||||
import {deferredAppEntryActions, entry, syncOtherServers} from './common';
|
||||
|
||||
export async function pushNotificationEntry(serverUrl: string, notification: NotificationWithData) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
|
|
@ -23,9 +21,10 @@ export async function pushNotificationEntry(serverUrl: string, notification: Not
|
|||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const isTabletDevice = await isTablet();
|
||||
|
||||
// We only reach this point if we have a channel Id in the notification payload
|
||||
const channelId = notification.payload!.channel_id!;
|
||||
const isTabletDevice = await isTablet();
|
||||
const {database} = operator;
|
||||
const currentTeamId = await getCurrentTeamId(database);
|
||||
const lastDisconnectedAt = await getWebSocketLastDisconnected(database);
|
||||
|
|
@ -46,22 +45,17 @@ export async function pushNotificationEntry(serverUrl: string, notification: Not
|
|||
// To make the switch faster we determine if we already have the team & channel
|
||||
const myChannel = await getMyChannel(database, channelId);
|
||||
const myTeam = await getMyTeamById(database, teamId);
|
||||
let switchedToTeamAndChanel = false;
|
||||
if (myChannel && myTeam) {
|
||||
switchedToTeamAndChanel = true;
|
||||
await EphemeralStore.waitUntilScreenHasLoaded(Screens.HOME);
|
||||
markChannelAsRead(serverUrl, channelId);
|
||||
await switchToChannel(serverUrl, channelId, teamId);
|
||||
}
|
||||
|
||||
const fetchedData = await fetchAppEntryData(serverUrl, lastDisconnectedAt, teamId);
|
||||
|
||||
if ('error' in fetchedData) {
|
||||
return {error: fetchedData.error};
|
||||
const entryData = await entry(serverUrl, teamId, channelId);
|
||||
if ('error' in entryData) {
|
||||
return {error: entryData.error};
|
||||
}
|
||||
|
||||
const {initialTeamId, teamData, chData, prefData, meData, removeTeamIds, removeChannelIds} = fetchedData;
|
||||
const rolesData = await fetchRoles(serverUrl, teamData?.memberships, chData?.memberships, meData?.user, true);
|
||||
const {models, initialTeamId, initialChannelId, prefData, teamData, chData} = entryData;
|
||||
|
||||
// There is a chance that after the above request returns
|
||||
// the user is no longer part of the team or channel
|
||||
|
|
@ -72,68 +66,36 @@ export async function pushNotificationEntry(serverUrl: string, notification: Not
|
|||
// We are no longer a part of the team that the notification belongs to
|
||||
// Immediately set the new team as the current team in the database so that the UI
|
||||
// renders the correct team.
|
||||
|
||||
selectedTeamId = initialTeamId;
|
||||
if (!isDirectChannel) {
|
||||
if (isTabletDevice) {
|
||||
const channel = await getDefaultChannelForTeam(operator.database, selectedTeamId);
|
||||
selectedChannelId = channel?.id || '';
|
||||
} else {
|
||||
selectedChannelId = '';
|
||||
}
|
||||
selectedChannelId = initialChannelId;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeChannelIds?.includes(channelId)) {
|
||||
// We are no longer a part of the channel that the notification belongs to
|
||||
// Immediately set the new channel as the current channel in the database so that the UI
|
||||
// renders the correct channel.
|
||||
|
||||
if (isTabletDevice) {
|
||||
const channel = await getDefaultChannelForTeam(operator.database, selectedTeamId);
|
||||
selectedChannelId = channel?.id || '';
|
||||
} else {
|
||||
selectedChannelId = '';
|
||||
}
|
||||
}
|
||||
|
||||
// If in the end the selected team or channel is different than the one from the notification
|
||||
// we switch again
|
||||
if (selectedTeamId !== teamId || selectedChannelId !== channelId) {
|
||||
let switchedToChannel = false;
|
||||
if (isTabletDevice || (selectedChannelId === channelId)) {
|
||||
// Make switch again to get the missing data and make sure the team is the correct one
|
||||
switchedToChannel = true;
|
||||
switchToChannelById(serverUrl, selectedChannelId, selectedTeamId);
|
||||
} else if (selectedTeamId !== teamId || selectedChannelId !== channelId) {
|
||||
// If in the end the selected team or channel is different than the one from the notification
|
||||
// we switch again
|
||||
setCurrentTeamAndChannelId(operator, selectedTeamId, selectedChannelId);
|
||||
}
|
||||
|
||||
if (selectedTeamId !== teamId) {
|
||||
emitNotificationError('Team');
|
||||
} else if (selectedChannelId === channelId) {
|
||||
if (!switchedToTeamAndChanel) {
|
||||
markChannelAsRead(serverUrl, channelId);
|
||||
switchToChannel(serverUrl, channelId, teamId);
|
||||
}
|
||||
} else {
|
||||
} else if (selectedChannelId !== channelId) {
|
||||
emitNotificationError('Channel');
|
||||
}
|
||||
|
||||
const removeTeams = await teamsToRemove(serverUrl, removeTeamIds);
|
||||
await operator.batchRecords(models);
|
||||
|
||||
let removeChannels;
|
||||
if (removeChannelIds?.length) {
|
||||
removeChannels = await queryChannelsById(operator.database, removeChannelIds).fetch();
|
||||
}
|
||||
|
||||
const modelPromises = await prepareModels({operator, initialTeamId, removeTeams, removeChannels, teamData, chData, prefData, meData});
|
||||
if (rolesData.roles?.length) {
|
||||
modelPromises.push(operator.handleRole({roles: rolesData.roles, prepareRecordsOnly: true}));
|
||||
}
|
||||
|
||||
const models = await Promise.all(modelPromises);
|
||||
await operator.batchRecords(models.flat());
|
||||
|
||||
const {id: currentUserId, locale: currentUserLocale} = meData.user || (await getCurrentUser(operator.database))!;
|
||||
const {id: currentUserId, locale: currentUserLocale} = (await getCurrentUser(operator.database))!;
|
||||
const {config, license} = await getCommonSystemValues(operator.database);
|
||||
|
||||
await deferredAppEntryActions(serverUrl, lastDisconnectedAt, currentUserId, currentUserLocale, prefData.preferences, config, license, teamData, chData, selectedTeamId, selectedChannelId);
|
||||
await deferredAppEntryActions(serverUrl, lastDisconnectedAt, currentUserId, currentUserLocale, prefData.preferences, config, license, teamData, chData, selectedTeamId, switchedToChannel ? selectedChannelId : undefined);
|
||||
syncOtherServers(serverUrl);
|
||||
const error = teamData.error || chData?.error || prefData.error || meData.error;
|
||||
return {error, userId: meData?.user?.id};
|
||||
|
||||
return {userId: currentUserId};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import {Model} from '@nozbe/watermelondb';
|
|||
import {DeviceEventEmitter} from 'react-native';
|
||||
|
||||
import {removeUserFromTeam as localRemoveUserFromTeam} from '@actions/local/team';
|
||||
import {switchToGlobalThreads} from '@actions/local/thread';
|
||||
import {Events, Screens} from '@constants';
|
||||
import {Events} from '@constants';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {prepareCategories, prepareCategoryChannels} from '@queries/servers/categories';
|
||||
|
|
@ -273,11 +272,7 @@ export async function handleTeamChange(serverUrl: string, teamId: string) {
|
|||
if (await isTablet()) {
|
||||
channelId = await getNthLastChannelFromTeam(database, teamId);
|
||||
if (channelId) {
|
||||
if (channelId === Screens.GLOBAL_THREADS) {
|
||||
await switchToGlobalThreads(serverUrl);
|
||||
} else {
|
||||
await switchToChannelById(serverUrl, channelId, teamId);
|
||||
}
|
||||
await switchToChannelById(serverUrl, channelId, teamId);
|
||||
DeviceEventEmitter.emit(Events.TEAM_SWITCH, false);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import {Events, Screens} from '@constants';
|
|||
import DatabaseManager from '@database/manager';
|
||||
import {queryActiveServer} from '@queries/app/servers';
|
||||
import {deleteChannelMembership, getChannelById, prepareMyChannelsForTeam, getCurrentChannel} from '@queries/servers/channel';
|
||||
import {prepareCommonSystemValues, getConfig, setCurrentChannelId, getCurrentChannelId} from '@queries/servers/system';
|
||||
import {prepareCommonSystemValues, getConfig, setCurrentChannelId, getCurrentChannelId, getCurrentTeamId} from '@queries/servers/system';
|
||||
import {getNthLastChannelFromTeam} from '@queries/servers/team';
|
||||
import {getCurrentUser, getTeammateNameDisplay, getUserById} from '@queries/servers/user';
|
||||
import {dismissAllModals, popToRoot} from '@screens/navigation';
|
||||
|
|
@ -354,10 +354,14 @@ export async function handleUserRemovedFromChannelEvent(serverUrl: string, msg:
|
|||
await popToRoot();
|
||||
|
||||
if (await isTablet()) {
|
||||
const channelToJumpTo = await getNthLastChannelFromTeam(database, channel?.teamId);
|
||||
let tId = channel.teamId;
|
||||
if (!tId) {
|
||||
tId = await getCurrentTeamId(database);
|
||||
}
|
||||
const channelToJumpTo = await getNthLastChannelFromTeam(database, tId);
|
||||
if (channelToJumpTo) {
|
||||
if (channelToJumpTo === Screens.GLOBAL_THREADS) {
|
||||
const {models: switchToGlobalThreadsModels} = await switchToGlobalThreads(serverUrl, true);
|
||||
const {models: switchToGlobalThreadsModels} = await switchToGlobalThreads(serverUrl, tId, true);
|
||||
if (switchToGlobalThreadsModels) {
|
||||
models.push(...switchToGlobalThreadsModels);
|
||||
}
|
||||
|
|
@ -422,10 +426,14 @@ export async function handleChannelDeletedEvent(serverUrl: string, msg: WebSocke
|
|||
await popToRoot();
|
||||
|
||||
if (await isTablet()) {
|
||||
const channelToJumpTo = await getNthLastChannelFromTeam(database, currentChannel?.teamId);
|
||||
let tId = currentChannel.teamId;
|
||||
if (!tId) {
|
||||
tId = await getCurrentTeamId(database);
|
||||
}
|
||||
const channelToJumpTo = await getNthLastChannelFromTeam(database, tId);
|
||||
if (channelToJumpTo) {
|
||||
if (channelToJumpTo === Screens.GLOBAL_THREADS) {
|
||||
switchToGlobalThreads(serverUrl);
|
||||
switchToGlobalThreads(serverUrl, tId);
|
||||
return;
|
||||
}
|
||||
switchToChannel(serverUrl, channelToJumpTo);
|
||||
|
|
|
|||
|
|
@ -1,26 +1,22 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {markChannelAsViewed} from '@actions/local/channel';
|
||||
import {fetchMissingSidebarInfo, markChannelAsRead, switchToChannelById} from '@actions/remote/channel';
|
||||
import {fetchAppEntryData, teamsToRemove} from '@actions/remote/entry/common';
|
||||
import {fetchPostsForUnreadChannels, fetchPostsSince} from '@actions/remote/post';
|
||||
import {fetchRoles} from '@actions/remote/role';
|
||||
import {fetchConfigAndLicense} from '@actions/remote/systems';
|
||||
import {fetchAllTeams, fetchTeamsChannelsAndUnreadPosts} from '@actions/remote/team';
|
||||
import {fetchNewThreads} from '@actions/remote/thread';
|
||||
import {fetchStatusByIds, updateAllUsersSince} from '@actions/remote/user';
|
||||
import {Screens, WebsocketEvents} from '@constants';
|
||||
import {DeviceEventEmitter} from 'react-native';
|
||||
|
||||
import {switchToChannelById} from '@actions/remote/channel';
|
||||
import {deferredAppEntryActions, entry} from '@actions/remote/entry/common';
|
||||
import {fetchStatusByIds} from '@actions/remote/user';
|
||||
import {Events, Screens, WebsocketEvents} from '@constants';
|
||||
import {SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import {getTeammateNameDisplaySetting} from '@helpers/api/preference';
|
||||
import {queryChannelsById, getDefaultChannelForTeam} from '@queries/servers/channel';
|
||||
import {prepareModels} from '@queries/servers/entry';
|
||||
import {getCommonSystemValues, getConfig, getCurrentChannelId, getWebSocketLastDisconnected, resetWebSocketLastDisconnected, setCurrentTeamAndChannelId} from '@queries/servers/system';
|
||||
import {queryActiveServer} from '@queries/app/servers';
|
||||
import {getCurrentChannel} from '@queries/servers/channel';
|
||||
import {getCommonSystemValues, getConfig, getWebSocketLastDisconnected, resetWebSocketLastDisconnected, setCurrentTeamAndChannelId} from '@queries/servers/system';
|
||||
import {getCurrentTeam} from '@queries/servers/team';
|
||||
import {getCurrentUser} from '@queries/servers/user';
|
||||
import {dismissAllModals, popToRoot} from '@screens/navigation';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {isDMorGM} from '@utils/channel';
|
||||
import {isTablet} from '@utils/helpers';
|
||||
import {isCRTEnabled} from '@utils/thread';
|
||||
|
||||
import {handleCategoryCreatedEvent, handleCategoryDeletedEvent, handleCategoryOrderUpdatedEvent, handleCategoryUpdatedEvent} from './category';
|
||||
import {handleChannelConvertedEvent, handleChannelCreatedEvent,
|
||||
|
|
@ -91,140 +87,57 @@ async function doReconnect(serverUrl: string) {
|
|||
return;
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
const tabletDevice = await isTablet();
|
||||
const system = await getCommonSystemValues(database);
|
||||
const lastDisconnectedAt = await getWebSocketLastDisconnected(database);
|
||||
|
||||
resetWebSocketLastDisconnected(operator);
|
||||
let {config, license} = await fetchConfigAndLicense(serverUrl);
|
||||
if (!config) {
|
||||
config = system.config;
|
||||
}
|
||||
|
||||
if (!license) {
|
||||
license = system.license;
|
||||
}
|
||||
|
||||
const fetchedData = await fetchAppEntryData(serverUrl, lastDisconnectedAt, system.currentTeamId);
|
||||
|
||||
if ('error' in fetchedData) {
|
||||
const appDatabase = DatabaseManager.appDatabase?.database;
|
||||
if (!appDatabase) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {initialTeamId, teamData, chData, prefData, meData, removeTeamIds, removeChannelIds} = fetchedData;
|
||||
const rolesData = await fetchRoles(serverUrl, teamData.memberships, chData?.memberships, meData.user, true);
|
||||
const profiles: UserProfile[] = [];
|
||||
const {database} = operator;
|
||||
const tabletDevice = await isTablet();
|
||||
const lastDisconnectedAt = await getWebSocketLastDisconnected(database);
|
||||
resetWebSocketLastDisconnected(operator);
|
||||
const currentTeam = await getCurrentTeam(database);
|
||||
const currentChannel = await getCurrentChannel(database);
|
||||
|
||||
if (chData?.channels?.length) {
|
||||
const teammateDisplayNameSetting = getTeammateNameDisplaySetting(prefData.preferences || [], config, license);
|
||||
let direct: Channel[];
|
||||
[chData.channels, direct] = chData.channels.reduce<Channel[][]>(([others, channels], c: Channel) => {
|
||||
if (isDMorGM(c)) {
|
||||
channels.push(c);
|
||||
} else {
|
||||
others.push(c);
|
||||
}
|
||||
|
||||
return [others, channels];
|
||||
}, [[], []]);
|
||||
|
||||
if (direct.length) {
|
||||
const {directChannels, users} = await fetchMissingSidebarInfo(serverUrl, direct, meData.user?.locale, teammateDisplayNameSetting, system.currentUserId, true);
|
||||
if (directChannels?.length) {
|
||||
chData.channels.push(...directChannels);
|
||||
}
|
||||
if (users?.length) {
|
||||
profiles.push(...users);
|
||||
}
|
||||
}
|
||||
const entryData = await entry(serverUrl, currentTeam?.id, currentChannel?.id, lastDisconnectedAt);
|
||||
if ('error' in entryData) {
|
||||
return;
|
||||
}
|
||||
const {models, initialTeamId, initialChannelId, prefData, teamData, chData} = entryData;
|
||||
|
||||
// if no longer a member of the current team
|
||||
if (initialTeamId !== system.currentTeamId) {
|
||||
let cId = '';
|
||||
if (tabletDevice) {
|
||||
if (!cId) {
|
||||
const channel = await getDefaultChannelForTeam(database, initialTeamId);
|
||||
if (channel) {
|
||||
cId = channel.id;
|
||||
}
|
||||
}
|
||||
switchToChannelById(serverUrl, cId, initialTeamId);
|
||||
} else {
|
||||
setCurrentTeamAndChannelId(operator, initialTeamId, cId);
|
||||
}
|
||||
}
|
||||
|
||||
const removeTeams = await teamsToRemove(serverUrl, removeTeamIds);
|
||||
|
||||
let removeChannels;
|
||||
if (removeChannelIds?.length) {
|
||||
removeChannels = await queryChannelsById(database, removeChannelIds).fetch();
|
||||
}
|
||||
|
||||
const modelPromises = await prepareModels({operator, initialTeamId, removeTeams, removeChannels, teamData, chData, prefData, meData});
|
||||
if (rolesData.roles?.length) {
|
||||
modelPromises.push(operator.handleRole({roles: rolesData.roles, prepareRecordsOnly: true}));
|
||||
}
|
||||
|
||||
if (profiles.length) {
|
||||
modelPromises.push(operator.handleUsers({users: profiles, prepareRecordsOnly: true}));
|
||||
}
|
||||
|
||||
if (modelPromises.length) {
|
||||
const models = await Promise.all(modelPromises);
|
||||
const flattenedModels = models.flat();
|
||||
if (flattenedModels?.length > 0) {
|
||||
try {
|
||||
await operator.batchRecords(flattenedModels);
|
||||
} catch {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('FAILED TO BATCH WS reconnection');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const currentChannelId = await getCurrentChannelId(database);
|
||||
if (currentChannelId) {
|
||||
// https://mattermost.atlassian.net/browse/MM-40098
|
||||
fetchPostsSince(serverUrl, currentChannelId, lastDisconnectedAt);
|
||||
let switchedToChannel = false;
|
||||
|
||||
// if no longer a member of the current team or the current channel
|
||||
if (initialTeamId !== currentTeam?.id || initialChannelId !== currentChannel?.id) {
|
||||
const currentServer = await queryActiveServer(appDatabase);
|
||||
const isChannelScreenMounted = EphemeralStore.getNavigationComponents().includes(Screens.CHANNEL);
|
||||
|
||||
if (isChannelScreenMounted || tabletDevice) {
|
||||
markChannelAsRead(serverUrl, currentChannelId);
|
||||
markChannelAsViewed(serverUrl, currentChannelId);
|
||||
}
|
||||
|
||||
// defer fetching posts for unread channels on initial team
|
||||
if (chData?.channels && chData.memberships) {
|
||||
fetchPostsForUnreadChannels(serverUrl, chData.channels, chData.memberships, currentChannelId);
|
||||
}
|
||||
}
|
||||
|
||||
// defer fetch channels and unread posts for other teams
|
||||
if (teamData.teams?.length && teamData.memberships?.length) {
|
||||
await fetchTeamsChannelsAndUnreadPosts(serverUrl, lastDisconnectedAt, teamData.teams, teamData.memberships, initialTeamId);
|
||||
}
|
||||
|
||||
if (prefData.preferences && isCRTEnabled(prefData.preferences, config)) {
|
||||
if (initialTeamId) {
|
||||
await fetchNewThreads(serverUrl, initialTeamId, false);
|
||||
}
|
||||
|
||||
if (teamData.teams?.length) {
|
||||
for await (const team of teamData.teams) {
|
||||
if (team.id !== initialTeamId) {
|
||||
// need to await here since GM/DM threads in different teams overlap
|
||||
await fetchNewThreads(serverUrl, team.id, false);
|
||||
}
|
||||
if (serverUrl === currentServer?.url) {
|
||||
if (currentTeam && initialTeamId !== currentTeam.id) {
|
||||
DeviceEventEmitter.emit(Events.LEAVE_TEAM, {displayName: currentTeam.displayName});
|
||||
await dismissAllModals();
|
||||
await popToRoot();
|
||||
} else if (currentChannel && initialChannelId !== currentChannel.id && isChannelScreenMounted) {
|
||||
DeviceEventEmitter.emit(Events.LEAVE_CHANNEL, {displayName: currentChannel?.displayName});
|
||||
await dismissAllModals();
|
||||
await popToRoot();
|
||||
}
|
||||
|
||||
if (tabletDevice && initialChannelId) {
|
||||
switchedToChannel = true;
|
||||
switchToChannelById(serverUrl, initialChannelId, initialTeamId);
|
||||
} else {
|
||||
setCurrentTeamAndChannelId(operator, initialTeamId, initialChannelId);
|
||||
}
|
||||
} else {
|
||||
setCurrentTeamAndChannelId(operator, initialTeamId, initialChannelId);
|
||||
}
|
||||
}
|
||||
|
||||
fetchAllTeams(serverUrl);
|
||||
updateAllUsersSince(serverUrl, lastDisconnectedAt);
|
||||
await operator.batchRecords(models);
|
||||
|
||||
const {id: currentUserId, locale: currentUserLocale} = (await getCurrentUser(database))!;
|
||||
const {config, license} = await getCommonSystemValues(database);
|
||||
await deferredAppEntryActions(serverUrl, lastDisconnectedAt, currentUserId, currentUserLocale, prefData.preferences, config, license, teamData, chData, initialTeamId, switchedToChannel ? initialChannelId : undefined);
|
||||
|
||||
// https://mattermost.atlassian.net/browse/MM-41520
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import {Events, Screens} from '@constants';
|
|||
import {useTheme} from '@context/theme';
|
||||
import {findChannels} from '@screens/navigation';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {alertTeamRemove} from '@utils/navigation';
|
||||
import {alertChannelRemove, alertTeamRemove} from '@utils/navigation';
|
||||
import {notificationError} from '@utils/notification';
|
||||
|
||||
import Account from './account';
|
||||
|
|
@ -62,6 +62,16 @@ export default function HomeScreen(props: HomeProps) {
|
|||
};
|
||||
}, [intl.locale]);
|
||||
|
||||
useEffect(() => {
|
||||
const listener = DeviceEventEmitter.addListener(Events.LEAVE_CHANNEL, (displayName: string) => {
|
||||
alertChannelRemove(displayName, intl);
|
||||
});
|
||||
|
||||
return () => {
|
||||
listener.remove();
|
||||
};
|
||||
}, [intl.locale]);
|
||||
|
||||
useEffect(() => {
|
||||
const listener = HWKeyboardEvent.onHWKeyPressed((keyEvent: {pressedKey: string}) => {
|
||||
const screen = EphemeralStore.getAllNavigationComponents();
|
||||
|
|
|
|||
|
|
@ -29,3 +29,20 @@ export async function alertTeamRemove(displayName: string, intl: IntlShape) {
|
|||
}],
|
||||
);
|
||||
}
|
||||
|
||||
export async function alertChannelRemove(displayName: string, intl: IntlShape) {
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
id: 'alert.removed_from_channel.title',
|
||||
defaultMessage: 'Removed from channel',
|
||||
}),
|
||||
intl.formatMessage({
|
||||
id: 'alert.removed_from_channel.description',
|
||||
defaultMessage: 'You have been removed from channel {displayName}.',
|
||||
}, {displayName}),
|
||||
[{
|
||||
style: 'cancel',
|
||||
text: intl.formatMessage({id: 'mobile.oauth.something_wrong.okButton', defaultMessage: 'OK'}),
|
||||
}],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue