Fix notification entry on graphQL (#6608)

Co-authored-by: Daniel Espino <danielespino@MacBook-Pro-de-Daniel.local>
This commit is contained in:
Daniel Espino García
2022-09-02 13:57:47 +02:00
committed by GitHub
parent fab4c1a216
commit b42710759a
4 changed files with 79 additions and 66 deletions

View File

@@ -35,7 +35,7 @@ export async function appEntry(serverUrl: string, since = 0, isUpgrade = false)
let result;
if (config?.FeatureFlagGraphQL === 'true') {
const {currentTeamId, currentChannelId} = await getCommonSystemValues(database);
result = await graphQLCommon(serverUrl, true, currentTeamId, currentChannelId, isUpgrade);
result = await graphQLCommon(serverUrl, true, currentTeamId, currentChannelId, '', isUpgrade);
if (result.error) {
logDebug('Error using GraphQL, trying REST', result.error);
result = restAppEntry(serverUrl, since, isUpgrade);

View File

@@ -3,16 +3,16 @@
import {Model} from '@nozbe/watermelondb';
import {fetchMissingDirectChannelsInfo, fetchMyChannelsForTeam, MyChannelsRequest} from '@actions/remote/channel';
import {fetchMissingDirectChannelsInfo, fetchMyChannelsForTeam, MyChannelsRequest, switchToChannelById} 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 {fetchAndSwitchToThread, fetchNewThreads} from '@actions/remote/thread';
import {fetchMe, MyUserRequest, updateAllUsersSince} from '@actions/remote/user';
import {gqlAllChannels} from '@client/graphQL/entry';
import {Preferences} from '@constants';
import {Preferences, 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';
@@ -22,14 +22,18 @@ import {DEFAULT_LOCALE} from '@i18n';
import NetworkManager from '@managers/network_manager';
import {getDeviceToken} from '@queries/app/global';
import {queryAllServers} from '@queries/app/servers';
import {prepareMyChannelsForTeam, queryAllChannelsForTeam, queryChannelsById} from '@queries/servers/channel';
import {getMyChannel, prepareMyChannelsForTeam, queryAllChannelsForTeam, queryChannelsById} from '@queries/servers/channel';
import {prepareModels, truncateCrtRelatedTables} from '@queries/servers/entry';
import {getHasCRTChanged} from '@queries/servers/preference';
import {getConfig, getCurrentUserId, getPushVerificationStatus, getWebSocketLastDisconnected} from '@queries/servers/system';
import {deleteMyTeams, getAvailableTeamIds, getNthLastChannelFromTeam, queryMyTeams, queryMyTeamsByIds, queryTeamsById} from '@queries/servers/team';
import {getConfig, getCurrentUserId, getPushVerificationStatus, getWebSocketLastDisconnected, setCurrentTeamAndChannelId} from '@queries/servers/system';
import {deleteMyTeams, getAvailableTeamIds, getMyTeamById, getNthLastChannelFromTeam, queryMyTeams, queryMyTeamsByIds, queryTeamsById} from '@queries/servers/team';
import {getIsCRTEnabled} from '@queries/servers/thread';
import NavigationStore from '@store/navigation_store';
import {isDMorGM} from '@utils/channel';
import {getMemberChannelsFromGQLQuery, gqlToClientChannelMembership} from '@utils/graphql';
import {isTablet} from '@utils/helpers';
import {logDebug} from '@utils/log';
import {emitNotificationError} from '@utils/notification';
import {processIsCRTEnabled} from '@utils/thread';
import {fetchGroupsForMember} from '../groups';
@@ -482,3 +486,61 @@ export async function verifyPushProxy(serverUrl: string) {
// Do nothing
}
}
export async function handleNotificationNavigation(serverUrl: string, selectedChannelId: string, selectedTeamId: string, notificationChannelId: string, notificationTeamId: string, rootId = '') {
try {
const {operator, database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
const myChannel = await getMyChannel(database, selectedChannelId);
const myTeam = await getMyTeamById(database, selectedTeamId);
const isCRTEnabled = await getIsCRTEnabled(database);
const isThreadNotification = isCRTEnabled && Boolean(rootId);
let switchedToScreen = false;
let switchedToChannel = false;
if (myChannel && myTeam) {
if (isThreadNotification) {
await fetchAndSwitchToThread(serverUrl, rootId, true);
} else {
switchedToChannel = true;
await switchToChannelById(serverUrl, selectedChannelId, selectedTeamId);
}
switchedToScreen = true;
}
if (!switchedToScreen) {
const isTabletDevice = await isTablet();
if (isTabletDevice || (notificationChannelId === selectedChannelId)) {
// Make switch again to get the missing data and make sure the team is the correct one
switchedToScreen = true;
if (isThreadNotification) {
await fetchAndSwitchToThread(serverUrl, rootId, true);
} else {
switchedToChannel = true;
await switchToChannelById(serverUrl, notificationChannelId, notificationTeamId);
}
} else if (notificationTeamId !== selectedTeamId || notificationChannelId !== selectedChannelId) {
// If in the end the selected team or channel is different than the one from the notification
// we switch again
await setCurrentTeamAndChannelId(operator, selectedTeamId, selectedChannelId);
}
}
if (notificationTeamId !== selectedTeamId) {
emitNotificationError('Team');
} else if (notificationChannelId !== selectedChannelId) {
emitNotificationError('Channel');
}
// Waiting for the screen to display fixes a race condition when fetching and storing data
if (switchedToChannel) {
await NavigationStore.waitUntilScreenHasLoaded(Screens.CHANNEL);
} else if (switchedToScreen && isThreadNotification) {
await NavigationStore.waitUntilScreenHasLoaded(Screens.THREAD);
}
return {};
} catch (error) {
return {error};
}
}

View File

@@ -24,7 +24,7 @@ import {filterAndTransformRoles, getMemberChannelsFromGQLQuery, getMemberTeamsFr
import {isTablet} from '@utils/helpers';
import {processIsCRTEnabled} from '@utils/thread';
import {teamsToRemove, FETCH_UNREADS_TIMEOUT} from './common';
import {teamsToRemove, FETCH_UNREADS_TIMEOUT, handleNotificationNavigation} from './common';
import type ClientError from '@client/rest/error';
import type ChannelModel from '@typings/database/models/servers/channel';
@@ -158,7 +158,7 @@ const getChannelData = async (serverUrl: string, initialTeamId: string, userId:
return {chData, roles};
};
export const graphQLCommon = async (serverUrl: string, syncDatabase: boolean, currentTeamId: string, currentChannelId: string, isUpgrade = false) => {
export const graphQLCommon = async (serverUrl: string, syncDatabase: boolean, currentTeamId: string, currentChannelId: string, rootId?: string, isUpgrade = false, isNotificationEntry = false) => {
const dt = Date.now();
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
@@ -303,6 +303,10 @@ export const graphQLCommon = async (serverUrl: string, syncDatabase: boolean, cu
await operator.batchRecords(models.flat());
}
if (isNotificationEntry) {
await handleNotificationNavigation(serverUrl, initialChannelId, initialTeamId, currentChannelId, currentTeamId, rootId);
}
const isCRTEnabled = Boolean(prefData.preferences && processIsCRTEnabled(prefData.preferences, config));
deferredAppEntryGraphQLActions(serverUrl, 0, meData, teamData, chData, isTabletDevice, initialTeamId, initialChannelId, isCRTEnabled, syncDatabase);

View File

@@ -1,25 +1,18 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {switchToChannelById} from '@actions/remote/channel';
import {fetchAndSwitchToThread} from '@actions/remote/thread';
import {Preferences, Screens} from '@constants';
import {getDefaultThemeByAppearance} from '@context/theme';
import DatabaseManager from '@database/manager';
import {getMyChannel} from '@queries/servers/channel';
import {queryPreferencesByCategoryAndName} from '@queries/servers/preference';
import {getCommonSystemValues, getConfig, getCurrentTeamId, getWebSocketLastDisconnected, setCurrentTeamAndChannelId} from '@queries/servers/system';
import {getMyTeamById} from '@queries/servers/team';
import {getIsCRTEnabled} from '@queries/servers/thread';
import {getCommonSystemValues, getConfig, getCurrentTeamId, getWebSocketLastDisconnected} from '@queries/servers/system';
import {getCurrentUser} from '@queries/servers/user';
import EphemeralStore from '@store/ephemeral_store';
import NavigationStore from '@store/navigation_store';
import {isTablet} from '@utils/helpers';
import {logDebug} from '@utils/log';
import {emitNotificationError} from '@utils/notification';
import {setThemeDefaults, updateThemeIfNeeded} from '@utils/theme';
import {deferredAppEntryActions, entry, syncOtherServers} from './common';
import {deferredAppEntryActions, entry, handleNotificationNavigation, syncOtherServers} from './common';
import {graphQLCommon} from './gql_common';
export async function pushNotificationEntry(serverUrl: string, notification: NotificationWithData) {
@@ -64,7 +57,7 @@ export async function pushNotificationEntry(serverUrl: string, notification: Not
const config = await getConfig(database);
let result;
if (config?.FeatureFlagGraphQL === 'true') {
result = await graphQLCommon(serverUrl, true, teamId, channelId);
result = await graphQLCommon(serverUrl, true, teamId, channelId, rootId, false, true);
if (result.error) {
logDebug('Error using GraphQL, trying REST', result.error);
result = restNotificationEntry(serverUrl, teamId, channelId, rootId, isDirectChannel);
@@ -106,61 +99,15 @@ const restNotificationEntry = async (serverUrl: string, teamId: string, channelI
}
}
const myChannel = await getMyChannel(database, channelId);
const myTeam = await getMyTeamById(database, teamId);
const isCRTEnabled = await getIsCRTEnabled(database);
const isThreadNotification = isCRTEnabled && Boolean(rootId);
await operator.batchRecords(models);
let switchedToScreen = false;
let switchedToChannel = false;
if (myChannel && myTeam) {
if (isThreadNotification) {
await fetchAndSwitchToThread(serverUrl, rootId, true);
} else {
switchedToChannel = true;
await switchToChannelById(serverUrl, channelId, teamId);
}
switchedToScreen = true;
}
if (!switchedToScreen) {
const isTabletDevice = await isTablet();
if (isTabletDevice || (selectedChannelId === channelId)) {
// Make switch again to get the missing data and make sure the team is the correct one
switchedToScreen = true;
if (isThreadNotification) {
await fetchAndSwitchToThread(serverUrl, rootId, true);
} else {
switchedToChannel = true;
await 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
await setCurrentTeamAndChannelId(operator, selectedTeamId, selectedChannelId);
}
}
if (selectedTeamId !== teamId) {
emitNotificationError('Team');
} else if (selectedChannelId !== channelId) {
emitNotificationError('Channel');
}
await handleNotificationNavigation(serverUrl, selectedChannelId, selectedTeamId, channelId, teamId, rootId);
const {id: currentUserId, locale: currentUserLocale} = (await getCurrentUser(operator.database))!;
const {config, license} = await getCommonSystemValues(operator.database);
const lastDisconnectedAt = await getWebSocketLastDisconnected(database);
// Waiting for the screen to display fixes a race condition when fetching and storing data
if (switchedToChannel) {
await NavigationStore.waitUntilScreenHasLoaded(Screens.CHANNEL);
} else if (switchedToScreen && isThreadNotification) {
await NavigationStore.waitUntilScreenHasLoaded(Screens.THREAD);
}
await deferredAppEntryActions(serverUrl, lastDisconnectedAt, currentUserId, currentUserLocale, prefData.preferences, config, license, teamData, chData, selectedTeamId, selectedChannelId);
return {userId: currentUserId};