diff --git a/app/components/channel_list/__snapshots__/index.test.tsx.snap b/app/components/channel_list/__snapshots__/index.test.tsx.snap
index 777c4c52a..6cc69754e 100644
--- a/app/components/channel_list/__snapshots__/index.test.tsx.snap
+++ b/app/components/channel_list/__snapshots__/index.test.tsx.snap
@@ -193,587 +193,147 @@ exports[`components/channel_list should match snapshot 1`] = `
style={
Object {
"alignItems": "center",
- "backgroundColor": "rgba(255,255,255,0.12)",
- "borderRadius": 8,
"flex": 1,
- "flexDirection": "row",
- "height": 40,
- "justifyContent": "flex-start",
- "marginVertical": 20,
- "maxHeight": 40,
- "padding": 8,
- "width": "100%",
+ "justifyContent": "center",
+ "padding": 20,
}
}
>
-
-
+
+
+
-
-
+ Couldn't load
+
+
-
+ >
+ There was a problem loading content for this server.
+
+
-
-
-
-
-
- Threads
-
-
-
-
-
-
-
-
- MY FIRST CATEGORY
-
-
-
+
-
-
-
-
- Just a channel
-
-
-
-
-
-
-
- A Highlighted Channel!!!
-
-
-
-
-
-
-
- And a longer channel name.
-
-
-
-
-
-
-
-
- ANOTHER CAT
-
-
-
-
-
-
-
- Just a channel
-
-
-
-
-
-
-
- A Highlighted Channel!!!
-
-
-
-
-
-
-
- And a longer channel name.
-
-
-
-
+ Retry
+
-
+
`;
diff --git a/app/components/channel_list/header/header.tsx b/app/components/channel_list/header/header.tsx
index 00b8fc829..ac5e92ccc 100644
--- a/app/components/channel_list/header/header.tsx
+++ b/app/components/channel_list/header/header.tsx
@@ -67,6 +67,7 @@ const ChannelListHeader = ({displayName, iconPad}: Props) => {
return (
+ {Boolean(displayName) &&
@@ -86,6 +87,7 @@ const ChannelListHeader = ({displayName, iconPad}: Props) => {
/>
+ }
{serverDisplayName}
diff --git a/app/components/channel_list/header/index.ts b/app/components/channel_list/header/index.ts
index 03d895392..fd8f25167 100644
--- a/app/components/channel_list/header/index.ts
+++ b/app/components/channel_list/header/index.ts
@@ -3,7 +3,7 @@
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
-import {of as of$} from 'rxjs';
+import {catchError, of as of$} from 'rxjs';
import {switchMap} from 'rxjs/operators';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
@@ -15,9 +15,10 @@ import type {WithDatabaseArgs} from '@typings/database/database';
import type SystemModel from '@typings/database/models/servers/system';
import type TeamModel from '@typings/database/models/servers/team';
-const withCurrentTeam = withObservables([], ({database}: WithDatabaseArgs) => {
+const enhanced = withObservables([], ({database}: WithDatabaseArgs) => {
const team = database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID).pipe(
switchMap((id) => database.get(TEAM).findAndObserve(id.value)),
+ catchError(() => of$({displayName: ''})),
);
return {
@@ -27,4 +28,4 @@ const withCurrentTeam = withObservables([], ({database}: WithDatabaseArgs) => {
};
});
-export default withDatabase(withCurrentTeam(ChannelListHeader));
+export default withDatabase(enhanced(ChannelListHeader));
diff --git a/app/components/channel_list/index.tsx b/app/components/channel_list/index.tsx
index 1afce0e96..c1e2b67f5 100644
--- a/app/components/channel_list/index.tsx
+++ b/app/components/channel_list/index.tsx
@@ -11,7 +11,8 @@ import {makeStyleSheetFromTheme} from '@utils/theme';
import Categories from './categories';
import ChannelListHeader from './header';
-import LoadingError from './loading_error';
+import LoadChannelsError from './load_channels_error';
+import LoadTeamsError from './load_teams_error';
import SearchField from './search';
// import Loading from '@components/loading';
@@ -38,12 +39,13 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
}));
type ChannelListProps = {
+ currentTeamId?: string;
iconPad?: boolean;
isTablet: boolean;
teamsCount: number;
}
-const ChannelList = ({iconPad, isTablet, teamsCount}: ChannelListProps) => {
+const ChannelList = ({currentTeamId, iconPad, isTablet, teamsCount}: ChannelListProps) => {
const theme = useTheme();
const styles = getStyleSheet(theme);
const tabletWidth = useSharedValue(TABLET_SIDEBAR_WIDTH);
@@ -64,6 +66,20 @@ const ChannelList = ({iconPad, isTablet, teamsCount}: ChannelListProps) => {
}, [isTablet, teamsCount]);
const [showCats, setShowCats] = useState(true);
+ let content;
+ if (!currentTeamId) {
+ content = ();
+ } else if (showCats) {
+ content = (
+ <>
+
+
+ >
+ );
+ } else {
+ content = ();
+ }
+
return (
setShowCats(!showCats)}>
@@ -71,15 +87,7 @@ const ChannelList = ({iconPad, isTablet, teamsCount}: ChannelListProps) => {
iconPad={iconPad}
/>
-
- {showCats && (
- <>
-
-
- >
- )}
- {/* */}
- {!showCats && ()}
+ {content}
);
};
diff --git a/app/components/channel_list/load_channels_error/index.ts b/app/components/channel_list/load_channels_error/index.ts
new file mode 100644
index 000000000..6f99af810
--- /dev/null
+++ b/app/components/channel_list/load_channels_error/index.ts
@@ -0,0 +1,27 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
+import withObservables from '@nozbe/with-observables';
+import {of as of$} from 'rxjs';
+import {switchMap} from 'rxjs/operators';
+
+import {MM_TABLES} from '@constants/database';
+
+const {SERVER: {TEAM}} = MM_TABLES;
+import LoadChannelsError from './load_channel_error';
+
+import type {WithDatabaseArgs} from '@typings/database/database';
+import type TeamModel from '@typings/database/models/servers/team';
+
+const enhanced = withObservables(['teamId'], ({database, teamId}: {teamId: string} & WithDatabaseArgs) => {
+ const team = database.get(TEAM).findAndObserve(teamId);
+
+ return {
+ teamDisplayName: team.pipe(
+ switchMap((t) => of$(t.displayName)),
+ ),
+ };
+});
+
+export default withDatabase(enhanced(LoadChannelsError));
diff --git a/app/components/channel_list/load_channels_error/load_channel_error.tsx b/app/components/channel_list/load_channels_error/load_channel_error.tsx
new file mode 100644
index 000000000..d1a9c8cdc
--- /dev/null
+++ b/app/components/channel_list/load_channels_error/load_channel_error.tsx
@@ -0,0 +1,40 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React, {useCallback, useState} from 'react';
+import {useIntl} from 'react-intl';
+
+import {retryInitialChannel} from '@actions/remote/retry';
+import LoadingError from '@components/channel_list/loading_error';
+import {useServerUrl} from '@context/server';
+
+type Props = {
+ teamDisplayName: string;
+ teamId: string;
+}
+
+const LoadChannelsError = ({teamDisplayName, teamId}: Props) => {
+ const {formatMessage} = useIntl();
+ const serverUrl = useServerUrl();
+ const [loading, setLoading] = useState(false);
+
+ const onRetryTeams = useCallback(async () => {
+ setLoading(true);
+ const {error} = await retryInitialChannel(serverUrl, teamId);
+
+ if (error) {
+ setLoading(false);
+ }
+ }, [teamId]);
+
+ return (
+
+ );
+};
+
+export default LoadChannelsError;
diff --git a/app/components/channel_list/load_teams_error/index.tsx b/app/components/channel_list/load_teams_error/index.tsx
new file mode 100644
index 000000000..d81f286c7
--- /dev/null
+++ b/app/components/channel_list/load_teams_error/index.tsx
@@ -0,0 +1,36 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React, {useCallback, useState} from 'react';
+import {useIntl} from 'react-intl';
+
+import {retryInitialTeamAndChannel} from '@actions/remote/retry';
+import LoadingError from '@components/channel_list/loading_error';
+import {useServerDisplayName, useServerUrl} from '@context/server';
+
+const LoadTeamsError = () => {
+ const {formatMessage} = useIntl();
+ const serverUrl = useServerUrl();
+ const serverName = useServerDisplayName();
+ const [loading, setLoading] = useState(false);
+
+ const onRetryTeams = useCallback(async () => {
+ setLoading(true);
+ const {error} = await retryInitialTeamAndChannel(serverUrl);
+
+ if (error) {
+ setLoading(false);
+ }
+ }, []);
+
+ return (
+
+ );
+};
+
+export default LoadTeamsError;
diff --git a/app/components/channel_list/loading_error/__snapshots__/index.test.tsx.snap b/app/components/channel_list/loading_error/__snapshots__/index.test.tsx.snap
index c6df4de1d..f9fb459ee 100644
--- a/app/components/channel_list/loading_error/__snapshots__/index.test.tsx.snap
+++ b/app/components/channel_list/loading_error/__snapshots__/index.test.tsx.snap
@@ -51,7 +51,7 @@ exports[`Loading Error should match snapshot 1`] = `
]
}
>
- Couldn’t load Staff
+ Error title
- There was a problem loading the content for this team.
+ Error description
{
const {toJSON} = renderWithIntlAndTheme(
- ,
+ true}
+ title='Error title'
+ />,
);
expect(toJSON()).toMatchSnapshot();
diff --git a/app/components/channel_list/loading_error/index.tsx b/app/components/channel_list/loading_error/index.tsx
index d928d4b8f..ab46c0312 100644
--- a/app/components/channel_list/loading_error/index.tsx
+++ b/app/components/channel_list/loading_error/index.tsx
@@ -1,15 +1,24 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
-import React from 'react';
+
+import React, {useMemo} from 'react';
import {Text, View} from 'react-native';
import CompassIcon from '@components/compass_icon';
+import Loading from '@components/loading';
import TouchableWithFeedback from '@components/touchable_with_feedback';
import {useTheme} from '@context/theme';
import {buttonBackgroundStyle, buttonTextStyle} from '@utils/buttonStyles';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
+type Props = {
+ loading: boolean;
+ message: string;
+ onRetry: () => void;
+ title: string;
+}
+
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
container: {
flex: 1,
@@ -42,9 +51,21 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
},
}));
-const LoadingError = () => {
+const LoadingError = ({loading, message, onRetry, title}: Props) => {
const theme = useTheme();
const styles = getStyleSheet(theme);
+ const buttonStyle = useMemo(() => {
+ return [{marginTop: 24}, buttonBackgroundStyle(theme, 'lg', 'primary', 'inverted')];
+ }, [theme]);
+
+ if (loading) {
+ return (
+
+ );
+ }
return (
@@ -55,12 +76,15 @@ const LoadingError = () => {
/>
- {'Couldn’t load Staff'}
+ {title}
- {'There was a problem loading the content for this team.'}
+ {message}
-
+
{'Retry'}
diff --git a/app/components/failed_action/cloud_svg.tsx b/app/components/failed_action/cloud_svg.tsx
deleted file mode 100644
index 586ca25af..000000000
--- a/app/components/failed_action/cloud_svg.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-import React from 'react';
-import {View} from 'react-native';
-import Svg, {Path} from 'react-native-svg';
-
-type CloudSvgProps = {
- color: string;
- height: number;
- width: number;
-}
-
-const CloudSvg = ({color, height, width}: CloudSvgProps) => {
- return (
-
-
-
- );
-};
-
-export default CloudSvg;
diff --git a/app/components/failed_action/index.tsx b/app/components/failed_action/index.tsx
deleted file mode 100644
index 2ad74f2bd..000000000
--- a/app/components/failed_action/index.tsx
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-import React from 'react';
-import {useIntl} from 'react-intl';
-import {Text, View} from 'react-native';
-import Button from 'react-native-button';
-
-import {useTheme} from '@context/theme';
-import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
-
-import CloudSvg from './cloud_svg';
-
-type FailedActionProps = {
- action?: string;
- message: string;
- title: string;
- onAction: () => void;
-}
-
-const getStyleFromTheme = makeStyleSheetFromTheme((theme: Theme) => {
- return {
- container: {
- alignItems: 'center',
- flex: 1,
- justifyContent: 'center',
- paddingHorizontal: 20,
- paddingBottom: 15,
- },
- title: {
- color: changeOpacity(theme.centerChannelColor, 0.8),
- fontSize: 20,
- fontFamily: 'OpenSans-SemiBold',
- marginBottom: 15,
- marginTop: 10,
- },
- description: {
- color: changeOpacity(theme.centerChannelColor, 0.4),
- fontSize: 17,
- lineHeight: 25,
- textAlign: 'center',
- },
- link: {
- color: theme.buttonColor,
- fontSize: 15,
- },
- buttonContainer: {
- backgroundColor: theme.buttonBg,
- borderRadius: 5,
- height: 42,
- justifyContent: 'center',
- marginTop: 20,
- paddingHorizontal: 12,
- },
- };
-});
-
-const FailedAction = ({action, message, title, onAction}: FailedActionProps) => {
- const intl = useIntl();
- const theme = useTheme();
- const style = getStyleFromTheme(theme);
-
- const text = action || intl.formatMessage({id: 'failed_action.try_again', defaultMessage: 'Try again'});
-
- return (
-
-
-
- {title}
-
-
- {message}
-
-
-
- );
-};
-
-export default FailedAction;
diff --git a/app/screens/channel/channel.tsx b/app/screens/channel/channel.tsx
index d826c75e6..6a6083e1a 100644
--- a/app/screens/channel/channel.tsx
+++ b/app/screens/channel/channel.tsx
@@ -16,8 +16,6 @@ import {popTopScreen} from '@screens/navigation';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import ChannelPostList from './channel_post_list';
-import FailedChannels from './failed_channels';
-import FailedTeams from './failed_teams';
import OtherMentionsBadge from './other_mentions_badge';
import type {HeaderRightButton} from '@components/navigation_header/header';
@@ -97,14 +95,6 @@ const Channel = ({channelId, componentId, displayName, isOwnDirectMessage, membe
console.log('Title Press go to Channel Info', displayName);
}, [channelId]);
- if (!teamId) {
- return ;
- }
-
- if (!channelId) {
- return ;
- }
-
let title = displayName;
if (isOwnDirectMessage) {
title = formatMessage({id: 'channel_header.directchannel.you', defaultMessage: '{displayName} (you)'}, {displayName});
diff --git a/app/screens/channel/failed_channels/index.tsx b/app/screens/channel/failed_channels/index.tsx
deleted file mode 100644
index 2d5eb7f46..000000000
--- a/app/screens/channel/failed_channels/index.tsx
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
-import withObservables from '@nozbe/with-observables';
-import React, {useCallback, useState} from 'react';
-import {useIntl} from 'react-intl';
-import {StyleSheet} from 'react-native';
-
-import {retryInitialChannel} from '@actions/remote/retry';
-import FailedAction from '@components/failed_action';
-import Loading from '@components/loading';
-import {MM_TABLES} from '@constants/database';
-import {useServerUrl} from '@context/server';
-import {useTheme} from '@context/theme';
-
-import type {WithDatabaseArgs} from '@typings/database/database';
-import type TeamModel from '@typings/database/models/servers/team';
-
-type FailedChannelsProps = {
- team: TeamModel;
-}
-
-const style = StyleSheet.create({
- loadingContainer: {
- flex: 1,
- alignItems: 'center',
- justifyContent: 'center',
- },
-});
-
-const FailedChannels = ({team}: FailedChannelsProps) => {
- const intl = useIntl();
- const serverUrl = useServerUrl();
- const theme = useTheme();
- const [loading, setLoading] = useState(false);
-
- const title = intl.formatMessage({id: 'failed_action.something_wrong', defaultMessage: 'Something went wrong'});
- const message = intl.formatMessage({id: 'failed_action.fetch_channels', defaultMessage: 'Channels could not be loaded for {teamName}.'}, {teamName: team.displayName});
-
- const onAction = useCallback(async () => {
- setLoading(true);
- const {error} = await retryInitialChannel(serverUrl, team.id);
-
- if (error) {
- setLoading(false);
- }
- }, []);
-
- if (loading) {
- return (
-
- );
- }
-
- return (
-
- );
-};
-
-const withTeam = withObservables(['teamId'], ({teamId, database}: {teamId: string} & WithDatabaseArgs) => ({
- team: database.get(MM_TABLES.SERVER.TEAM).findAndObserve(teamId),
-}));
-
-export default withDatabase(withTeam(FailedChannels));
diff --git a/app/screens/channel/failed_teams/index.tsx b/app/screens/channel/failed_teams/index.tsx
deleted file mode 100644
index 7cb549578..000000000
--- a/app/screens/channel/failed_teams/index.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-import React, {useCallback, useState} from 'react';
-import {useIntl} from 'react-intl';
-
-import {retryInitialTeamAndChannel} from '@actions/remote/retry';
-import FailedAction from '@components/failed_action';
-import Loading from '@components/loading';
-import {useServerUrl} from '@context/server';
-import {useTheme} from '@context/theme';
-
-const FailedTeams = () => {
- const intl = useIntl();
- const serverUrl = useServerUrl();
- const theme = useTheme();
- const [loading, setLoading] = useState(false);
-
- const title = intl.formatMessage({id: 'failed_action.something_wrong', defaultMessage: 'Something went wrong'});
- const message = intl.formatMessage({id: 'failed_action.fetch_teams', defaultMessage: 'An error ocurred while loading the teams of this server'});
-
- const onAction = useCallback(async () => {
- setLoading(true);
- const {error} = await retryInitialTeamAndChannel(serverUrl);
-
- if (error) {
- setLoading(false);
- }
- }, []);
-
- if (loading) {
- return (
-
- );
- }
-
- return (
-
- );
-};
-
-export default FailedTeams;
diff --git a/app/screens/home/channel_list/channel_list.tsx b/app/screens/home/channel_list/channel_list.tsx
index 2ec01ab1e..688dcccd8 100644
--- a/app/screens/home/channel_list/channel_list.tsx
+++ b/app/screens/home/channel_list/channel_list.tsx
@@ -16,6 +16,7 @@ import ServerIcon from '@screens/home/channel_list/server_icon/server_icon';
import {makeStyleSheetFromTheme} from '@utils/theme';
type ChannelProps = {
+ currentTeamId?: string;
teamsCount: number;
time?: number;
};
@@ -89,11 +90,12 @@ const ChannelListScreen = (props: ChannelProps) => {
teamsCount={props.teamsCount}
/>
- {isTablet &&
+ {isTablet && Boolean(props.currentTeamId) &&
}
diff --git a/app/screens/home/channel_list/index.ts b/app/screens/home/channel_list/index.ts
index 89773fec1..ee1890448 100644
--- a/app/screens/home/channel_list/index.ts
+++ b/app/screens/home/channel_list/index.ts
@@ -3,17 +3,24 @@
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
+import {catchError, of as of$} from 'rxjs';
+import {switchMap} from 'rxjs/operators';
-import {MM_TABLES} from '@constants/database';
+import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import MyTeamModel from '@typings/database/models/servers/my_team';
import ChannelsList from './channel_list';
import type {WithDatabaseArgs} from '@typings/database/database';
+import type SystemModel from '@typings/database/models/servers/system';
-const {SERVER: {MY_TEAM}} = MM_TABLES;
+const {SERVER: {MY_TEAM, SYSTEM}} = MM_TABLES;
const enhanced = withObservables([], ({database}: WithDatabaseArgs) => ({
+ currentTeamId: database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID).pipe(
+ switchMap((id) => of$(id.value)),
+ catchError(() => of$(undefined)),
+ ),
teamsCount: database.get(MY_TEAM).query().observeCount(),
}));
diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json
index 55bbd9378..2361ea1bf 100644
--- a/assets/base/i18n/en.json
+++ b/assets/base/i18n/en.json
@@ -102,10 +102,6 @@
"emoji_skin.medium_dark_skin_tone": "medium dark skin tone",
"emoji_skin.medium_light_skin_tone": "medium light skin tone",
"emoji_skin.medium_skin_tone": "medium skin tone",
- "failed_action.fetch_channels": "Channels could not be loaded for {teamName}.",
- "failed_action.fetch_teams": "An error ocurred while loading the teams of this server",
- "failed_action.something_wrong": "Something went wrong",
- "failed_action.try_again": "Try again",
"intro.add_people": "Add People",
"intro.channel_details": "Details",
"intro.created_by": "created by {creator} on {date}.",
@@ -129,6 +125,10 @@
"last_users_message.others": "{numOthers} others ",
"last_users_message.removed_from_channel.type": "were **removed from the channel**.",
"last_users_message.removed_from_team.type": "were **removed from the team**.",
+ "load_channels_error.message": "There was a problem loading content for this team.",
+ "load_channels_error.title": "Couldn't load {teamDisplayName}",
+ "load_teams_error.message": "There was a problem loading content for this server.",
+ "load_teams_error.title": "Couldn't load {serverName}",
"login_mfa.enterToken": "To complete the sign in process, please enter the code from your mobile device's authenticator app.",
"login_mfa.token": "Enter MFA Token",
"login_mfa.tokenReq": "Please enter an MFA token",