From 8fd3b99887a7ddeb532e4e7d7df572faaac57581 Mon Sep 17 00:00:00 2001 From: Chewbacca Date: Wed, 1 Mar 2023 11:16:34 -0500 Subject: [PATCH] Use Groups Discovery if user has no groups --- app/soapbox/components/sidebar-menu.tsx | 5 +- app/soapbox/components/sidebar-navigation.tsx | 6 +- .../hooks/__tests__/useGroupsPath.test.ts | 73 +++++++++++++++++++ app/soapbox/hooks/index.ts | 1 + app/soapbox/hooks/useGroupsPath.ts | 23 ++++++ app/soapbox/queries/groups.ts | 5 +- 6 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 app/soapbox/hooks/__tests__/useGroupsPath.test.ts create mode 100644 app/soapbox/hooks/useGroupsPath.ts diff --git a/app/soapbox/components/sidebar-menu.tsx b/app/soapbox/components/sidebar-menu.tsx index ffe3a0e98..0c68b2aff 100644 --- a/app/soapbox/components/sidebar-menu.tsx +++ b/app/soapbox/components/sidebar-menu.tsx @@ -10,7 +10,7 @@ import { closeSidebar } from 'soapbox/actions/sidebar'; import Account from 'soapbox/components/account'; import { Stack } from 'soapbox/components/ui'; import ProfileStats from 'soapbox/features/ui/components/profile-stats'; -import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks'; +import { useAppDispatch, useAppSelector, useGroupsPath, useFeatures } from 'soapbox/hooks'; import { makeGetAccount, makeGetOtherAccounts } from 'soapbox/selectors'; import { Divider, HStack, Icon, IconButton, Text } from './ui'; @@ -90,6 +90,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { const sidebarOpen = useAppSelector((state) => state.sidebar.sidebarOpen); const settings = useAppSelector((state) => getSettings(state)); const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.count()); + const groupsPath = useGroupsPath(); const closeButtonRef = React.useRef(null); @@ -210,7 +211,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { {features.groups && ( { const features = useFeatures(); const settings = useSettings(); const account = useOwnAccount(); + const groupsPath = useGroupsPath(); + const notificationCount = useAppSelector((state) => state.notifications.unread); const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.count()); const dashboardCount = useAppSelector((state) => state.admin.openReports.count() + state.admin.awaitingApproval.count()); @@ -135,7 +137,7 @@ const SidebarNavigation = () => { {features.groups && ( } /> diff --git a/app/soapbox/hooks/__tests__/useGroupsPath.test.ts b/app/soapbox/hooks/__tests__/useGroupsPath.test.ts new file mode 100644 index 000000000..d2ffb2452 --- /dev/null +++ b/app/soapbox/hooks/__tests__/useGroupsPath.test.ts @@ -0,0 +1,73 @@ +import { Map as ImmutableMap } from 'immutable'; + +import { __stub } from 'soapbox/api'; +import { renderHook, waitFor } from 'soapbox/jest/test-helpers'; +import { normalizeAccount, normalizeGroup, normalizeInstance } from 'soapbox/normalizers'; + +import { useGroupsPath } from '../useGroupsPath'; + +describe('useGroupsPath()', () => { + test('without the groupsDiscovery feature', () => { + const store = { + instance: normalizeInstance({ + version: '2.7.2 (compatible; Pleroma 2.3.0)', + }), + }; + + const { result } = renderHook(useGroupsPath, undefined, store); + + expect(result.current).toEqual('/groups'); + }); + + describe('with the "groupsDiscovery" feature', () => { + let store: any; + + beforeEach(() => { + const userId = '1'; + store = { + instance: normalizeInstance({ + version: '3.4.1 (compatible; TruthSocial 1.0.0+unreleased)', + }), + me: userId, + accounts: ImmutableMap({ + [userId]: normalizeAccount({ + id: userId, + acct: 'justin-username', + display_name: 'Justin L', + avatar: 'test.jpg', + chats_onboarded: false, + }), + }), + }; + }); + + describe('when the user has no groups', () => { + test('should default to the discovery page', () => { + const { result } = renderHook(useGroupsPath, undefined, store); + + expect(result.current).toEqual('/groups/discover'); + }); + }); + + describe('when the user has groups', () => { + beforeEach(() => { + __stub((mock) => { + mock.onGet('/api/v1/groups').reply(200, [ + normalizeGroup({ + display_name: 'Group', + id: '1', + }), + ]); + }); + }); + + test('should default to the discovery page', async () => { + const { result } = renderHook(useGroupsPath, undefined, store); + + await waitFor(() => { + expect(result.current).toEqual('/groups'); + }); + }); + }); + }); +}); diff --git a/app/soapbox/hooks/index.ts b/app/soapbox/hooks/index.ts index 6460938b6..afefefd72 100644 --- a/app/soapbox/hooks/index.ts +++ b/app/soapbox/hooks/index.ts @@ -5,6 +5,7 @@ export { useAppSelector } from './useAppSelector'; export { useClickOutside } from './useClickOutside'; export { useCompose } from './useCompose'; export { useDebounce } from './useDebounce'; +export { useGroupsPath } from './useGroupsPath'; export { useDimensions } from './useDimensions'; export { useFeatures } from './useFeatures'; export { useInstance } from './useInstance'; diff --git a/app/soapbox/hooks/useGroupsPath.ts b/app/soapbox/hooks/useGroupsPath.ts new file mode 100644 index 000000000..8a4759f32 --- /dev/null +++ b/app/soapbox/hooks/useGroupsPath.ts @@ -0,0 +1,23 @@ +import { useGroups } from 'soapbox/queries/groups'; + +import { useFeatures } from './useFeatures'; + +/** + * Determine the correct URL to use for /groups. + * If the user does not have any Groups, let's default to the discovery tab. + * Otherwise, let's default to My Groups. + * + * @returns String (as link) + */ +const useGroupsPath = () => { + const features = useFeatures(); + const { groups } = useGroups(); + + if (!features.groupsDiscovery) { + return '/groups'; + } + + return groups.length > 0 ? '/groups' : '/groups/discover'; +}; + +export { useGroupsPath }; \ No newline at end of file diff --git a/app/soapbox/queries/groups.ts b/app/soapbox/queries/groups.ts index fbacb7182..612c60b43 100644 --- a/app/soapbox/queries/groups.ts +++ b/app/soapbox/queries/groups.ts @@ -18,9 +18,10 @@ const useGroups = () => { const api = useApi(); const account = useOwnAccount(); const dispatch = useAppDispatch(); + const features = useFeatures(); const getGroups = async (pageParam?: any): Promise> => { - const endpoint = '/api/mock/groups'; // '/api/v1/groups'; + const endpoint = '/api/v1/groups'; const nextPageLink = pageParam?.link; const uri = nextPageLink || endpoint; const response = await api.get(uri); @@ -45,7 +46,7 @@ const useGroups = () => { GroupKeys.myGroups(account?.id as string), ({ pageParam }: any) => getGroups(pageParam), { - enabled: !!account, + enabled: !!account && features.groups, keepPreviousData: true, getNextPageParam: (config) => { if (config?.hasMore) {