diff --git a/app/actions/remote/team.ts b/app/actions/remote/team.ts index 8e8566442..84ea899d9 100644 --- a/app/actions/remote/team.ts +++ b/app/actions/remote/team.ts @@ -269,6 +269,7 @@ export async function handleTeamChange(serverUrl: string, teamId: string) { } let channelId = ''; + DeviceEventEmitter.emit(Events.TEAM_SWITCH, true); if (await isTablet()) { channelId = await getNthLastChannelFromTeam(database, teamId); if (channelId) { @@ -277,6 +278,7 @@ export async function handleTeamChange(serverUrl: string, teamId: string) { } else { await switchToChannelById(serverUrl, channelId, teamId); } + DeviceEventEmitter.emit(Events.TEAM_SWITCH, false); completeTeamChange(serverUrl, teamId, channelId); return; } @@ -295,6 +297,7 @@ export async function handleTeamChange(serverUrl: string, teamId: string) { if (models.length) { await operator.batchRecords(models); } + DeviceEventEmitter.emit(Events.TEAM_SWITCH, false); completeTeamChange(serverUrl, teamId, channelId); } diff --git a/app/components/channel_item/channel_item.test.tsx b/app/components/channel_item/channel_item.test.tsx index b8b5a8f48..fd0f68205 100644 --- a/app/components/channel_item/channel_item.test.tsx +++ b/app/components/channel_item/channel_item.test.tsx @@ -35,11 +35,13 @@ describe('components/channel_list/categories/body/channel_item', () => { hasDraft={false} isActive={false} membersCount={0} - myChannel={myChannel} isMuted={false} currentUserId={'id'} testID='channel_list_item' onPress={() => undefined} + isUnread={myChannel.isUnread} + mentionsCount={myChannel.mentionsCount} + hasMember={Boolean(myChannel)} />, ); @@ -53,11 +55,13 @@ describe('components/channel_list/categories/body/channel_item', () => { hasDraft={true} isActive={false} membersCount={3} - myChannel={myChannel} isMuted={false} currentUserId={'id'} testID='channel_list_item' onPress={() => undefined} + isUnread={myChannel.isUnread} + mentionsCount={myChannel.mentionsCount} + hasMember={Boolean(myChannel)} />, ); diff --git a/app/components/channel_item/channel_item.tsx b/app/components/channel_item/channel_item.tsx index 728452ef0..1627ce8b0 100644 --- a/app/components/channel_item/channel_item.tsx +++ b/app/components/channel_item/channel_item.tsx @@ -17,7 +17,6 @@ import {getUserIdFromChannelName} from '@utils/user'; import CustomStatus from './custom_status'; import type ChannelModel from '@typings/database/models/servers/channel'; -import type MyChannelModel from '@typings/database/models/servers/my_channel'; type Props = { channel: ChannelModel; @@ -27,8 +26,10 @@ type Props = { isInfo?: boolean; isMuted: boolean; membersCount: number; - myChannel?: MyChannelModel; + isUnread: boolean; + mentionsCount: number; onPress: (channelId: string) => void; + hasMember: boolean; teamDisplayName?: string; testID?: string; } @@ -114,15 +115,15 @@ export const textStyle = StyleSheet.create({ const ChannelListItem = ({ channel, currentUserId, hasDraft, - isActive, isInfo, isMuted, membersCount, - myChannel, onPress, teamDisplayName, testID}: Props) => { + isActive, isInfo, isMuted, membersCount, hasMember, + isUnread, mentionsCount, onPress, teamDisplayName, testID}: Props) => { const {formatMessage} = useIntl(); const theme = useTheme(); const isTablet = useIsTablet(); const styles = getStyleSheet(theme); // Make it brighter if it's not muted, and highlighted or has unreads - const isBright = myChannel && (myChannel.isUnread || myChannel.mentionsCount > 0); + const isBright = isUnread || mentionsCount > 0; const height = useMemo(() => { let h = 40; @@ -133,8 +134,8 @@ const ChannelListItem = ({ }, [teamDisplayName, isInfo, isTablet]); const handleOnPress = useCallback(() => { - onPress(myChannel?.id || channel.id); - }, [channel.id, myChannel?.id]); + onPress(channel.id); + }, [channel.id]); const textStyles = useMemo(() => [ isBright ? textStyle.bright : textStyle.regular, @@ -153,7 +154,7 @@ const ChannelListItem = ({ ], [height, isActive, isInfo, styles]); - if (!myChannel) { + if (!hasMember) { return null; } @@ -196,14 +197,14 @@ const ChannelListItem = ({ {displayName} {isInfo && Boolean(teamDisplayName) && !isTablet && - - {teamDisplayName} - + + {teamDisplayName} + } {Boolean(teammateId) && @@ -224,8 +225,8 @@ const ChannelListItem = ({ } 0} - value={myChannel.mentionsCount} + visible={mentionsCount > 0} + value={mentionsCount} style={[styles.badge, isMuted && styles.mutedBadge, isInfo && styles.infoBadge]} /> diff --git a/app/components/channel_item/custom_status/custom_status.tsx b/app/components/channel_item/custom_status/custom_status.tsx index 56166f261..671c92234 100644 --- a/app/components/channel_item/custom_status/custom_status.tsx +++ b/app/components/channel_item/custom_status/custom_status.tsx @@ -16,7 +16,7 @@ type Props = { const style = StyleSheet.create({ customStatusEmoji: { color: '#000', - marginHorizontal: 5, + marginHorizontal: -5, top: 3, }, info: { diff --git a/app/components/channel_item/index.ts b/app/components/channel_item/index.ts index ce8655ad9..8da82b20c 100644 --- a/app/components/channel_item/index.ts +++ b/app/components/channel_item/index.ts @@ -32,9 +32,13 @@ const enhance = withObservables(['channel', 'showTeamName', 'isCategoryMuted'], const hasDraft = queryDraft(database, channel.id).observeWithColumns(['message', 'files']).pipe( switchMap((draft) => of$(draft.length > 0)), + distinctUntilChanged(), ); - const isActive = observeCurrentChannelId(database).pipe(switchMap((id) => of$(id ? id === channel.id : false)), distinctUntilChanged()); + const isActive = observeCurrentChannelId(database).pipe( + switchMap((id) => of$(id ? id === channel.id : false)), + distinctUntilChanged(), + ); const isMuted = myChannel.pipe( switchMap((mc) => { @@ -50,6 +54,7 @@ const enhance = withObservables(['channel', 'showTeamName', 'isCategoryMuted'], if (channel.teamId && showTeamName) { teamDisplayName = channel.team.observe().pipe( switchMap((team) => of$(team?.displayName || '')), + distinctUntilChanged(), ); } @@ -58,6 +63,21 @@ const enhance = withObservables(['channel', 'showTeamName', 'isCategoryMuted'], membersCount = channel.members.observeCount(); } + const isUnread = myChannel.pipe( + switchMap((mc) => of$(mc?.isUnread)), + distinctUntilChanged(), + ); + + const mentionsCount = myChannel.pipe( + switchMap((mc) => of$(mc?.mentionsCount)), + distinctUntilChanged(), + ); + + const hasMember = myChannel.pipe( + switchMap((mc) => of$(Boolean(mc))), + distinctUntilChanged(), + ); + return { channel: channel.observe(), currentUserId, @@ -65,8 +85,10 @@ const enhance = withObservables(['channel', 'showTeamName', 'isCategoryMuted'], isActive, isMuted, membersCount, - myChannel, + isUnread, + mentionsCount, teamDisplayName, + hasMember, }; }); diff --git a/app/components/team_sidebar/team_list/team_item/index.ts b/app/components/team_sidebar/team_list/team_item/index.ts index 1a5b66c00..dade42701 100644 --- a/app/components/team_sidebar/team_list/team_item/index.ts +++ b/app/components/team_sidebar/team_list/team_item/index.ts @@ -3,7 +3,8 @@ import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; import withObservables from '@nozbe/with-observables'; -import {combineLatestWith, map} from 'rxjs/operators'; +import {of as of$} from 'rxjs'; +import {combineLatestWith, map, switchMap, distinctUntilChanged} from 'rxjs/operators'; import {observeAllMyChannelNotifyProps, queryMyChannelsByTeam} from '@queries/servers/channel'; import {observeCurrentTeamId} from '@queries/servers/system'; @@ -30,8 +31,13 @@ const enhance = withObservables(['myTeam'], ({myTeam, database}: WithTeamsArgs) }, false)), ); + const selected = observeCurrentTeamId(database).pipe( + switchMap((ctid) => of$(ctid === myTeam.id)), + distinctUntilChanged(), + ); + return { - currentTeamId: observeCurrentTeamId(database), + selected, team: myTeam.team.observe(), mentionCount: observeMentionCount(database, myTeam.id, false), hasUnreads, diff --git a/app/components/team_sidebar/team_list/team_item/team_item.tsx b/app/components/team_sidebar/team_list/team_item/team_item.tsx index a76a89082..7f9e02cc5 100644 --- a/app/components/team_sidebar/team_list/team_item/team_item.tsx +++ b/app/components/team_sidebar/team_list/team_item/team_item.tsx @@ -19,7 +19,7 @@ type Props = { team: TeamModel; hasUnreads: boolean; mentionCount: number; - currentTeamId: string; + selected: boolean; } const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { @@ -57,11 +57,10 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { }; }); -export default function TeamItem({team, hasUnreads, mentionCount, currentTeamId}: Props) { +export default function TeamItem({team, hasUnreads, mentionCount, selected}: Props) { const theme = useTheme(); const styles = getStyleSheet(theme); const serverUrl = useServerUrl(); - const selected = team.id === currentTeamId; const hasBadge = Boolean(mentionCount || hasUnreads); let badgeStyle = styles.unread; diff --git a/app/constants/events.ts b/app/constants/events.ts index cb6f5a64c..f27945df6 100644 --- a/app/constants/events.ts +++ b/app/constants/events.ts @@ -19,6 +19,7 @@ export default keyMirror({ SERVER_VERSION_CHANGED: null, TAB_BAR_VISIBLE: null, TEAM_LOAD_ERROR: null, + TEAM_SWITCH: null, USER_TYPING: null, USER_STOP_TYPING: null, POST_LIST_SCROLL_TO_BOTTOM: null, diff --git a/app/hooks/team_switch.ts b/app/hooks/team_switch.ts new file mode 100644 index 000000000..8d7007334 --- /dev/null +++ b/app/hooks/team_switch.ts @@ -0,0 +1,33 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {useEffect, useState} from 'react'; +import {DeviceEventEmitter} from 'react-native'; + +import {Events} from '@constants'; + +export const useTeamSwitch = () => { + const [loading, setLoading] = useState(false); + useEffect(() => { + let time: NodeJS.Timeout | undefined; + const l = DeviceEventEmitter.addListener(Events.TEAM_SWITCH, (switching: boolean) => { + if (time) { + clearTimeout(time); + } + if (switching) { + setLoading(true); + } else { + // eslint-disable-next-line max-nested-callbacks + time = setTimeout(() => setLoading(false), 200); + } + }); + return () => { + l.remove(); + if (time) { + clearTimeout(time); + } + }; + }, []); + + return loading; +}; diff --git a/app/queries/servers/channel.ts b/app/queries/servers/channel.ts index 07eb1815b..2b9e600f7 100644 --- a/app/queries/servers/channel.ts +++ b/app/queries/servers/channel.ts @@ -174,6 +174,12 @@ export const queryAllMyChannel = (database: Database) => { return database.get(MY_CHANNEL).query(); }; +export const queryAllMyChannelsForTeam = (database: Database, teamId: string) => { + return database.get(MY_CHANNEL).query( + Q.on(CHANNEL, Q.where('team_id', Q.oneOf([teamId, '']))), + ); +}; + export const getMyChannel = async (database: Database, channelId: string) => { try { const member = await database.get(MY_CHANNEL).find(channelId); diff --git a/app/screens/channel/channel.tsx b/app/screens/channel/channel.tsx index 164e57c1f..595e1097e 100644 --- a/app/screens/channel/channel.tsx +++ b/app/screens/channel/channel.tsx @@ -12,6 +12,7 @@ import {Events} from '@constants'; import {ACCESSORIES_CONTAINER_NATIVE_ID} from '@constants/post_draft'; import {useAppState, useIsTablet} from '@hooks/device'; import {useDefaultHeaderHeight} from '@hooks/header'; +import {useTeamSwitch} from '@hooks/team_switch'; import ChannelPostList from './channel_post_list'; import ChannelHeader from './header'; @@ -34,6 +35,7 @@ const Channel = ({channelId, componentId}: ChannelProps) => { const isTablet = useIsTablet(); const insets = useSafeAreaInsets(); const [shouldRenderPosts, setShouldRenderPosts] = useState(false); + const switchingTeam = useTeamSwitch(); const defaultHeight = useDefaultHeaderHeight(); const postDraftRef = useRef(null); @@ -70,7 +72,7 @@ const Channel = ({channelId, componentId}: ChannelProps) => { testID='channel.screen' > - {shouldRenderPosts && Boolean(channelId) && + {!switchingTeam && shouldRenderPosts && Boolean(channelId) && <> { const appState = useAppState(); const intl = useIntl(); const insets = useSafeAreaInsets(); + const switchingTeam = useTeamSwitch(); const isTablet = useIsTablet(); const defaultHeight = useDefaultHeaderHeight(); @@ -63,6 +65,7 @@ const GlobalThreads = ({componentId}: Props) => { }) } /> + {!switchingTeam && { testID={'global_threads.threads_list'} /> + } ); }; diff --git a/app/screens/home/channel_list/additional_tablet_view/additional_tablet_view.tsx b/app/screens/home/channel_list/additional_tablet_view/additional_tablet_view.tsx index e210d89fb..a41b29a56 100644 --- a/app/screens/home/channel_list/additional_tablet_view/additional_tablet_view.tsx +++ b/app/screens/home/channel_list/additional_tablet_view/additional_tablet_view.tsx @@ -14,6 +14,7 @@ type SelectedView = { } type Props = { + onTeam: boolean; currentChannelId: string; isCRTEnabled: boolean; } @@ -26,7 +27,7 @@ const ComponentsList: Record = { const channelScreen: SelectedView = {id: Screens.CHANNEL, Component: Channel}; const globalScreen: SelectedView = {id: Screens.GLOBAL_THREADS, Component: GlobalThreads}; -const AdditionalTabletView = ({currentChannelId, isCRTEnabled}: Props) => { +const AdditionalTabletView = ({onTeam, currentChannelId, isCRTEnabled}: Props) => { const [selected, setSelected] = useState(isCRTEnabled && !currentChannelId ? globalScreen : channelScreen); useEffect(() => { @@ -43,7 +44,7 @@ const AdditionalTabletView = ({currentChannelId, isCRTEnabled}: Props) => { return () => listener.remove(); }, []); - if (!selected) { + if (!selected || !onTeam) { return null; } diff --git a/app/screens/home/channel_list/additional_tablet_view/index.ts b/app/screens/home/channel_list/additional_tablet_view/index.ts index 01ca730e6..6c91c2647 100644 --- a/app/screens/home/channel_list/additional_tablet_view/index.ts +++ b/app/screens/home/channel_list/additional_tablet_view/index.ts @@ -3,8 +3,10 @@ import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; import withObservables from '@nozbe/with-observables'; +import {of as of$} from 'rxjs'; +import {switchMap, distinctUntilChanged} from 'rxjs/operators'; -import {observeCurrentChannelId} from '@queries/servers/system'; +import {observeCurrentChannelId, observeCurrentTeamId} from '@queries/servers/system'; import {observeIsCRTEnabled} from '@queries/servers/thread'; import AdditionalTabletView from './additional_tablet_view'; @@ -12,6 +14,10 @@ import AdditionalTabletView from './additional_tablet_view'; import type {WithDatabaseArgs} from '@typings/database/database'; const enhanced = withObservables([], ({database}: WithDatabaseArgs) => ({ + onTeam: observeCurrentTeamId(database).pipe( + switchMap((id) => of$(Boolean(id))), + distinctUntilChanged(), + ), currentChannelId: observeCurrentChannelId(database), isCRTEnabled: observeIsCRTEnabled(database), })); diff --git a/app/screens/home/channel_list/categories_list/categories/categories.test.tsx b/app/screens/home/channel_list/categories_list/categories/categories.test.tsx index fe09890fa..59b61b50e 100644 --- a/app/screens/home/channel_list/categories_list/categories/categories.test.tsx +++ b/app/screens/home/channel_list/categories_list/categories/categories.test.tsx @@ -18,7 +18,7 @@ describe('components/channel_list/categories', () => { it('render without error', () => { const wrapper = renderWithEverything( - , + , {database}, ); diff --git a/app/screens/home/channel_list/categories_list/categories/categories.tsx b/app/screens/home/channel_list/categories_list/categories/categories.tsx index 41fca251f..8345a6028 100644 --- a/app/screens/home/channel_list/categories_list/categories/categories.tsx +++ b/app/screens/home/channel_list/categories_list/categories/categories.tsx @@ -1,13 +1,15 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {useCallback, useEffect, useMemo, useRef} from 'react'; +import React, {useCallback, useMemo, useRef} from 'react'; import {useIntl} from 'react-intl'; -import {FlatList, StyleSheet} from 'react-native'; +import {FlatList, StyleSheet, View} from 'react-native'; import {switchToChannelById} from '@actions/remote/channel'; +import Loading from '@components/loading'; import {useServerUrl} from '@context/server'; import {useIsTablet} from '@hooks/device'; +import {useTeamSwitch} from '@hooks/team_switch'; import CategoryBody from './body'; import LoadCategoriesError from './error'; @@ -18,7 +20,6 @@ import type CategoryModel from '@typings/database/models/servers/category'; type Props = { categories: CategoryModel[]; - currentTeamId: string; onlyUnreads: boolean; unreadsOnTop: boolean; } @@ -29,15 +30,27 @@ const styles = StyleSheet.create({ marginLeft: -18, marginRight: -20, }, + loadingView: { + alignItems: 'center', + justifyContent: 'center', + flex: 1, + }, + loading: { + justifyContent: 'center', + height: 32, + width: 32, + }, }); const extractKey = (item: CategoryModel | 'UNREADS') => (item === 'UNREADS' ? 'UNREADS' : item.id); -const Categories = ({categories, currentTeamId, onlyUnreads, unreadsOnTop}: Props) => { +const Categories = ({categories, onlyUnreads, unreadsOnTop}: Props) => { const intl = useIntl(); const listRef = useRef(null); const serverUrl = useServerUrl(); const isTablet = useIsTablet(); + const switchingTeam = useTeamSwitch(); + const teamId = categories[0]?.teamId; const onChannelSwitch = useCallback(async (channelId: string) => { switchToChannelById(serverUrl, channelId); @@ -47,7 +60,7 @@ const Categories = ({categories, currentTeamId, onlyUnreads, unreadsOnTop}: Prop if (data.item === 'UNREADS') { return ( ); - }, [currentTeamId, intl.locale, isTablet, onChannelSwitch, onlyUnreads]); - - useEffect(() => { - listRef.current?.scrollToOffset({animated: false, offset: 0}); - }, [currentTeamId]); + }, [teamId, intl.locale, isTablet, onChannelSwitch, onlyUnreads]); const categoriesToShow = useMemo(() => { if (onlyUnreads && !unreadsOnTop) { @@ -88,19 +97,28 @@ const Categories = ({categories, currentTeamId, onlyUnreads, unreadsOnTop}: Prop } return ( - + {!switchingTeam && ( + + // @ts-expect-error strictMode not included in the types + strictMode={true} + /> + )} + {switchingTeam && ( + + + + )} + ); }; diff --git a/app/screens/home/channel_list/categories_list/categories/index.ts b/app/screens/home/channel_list/categories_list/categories/index.ts index 0161f676c..89d474e8f 100644 --- a/app/screens/home/channel_list/categories_list/categories/index.ts +++ b/app/screens/home/channel_list/categories_list/categories/index.ts @@ -10,19 +10,18 @@ import {Preferences} from '@constants'; import {getPreferenceAsBool} from '@helpers/api/preference'; import {queryCategoriesByTeamIds} from '@queries/servers/categories'; import {queryPreferencesByCategoryAndName} from '@queries/servers/preference'; -import {observeOnlyUnreads} from '@queries/servers/system'; +import {observeCurrentTeamId, observeOnlyUnreads} from '@queries/servers/system'; import Categories from './categories'; import type {WithDatabaseArgs} from '@typings/database/database'; import type PreferenceModel from '@typings/database/models/servers/preference'; -type WithDatabaseProps = { currentTeamId: string } & WithDatabaseArgs - const enhanced = withObservables( - ['currentTeamId'], - ({currentTeamId, database}: WithDatabaseProps) => { - const categories = queryCategoriesByTeamIds(database, [currentTeamId]).observeWithColumns(['sort_order']); + [], + ({database}: WithDatabaseArgs) => { + const currentTeamId = observeCurrentTeamId(database); + const categories = currentTeamId.pipe(switchMap((ctid) => queryCategoriesByTeamIds(database, [ctid]).observeWithColumns(['sort_order']))); const unreadsOnTop = queryPreferencesByCategoryAndName(database, Preferences.CATEGORY_SIDEBAR_SETTINGS, Preferences.CHANNEL_SIDEBAR_GROUP_UNREADS). observeWithColumns(['value']). diff --git a/app/screens/home/channel_list/categories_list/categories/unreads/index.ts b/app/screens/home/channel_list/categories_list/categories/unreads/index.ts index efe1f65b5..5973b4dc7 100644 --- a/app/screens/home/channel_list/categories_list/categories/unreads/index.ts +++ b/app/screens/home/channel_list/categories_list/categories/unreads/index.ts @@ -6,7 +6,6 @@ import withObservables from '@nozbe/with-observables'; import {of as of$, combineLatest} from 'rxjs'; import {combineLatestWith, concatAll, map, switchMap} from 'rxjs/operators'; -import {MyChannelModel} from '@app/database/models/server'; import {Preferences} from '@constants'; import {getPreferenceAsBool} from '@helpers/api/preference'; import {getChannelById, observeAllMyChannelNotifyProps, queryMyChannelUnreads} from '@queries/servers/channel'; @@ -19,6 +18,7 @@ import UnreadCategories from './unreads'; import type {WithDatabaseArgs} from '@typings/database/database'; import type ChannelModel from '@typings/database/models/servers/channel'; +import type MyChannelModel from '@typings/database/models/servers/my_channel'; import type PreferenceModel from '@typings/database/models/servers/preference'; type WithDatabaseProps = WithDatabaseArgs & { diff --git a/app/screens/home/channel_list/categories_list/categories/unreads/unreads.tsx b/app/screens/home/channel_list/categories_list/categories/unreads/unreads.tsx index 2b9d65241..3649b8a73 100644 --- a/app/screens/home/channel_list/categories_list/categories/unreads/unreads.tsx +++ b/app/screens/home/channel_list/categories_list/categories/unreads/unreads.tsx @@ -27,6 +27,8 @@ type UnreadCategoriesProps = { onChannelSwitch: (channelId: string) => void; } +const extractKey = (item: ChannelModel) => item.id; + const UnreadCategories = ({onChannelSwitch, unreadChannels}: UnreadCategoriesProps) => { const theme = useTheme(); const styles = getStyleSheet(theme); @@ -54,6 +56,8 @@ const UnreadCategories = ({onChannelSwitch, unreadChannels}: UnreadCategoriesPro ); diff --git a/app/screens/home/channel_list/categories_list/header/index.ts b/app/screens/home/channel_list/categories_list/header/index.ts index 10d44885d..4e7ad2e6d 100644 --- a/app/screens/home/channel_list/categories_list/header/index.ts +++ b/app/screens/home/channel_list/categories_list/header/index.ts @@ -4,7 +4,7 @@ import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; import withObservables from '@nozbe/with-observables'; import {combineLatest, of as of$} from 'rxjs'; -import {switchMap} from 'rxjs/operators'; +import {switchMap, distinctUntilChanged} from 'rxjs/operators'; import {Permissions} from '@constants'; import {observePermissionForTeam} from '@queries/servers/role'; @@ -23,14 +23,17 @@ const enhanced = withObservables([], ({database}: WithDatabaseArgs) => { const canJoinChannels = combineLatest([currentUser, team]).pipe( switchMap(([u, t]) => (t && u ? observePermissionForTeam(t, u, Permissions.JOIN_PUBLIC_CHANNELS, true) : of$(false))), + distinctUntilChanged(), ); const canCreatePublicChannels = combineLatest([currentUser, team]).pipe( switchMap(([u, t]) => (t && u ? observePermissionForTeam(t, u, Permissions.CREATE_PUBLIC_CHANNEL, true) : of$(false))), + distinctUntilChanged(), ); const canCreatePrivateChannels = combineLatest([currentUser, team]).pipe( switchMap(([u, t]) => (t && u ? observePermissionForTeam(t, u, Permissions.CREATE_PRIVATE_CHANNEL, false) : of$(false))), + distinctUntilChanged(), ); const canCreateChannels = combineLatest([canCreatePublicChannels, canCreatePrivateChannels]).pipe( diff --git a/app/screens/home/channel_list/categories_list/index.test.tsx b/app/screens/home/channel_list/categories_list/index.test.tsx index df7b74ed9..d941a826f 100644 --- a/app/screens/home/channel_list/categories_list/index.test.tsx +++ b/app/screens/home/channel_list/categories_list/index.test.tsx @@ -33,7 +33,6 @@ describe('components/categories_list', () => { , {database}, @@ -47,7 +46,6 @@ describe('components/categories_list', () => { isCRTEnabled={true} isTablet={false} teamsCount={1} - currentTeamId={TestHelper.basicTeam!.id} channelsCount={1} />, {database}, @@ -65,7 +63,6 @@ describe('components/categories_list', () => { , {database}, @@ -84,7 +81,6 @@ describe('components/categories_list', () => { , {database}, diff --git a/app/screens/home/channel_list/categories_list/index.tsx b/app/screens/home/channel_list/categories_list/index.tsx index 6bfe9904d..5245ac3d9 100644 --- a/app/screens/home/channel_list/categories_list/index.tsx +++ b/app/screens/home/channel_list/categories_list/index.tsx @@ -11,7 +11,6 @@ import {makeStyleSheetFromTheme} from '@utils/theme'; import Categories from './categories'; import ChannelListHeader from './header'; import LoadChannelsError from './load_channels_error'; -import LoadTeamsError from './load_teams_error'; import SubHeader from './subheader'; import ThreadsButton from './threads_button'; @@ -27,7 +26,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ type ChannelListProps = { channelsCount: number; - currentTeamId?: string; iconPad?: boolean; isCRTEnabled?: boolean; isTablet: boolean; @@ -38,7 +36,7 @@ const getTabletWidth = (teamsCount: number) => { return TABLET_SIDEBAR_WIDTH - (teamsCount > 1 ? TEAM_SIDEBAR_WIDTH : 0); }; -const CategoriesList = ({channelsCount, currentTeamId, iconPad, isCRTEnabled, isTablet, teamsCount}: ChannelListProps) => { +const CategoriesList = ({channelsCount, iconPad, isCRTEnabled, isTablet, teamsCount}: ChannelListProps) => { const theme = useTheme(); const styles = getStyleSheet(theme); const tabletWidth = useSharedValue(isTablet ? getTabletWidth(teamsCount) : 0); @@ -61,18 +59,14 @@ const CategoriesList = ({channelsCount, currentTeamId, iconPad, isCRTEnabled, is let content; - if (!currentTeamId) { - content = (); - } else if (channelsCount < 1) { - content = (); + if (channelsCount < 1) { + content = (); } else { content = ( <> {isCRTEnabled && } - + ); } diff --git a/app/screens/home/channel_list/categories_list/load_channels_error/index.ts b/app/screens/home/channel_list/categories_list/load_channels_error/index.ts index 5339f103b..ed61224c8 100644 --- a/app/screens/home/channel_list/categories_list/load_channels_error/index.ts +++ b/app/screens/home/channel_list/categories_list/load_channels_error/index.ts @@ -6,19 +6,22 @@ import withObservables from '@nozbe/with-observables'; import {of as of$} from 'rxjs'; import {switchMap} from 'rxjs/operators'; -import {observeTeam} from '@queries/servers/team'; +import {observeCurrentTeam} from '@queries/servers/team'; import LoadChannelsError from './load_channel_error'; import type {WithDatabaseArgs} from '@typings/database/database'; -const enhanced = withObservables(['teamId'], ({database, teamId}: {teamId: string} & WithDatabaseArgs) => { - const team = observeTeam(database, teamId); +const enhanced = withObservables([], ({database}: WithDatabaseArgs) => { + const team = observeCurrentTeam(database); return { teamDisplayName: team.pipe( switchMap((t) => of$(t?.displayName)), ), + teamId: team.pipe( + switchMap((t) => of$(t?.id)), + ), }; }); 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 1235d4be9..c89c45346 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 @@ -8,6 +8,8 @@ import {retryInitialChannel} from '@actions/remote/retry'; import LoadingError from '@components/loading_error'; import {useServerUrl} from '@context/server'; +import LoadTeamsError from '../load_teams_error'; + type Props = { teamDisplayName: string; teamId: string; @@ -27,6 +29,9 @@ const LoadChannelsError = ({teamDisplayName, teamId}: Props) => { } }, [teamId]); + if (!teamId) { + ; + } return ( { isTablet={isTablet} teamsCount={props.teamsCount} channelsCount={props.channelsCount} - currentTeamId={props.currentTeamId} /> - {isTablet && Boolean(props.currentTeamId) && + {isTablet && } diff --git a/app/screens/home/channel_list/index.ts b/app/screens/home/channel_list/index.ts index 9d9463833..f11d0cfac 100644 --- a/app/screens/home/channel_list/index.ts +++ b/app/screens/home/channel_list/index.ts @@ -3,8 +3,10 @@ import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; import withObservables from '@nozbe/with-observables'; +import {of as of$} from 'rxjs'; +import {switchMap} from 'rxjs/operators'; -import {queryAllMyChannel} from '@queries/servers/channel'; +import {queryAllMyChannelsForTeam} from '@queries/servers/channel'; import {observeCurrentTeamId} from '@queries/servers/system'; import {queryMyTeams} from '@queries/servers/team'; import {observeIsCRTEnabled} from '@queries/servers/thread'; @@ -14,10 +16,11 @@ import ChannelsList from './channel_list'; import type {WithDatabaseArgs} from '@typings/database/database'; const enhanced = withObservables([], ({database}: WithDatabaseArgs) => ({ - currentTeamId: observeCurrentTeamId(database), isCRTEnabled: observeIsCRTEnabled(database), teamsCount: queryMyTeams(database).observeCount(false), - channelsCount: queryAllMyChannel(database).observeCount(), + channelsCount: observeCurrentTeamId(database).pipe( + switchMap((id) => (id ? queryAllMyChannelsForTeam(database, id).observeCount() : of$(0))), + ), })); export default withDatabase(enhanced(ChannelsList));