) => {
const { group, width = 'auto' } = props;
- const joinGroup = useJoinGroup(group);
-
- const onJoinGroup = () => joinGroup.mutate(group);
-
return (
-
+
);
});
diff --git a/app/soapbox/features/groups/components/discover/group-list-item.tsx b/app/soapbox/features/groups/components/discover/group-list-item.tsx
index 55190b85e..cb492503f 100644
--- a/app/soapbox/features/groups/components/discover/group-list-item.tsx
+++ b/app/soapbox/features/groups/components/discover/group-list-item.tsx
@@ -3,8 +3,8 @@ import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import GroupAvatar from 'soapbox/components/groups/group-avatar';
-import { Button, HStack, Icon, Stack, Text } from 'soapbox/components/ui';
-import { useJoinGroup } from 'soapbox/hooks/api';
+import { HStack, Icon, Stack, Text } from 'soapbox/components/ui';
+import GroupActionButton from 'soapbox/features/group/components/group-action-button';
import { Group as GroupEntity } from 'soapbox/types/entities';
import { shortNumberFormat } from 'soapbox/utils/numbers';
@@ -16,10 +16,6 @@ interface IGroup {
const GroupListItem = (props: IGroup) => {
const { group, withJoinAction = true } = props;
- const joinGroup = useJoinGroup(group);
-
- const onJoinGroup = () => joinGroup.mutate(group);
-
return (
{
{withJoinAction && (
-
+
)}
);
diff --git a/app/soapbox/features/groups/components/discover/search/results.tsx b/app/soapbox/features/groups/components/discover/search/results.tsx
index 72bca24ad..14e1e5a67 100644
--- a/app/soapbox/features/groups/components/discover/search/results.tsx
+++ b/app/soapbox/features/groups/components/discover/search/results.tsx
@@ -4,7 +4,7 @@ import { FormattedMessage } from 'react-intl';
import { Components, Virtuoso, VirtuosoGrid } from 'react-virtuoso';
import { HStack, Icon, Stack, Text } from 'soapbox/components/ui';
-import { useGroupSearch } from 'soapbox/queries/groups/search';
+import { useGroupSearch } from 'soapbox/hooks/api';
import { Group } from 'soapbox/types/entities';
import GroupGridItem from '../group-grid-item';
diff --git a/app/soapbox/features/groups/components/discover/search/search.tsx b/app/soapbox/features/groups/components/discover/search/search.tsx
index ef8605435..4e3308353 100644
--- a/app/soapbox/features/groups/components/discover/search/search.tsx
+++ b/app/soapbox/features/groups/components/discover/search/search.tsx
@@ -4,7 +4,7 @@ import { FormattedMessage } from 'react-intl';
import { Stack } from 'soapbox/components/ui';
import PlaceholderGroupSearch from 'soapbox/features/placeholder/components/placeholder-group-search';
import { useDebounce, useOwnAccount } from 'soapbox/hooks';
-import { useGroupSearch } from 'soapbox/queries/groups/search';
+import { useGroupSearch } from 'soapbox/hooks/api';
import { saveGroupSearch } from 'soapbox/utils/groups';
import Blankslate from './blankslate';
diff --git a/app/soapbox/hooks/api/groups/useGroupSearch.ts b/app/soapbox/hooks/api/groups/useGroupSearch.ts
new file mode 100644
index 000000000..17c10e90f
--- /dev/null
+++ b/app/soapbox/hooks/api/groups/useGroupSearch.ts
@@ -0,0 +1,39 @@
+import { Entities } from 'soapbox/entity-store/entities';
+import { useEntities } from 'soapbox/entity-store/hooks';
+import { groupSchema } from 'soapbox/schemas';
+
+import { useApi } from '../../useApi';
+import { useFeatures } from '../../useFeatures';
+
+import { useGroupRelationships } from './useGroups';
+
+import type { Group } from 'soapbox/schemas';
+
+function useGroupSearch(search: string) {
+ const api = useApi();
+ const features = useFeatures();
+
+ const { entities, ...result } = useEntities(
+ [Entities.GROUPS, 'discover', 'search', search],
+ () => api.get('/api/v1/groups/search', {
+ params: {
+ q: search,
+ },
+ }),
+ { enabled: features.groupsDiscovery && !!search, schema: groupSchema },
+ );
+
+ const { relationships } = useGroupRelationships(entities.map(entity => entity.id));
+
+ const groups = entities.map((group) => ({
+ ...group,
+ relationship: relationships[group.id] || null,
+ }));
+
+ return {
+ ...result,
+ groups,
+ };
+}
+
+export { useGroupSearch };
\ No newline at end of file
diff --git a/app/soapbox/hooks/api/groups/useJoinGroup.ts b/app/soapbox/hooks/api/groups/useJoinGroup.ts
index f30a9c25b..46cd1d5bd 100644
--- a/app/soapbox/hooks/api/groups/useJoinGroup.ts
+++ b/app/soapbox/hooks/api/groups/useJoinGroup.ts
@@ -2,9 +2,13 @@ import { Entities } from 'soapbox/entity-store/entities';
import { useEntityActions } from 'soapbox/entity-store/hooks';
import { groupRelationshipSchema } from 'soapbox/schemas';
+import { useGroups } from './useGroups';
+
import type { Group, GroupRelationship } from 'soapbox/schemas';
function useJoinGroup(group: Group) {
+ const { invalidate } = useGroups();
+
const { createEntity, isLoading } = useEntityActions(
[Entities.GROUP_RELATIONSHIPS, group.id],
{ post: `/api/v1/groups/${group.id}/join` },
@@ -14,6 +18,7 @@ function useJoinGroup(group: Group) {
return {
mutate: createEntity,
isLoading,
+ invalidate,
};
}
diff --git a/app/soapbox/hooks/api/groups/useLeaveGroup.ts b/app/soapbox/hooks/api/groups/useLeaveGroup.ts
index 1f6b99f8d..af78c6d35 100644
--- a/app/soapbox/hooks/api/groups/useLeaveGroup.ts
+++ b/app/soapbox/hooks/api/groups/useLeaveGroup.ts
@@ -1,8 +1,14 @@
import { Entities } from 'soapbox/entity-store/entities';
import { useEntityActions } from 'soapbox/entity-store/hooks';
-import { Group, GroupRelationship, groupRelationshipSchema } from 'soapbox/schemas';
+import { groupRelationshipSchema } from 'soapbox/schemas';
+
+import { useGroups } from './useGroups';
+
+import type { Group, GroupRelationship } from 'soapbox/schemas';
function useLeaveGroup(group: Group) {
+ const { invalidate } = useGroups();
+
const { createEntity, isLoading } = useEntityActions(
[Entities.GROUP_RELATIONSHIPS, group.id],
{ post: `/api/v1/groups/${group.id}/leave` },
@@ -12,6 +18,7 @@ function useLeaveGroup(group: Group) {
return {
mutate: createEntity,
isLoading,
+ invalidate,
};
}
diff --git a/app/soapbox/hooks/api/index.ts b/app/soapbox/hooks/api/index.ts
index d1c8ec09f..b70314633 100644
--- a/app/soapbox/hooks/api/index.ts
+++ b/app/soapbox/hooks/api/index.ts
@@ -6,6 +6,7 @@ export { useCancelMembershipRequest } from './groups/useCancelMembershipRequest'
export { useDeleteGroup } from './groups/useDeleteGroup';
export { useDemoteGroupMember } from './groups/useDemoteGroupMember';
export { useGroup, useGroups } from './groups/useGroups';
+export { useGroupSearch } from './groups/useGroupSearch';
export { useJoinGroup } from './groups/useJoinGroup';
export { useLeaveGroup } from './groups/useLeaveGroup';
export { usePromoteGroupMember } from './groups/usePromoteGroupMember';
diff --git a/app/soapbox/normalizers/group-relationship.ts b/app/soapbox/normalizers/group-relationship.ts
index c9326db91..4ac579e6d 100644
--- a/app/soapbox/normalizers/group-relationship.ts
+++ b/app/soapbox/normalizers/group-relationship.ts
@@ -8,13 +8,15 @@ import {
fromJS,
} from 'immutable';
+import { GroupRoles } from 'soapbox/schemas/group-member';
+
export const GroupRelationshipRecord = ImmutableRecord({
id: '',
blocked_by: false,
member: false,
notifying: null,
requested: false,
- role: null as 'admin' | 'moderator' | 'user' | null,
+ role: 'user' as GroupRoles,
});
export const normalizeGroupRelationship = (relationship: Record) => {
diff --git a/app/soapbox/queries/groups/members.ts b/app/soapbox/queries/groups/members.ts
deleted file mode 100644
index 4d0a0bb66..000000000
--- a/app/soapbox/queries/groups/members.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { useQuery } from '@tanstack/react-query';
-
-import { useApi } from 'soapbox/hooks';
-import { normalizeAccount } from 'soapbox/normalizers';
-import { GroupRoles } from 'soapbox/schemas/group-member';
-
-const GroupMemberKeys = {
- members: (id: string, role: string) => ['group', id, role] as const,
-};
-
-const useGroupMembers = (groupId: string, role: GroupRoles) => {
- const api = useApi();
-
- const getQuery = async () => {
- const { data } = await api.get(`/api/v1/groups/${groupId}/memberships`, {
- params: {
- role,
- },
- });
-
- const result = data.map((member: any) => {
- return {
- ...member,
- account: normalizeAccount(member.account),
- };
- });
-
- return result;
- };
-
- return useQuery(
- GroupMemberKeys.members(groupId, role),
- getQuery,
- {
- placeholderData: [],
- },
- );
-};
-
-export { useGroupMembers };
\ No newline at end of file
diff --git a/app/soapbox/schemas/group-relationship.ts b/app/soapbox/schemas/group-relationship.ts
index 9f6eaaf35..75584955e 100644
--- a/app/soapbox/schemas/group-relationship.ts
+++ b/app/soapbox/schemas/group-relationship.ts
@@ -1,10 +1,12 @@
import z from 'zod';
+import { GroupRoles } from './group-member';
+
const groupRelationshipSchema = z.object({
id: z.string(),
member: z.boolean().catch(false),
requested: z.boolean().catch(false),
- role: z.string().nullish().catch(null),
+ role: z.nativeEnum(GroupRoles).catch(GroupRoles.USER),
blocked_by: z.boolean().catch(false),
notifying: z.boolean().nullable().catch(null),
});