diff --git a/app/actions/remote/entry/app.ts b/app/actions/remote/entry/app.ts index c829d866e7..3f0c37b6da 100644 --- a/app/actions/remote/entry/app.ts +++ b/app/actions/remote/entry/app.ts @@ -8,12 +8,11 @@ import DatabaseManager from '@database/manager'; import {queryChannelsById, queryDefaultChannelForTeam} from '@queries/servers/channel'; import {prepareModels} from '@queries/servers/entry'; import {prepareCommonSystemValues, queryCommonSystemValues, queryCurrentChannelId, queryCurrentTeamId, queryWebSocketLastDisconnected, setCurrentTeamAndChannelId} from '@queries/servers/system'; -import {deleteMyTeams, queryTeamsById} from '@queries/servers/team'; import {queryCurrentUser} from '@queries/servers/user'; import {deleteV1Data} from '@utils/file'; import {isTablet} from '@utils/helpers'; -import {AppEntryData, AppEntryError, deferredAppEntryActions, fetchAppEntryData, syncOtherServers} from './common'; +import {AppEntryData, AppEntryError, deferredAppEntryActions, fetchAppEntryData, syncOtherServers, teamsToRemove} from './common'; export const appEntry = async (serverUrl: string, since = 0) => { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; @@ -62,12 +61,7 @@ export const appEntry = async (serverUrl: string, since = 0) => { } } - let removeTeams; - if (removeTeamIds?.length) { - // Immediately delete myTeams so that the UI renders only teams the user is a member of. - removeTeams = await queryTeamsById(database, removeTeamIds); - await deleteMyTeams(operator, removeTeams!); - } + const removeTeams = await teamsToRemove(serverUrl, removeTeamIds); let removeChannels; if (removeChannelIds?.length) { diff --git a/app/actions/remote/entry/common.ts b/app/actions/remote/entry/common.ts index c04d0b576f..44602c7526 100644 --- a/app/actions/remote/entry/common.ts +++ b/app/actions/remote/entry/common.ts @@ -5,7 +5,7 @@ import {fetchChannelStats, fetchMissingSidebarInfo, fetchMyChannelsForTeam, mark import {fetchPostsForChannel, fetchPostsForUnreadChannels} from '@actions/remote/post'; import {MyPreferencesRequest, fetchMyPreferences} from '@actions/remote/preference'; import {fetchConfigAndLicense} from '@actions/remote/systems'; -import {fetchMyTeams, fetchTeamsChannelsAndUnreadPosts, MyTeamsRequest} from '@actions/remote/team'; +import {fetchAllTeams, fetchMyTeams, fetchTeamsChannelsAndUnreadPosts, MyTeamsRequest} from '@actions/remote/team'; import {fetchMe, MyUserRequest, updateAllUsersSince} from '@actions/remote/user'; import {General, Preferences} from '@constants'; import DatabaseManager from '@database/manager'; @@ -16,7 +16,7 @@ import NetworkManager from '@init/network_manager'; import {queryAllServers} from '@queries/app/servers'; import {queryAllChannelsForTeam} from '@queries/servers/channel'; import {queryConfig} from '@queries/servers/system'; -import {queryAvailableTeamIds, queryMyTeams} from '@queries/servers/team'; +import {deleteMyTeams, queryAvailableTeamIds, queryMyTeams, queryMyTeamsById, queryTeamsById} from '@queries/servers/team'; import type ClientError from '@client/rest/error'; @@ -34,6 +34,27 @@ export type AppEntryError = { error?: Error | ClientError | string; } +export const teamsToRemove = async (serverUrl: string, removeTeamIds?: string[]) => { + const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; + if (!operator) { + return undefined; + } + + const {database} = operator; + if (removeTeamIds?.length) { + // Immediately delete myTeams so that the UI renders only teams the user is a member of. + const removeMyTeams = await queryMyTeamsById(database, removeTeamIds); + if (removeMyTeams?.length) { + await deleteMyTeams(operator, removeMyTeams); + const ids = removeMyTeams.map((m) => m.id); + const removeTeams = await queryTeamsById(database, ids); + return removeTeams; + } + } + + return undefined; +}; + export const fetchAppEntryData = async (serverUrl: string, since: number, initialTeamId: string): Promise => { const database = DatabaseManager.serverDatabases[serverUrl]?.database; if (!database) { @@ -187,6 +208,7 @@ export const deferredAppEntryActions = async ( await fetchTeamsChannelsAndUnreadPosts(serverUrl, since, teamData.teams, teamData.memberships, initialTeamId); } + fetchAllTeams(serverUrl); updateAllUsersSince(serverUrl, since); }; diff --git a/app/actions/remote/entry/notification.ts b/app/actions/remote/entry/notification.ts index 19f8c0f742..743b82280f 100644 --- a/app/actions/remote/entry/notification.ts +++ b/app/actions/remote/entry/notification.ts @@ -11,13 +11,13 @@ import DatabaseManager from '@database/manager'; import {queryChannelsById, queryDefaultChannelForTeam, queryMyChannel} from '@queries/servers/channel'; import {prepareModels} from '@queries/servers/entry'; import {queryCommonSystemValues, queryCurrentTeamId, queryWebSocketLastDisconnected, setCurrentTeamAndChannelId} from '@queries/servers/system'; -import {deleteMyTeams, queryMyTeamById, queryTeamsById} from '@queries/servers/team'; +import {queryMyTeamById} from '@queries/servers/team'; import {queryCurrentUser} from '@queries/servers/user'; import EphemeralStore from '@store/ephemeral_store'; import {isTablet} from '@utils/helpers'; import {emitNotificationError} from '@utils/notification'; -import {AppEntryData, AppEntryError, deferredAppEntryActions, fetchAppEntryData, syncOtherServers} from './common'; +import {AppEntryData, AppEntryError, deferredAppEntryActions, fetchAppEntryData, syncOtherServers, teamsToRemove} from './common'; export const pushNotificationEntry = async (serverUrl: string, notification: NotificationWithData) => { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; @@ -117,12 +117,7 @@ export const pushNotificationEntry = async (serverUrl: string, notification: Not emitNotificationError('Channel'); } - let removeTeams; - if (removeTeamIds?.length) { - // Immediately delete myTeams so that the UI renders only teams the user is a member of. - removeTeams = await queryTeamsById(operator.database, removeTeamIds); - await deleteMyTeams(operator, removeTeams!); - } + const removeTeams = await teamsToRemove(serverUrl, removeTeamIds); let removeChannels; if (removeChannelIds?.length) { diff --git a/app/actions/websocket/index.ts b/app/actions/websocket/index.ts index aa203346d5..4f4cb1c83b 100644 --- a/app/actions/websocket/index.ts +++ b/app/actions/websocket/index.ts @@ -2,7 +2,7 @@ // See LICENSE.txt for license information. import {fetchMissingSidebarInfo, switchToChannelById} from '@actions/remote/channel'; -import {AppEntryData, AppEntryError, fetchAppEntryData} from '@actions/remote/entry/common'; +import {AppEntryData, AppEntryError, 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'; @@ -15,7 +15,6 @@ import {getTeammateNameDisplaySetting} from '@helpers/api/preference'; import {queryChannelsById, queryDefaultChannelForTeam} from '@queries/servers/channel'; import {prepareModels} from '@queries/servers/entry'; import {queryCommonSystemValues, queryConfig, queryCurrentChannelId, queryWebSocketLastDisconnected, resetWebSocketLastDisconnected, setCurrentTeamAndChannelId} from '@queries/servers/system'; -import {deleteMyTeams, queryTeamsById} from '@queries/servers/team'; import {isTablet} from '@utils/helpers'; import {handleCategoryCreatedEvent, handleCategoryDeletedEvent, handleCategoryOrderUpdatedEvent, handleCategoryUpdatedEvent} from './category'; @@ -137,12 +136,7 @@ async function doReconnect(serverUrl: string) { } } - let removeTeams; - if (removeTeamIds?.length) { - // Immediately delete myTeams so that the UI renders only teams the user is a member of. - removeTeams = await queryTeamsById(database, removeTeamIds); - await deleteMyTeams(operator, removeTeams!); - } + const removeTeams = await teamsToRemove(serverUrl, removeTeamIds); let removeChannels; if (removeChannelIds?.length) { diff --git a/app/components/team_sidebar/team_sidebar.tsx b/app/components/team_sidebar/team_sidebar.tsx index 00d89d51af..1aa08528a3 100644 --- a/app/components/team_sidebar/team_sidebar.tsx +++ b/app/components/team_sidebar/team_sidebar.tsx @@ -4,9 +4,7 @@ import React, {useEffect} from 'react'; import Animated, {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; -import {fetchAllTeams} from '@actions/remote/team'; import {TEAM_SIDEBAR_WIDTH} from '@constants/view'; -import {useServerUrl} from '@context/server'; import {useTheme} from '@context/theme'; import {makeStyleSheetFromTheme} from '@utils/theme'; @@ -47,7 +45,6 @@ export default function TeamSidebar({canCreateTeams, iconPad, otherTeams, teamsC const width = useSharedValue(initialWidth); const marginTop = useSharedValue(iconPad ? 44 : 0); const theme = useTheme(); - const serverUrl = useServerUrl(); const styles = getStyleSheet(theme); const transform = useAnimatedStyle(() => { @@ -64,10 +61,6 @@ export default function TeamSidebar({canCreateTeams, iconPad, otherTeams, teamsC marginTop.value = iconPad ? 44 : 0; }, [iconPad]); - useEffect(() => { - fetchAllTeams(serverUrl); - }, [serverUrl]); - useEffect(() => { width.value = teamsCount > 1 ? TEAM_SIDEBAR_WIDTH : 0; }, [teamsCount]); diff --git a/app/queries/servers/team.ts b/app/queries/servers/team.ts index 36ad740368..2a266e82d1 100644 --- a/app/queries/servers/team.ts +++ b/app/queries/servers/team.ts @@ -188,16 +188,11 @@ export const prepareMyTeams = (operator: ServerDataOperator, teams: Team[], memb } }; -export const deleteMyTeams = async (operator: ServerDataOperator, teams: TeamModel[]) => { +export const deleteMyTeams = async (operator: ServerDataOperator, myTeams: MyTeamModel[]) => { try { const preparedModels: Model[] = []; - for await (const team of teams) { - try { - const myTeam = await team.myTeam.fetch() as MyTeamModel; - preparedModels.push(myTeam.prepareDestroyPermanently()); - } catch { - // Record not found, do nothing - } + for (const myTeam of myTeams) { + preparedModels.push(myTeam.prepareDestroyPermanently()); } if (preparedModels.length) { @@ -296,6 +291,15 @@ export const queryTeamsById = async (database: Database, teamIds: string[]): Pro } }; +export const queryMyTeamsById = async (database: Database, teamIds: string[]): Promise => { + try { + const teams = (await database.get(MY_TEAM).query(Q.where('id', Q.oneOf(teamIds))).fetch()); + return teams; + } catch { + return undefined; + } +}; + export const queryTeamByName = async (database: Database, teamName: string): Promise => { try { const team = (await database.get(TEAM).query(Q.where('name', teamName)).fetch()) as TeamModel[];