From 0fc8a2993f7be8d6d2507513fbf1589e190c9abd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Tue, 6 Aug 2024 23:19:00 +0200 Subject: [PATCH] More work on pl-api migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- src/actions/admin.ts | 18 +++---- src/actions/aliases.ts | 6 --- src/actions/apps.ts | 4 +- src/actions/compose.ts | 2 +- src/actions/directory.ts | 2 +- src/actions/events.ts | 4 +- src/actions/filters.ts | 5 +- src/actions/me.ts | 6 +-- src/actions/media.ts | 1 - src/actions/notifications.ts | 3 -- src/actions/polls.ts | 7 ++- src/actions/push-subscriptions.ts | 10 ++-- src/actions/reports.ts | 2 +- src/actions/search.ts | 2 +- src/api/hooks/accounts/useAccountList.ts | 4 +- src/api/hooks/accounts/useRelationship.ts | 2 +- src/api/hooks/admin/useAnnouncements.ts | 2 +- src/api/hooks/admin/useDomains.ts | 2 +- src/api/hooks/admin/useModerationLog.ts | 2 +- src/api/hooks/groups/useBlockGroupMember.ts | 11 +++-- src/api/hooks/groups/useCreateGroup.ts | 2 - src/api/hooks/groups/useDeleteGroup.ts | 13 ++--- src/api/hooks/groups/useDemoteGroupMember.ts | 10 ++-- src/api/hooks/groups/useGroupRelationship.ts | 2 +- src/api/hooks/groups/useJoinGroup.ts | 12 ++--- src/api/hooks/groups/useLeaveGroup.ts | 12 ++--- src/api/hooks/groups/usePromoteGroupMember.ts | 12 +++-- src/api/hooks/statuses/useBookmarkFolders.ts | 2 +- src/components/status-action-bar.tsx | 2 +- src/entity-store/hooks/index.ts | 1 - src/entity-store/hooks/types.ts | 3 +- src/entity-store/hooks/useEntities.ts | 2 - src/entity-store/hooks/useEntityActions.ts | 49 ------------------- .../components/registration-mode-picker.tsx | 2 +- .../compose/components/privacy-dropdown.tsx | 8 +-- src/features/edit-profile/index.tsx | 2 +- src/features/filters/edit-filter.tsx | 3 +- .../components/group-member-list-item.tsx | 6 +-- .../steps/avatar-selection-step.tsx | 2 +- src/features/settings/index.tsx | 4 +- src/features/soapbox-config/index.tsx | 3 +- .../account-moderation-modal.tsx | 9 ++-- src/features/ui/index.tsx | 4 +- src/hooks/useFeatures.ts | 2 +- src/queries/trends.ts | 6 +-- src/reducers/compose.ts | 6 +-- src/reducers/domain-lists.ts | 2 +- src/reducers/followed-tags.ts | 2 +- src/reducers/search.ts | 13 +++-- src/reducers/suggestions.ts | 1 - src/reducers/trends.ts | 6 +-- src/schemas/index.ts | 2 - src/sentry.ts | 2 +- 53 files changed, 119 insertions(+), 183 deletions(-) delete mode 100644 src/entity-store/hooks/useEntityActions.ts diff --git a/src/actions/admin.ts b/src/actions/admin.ts index 6f4901f48..97ab4730c 100644 --- a/src/actions/admin.ts +++ b/src/actions/admin.ts @@ -329,7 +329,7 @@ const deleteUsers = (accountIds: string[]) => const approveMastodonUsers = (accountIds: string[]) => (dispatch: AppDispatch, getState: () => RootState) => { const client = getClient(getState); - Promise.all(accountIds.map(accountId => { + return Promise.all(accountIds.map(accountId => { client.request(`/api/v1/admin/accounts/${accountId}/approve`, { method: 'POST' }) .then(({ json: user }) => { dispatch({ type: ADMIN_USERS_APPROVE_SUCCESS, users: [user], accountIds: [accountId] }); @@ -450,10 +450,10 @@ const addPermission = (accountIds: string[], permissionGroup: string) => return getClient(getState).request(`/api/v1/pleroma/admin/users/permission_group/${permissionGroup}`, { method: 'POST', body: { nicknames }, }).then(({ json: data }) => { - dispatch({ type: ADMIN_ADD_PERMISSION_GROUP_SUCCESS, accountIds, permissionGroup, data }); - }).catch(error => { - dispatch({ type: ADMIN_ADD_PERMISSION_GROUP_FAIL, error, accountIds, permissionGroup }); - }); + dispatch({ type: ADMIN_ADD_PERMISSION_GROUP_SUCCESS, accountIds, permissionGroup, data }); + }).catch(error => { + dispatch({ type: ADMIN_ADD_PERMISSION_GROUP_FAIL, error, accountIds, permissionGroup }); + }); }; const removePermission = (accountIds: string[], permissionGroup: string) => @@ -463,10 +463,10 @@ const removePermission = (accountIds: string[], permissionGroup: string) => return getClient(getState).request(`/api/v1/pleroma/admin/users/permission_group/${permissionGroup}`, { method: 'DELETE', body: { nicknames }, }).then(({ json: data }) => { - dispatch({ type: ADMIN_REMOVE_PERMISSION_GROUP_SUCCESS, accountIds, permissionGroup, data }); - }).catch(error => { - dispatch({ type: ADMIN_REMOVE_PERMISSION_GROUP_FAIL, error, accountIds, permissionGroup }); - }); + dispatch({ type: ADMIN_REMOVE_PERMISSION_GROUP_SUCCESS, accountIds, permissionGroup, data }); + }).catch(error => { + dispatch({ type: ADMIN_REMOVE_PERMISSION_GROUP_FAIL, error, accountIds, permissionGroup }); + }); }; const promoteToAdmin = (accountId: string) => diff --git a/src/actions/aliases.ts b/src/actions/aliases.ts index aaf737466..ac40cda95 100644 --- a/src/actions/aliases.ts +++ b/src/actions/aliases.ts @@ -2,7 +2,6 @@ import { defineMessages } from 'react-intl'; import toast from 'soapbox/toast'; import { isLoggedIn } from 'soapbox/utils/auth'; -import { getFeatures } from 'soapbox/utils/features'; import { getClient } from '../api'; @@ -86,11 +85,6 @@ const changeAliasesSuggestions = (value: string) => ({ const addToAliases = (account: Account) => (dispatch: AppDispatch, getState: () => RootState) => { if (!isLoggedIn(getState)) return; - const state = getState(); - - const instance = state.instance; - const features = getFeatures(instance); - dispatch(addToAliasesRequest()); return getClient(getState).settings.addAccountAlias(account.acct).then(() => { diff --git a/src/actions/apps.ts b/src/actions/apps.ts index 0ebe76cbf..28bb785d5 100644 --- a/src/actions/apps.ts +++ b/src/actions/apps.ts @@ -6,7 +6,7 @@ * @see module:soapbox/actions/auth */ -import { PlApiClient } from 'pl-api'; +import { PlApiClient, type CreateApplicationParams } from 'pl-api'; import * as BuildConfig from 'soapbox/build-config'; @@ -16,7 +16,7 @@ const APP_CREATE_REQUEST = 'APP_CREATE_REQUEST'; const APP_CREATE_SUCCESS = 'APP_CREATE_SUCCESS'; const APP_CREATE_FAIL = 'APP_CREATE_FAIL'; -const createApp = (params?: Record, baseURL?: string) => +const createApp = (params: CreateApplicationParams, baseURL?: string) => (dispatch: React.Dispatch) => { dispatch({ type: APP_CREATE_REQUEST, params }); diff --git a/src/actions/compose.ts b/src/actions/compose.ts index 9320e11a0..e7d431589 100644 --- a/src/actions/compose.ts +++ b/src/actions/compose.ts @@ -599,7 +599,7 @@ const fetchComposeSuggestionsTags = (dispatch: AppDispatch, getState: () => Root const { trends } = getFeatures(instance); if (trends) { - const currentTrends = state.trends.items; + const currentTrends = state.trends.items.toArray(); return dispatch(updateSuggestionTags(composeId, token, currentTrends)); } diff --git a/src/actions/directory.ts b/src/actions/directory.ts index f423ac5c4..b02d1c493 100644 --- a/src/actions/directory.ts +++ b/src/actions/directory.ts @@ -18,7 +18,7 @@ const fetchDirectory = (params: Record) => (dispatch: AppDispatch, getState: () => RootState) => { dispatch(fetchDirectoryRequest()); - return getClient(getState()).instance.profileDirectory({...params, limit: 20}).then((data) => { + return getClient(getState()).instance.profileDirectory({ ...params, limit: 20 }).then((data) => { dispatch(importFetchedAccounts(data)); dispatch(fetchDirectorySuccess(data)); dispatch(fetchRelationships(data.map((x: APIEntity) => x.id))); diff --git a/src/actions/events.ts b/src/actions/events.ts index 02458c5a9..2660aa77c 100644 --- a/src/actions/events.ts +++ b/src/actions/events.ts @@ -215,12 +215,12 @@ const submitEvent = () => const params: CreateEventParams = { name, status, - start_time: startTime, + start_time: startTime.toISOString(), join_mode: joinMode, content_type: 'text/markdown', }; - if (endTime) params.end_time = endTime; + if (endTime) params.end_time = endTime?.toISOString(); if (banner) params.banner_id = banner.id; if (location) params.location_id = location.origin_id; diff --git a/src/actions/filters.ts b/src/actions/filters.ts index 6bbbd6d88..35b5867cf 100644 --- a/src/actions/filters.ts +++ b/src/actions/filters.ts @@ -5,6 +5,7 @@ import { isLoggedIn } from 'soapbox/utils/auth'; import { getClient } from '../api'; +import type { FilterContext } from 'pl-api'; import type { AppDispatch, RootState } from 'soapbox/store'; const FILTERS_FETCH_REQUEST = 'FILTERS_FETCH_REQUEST'; @@ -78,7 +79,7 @@ const fetchFilter = (id: string) => })); }; -const createFilter = (title: string, expires_in: number | undefined, context: Array, hide: boolean, keywords_attributes: FilterKeywords) => +const createFilter = (title: string, expires_in: number | undefined, context: Array, hide: boolean, keywords_attributes: FilterKeywords) => (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: FILTERS_CREATE_REQUEST }); @@ -96,7 +97,7 @@ const createFilter = (title: string, expires_in: number | undefined, context: Ar }); }; -const updateFilter = (id: string, title: string, expires_in: number | undefined, context: Array, hide: boolean, keywords_attributes: FilterKeywords) => +const updateFilter = (id: string, title: string, expires_in: number | undefined, context: Array, hide: boolean, keywords_attributes: FilterKeywords) => (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: FILTERS_UPDATE_REQUEST }); diff --git a/src/actions/me.ts b/src/actions/me.ts index 96c265a06..e28d22baf 100644 --- a/src/actions/me.ts +++ b/src/actions/me.ts @@ -1,5 +1,3 @@ -import { serialize } from 'object-to-formdata'; - import { selectAccount } from 'soapbox/selectors'; import { setSentryAccount } from 'soapbox/sentry'; import KVStore from 'soapbox/storage/kv-store'; @@ -68,11 +66,11 @@ const persistAuthAccount = (account: APIEntity, params: Record) => } }; -const patchMe = (params: Record, isFormData = false) => +const patchMe = (params: Record) => (dispatch: AppDispatch, getState: () => RootState) => { dispatch(patchMeRequest()); - return getClient(getState()).settings.updateCredentials(params) + return getClient(getState).settings.updateCredentials(params) .then(response => { persistAuthAccount(response, params); dispatch(patchMeSuccess(response)); diff --git a/src/actions/media.ts b/src/actions/media.ts index 3d8c7e0df..cd62d3cc1 100644 --- a/src/actions/media.ts +++ b/src/actions/media.ts @@ -2,7 +2,6 @@ import { defineMessages, type IntlShape } from 'react-intl'; import toast from 'soapbox/toast'; import { isLoggedIn } from 'soapbox/utils/auth'; -import { getFeatures } from 'soapbox/utils/features'; import { formatBytes, getVideoDuration } from 'soapbox/utils/media'; import resizeImage from 'soapbox/utils/resize-image'; diff --git a/src/actions/notifications.ts b/src/actions/notifications.ts index cb5ca6fe6..a87cdab88 100644 --- a/src/actions/notifications.ts +++ b/src/actions/notifications.ts @@ -273,8 +273,6 @@ const expandNotifications = ({ maxId }: Record = {}, done: () => an dispatch(expandNotificationsRequest(isLoadingMore)); return getClient(state).notifications.getNotifications(params, { signal: abortExpandNotifications.signal }).then(response => { - console.log(response); - const entries = (response.items).reduce((acc, item) => { if (item.account?.id) { acc.accounts[item.account.id] = item.account; @@ -301,7 +299,6 @@ const expandNotifications = ({ maxId }: Record = {}, done: () => an fetchRelatedRelationships(dispatch, response.items); done(); }).catch(error => { - console.log(error); dispatch(expandNotificationsFail(error, isLoadingMore)); done(); }); diff --git a/src/actions/polls.ts b/src/actions/polls.ts index 959a0f317..5f936dfdb 100644 --- a/src/actions/polls.ts +++ b/src/actions/polls.ts @@ -28,10 +28,9 @@ const fetchPoll = (pollId: string) => dispatch(fetchPollRequest()); return getClient(getState()).polls.getPoll(pollId).then((data) => { - dispatch(importFetchedPoll(data)); - dispatch(fetchPollSuccess(data)); - }) - .catch(err => dispatch(fetchPollFail(err))); + dispatch(importFetchedPoll(data)); + dispatch(fetchPollSuccess(data)); + }).catch(err => dispatch(fetchPollFail(err))); }; const voteRequest = () => ({ diff --git a/src/actions/push-subscriptions.ts b/src/actions/push-subscriptions.ts index a3726adb0..6162726f1 100644 --- a/src/actions/push-subscriptions.ts +++ b/src/actions/push-subscriptions.ts @@ -23,11 +23,11 @@ const createPushSubscription = (params: CreatePushNotificationsSubscriptionParam (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: PUSH_SUBSCRIPTION_CREATE_REQUEST, params }); return getClient(getState).pushNotifications.createSubscription(params) - .then((subscription) => - dispatch({ type: PUSH_SUBSCRIPTION_CREATE_SUCCESS, params, subscription }), - ).catch(error => - dispatch({ type: PUSH_SUBSCRIPTION_CREATE_FAIL, params, error }), - ); + .then((subscription) => + dispatch({ type: PUSH_SUBSCRIPTION_CREATE_SUCCESS, params, subscription }), + ).catch(error => + dispatch({ type: PUSH_SUBSCRIPTION_CREATE_FAIL, params, error }), + ); }; const fetchPushSubscription = () => diff --git a/src/actions/reports.ts b/src/actions/reports.ts index 7639e7966..511924f26 100644 --- a/src/actions/reports.ts +++ b/src/actions/reports.ts @@ -67,7 +67,7 @@ const submitReport = () => rule_ids: reports.new.rule_ids.toArray(), comment: reports.new.comment, forward: reports.new.forward, - }) + }); }; const submitReportRequest = () => ({ diff --git a/src/actions/search.ts b/src/actions/search.ts index 0a39c4443..f9a924bfb 100644 --- a/src/actions/search.ts +++ b/src/actions/search.ts @@ -122,7 +122,7 @@ const expandSearch = (type: SearchFilter) => (dispatch: AppDispatch, getState: ( dispatch(expandSearchRequest(type)); - let params: Record = { + const params: Record = { type, offset, }; diff --git a/src/api/hooks/accounts/useAccountList.ts b/src/api/hooks/accounts/useAccountList.ts index 0cdfbe759..4fd4e35b9 100644 --- a/src/api/hooks/accounts/useAccountList.ts +++ b/src/api/hooks/accounts/useAccountList.ts @@ -46,7 +46,7 @@ const useFollowing = (accountId: string | undefined) => { return useAccountList( [accountId!, 'following'], - () => client.accounts.getAccountFollowing(accountId), + () => client.accounts.getAccountFollowing(accountId!), { enabled: !!accountId }, ); }; @@ -56,7 +56,7 @@ const useFollowers = (accountId: string | undefined) => { return useAccountList( [accountId!, 'followers'], - () => client.accounts.getAccountFollowers(accountId), + () => client.accounts.getAccountFollowers(accountId!), { enabled: !!accountId }, ); }; diff --git a/src/api/hooks/accounts/useRelationship.ts b/src/api/hooks/accounts/useRelationship.ts index 3464600a6..c470f2f28 100644 --- a/src/api/hooks/accounts/useRelationship.ts +++ b/src/api/hooks/accounts/useRelationship.ts @@ -15,7 +15,7 @@ const useRelationship = (accountId: string | undefined, opts: UseRelationshipOpt const { entity: relationship, ...result } = useEntity( [Entities.RELATIONSHIPS, accountId!], - () => client.accounts.getRelationships([accountId]), + () => client.accounts.getRelationships([accountId!]), { enabled: enabled && !!accountId, schema: z.array(relationshipSchema).nonempty().transform(arr => arr[0]), diff --git a/src/api/hooks/admin/useAnnouncements.ts b/src/api/hooks/admin/useAnnouncements.ts index 543575313..4d535c00c 100644 --- a/src/api/hooks/admin/useAnnouncements.ts +++ b/src/api/hooks/admin/useAnnouncements.ts @@ -1,10 +1,10 @@ import { useMutation, useQuery } from '@tanstack/react-query'; +import { useClient } from 'soapbox/hooks'; import { queryClient } from 'soapbox/queries/client'; import { adminAnnouncementSchema, type AdminAnnouncement } from 'soapbox/schemas'; import { useAnnouncements as useUserAnnouncements } from '../announcements'; -import { useClient } from 'soapbox/hooks'; interface CreateAnnouncementParams { content: string; diff --git a/src/api/hooks/admin/useDomains.ts b/src/api/hooks/admin/useDomains.ts index ce9aa23ca..7d2ab7727 100644 --- a/src/api/hooks/admin/useDomains.ts +++ b/src/api/hooks/admin/useDomains.ts @@ -1,6 +1,6 @@ import { useMutation, useQuery } from '@tanstack/react-query'; -import { useClient } from 'soapbox/hooks'; +import { useClient } from 'soapbox/hooks'; import { queryClient } from 'soapbox/queries/client'; import { domainSchema, type Domain } from 'soapbox/schemas'; diff --git a/src/api/hooks/admin/useModerationLog.ts b/src/api/hooks/admin/useModerationLog.ts index efd2f5e2b..308425895 100644 --- a/src/api/hooks/admin/useModerationLog.ts +++ b/src/api/hooks/admin/useModerationLog.ts @@ -1,6 +1,6 @@ import { useInfiniteQuery } from '@tanstack/react-query'; -import { useClient } from 'soapbox/hooks'; +import { useClient } from 'soapbox/hooks'; import { moderationLogEntrySchema, type ModerationLogEntry } from 'soapbox/schemas'; interface ModerationLogResult { diff --git a/src/api/hooks/groups/useBlockGroupMember.ts b/src/api/hooks/groups/useBlockGroupMember.ts index b9d30d990..0372b0dec 100644 --- a/src/api/hooks/groups/useBlockGroupMember.ts +++ b/src/api/hooks/groups/useBlockGroupMember.ts @@ -1,12 +1,15 @@ import { Entities } from 'soapbox/entity-store/entities'; -import { useEntityActions } from 'soapbox/entity-store/hooks'; +import { useCreateEntity } from 'soapbox/entity-store/hooks'; +import { useClient } from 'soapbox/hooks'; -import type { Account, Group, GroupMember } from 'soapbox/schemas'; +import type { Account, Group } from 'soapbox/schemas'; const useBlockGroupMember = (group: Group, account: Account) => { - const { createEntity } = useEntityActions( + const client = useClient(); + + const { createEntity } = useCreateEntity( [Entities.GROUP_MEMBERSHIPS, account.id], - { post: `/api/v1/groups/${group?.id}/blocks` }, + (accountIds: string[]) => client.experimental.groups.blockGroupUsers(group.id, accountIds), ); return createEntity; diff --git a/src/api/hooks/groups/useCreateGroup.ts b/src/api/hooks/groups/useCreateGroup.ts index 9e9a0c0fd..2217ec800 100644 --- a/src/api/hooks/groups/useCreateGroup.ts +++ b/src/api/hooks/groups/useCreateGroup.ts @@ -1,5 +1,3 @@ -import { serialize } from 'object-to-formdata'; - import { Entities } from 'soapbox/entity-store/entities'; import { useCreateEntity } from 'soapbox/entity-store/hooks'; import { useClient } from 'soapbox/hooks'; diff --git a/src/api/hooks/groups/useDeleteGroup.ts b/src/api/hooks/groups/useDeleteGroup.ts index 9e58250e5..593b67d05 100644 --- a/src/api/hooks/groups/useDeleteGroup.ts +++ b/src/api/hooks/groups/useDeleteGroup.ts @@ -1,12 +1,13 @@ import { Entities } from 'soapbox/entity-store/entities'; -import { useEntityActions } from 'soapbox/entity-store/hooks'; - -import type { Group } from 'soapbox/schemas'; +import { useDeleteEntity } from 'soapbox/entity-store/hooks'; +import { useClient } from 'soapbox/hooks'; const useDeleteGroup = () => { - const { deleteEntity, isSubmitting } = useEntityActions( - [Entities.GROUPS], - { delete: '/api/v1/groups/:id' }, + const client = useClient(); + + const { deleteEntity, isSubmitting } = useDeleteEntity( + Entities.GROUPS, + (groupId: string) => client.experimental.groups.deleteGroup(groupId), ); return { diff --git a/src/api/hooks/groups/useDemoteGroupMember.ts b/src/api/hooks/groups/useDemoteGroupMember.ts index 6ce4a55f7..bdf1976ff 100644 --- a/src/api/hooks/groups/useDemoteGroupMember.ts +++ b/src/api/hooks/groups/useDemoteGroupMember.ts @@ -1,15 +1,19 @@ import { z } from 'zod'; import { Entities } from 'soapbox/entity-store/entities'; -import { useEntityActions } from 'soapbox/entity-store/hooks'; +import { useCreateEntity } from 'soapbox/entity-store/hooks'; +import { useClient } from 'soapbox/hooks'; import { groupMemberSchema } from 'soapbox/schemas'; +import type { GroupRole } from 'pl-api'; import type { Group, GroupMember } from 'soapbox/schemas'; const useDemoteGroupMember = (group: Group, groupMember: GroupMember) => { - const { createEntity } = useEntityActions( + const client = useClient(); + + const { createEntity } = useCreateEntity( [Entities.GROUP_MEMBERSHIPS, groupMember.id], - { post: `/api/v1/groups/${group.id}/demote` }, + ({ account_ids, role }: { account_ids: string[]; role: GroupRole }) => client.experimental.groups.demoteGroupUsers(group.id, account_ids, role), { schema: z.array(groupMemberSchema).transform((arr) => arr[0]) }, ); diff --git a/src/api/hooks/groups/useGroupRelationship.ts b/src/api/hooks/groups/useGroupRelationship.ts index 28771a0da..666197c56 100644 --- a/src/api/hooks/groups/useGroupRelationship.ts +++ b/src/api/hooks/groups/useGroupRelationship.ts @@ -10,7 +10,7 @@ const useGroupRelationship = (groupId: string | undefined) => { const { entity: groupRelationship, ...result } = useEntity( [Entities.GROUP_RELATIONSHIPS, groupId!], - () => client.experimental.groups.getGroupRelationships([groupId]), + () => client.experimental.groups.getGroupRelationships([groupId!]), { enabled: !!groupId, schema: z.array(groupRelationshipSchema).nonempty().transform(arr => arr[0]), diff --git a/src/api/hooks/groups/useJoinGroup.ts b/src/api/hooks/groups/useJoinGroup.ts index de635397b..6e31c4433 100644 --- a/src/api/hooks/groups/useJoinGroup.ts +++ b/src/api/hooks/groups/useJoinGroup.ts @@ -1,18 +1,18 @@ import { Entities } from 'soapbox/entity-store/entities'; -import { useEntityActions } from 'soapbox/entity-store/hooks'; -import { groupRelationshipSchema } from 'soapbox/schemas'; +import { useCreateEntity } from 'soapbox/entity-store/hooks'; +import { useClient } from 'soapbox/hooks'; import { useGroups } from './useGroups'; -import type { Group, GroupRelationship } from 'soapbox/schemas'; +import type { Group } from 'soapbox/schemas'; const useJoinGroup = (group: Group) => { + const client = useClient(); const { invalidate } = useGroups(); - const { createEntity, isSubmitting } = useEntityActions( + const { createEntity, isSubmitting } = useCreateEntity( [Entities.GROUP_RELATIONSHIPS, group.id], - { post: `/api/v1/groups/${group.id}/join` }, - { schema: groupRelationshipSchema }, + () => client.experimental.groups.joinGroup(group.id), ); return { diff --git a/src/api/hooks/groups/useLeaveGroup.ts b/src/api/hooks/groups/useLeaveGroup.ts index 5253da306..26bca3849 100644 --- a/src/api/hooks/groups/useLeaveGroup.ts +++ b/src/api/hooks/groups/useLeaveGroup.ts @@ -1,18 +1,18 @@ import { Entities } from 'soapbox/entity-store/entities'; -import { useEntityActions } from 'soapbox/entity-store/hooks'; -import { groupRelationshipSchema } from 'soapbox/schemas'; +import { useCreateEntity } from 'soapbox/entity-store/hooks'; +import { useClient } from 'soapbox/hooks'; import { useGroups } from './useGroups'; -import type { Group, GroupRelationship } from 'soapbox/schemas'; +import type { Group } from 'soapbox/schemas'; const useLeaveGroup = (group: Group) => { + const client = useClient(); const { invalidate } = useGroups(); - const { createEntity, isSubmitting } = useEntityActions( + const { createEntity, isSubmitting } = useCreateEntity( [Entities.GROUP_RELATIONSHIPS, group.id], - { post: `/api/v1/groups/${group.id}/leave` }, - { schema: groupRelationshipSchema }, + () => client.experimental.groups.leaveGroup(group.id), ); return { diff --git a/src/api/hooks/groups/usePromoteGroupMember.ts b/src/api/hooks/groups/usePromoteGroupMember.ts index 124df8aee..8c057eda3 100644 --- a/src/api/hooks/groups/usePromoteGroupMember.ts +++ b/src/api/hooks/groups/usePromoteGroupMember.ts @@ -1,15 +1,19 @@ import { z } from 'zod'; import { Entities } from 'soapbox/entity-store/entities'; -import { useEntityActions } from 'soapbox/entity-store/hooks'; +import { useCreateEntity } from 'soapbox/entity-store/hooks'; +import { useClient } from 'soapbox/hooks'; import { groupMemberSchema } from 'soapbox/schemas'; +import type { GroupRole } from 'pl-api'; import type { Group, GroupMember } from 'soapbox/schemas'; const usePromoteGroupMember = (group: Group, groupMember: GroupMember) => { - const { createEntity } = useEntityActions( - [Entities.GROUP_MEMBERSHIPS, groupMember.account.id], - { post: `/api/v1/groups/${group.id}/promote` }, + const client = useClient(); + + const { createEntity } = useCreateEntity( + [Entities.GROUP_MEMBERSHIPS, groupMember.id], + ({ account_ids, role }: { account_ids: string[]; role: GroupRole }) => client.experimental.groups.promoteGroupUsers(group.id, account_ids, role), { schema: z.array(groupMemberSchema).transform((arr) => arr[0]) }, ); diff --git a/src/api/hooks/statuses/useBookmarkFolders.ts b/src/api/hooks/statuses/useBookmarkFolders.ts index 816353cdb..07d398b97 100644 --- a/src/api/hooks/statuses/useBookmarkFolders.ts +++ b/src/api/hooks/statuses/useBookmarkFolders.ts @@ -1,6 +1,6 @@ -import { useClient } from 'soapbox/hooks'; import { Entities } from 'soapbox/entity-store/entities'; import { useEntities } from 'soapbox/entity-store/hooks'; +import { useClient } from 'soapbox/hooks'; import { useFeatures } from 'soapbox/hooks/useFeatures'; import { bookmarkFolderSchema, type BookmarkFolder } from 'soapbox/schemas/bookmark-folder'; diff --git a/src/components/status-action-bar.tsx b/src/components/status-action-bar.tsx index df88f76a4..19d11a752 100644 --- a/src/components/status-action-bar.tsx +++ b/src/components/status-action-bar.tsx @@ -360,7 +360,7 @@ const StatusActionBar: React.FC = ({ message: intl.formatMessage(messages.groupBlockFromGroupMessage, { name: status.account.username }), confirm: intl.formatMessage(messages.groupBlockConfirm), onConfirm: () => { - blockGroupMember({ account_ids: [status.account.id] }, { + blockGroupMember([status.account.id], { onSuccess() { toast.success(intl.formatMessage(messages.blocked, { name: account?.acct })); }, diff --git a/src/entity-store/hooks/index.ts b/src/entity-store/hooks/index.ts index 52a5fc499..f0e73473b 100644 --- a/src/entity-store/hooks/index.ts +++ b/src/entity-store/hooks/index.ts @@ -1,6 +1,5 @@ export { useEntities } from './useEntities'; export { useEntity } from './useEntity'; -export { useEntityActions } from './useEntityActions'; export { useEntityLookup } from './useEntityLookup'; export { useCreateEntity } from './useCreateEntity'; export { useDeleteEntity } from './useDeleteEntity'; diff --git a/src/entity-store/hooks/types.ts b/src/entity-store/hooks/types.ts index ae48e6660..a951b0b7a 100644 --- a/src/entity-store/hooks/types.ts +++ b/src/entity-store/hooks/types.ts @@ -1,5 +1,4 @@ import type { Entity } from '../types'; -import type { PlApiResponse } from 'pl-api'; import type z from 'zod'; type EntitySchema = z.ZodType; @@ -35,7 +34,7 @@ interface EntityCallbacks { * Passed into hooks to make requests. * Must return a response. */ -type EntityFn = (value: T) => Promise +type EntityFn = (value: T) => Promise; export type { EntitySchema, diff --git a/src/entity-store/hooks/useEntities.ts b/src/entity-store/hooks/useEntities.ts index 4e2aac28e..2d982d0de 100644 --- a/src/entity-store/hooks/useEntities.ts +++ b/src/entity-store/hooks/useEntities.ts @@ -1,7 +1,6 @@ import { useEffect } from 'react'; import z from 'zod'; -import { useClient } from 'soapbox/hooks'; import { useAppDispatch } from 'soapbox/hooks/useAppDispatch'; import { useAppSelector } from 'soapbox/hooks/useAppSelector'; import { useGetState } from 'soapbox/hooks/useGetState'; @@ -38,7 +37,6 @@ const useEntities = ( /** Additional options for the hook. */ opts: UseEntitiesOpts = {}, ) => { - const client = useClient(); const dispatch = useAppDispatch(); const getState = useGetState(); diff --git a/src/entity-store/hooks/useEntityActions.ts b/src/entity-store/hooks/useEntityActions.ts deleted file mode 100644 index d6d537881..000000000 --- a/src/entity-store/hooks/useEntityActions.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { useClient } from 'soapbox/hooks'; - -import { useCreateEntity } from './useCreateEntity'; -import { useDeleteEntity } from './useDeleteEntity'; -import { parseEntitiesPath } from './utils'; - -import type { EntitySchema, ExpandedEntitiesPath } from './types'; -import type { Entity } from '../types'; - -interface UseEntityActionsOpts { - schema?: EntitySchema; -} - -interface EntityActionEndpoints { - delete?: string; - patch?: string; - post?: string; -} - -const useEntityActions = ( - expandedPath: ExpandedEntitiesPath, - endpoints: EntityActionEndpoints, - opts: UseEntityActionsOpts = {}, -) => { - const client = useClient(); - const { entityType, path } = parseEntitiesPath(expandedPath); - - const { deleteEntity, isSubmitting: deleteSubmitting } = - useDeleteEntity(entityType, (entityId) => client.request(endpoints.delete!.replace(/:id/g, entityId), { method: 'DELETE' })); - - const { createEntity, isSubmitting: createSubmitting } = - useCreateEntity(path, (data) => client.request(endpoints.post!, { - method: 'POST', body: data, - }), opts); - - const { createEntity: updateEntity, isSubmitting: updateSubmitting } = - useCreateEntity(path, (data) => client.request(endpoints.patch!, { - method: 'PATCH', body: data, - }), opts); - - return { - createEntity, - deleteEntity, - updateEntity, - isSubmitting: createSubmitting || deleteSubmitting || updateSubmitting, - }; -}; - -export { useEntityActions }; \ No newline at end of file diff --git a/src/features/admin/components/registration-mode-picker.tsx b/src/features/admin/components/registration-mode-picker.tsx index 9111d5283..a44ca2325 100644 --- a/src/features/admin/components/registration-mode-picker.tsx +++ b/src/features/admin/components/registration-mode-picker.tsx @@ -1,10 +1,10 @@ +import { Instance } from 'pl-api'; import React from 'react'; import { useIntl, defineMessages, FormattedMessage } from 'react-intl'; import { updateConfig } from 'soapbox/actions/admin'; import { RadioGroup, RadioItem } from 'soapbox/components/radio'; import { useAppDispatch, useInstance } from 'soapbox/hooks'; -import { Instance } from 'pl-api'; import toast from 'soapbox/toast'; type RegistrationMode = 'open' | 'approval' | 'closed'; diff --git a/src/features/compose/components/privacy-dropdown.tsx b/src/features/compose/components/privacy-dropdown.tsx index d83ac24be..1b544b6e5 100644 --- a/src/features/compose/components/privacy-dropdown.tsx +++ b/src/features/compose/components/privacy-dropdown.tsx @@ -10,9 +10,8 @@ import { changeComposeFederated, changeComposeVisibility } from 'soapbox/actions import { closeModal, openModal } from 'soapbox/actions/modals'; import Icon from 'soapbox/components/icon'; import { Button, Toggle } from 'soapbox/components/ui'; -import { useAppDispatch, useCompose, useFeatures, useInstance } from 'soapbox/hooks'; +import { useAppDispatch, useCompose, useFeatures } from 'soapbox/hooks'; import { userTouching } from 'soapbox/is-mobile'; -import { GOTOSOCIAL, parseVersion, PLEROMA } from 'soapbox/utils/features'; import Motion from '../../ui/util/optional-motion'; @@ -226,11 +225,8 @@ const PrivacyDropdown: React.FC = ({ const intl = useIntl(); const node = useRef(null); const activeElement = useRef(null); - const instance = useInstance(); const features = useFeatures(); - const v = parseVersion(instance.version); - const compose = useCompose(composeId); const value = compose.privacy; @@ -243,7 +239,7 @@ const PrivacyDropdown: React.FC = ({ { icon: require('@tabler/icons/outline/world.svg'), value: 'public', text: intl.formatMessage(messages.public_short), meta: intl.formatMessage(messages.public_long) }, { icon: require('@tabler/icons/outline/lock-open.svg'), value: 'unlisted', text: intl.formatMessage(messages.unlisted_short), meta: intl.formatMessage(messages.unlisted_long) }, { icon: require('@tabler/icons/outline/lock.svg'), value: 'private', text: intl.formatMessage(messages.private_short), meta: intl.formatMessage(messages.private_long) }, - features.mutualsOnlyStatuses ? { icon: require('@tabler/icons/outline/users-group.svg'), value: 'mutuals_only', text: intl.formatMessage(messages.mutuals_only_short), meta: intl.formatMessage(messages.mutuals_only_long) } : undefined, + features.visibilityMutualsOnly ? { icon: require('@tabler/icons/outline/users-group.svg'), value: 'mutuals_only', text: intl.formatMessage(messages.mutuals_only_short), meta: intl.formatMessage(messages.mutuals_only_long) } : undefined, { icon: require('@tabler/icons/outline/mail.svg'), value: 'direct', text: intl.formatMessage(messages.direct_short), meta: intl.formatMessage(messages.direct_long) }, features.visibilityLocalOnly ? { icon: require('@tabler/icons/outline/affiliate.svg'), value: 'local', text: intl.formatMessage(messages.local_short), meta: intl.formatMessage(messages.local_long) } : undefined, ].filter((option): option is Option => !!option); diff --git a/src/features/edit-profile/index.tsx b/src/features/edit-profile/index.tsx index 7d1c34a05..f5b4a9cee 100644 --- a/src/features/edit-profile/index.tsx +++ b/src/features/edit-profile/index.tsx @@ -216,7 +216,7 @@ const EditProfile: React.FC = () => { if (header.file !== undefined) params.header = header.file || ''; if (avatar.file !== undefined) params.avatar = avatar.file || ''; - promises.push(dispatch(patchMe(params, true))); + promises.push(dispatch(patchMe(params))); if (features.muteStrangers) { promises.push( diff --git a/src/features/filters/edit-filter.tsx b/src/features/filters/edit-filter.tsx index de1b20970..c01948993 100644 --- a/src/features/filters/edit-filter.tsx +++ b/src/features/filters/edit-filter.tsx @@ -12,6 +12,7 @@ import toast from 'soapbox/toast'; import { SelectDropdown } from '../forms'; +import type { FilterContext } from 'pl-api'; import type { StreamfieldComponent } from 'soapbox/components/ui/streamfield/streamfield'; interface IFilterField { @@ -116,7 +117,7 @@ const EditFilter: React.FC = ({ params }) => { const handleAddNew: React.FormEventHandler = e => { e.preventDefault(); - const context: Array = []; + const context: Array = []; if (homeTimeline) { context.push('home'); diff --git a/src/features/group/components/group-member-list-item.tsx b/src/features/group/components/group-member-list-item.tsx index 1a51aad4d..c933665bf 100644 --- a/src/features/group/components/group-member-list-item.tsx +++ b/src/features/group/components/group-member-list-item.tsx @@ -80,7 +80,7 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => { message: intl.formatMessage(messages.blockFromGroupMessage, { name: account?.username }), confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => { - blockGroupMember({ account_ids: [member.account.id] }, { + blockGroupMember([member.account.id], { onSuccess() { dispatch(deleteEntities([member.id], Entities.GROUP_MEMBERSHIPS)); toast.success(intl.formatMessage(messages.blocked, { name: account?.acct })); @@ -97,7 +97,7 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => { confirm: intl.formatMessage(messages.promoteConfirm), confirmationTheme: 'primary', onConfirm: () => { - promoteGroupMember({ role: GroupRoles.ADMIN, account_ids: [account?.id] }, { + promoteGroupMember({ role: GroupRoles.ADMIN, account_ids: [member.account.id] }, { onSuccess() { toast.success( intl.formatMessage(messages.promotedToAdmin, { name: account?.acct }), @@ -109,7 +109,7 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => { }; const handleUserAssignment = () => { - demoteGroupMember({ role: GroupRoles.USER, account_ids: [account?.id] }, { + demoteGroupMember({ role: GroupRoles.USER, account_ids: [member.account.id] }, { onSuccess() { toast.success(intl.formatMessage(messages.demotedToUser, { name: account?.acct })); }, diff --git a/src/features/onboarding/steps/avatar-selection-step.tsx b/src/features/onboarding/steps/avatar-selection-step.tsx index 5dd2cd98c..23994ab7b 100644 --- a/src/features/onboarding/steps/avatar-selection-step.tsx +++ b/src/features/onboarding/steps/avatar-selection-step.tsx @@ -46,7 +46,7 @@ const AvatarSelectionStep = ({ onNext }: { onNext: () => void }) => { formData.append('avatar', rawFile); const credentials = dispatch(patchMe(formData)); - Promise.all([credentials]).then(() => { + return Promise.all([credentials]).then(() => { setDisabled(false); setSubmitting(false); onNext(); diff --git a/src/features/settings/index.tsx b/src/features/settings/index.tsx index 71b3b4c87..243291838 100644 --- a/src/features/settings/index.tsx +++ b/src/features/settings/index.tsx @@ -148,13 +148,13 @@ const Settings = () => { )} - {features.backups && ( + {features.accountBackups && ( )} {features.federating && (features.accountMoving ? ( - ) : features.accountAliases && ( + ) : features.manageAccountAliases && ( ))} diff --git a/src/features/soapbox-config/index.tsx b/src/features/soapbox-config/index.tsx index 5e9bc041e..9f7b8544b 100644 --- a/src/features/soapbox-config/index.tsx +++ b/src/features/soapbox-config/index.tsx @@ -115,11 +115,10 @@ const SoapboxConfig: React.FC = () => { }; const handleFileChange = (path: ConfigPath): React.ChangeEventHandler => e => { - const data = new FormData(); const file = e.target.files?.item(0); if (file) { - dispatch(uploadMedia({ file})).then((data: any) => { + dispatch(uploadMedia({ file })).then((data: any) => { handleChange(path, () => data.url)(e); }).catch(console.error); } diff --git a/src/features/ui/components/modals/account-moderation-modal/account-moderation-modal.tsx b/src/features/ui/components/modals/account-moderation-modal/account-moderation-modal.tsx index e1a6801ec..c16c0458a 100644 --- a/src/features/ui/components/modals/account-moderation-modal/account-moderation-modal.tsx +++ b/src/features/ui/components/modals/account-moderation-modal/account-moderation-modal.tsx @@ -1,3 +1,4 @@ +import { PLEROMA } from 'pl-api'; import React, { ChangeEventHandler, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -10,9 +11,10 @@ import List, { ListItem } from 'soapbox/components/list'; import MissingIndicator from 'soapbox/components/missing-indicator'; import OutlineBox from 'soapbox/components/outline-box'; import { Button, Text, HStack, Modal, Stack, Toggle } from 'soapbox/components/ui'; -import { useAppDispatch, useFeatures, useOwnAccount } from 'soapbox/hooks'; +import { useAppDispatch, useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks'; import toast from 'soapbox/toast'; import { getBadges } from 'soapbox/utils/badges'; +import { parseVersion } from 'soapbox/utils/features'; import BadgeInput from './badge-input'; import StaffRolePicker from './staff-role-picker'; @@ -38,7 +40,8 @@ interface IAccountModerationModal { const AccountModerationModal: React.FC = ({ onClose, accountId }) => { const intl = useIntl(); const dispatch = useAppDispatch(); - + + const { software } = useAppSelector((state) => parseVersion(state.instance.version)); const { suggest, unsuggest } = useSuggest(); const { verify, unverify } = useVerify(); const { account: ownAccount } = useOwnAccount(); @@ -170,7 +173,7 @@ const AccountModerationModal: React.FC = ({ onClose, ac /> - {features.adminFE && ( + {software === PLEROMA && (