Use Groups Discovery if user has no groups
This commit is contained in:
parent
01dfbad7bc
commit
8fd3b99887
6 changed files with 107 additions and 6 deletions
|
@ -10,7 +10,7 @@ import { closeSidebar } from 'soapbox/actions/sidebar';
|
||||||
import Account from 'soapbox/components/account';
|
import Account from 'soapbox/components/account';
|
||||||
import { Stack } from 'soapbox/components/ui';
|
import { Stack } from 'soapbox/components/ui';
|
||||||
import ProfileStats from 'soapbox/features/ui/components/profile-stats';
|
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 { makeGetAccount, makeGetOtherAccounts } from 'soapbox/selectors';
|
||||||
|
|
||||||
import { Divider, HStack, Icon, IconButton, Text } from './ui';
|
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 sidebarOpen = useAppSelector((state) => state.sidebar.sidebarOpen);
|
||||||
const settings = useAppSelector((state) => getSettings(state));
|
const settings = useAppSelector((state) => getSettings(state));
|
||||||
const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.count());
|
const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.count());
|
||||||
|
const groupsPath = useGroupsPath();
|
||||||
|
|
||||||
const closeButtonRef = React.useRef(null);
|
const closeButtonRef = React.useRef(null);
|
||||||
|
|
||||||
|
@ -210,7 +211,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
|
||||||
|
|
||||||
{features.groups && (
|
{features.groups && (
|
||||||
<SidebarLink
|
<SidebarLink
|
||||||
to='/groups'
|
to={groupsPath}
|
||||||
icon={require('@tabler/icons/circles.svg')}
|
icon={require('@tabler/icons/circles.svg')}
|
||||||
text={intl.formatMessage(messages.groups)}
|
text={intl.formatMessage(messages.groups)}
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
import { Stack } from 'soapbox/components/ui';
|
import { Stack } from 'soapbox/components/ui';
|
||||||
import { useStatContext } from 'soapbox/contexts/stat-context';
|
import { useStatContext } from 'soapbox/contexts/stat-context';
|
||||||
import ComposeButton from 'soapbox/features/ui/components/compose-button';
|
import ComposeButton from 'soapbox/features/ui/components/compose-button';
|
||||||
import { useAppSelector, useFeatures, useOwnAccount, useSettings } from 'soapbox/hooks';
|
import { useAppSelector, useGroupsPath, useFeatures, useOwnAccount, useSettings } from 'soapbox/hooks';
|
||||||
|
|
||||||
import DropdownMenu, { Menu } from './dropdown-menu';
|
import DropdownMenu, { Menu } from './dropdown-menu';
|
||||||
import SidebarNavigationLink from './sidebar-navigation-link';
|
import SidebarNavigationLink from './sidebar-navigation-link';
|
||||||
|
@ -25,6 +25,8 @@ const SidebarNavigation = () => {
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
const settings = useSettings();
|
const settings = useSettings();
|
||||||
const account = useOwnAccount();
|
const account = useOwnAccount();
|
||||||
|
const groupsPath = useGroupsPath();
|
||||||
|
|
||||||
const notificationCount = useAppSelector((state) => state.notifications.unread);
|
const notificationCount = useAppSelector((state) => state.notifications.unread);
|
||||||
const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.count());
|
const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.count());
|
||||||
const dashboardCount = useAppSelector((state) => state.admin.openReports.count() + state.admin.awaitingApproval.count());
|
const dashboardCount = useAppSelector((state) => state.admin.openReports.count() + state.admin.awaitingApproval.count());
|
||||||
|
@ -135,7 +137,7 @@ const SidebarNavigation = () => {
|
||||||
|
|
||||||
{features.groups && (
|
{features.groups && (
|
||||||
<SidebarNavigationLink
|
<SidebarNavigationLink
|
||||||
to='/groups'
|
to={groupsPath}
|
||||||
icon={require('@tabler/icons/circles.svg')}
|
icon={require('@tabler/icons/circles.svg')}
|
||||||
text={<FormattedMessage id='tabs_bar.groups' defaultMessage='Groups' />}
|
text={<FormattedMessage id='tabs_bar.groups' defaultMessage='Groups' />}
|
||||||
/>
|
/>
|
||||||
|
|
73
app/soapbox/hooks/__tests__/useGroupsPath.test.ts
Normal file
73
app/soapbox/hooks/__tests__/useGroupsPath.test.ts
Normal file
|
@ -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');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -5,6 +5,7 @@ export { useAppSelector } from './useAppSelector';
|
||||||
export { useClickOutside } from './useClickOutside';
|
export { useClickOutside } from './useClickOutside';
|
||||||
export { useCompose } from './useCompose';
|
export { useCompose } from './useCompose';
|
||||||
export { useDebounce } from './useDebounce';
|
export { useDebounce } from './useDebounce';
|
||||||
|
export { useGroupsPath } from './useGroupsPath';
|
||||||
export { useDimensions } from './useDimensions';
|
export { useDimensions } from './useDimensions';
|
||||||
export { useFeatures } from './useFeatures';
|
export { useFeatures } from './useFeatures';
|
||||||
export { useInstance } from './useInstance';
|
export { useInstance } from './useInstance';
|
||||||
|
|
23
app/soapbox/hooks/useGroupsPath.ts
Normal file
23
app/soapbox/hooks/useGroupsPath.ts
Normal file
|
@ -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 };
|
|
@ -18,9 +18,10 @@ const useGroups = () => {
|
||||||
const api = useApi();
|
const api = useApi();
|
||||||
const account = useOwnAccount();
|
const account = useOwnAccount();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const features = useFeatures();
|
||||||
|
|
||||||
const getGroups = async (pageParam?: any): Promise<PaginatedResult<Group>> => {
|
const getGroups = async (pageParam?: any): Promise<PaginatedResult<Group>> => {
|
||||||
const endpoint = '/api/mock/groups'; // '/api/v1/groups';
|
const endpoint = '/api/v1/groups';
|
||||||
const nextPageLink = pageParam?.link;
|
const nextPageLink = pageParam?.link;
|
||||||
const uri = nextPageLink || endpoint;
|
const uri = nextPageLink || endpoint;
|
||||||
const response = await api.get<Group[]>(uri);
|
const response = await api.get<Group[]>(uri);
|
||||||
|
@ -45,7 +46,7 @@ const useGroups = () => {
|
||||||
GroupKeys.myGroups(account?.id as string),
|
GroupKeys.myGroups(account?.id as string),
|
||||||
({ pageParam }: any) => getGroups(pageParam),
|
({ pageParam }: any) => getGroups(pageParam),
|
||||||
{
|
{
|
||||||
enabled: !!account,
|
enabled: !!account && features.groups,
|
||||||
keepPreviousData: true,
|
keepPreviousData: true,
|
||||||
getNextPageParam: (config) => {
|
getNextPageParam: (config) => {
|
||||||
if (config?.hasMore) {
|
if (config?.hasMore) {
|
||||||
|
|
Loading…
Reference in a new issue