diff --git a/app/actions/remote/channel.ts b/app/actions/remote/channel.ts index 780ebf190..6c312e921 100644 --- a/app/actions/remote/channel.ts +++ b/app/actions/remote/channel.ts @@ -24,6 +24,7 @@ import {getNthLastChannelFromTeam, getMyTeamById, getTeamByName, queryMyTeams, r import {getCurrentUser} from '@queries/servers/user'; import {dismissAllModals, popToRoot} from '@screens/navigation'; import EphemeralStore from '@store/ephemeral_store'; +import {setTeamLoading} from '@store/team_load_store'; import {generateChannelNameFromDisplayName, getDirectChannelName, isDMorGM} from '@utils/channel'; import {isTablet} from '@utils/helpers'; import {logDebug, logError, logInfo} from '@utils/log'; @@ -359,6 +360,9 @@ export async function fetchMyChannelsForTeam(serverUrl: string, teamId: string, } try { + if (!fetchOnly) { + setTeamLoading(serverUrl, true); + } const [allChannels, channelMemberships, categoriesWithOrder] = await Promise.all([ client.getMyChannels(teamId, includeDeleted, since), client.getMyChannelMembers(teamId), @@ -387,10 +391,14 @@ export async function fetchMyChannelsForTeam(serverUrl: string, teamId: string, if (models.length) { await operator.batchRecords(models); } + setTeamLoading(serverUrl, false); } return {channels, memberships, categories}; } catch (error) { + if (!fetchOnly) { + setTeamLoading(serverUrl, false); + } forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } diff --git a/app/actions/remote/entry/app.ts b/app/actions/remote/entry/app.ts index 1339bdaaf..a68e9dafe 100644 --- a/app/actions/remote/entry/app.ts +++ b/app/actions/remote/entry/app.ts @@ -6,6 +6,7 @@ import {fetchConfigAndLicense} from '@actions/remote/systems'; import DatabaseManager from '@database/manager'; import {prepareCommonSystemValues, getCurrentTeamId, getWebSocketLastDisconnected, getCurrentChannelId, getConfig, getLicense} from '@queries/servers/system'; import {getCurrentUser} from '@queries/servers/user'; +import {setTeamLoading} from '@store/team_load_store'; import {deleteV1Data} from '@utils/file'; import {logInfo} from '@utils/log'; @@ -37,8 +38,10 @@ export async function appEntry(serverUrl: string, since = 0, isUpgrade = false) const currentChannelId = await getCurrentChannelId(database); const lastDisconnectedAt = (await getWebSocketLastDisconnected(database)) || since; + setTeamLoading(serverUrl, true); const entryData = await entry(serverUrl, currentTeamId, currentChannelId, since); if ('error' in entryData) { + setTeamLoading(serverUrl, false); return {error: entryData.error}; } @@ -55,6 +58,7 @@ export async function appEntry(serverUrl: string, since = 0, isUpgrade = false) const dt = Date.now(); await operator.batchRecords(models); logInfo('ENTRY MODELS BATCHING TOOK', `${Date.now() - dt}ms`); + setTeamLoading(serverUrl, false); const {id: currentUserId, locale: currentUserLocale} = meData?.user || (await getCurrentUser(database))!; const config = await getConfig(database); diff --git a/app/actions/remote/entry/common.ts b/app/actions/remote/entry/common.ts index a6dc2ff58..3fae907da 100644 --- a/app/actions/remote/entry/common.ts +++ b/app/actions/remote/entry/common.ts @@ -2,7 +2,6 @@ // See LICENSE.txt for license information. import {Database, Model} from '@nozbe/watermelondb'; -import {DeviceEventEmitter} from 'react-native'; import {fetchMissingDirectChannelsInfo, fetchMyChannelsForTeam, handleKickFromChannel, MyChannelsRequest} from '@actions/remote/channel'; import {fetchGroupsForMember} from '@actions/remote/groups'; @@ -14,7 +13,7 @@ import {fetchAllTeams, fetchMyTeams, fetchTeamsChannelsAndUnreadPosts, handleKic import {syncTeamThreads} from '@actions/remote/thread'; import {autoUpdateTimezone, fetchMe, MyUserRequest, updateAllUsersSince} from '@actions/remote/user'; import {gqlAllChannels} from '@client/graphQL/entry'; -import {Events, General, Preferences, Screens} from '@constants'; +import {General, 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'; @@ -320,9 +319,7 @@ export async function restDeferredAppEntryActions( channelsToFetchProfiles = new Set(directChannels); // defer fetching posts for unread channels on initial team - fetchPostsForUnreadChannels(serverUrl, chData.channels, chData.memberships, initialChannelId, true); - } else { - DeviceEventEmitter.emit(Events.FETCHING_POSTS, false); + fetchPostsForUnreadChannels(serverUrl, chData.channels, chData.memberships, initialChannelId); } }, FETCH_UNREADS_TIMEOUT); diff --git a/app/actions/remote/entry/gql_common.ts b/app/actions/remote/entry/gql_common.ts index 8d11a2012..b2db28b10 100644 --- a/app/actions/remote/entry/gql_common.ts +++ b/app/actions/remote/entry/gql_common.ts @@ -2,7 +2,6 @@ // See LICENSE.txt for license information. import {Database} from '@nozbe/watermelondb'; -import {DeviceEventEmitter} from 'react-native'; import {storeConfigAndLicense} from '@actions/local/systems'; import {MyChannelsRequest} from '@actions/remote/channel'; @@ -12,7 +11,7 @@ import {MyTeamsRequest} from '@actions/remote/team'; import {syncTeamThreads} from '@actions/remote/thread'; import {autoUpdateTimezone, updateAllUsersSince} from '@actions/remote/user'; import {gqlEntry, gqlEntryChannels, gqlOtherChannels} from '@client/graphQL/entry'; -import {Events, Preferences} from '@constants'; +import {Preferences} from '@constants'; import DatabaseManager from '@database/manager'; import {getPreferenceValue} from '@helpers/api/preference'; import {selectDefaultTeam} from '@helpers/api/team'; @@ -49,9 +48,7 @@ export async function deferredAppEntryGraphQLActions( setTimeout(() => { if (chData?.channels?.length && chData.memberships?.length) { // defer fetching posts for unread channels on initial team - fetchPostsForUnreadChannels(serverUrl, chData.channels, chData.memberships, initialChannelId, true); - } else { - DeviceEventEmitter.emit(Events.FETCHING_POSTS, false); + fetchPostsForUnreadChannels(serverUrl, chData.channels, chData.memberships, initialChannelId); } }, FETCH_UNREADS_TIMEOUT); diff --git a/app/actions/remote/entry/login.ts b/app/actions/remote/entry/login.ts index dd141f0d3..751bafe0c 100644 --- a/app/actions/remote/entry/login.ts +++ b/app/actions/remote/entry/login.ts @@ -6,6 +6,7 @@ import {fetchConfigAndLicense} from '@actions/remote/systems'; import DatabaseManager from '@database/manager'; import NetworkManager from '@managers/network_manager'; import {setCurrentTeamAndChannelId} from '@queries/servers/system'; +import {setTeamLoading} from '@store/team_load_store'; import {isTablet} from '@utils/helpers'; import {deferredAppEntryActions, entry} from './gql_common'; @@ -47,9 +48,11 @@ export async function loginEntry({serverUrl, user, deviceToken}: AfterLoginArgs) return {error: clData.error}; } + setTeamLoading(serverUrl, true); const entryData = await entry(serverUrl, '', ''); if ('error' in entryData) { + setTeamLoading(serverUrl, false); return {error: entryData.error}; } @@ -66,6 +69,7 @@ export async function loginEntry({serverUrl, user, deviceToken}: AfterLoginArgs) } await operator.batchRecords(models); + setTeamLoading(serverUrl, false); const config = clData.config || {} as ClientConfig; const license = clData.license || {} as ClientLicense; diff --git a/app/actions/remote/entry/notification.ts b/app/actions/remote/entry/notification.ts index 25eb4bb73..76ef6ee38 100644 --- a/app/actions/remote/entry/notification.ts +++ b/app/actions/remote/entry/notification.ts @@ -14,6 +14,7 @@ import {getIsCRTEnabled} from '@queries/servers/thread'; import {getCurrentUser} from '@queries/servers/user'; import EphemeralStore from '@store/ephemeral_store'; import NavigationStore from '@store/navigation_store'; +import {setTeamLoading} from '@store/team_load_store'; import {isTablet} from '@utils/helpers'; import {emitNotificationError} from '@utils/notification'; import {setThemeDefaults, updateThemeIfNeeded} from '@utils/theme'; @@ -81,8 +82,10 @@ export async function pushNotificationEntry(serverUrl: string, notification: Not switchedToScreen = true; } + setTeamLoading(serverUrl, true); const entryData = await entry(serverUrl, teamId, channelId); if ('error' in entryData) { + setTeamLoading(serverUrl, false); return {error: entryData.error}; } const {models, initialTeamId, initialChannelId, prefData, teamData, chData} = entryData; @@ -134,6 +137,7 @@ export async function pushNotificationEntry(serverUrl: string, notification: Not } await operator.batchRecords(models); + setTeamLoading(serverUrl, false); const {id: currentUserId, locale: currentUserLocale} = (await getCurrentUser(operator.database))!; const config = await getConfig(database); diff --git a/app/actions/remote/post.ts b/app/actions/remote/post.ts index 9ead1cc40..6adf5acfe 100644 --- a/app/actions/remote/post.ts +++ b/app/actions/remote/post.ts @@ -326,12 +326,9 @@ export async function fetchPostsForChannel(serverUrl: string, channelId: string, } } -export const fetchPostsForUnreadChannels = async (serverUrl: string, channels: Channel[], memberships: ChannelMembership[], excludeChannelId?: string, emitEvent = false) => { +export const fetchPostsForUnreadChannels = async (serverUrl: string, channels: Channel[], memberships: ChannelMembership[], excludeChannelId?: string) => { try { const promises = []; - if (emitEvent) { - DeviceEventEmitter.emit(Events.FETCHING_POSTS, true); - } for (const member of memberships) { const channel = channels.find((c) => c.id === member.channel_id); if (channel && (channel.total_msg_count - member.msg_count) > 0 && channel.id !== excludeChannelId) { @@ -339,13 +336,7 @@ export const fetchPostsForUnreadChannels = async (serverUrl: string, channels: C } } await Promise.all(promises); - if (emitEvent) { - DeviceEventEmitter.emit(Events.FETCHING_POSTS, false); - } } catch (error) { - if (emitEvent) { - DeviceEventEmitter.emit(Events.FETCHING_POSTS, false); - } return {error}; } diff --git a/app/actions/remote/team.ts b/app/actions/remote/team.ts index a00a83b09..c23ece7cb 100644 --- a/app/actions/remote/team.ts +++ b/app/actions/remote/team.ts @@ -15,6 +15,7 @@ import {prepareCommonSystemValues, getCurrentTeamId, getCurrentUserId} from '@qu import {addTeamToTeamHistory, prepareDeleteTeam, prepareMyTeams, getNthLastChannelFromTeam, queryTeamsById, syncTeamTable, getLastTeam, getTeamById, removeTeamFromTeamHistory} from '@queries/servers/team'; import {dismissAllModals, popToRoot, resetToTeams} from '@screens/navigation'; import EphemeralStore from '@store/ephemeral_store'; +import {setTeamLoading} from '@store/team_load_store'; import {isTablet} from '@utils/helpers'; import {logDebug} from '@utils/log'; @@ -56,12 +57,16 @@ export async function addUserToTeam(serverUrl: string, teamId: string, userId: s return {error}; } + let loadEventSent = false; try { EphemeralStore.startAddingToTeam(teamId); const team = await client.getTeam(teamId); const member = await client.addToTeam(teamId, userId); if (!fetchOnly) { + setTeamLoading(serverUrl, true); + loadEventSent = true; + fetchRolesIfNeeded(serverUrl, member.roles.split(' ')); const {channels, memberships: channelMembers, categories} = await fetchMyChannelsForTeam(serverUrl, teamId, false, 0, true); const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; @@ -80,6 +85,8 @@ export async function addUserToTeam(serverUrl: string, teamId: string, userId: s ])).flat(); await operator.batchRecords(models); + setTeamLoading(serverUrl, false); + loadEventSent = false; if (await isTablet()) { const channel = await getDefaultChannelForTeam(operator.database, teamId); @@ -87,11 +94,17 @@ export async function addUserToTeam(serverUrl: string, teamId: string, userId: s fetchPostsForChannel(serverUrl, channel.id); } } + } else { + setTeamLoading(serverUrl, false); + loadEventSent = false; } } EphemeralStore.finishAddingToTeam(teamId); return {member}; } catch (error) { + if (loadEventSent) { + setTeamLoading(serverUrl, false); + } EphemeralStore.finishAddingToTeam(teamId); forceLogoutIfNecessary(serverUrl, error as ClientError); return {error}; diff --git a/app/actions/websocket/index.ts b/app/actions/websocket/index.ts index 23e6f0d74..5f094dbd3 100644 --- a/app/actions/websocket/index.ts +++ b/app/actions/websocket/index.ts @@ -1,8 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {DeviceEventEmitter} from 'react-native'; - import {markChannelAsViewed} from '@actions/local/channel'; import {markChannelAsRead} from '@actions/remote/channel'; import {handleEntryAfterLoadNavigation} from '@actions/remote/entry/common'; @@ -30,11 +28,10 @@ import { handleCallUserVoiceOn, } from '@calls/connection/websocket_event_handlers'; import {isSupportedServerCalls} from '@calls/utils'; -import {Events, Screens, WebsocketEvents} from '@constants'; +import {Screens, WebsocketEvents} from '@constants'; import {SYSTEM_IDENTIFIERS} from '@constants/database'; import DatabaseManager from '@database/manager'; import AppsManager from '@managers/apps_manager'; -import {getActiveServerUrl} from '@queries/app/servers'; import {getCurrentChannel} from '@queries/servers/channel'; import {getLastPostInThread} from '@queries/servers/post'; import { @@ -50,6 +47,7 @@ import {getIsCRTEnabled} from '@queries/servers/thread'; import {getCurrentUser} from '@queries/servers/user'; import EphemeralStore from '@store/ephemeral_store'; import NavigationStore from '@store/navigation_store'; +import {setTeamLoading} from '@store/team_load_store'; import {isTablet} from '@utils/helpers'; import {logDebug, logInfo} from '@utils/log'; @@ -141,15 +139,10 @@ async function doReconnect(serverUrl: string) { const currentTeam = await getCurrentTeam(database); const currentChannel = await getCurrentChannel(database); - const currentActiveServerUrl = await getActiveServerUrl(); - if (serverUrl === currentActiveServerUrl) { - DeviceEventEmitter.emit(Events.FETCHING_POSTS, true); - } + setTeamLoading(serverUrl, true); const entryData = await entry(serverUrl, currentTeam?.id, currentChannel?.id, lastDisconnectedAt); if ('error' in entryData) { - if (serverUrl === currentActiveServerUrl) { - DeviceEventEmitter.emit(Events.FETCHING_POSTS, false); - } + setTeamLoading(serverUrl, false); return; } const {models, initialTeamId, initialChannelId, prefData, teamData, chData} = entryData; @@ -159,6 +152,7 @@ async function doReconnect(serverUrl: string) { const dt = Date.now(); await operator.batchRecords(models); logInfo('WEBSOCKET RECONNECT MODELS BATCHING TOOK', `${Date.now() - dt}ms`); + setTeamLoading(serverUrl, false); await fetchPostDataIfNeeded(serverUrl); diff --git a/app/actions/websocket/teams.ts b/app/actions/websocket/teams.ts index cf5b50183..3602f94ce 100644 --- a/app/actions/websocket/teams.ts +++ b/app/actions/websocket/teams.ts @@ -14,6 +14,7 @@ import {prepareMyChannelsForTeam} from '@queries/servers/channel'; import {getCurrentTeam, prepareMyTeams} from '@queries/servers/team'; import {getCurrentUser} from '@queries/servers/user'; import EphemeralStore from '@store/ephemeral_store'; +import {setTeamLoading} from '@store/team_load_store'; import {logDebug} from '@utils/log'; export async function handleLeaveTeamEvent(serverUrl: string, msg: WebSocketMessage) { @@ -62,10 +63,6 @@ export async function handleUpdateTeamEvent(serverUrl: string, msg: WebSocketMes } export async function handleUserAddedToTeamEvent(serverUrl: string, msg: WebSocketMessage) { - const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; - if (!operator) { - return; - } const {team_id: teamId} = msg.data; // Ignore duplicated team join events sent by the server @@ -74,24 +71,32 @@ export async function handleUserAddedToTeamEvent(serverUrl: string, msg: WebSock } EphemeralStore.startAddingToTeam(teamId); - const {teams, memberships: teamMemberships} = await fetchMyTeam(serverUrl, teamId, true); + try { + setTeamLoading(serverUrl, true); + const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl); + const {teams, memberships: teamMemberships} = await fetchMyTeam(serverUrl, teamId, true); - const modelPromises: Array> = []; - if (teams?.length && teamMemberships?.length) { - const {channels, memberships, categories} = await fetchMyChannelsForTeam(serverUrl, teamId, false, 0, true); - modelPromises.push(prepareCategoriesAndCategoriesChannels(operator, categories || [], true)); - modelPromises.push(...await prepareMyChannelsForTeam(operator, teamId, channels || [], memberships || [])); + const modelPromises: Array> = []; + if (teams?.length && teamMemberships?.length) { + const {channels, memberships, categories} = await fetchMyChannelsForTeam(serverUrl, teamId, false, 0, true); + modelPromises.push(prepareCategoriesAndCategoriesChannels(operator, categories || [], true)); + modelPromises.push(...await prepareMyChannelsForTeam(operator, teamId, channels || [], memberships || [])); - const {roles} = await fetchRoles(serverUrl, teamMemberships, memberships, undefined, true); - modelPromises.push(operator.handleRole({roles, prepareRecordsOnly: true})); + const {roles} = await fetchRoles(serverUrl, teamMemberships, memberships, undefined, true); + modelPromises.push(operator.handleRole({roles, prepareRecordsOnly: true})); + } + + if (teams && teamMemberships) { + modelPromises.push(...prepareMyTeams(operator, teams, teamMemberships)); + } + + const models = await Promise.all(modelPromises); + await operator.batchRecords(models.flat()); + setTeamLoading(serverUrl, false); + } catch (error) { + logDebug('could not handle user added to team websocket event'); + setTeamLoading(serverUrl, false); } - if (teams && teamMemberships) { - modelPromises.push(...prepareMyTeams(operator, teams, teamMemberships)); - } - - const models = await Promise.all(modelPromises); - await operator.batchRecords(models.flat()); - EphemeralStore.finishAddingToTeam(teamId); } diff --git a/app/constants/events.ts b/app/constants/events.ts index 0dc6c1afc..5d34955ce 100644 --- a/app/constants/events.ts +++ b/app/constants/events.ts @@ -9,7 +9,6 @@ export default keyMirror({ CHANNEL_SWITCH: null, CLOSE_BOTTOM_SHEET: null, CONFIG_CHANGED: null, - FETCHING_POSTS: null, FREEZE_SCREEN: null, GALLERY_ACTIONS: null, LEAVE_CHANNEL: null, diff --git a/app/hooks/teams_loading.ts b/app/hooks/teams_loading.ts new file mode 100644 index 000000000..661282bd8 --- /dev/null +++ b/app/hooks/teams_loading.ts @@ -0,0 +1,24 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {useEffect, useState} from 'react'; +import {of as of$} from 'rxjs'; +import {switchMap, distinctUntilChanged} from 'rxjs/operators'; + +import {getLoadingTeamChannelsSubject} from '@store/team_load_store'; + +export const useTeamsLoading = (serverUrl: string) => { + // const subject = getLoadingTeamChannelsSubject(serverUrl); + // const [loading, setLoading] = useState(subject.getValue() !== 0); + const [loading, setLoading] = useState(false); + useEffect(() => { + const sub = getLoadingTeamChannelsSubject(serverUrl).pipe( + switchMap((v) => of$(v !== 0)), + distinctUntilChanged(), + ).subscribe(setLoading); + + return () => sub.unsubscribe(); + }, []); + + return loading; +}; diff --git a/app/screens/home/channel_list/categories_list/__snapshots__/index.test.tsx.snap b/app/screens/home/channel_list/categories_list/__snapshots__/index.test.tsx.snap index 74f6b532f..f9a4925f8 100644 --- a/app/screens/home/channel_list/categories_list/__snapshots__/index.test.tsx.snap +++ b/app/screens/home/channel_list/categories_list/__snapshots__/index.test.tsx.snap @@ -144,40 +144,6 @@ exports[`components/categories_list should render channels error 1`] = ` } testID="channel_list_header.server_display_name" /> - { const {formatMessage} = useIntl(); @@ -16,7 +17,10 @@ const LoadCategoriesError = () => { const onRetryTeams = useCallback(async () => { setLoading(true); + + setTeamLoading(serverUrl, true); const {error} = await retryInitialTeamAndChannel(serverUrl); + setTeamLoading(serverUrl, false); if (error) { setLoading(false); diff --git a/app/screens/home/channel_list/categories_list/header/__snapshots__/header.test.tsx.snap b/app/screens/home/channel_list/categories_list/header/__snapshots__/header.test.tsx.snap index e2ee64617..a016dddf9 100644 --- a/app/screens/home/channel_list/categories_list/header/__snapshots__/header.test.tsx.snap +++ b/app/screens/home/channel_list/categories_list/header/__snapshots__/header.test.tsx.snap @@ -124,40 +124,6 @@ exports[`components/channel_list/header Channel List Header Component should mat } testID="channel_list_header.server_display_name" /> - `; diff --git a/app/screens/home/channel_list/categories_list/header/loading_unreads.tsx b/app/screens/home/channel_list/categories_list/header/loading_unreads.tsx index bdd337885..ae1fd0ae1 100644 --- a/app/screens/home/channel_list/categories_list/header/loading_unreads.tsx +++ b/app/screens/home/channel_list/categories_list/header/loading_unreads.tsx @@ -1,12 +1,12 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {useEffect, useState} from 'react'; -import {DeviceEventEmitter} from 'react-native'; +import React, {useEffect} from 'react'; import Animated, {cancelAnimation, Easing, useAnimatedStyle, useSharedValue, withRepeat, withTiming} from 'react-native-reanimated'; -import {Events} from '@constants'; +import {useServerUrl} from '@context/server'; import {useTheme} from '@context/theme'; +import {useTeamsLoading} from '@hooks/teams_loading'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ @@ -26,9 +26,10 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ const LoadingUnreads = () => { const theme = useTheme(); const style = getStyleSheet(theme); - const [loading, setLoading] = useState(true); const opacity = useSharedValue(1); const rotation = useSharedValue(0); + const serverUrl = useServerUrl(); + const loading = useTeamsLoading(serverUrl); const animatedStyle = useAnimatedStyle(() => ({ opacity: opacity.value, @@ -52,17 +53,6 @@ const LoadingUnreads = () => { }; }, [loading]); - useEffect(() => { - const listener = DeviceEventEmitter.addListener(Events.FETCHING_POSTS, (value: boolean) => { - setLoading(value); - if (value) { - rotation.value = 0; - } - }); - - return () => listener.remove(); - }, []); - if (!loading) { return null; } diff --git a/app/screens/home/channel_list/categories_list/load_channels_error/load_channel_error.tsx b/app/screens/home/channel_list/categories_list/load_channels_error/load_channel_error.tsx index c89c45346..50cac10f7 100644 --- a/app/screens/home/channel_list/categories_list/load_channels_error/load_channel_error.tsx +++ b/app/screens/home/channel_list/categories_list/load_channels_error/load_channel_error.tsx @@ -7,6 +7,7 @@ import {useIntl} from 'react-intl'; import {retryInitialChannel} from '@actions/remote/retry'; import LoadingError from '@components/loading_error'; import {useServerUrl} from '@context/server'; +import {setTeamLoading} from '@store/team_load_store'; import LoadTeamsError from '../load_teams_error'; @@ -22,7 +23,10 @@ const LoadChannelsError = ({teamDisplayName, teamId}: Props) => { const onRetryTeams = useCallback(async () => { setLoading(true); + + setTeamLoading(serverUrl, true); const {error} = await retryInitialChannel(serverUrl, teamId); + setTeamLoading(serverUrl, false); if (error) { setLoading(false); diff --git a/app/screens/home/channel_list/categories_list/load_teams_error/index.tsx b/app/screens/home/channel_list/categories_list/load_teams_error/index.tsx index 953cc5296..82f6a2123 100644 --- a/app/screens/home/channel_list/categories_list/load_teams_error/index.tsx +++ b/app/screens/home/channel_list/categories_list/load_teams_error/index.tsx @@ -7,6 +7,7 @@ import {useIntl} from 'react-intl'; import {retryInitialTeamAndChannel} from '@actions/remote/retry'; import LoadingError from '@components/loading_error'; import {useServerDisplayName, useServerUrl} from '@context/server'; +import {setTeamLoading} from '@store/team_load_store'; const LoadTeamsError = () => { const {formatMessage} = useIntl(); @@ -16,7 +17,10 @@ const LoadTeamsError = () => { const onRetryTeams = useCallback(async () => { setLoading(true); + + setTeamLoading(serverUrl, true); const {error} = await retryInitialTeamAndChannel(serverUrl); + setTeamLoading(serverUrl, false); if (error) { setLoading(false); diff --git a/app/screens/navigation.ts b/app/screens/navigation.ts index eb93f223e..e8b188209 100644 --- a/app/screens/navigation.ts +++ b/app/screens/navigation.ts @@ -252,7 +252,6 @@ export function resetToHome(passProps: LaunchProps = {launchType: Launch.Normal} dismissModal({componentId: Screens.LOGIN}); dismissModal({componentId: Screens.SSO}); dismissModal({componentId: Screens.BOTTOM_SHEET}); - DeviceEventEmitter.emit(Events.FETCHING_POSTS, false); if (passProps.launchType === Launch.AddServerFromDeepLink) { Navigation.updateProps(Screens.HOME, {launchType: Launch.DeepLink, extra: passProps.extra}); } diff --git a/app/store/team_load_store.ts b/app/store/team_load_store.ts new file mode 100644 index 000000000..1721eb5b1 --- /dev/null +++ b/app/store/team_load_store.ts @@ -0,0 +1,17 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. +import {BehaviorSubject} from 'rxjs'; + +const loadingTeamChannels: {[serverUrl: string]: BehaviorSubject} = {}; + +export const getLoadingTeamChannelsSubject = (serverUrl: string) => { + if (!loadingTeamChannels[serverUrl]) { + loadingTeamChannels[serverUrl] = new BehaviorSubject(0); + } + return loadingTeamChannels[serverUrl]; +}; + +export const setTeamLoading = (serverUrl: string, loading: boolean) => { + const subject = getLoadingTeamChannelsSubject(serverUrl); + subject.next(subject.value + (loading ? 1 : -1)); +};