Show loading only when team channels are being loaded (#6872)
* Show loading only when team channels are being loaded * Fix tests * Remove unneeded event * Refactor into using hooks
This commit is contained in:
parent
63e6b0f626
commit
191a640007
20 changed files with 125 additions and 135 deletions
|
|
@ -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};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<Channel>(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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Promise<Model[]>> = [];
|
||||
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<Promise<Model[]>> = [];
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
24
app/hooks/teams_loading.ts
Normal file
24
app/hooks/teams_loading.ts
Normal file
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -144,40 +144,6 @@ exports[`components/categories_list should render channels error 1`] = `
|
|||
}
|
||||
testID="channel_list_header.server_display_name"
|
||||
/>
|
||||
<View
|
||||
animatedStyle={
|
||||
{
|
||||
"value": {
|
||||
"opacity": 1,
|
||||
"transform": [
|
||||
{
|
||||
"rotateZ": "0deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
collapsable={false}
|
||||
style={
|
||||
{
|
||||
"borderBottomColor": "rgba(255,255,255,0.16)",
|
||||
"borderLeftColor": "#ffffff",
|
||||
"borderRadius": 7,
|
||||
"borderRightColor": "rgba(255,255,255,0.16)",
|
||||
"borderTopColor": "rgba(255,255,255,0.16)",
|
||||
"borderWidth": 2,
|
||||
"height": 14,
|
||||
"marginLeft": 5,
|
||||
"opacity": 1,
|
||||
"transform": [
|
||||
{
|
||||
"rotateZ": "0deg",
|
||||
},
|
||||
],
|
||||
"width": 14,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
|
|
|
|||
|
|
@ -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 LoadCategoriesError = () => {
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -124,40 +124,6 @@ exports[`components/channel_list/header Channel List Header Component should mat
|
|||
}
|
||||
testID="channel_list_header.server_display_name"
|
||||
/>
|
||||
<View
|
||||
animatedStyle={
|
||||
{
|
||||
"value": {
|
||||
"opacity": 1,
|
||||
"transform": [
|
||||
{
|
||||
"rotateZ": "0deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
collapsable={false}
|
||||
style={
|
||||
{
|
||||
"borderBottomColor": "rgba(255,255,255,0.16)",
|
||||
"borderLeftColor": "#ffffff",
|
||||
"borderRadius": 7,
|
||||
"borderRightColor": "rgba(255,255,255,0.16)",
|
||||
"borderTopColor": "rgba(255,255,255,0.16)",
|
||||
"borderWidth": 2,
|
||||
"height": 14,
|
||||
"marginLeft": 5,
|
||||
"opacity": 1,
|
||||
"transform": [
|
||||
{
|
||||
"rotateZ": "0deg",
|
||||
},
|
||||
],
|
||||
"width": 14,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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});
|
||||
}
|
||||
|
|
|
|||
17
app/store/team_load_store.ts
Normal file
17
app/store/team_load_store.ts
Normal file
|
|
@ -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<number>} = {};
|
||||
|
||||
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));
|
||||
};
|
||||
Loading…
Reference in a new issue