From 99e8f6912d40aa4ef6fabae6248847a6d780f476 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Fri, 21 Jul 2023 12:48:47 -0500 Subject: [PATCH] Add useVerify hook --- app/soapbox/actions/admin.ts | 10 --- app/soapbox/api/hooks/admin/useVerify.ts | 76 +++++++++++++++++++ .../account-moderation-modal.tsx | 16 ++-- 3 files changed, 83 insertions(+), 19 deletions(-) create mode 100644 app/soapbox/api/hooks/admin/useVerify.ts diff --git a/app/soapbox/actions/admin.ts b/app/soapbox/actions/admin.ts index a7f708d83..0ab2b827f 100644 --- a/app/soapbox/actions/admin.ts +++ b/app/soapbox/actions/admin.ts @@ -488,14 +488,6 @@ const setBadges = (accountId: string, oldTags: string[], newTags: string[]) => return dispatch(setTags(accountId, oldBadges, newBadges)); }; -const verifyUser = (accountId: string) => - (dispatch: AppDispatch) => - dispatch(tagUsers([accountId], ['verified'])); - -const unverifyUser = (accountId: string) => - (dispatch: AppDispatch) => - dispatch(untagUsers([accountId], ['verified'])); - const addPermission = (accountIds: string[], permissionGroup: string) => (dispatch: AppDispatch, getState: () => RootState) => { const nicknames = nicknamesFromIds(getState, accountIds); @@ -772,8 +764,6 @@ export { untagUsers, setTags, setBadges, - verifyUser, - unverifyUser, addPermission, removePermission, promoteToAdmin, diff --git a/app/soapbox/api/hooks/admin/useVerify.ts b/app/soapbox/api/hooks/admin/useVerify.ts new file mode 100644 index 000000000..adee278b6 --- /dev/null +++ b/app/soapbox/api/hooks/admin/useVerify.ts @@ -0,0 +1,76 @@ +import { Entities } from 'soapbox/entity-store/entities'; +import { useTransaction } from 'soapbox/entity-store/hooks'; +import { EntityCallbacks } from 'soapbox/entity-store/hooks/types'; +import { findEntity } from 'soapbox/entity-store/selectors'; +import { useApi, useGetState } from 'soapbox/hooks'; + +import type { Account } from 'soapbox/schemas'; +import type { RootState } from 'soapbox/store'; + +function useVerify() { + const api = useApi(); + const getState = useGetState(); + const { transaction } = useTransaction(); + + function verifyEffect(accts: string[], verified: boolean) { + const ids = selectIdsForAccts(getState(), accts); + + const updater = (account: Account): Account => { + if (account.pleroma) { + const tags = account.pleroma.tags.filter((tag) => tag !== 'verified'); + if (verified) { + tags.push('verified'); + } + account.pleroma.tags = tags; + } + account.verified = verified; + return account; + }; + + transaction({ + Accounts: ids.reduce Account>>( + (result, id) => ({ ...result, [id]: updater }), + {}), + }); + } + + async function verify(accts: string[], callbacks?: EntityCallbacks) { + verifyEffect(accts, true); + try { + await api.put('/api/v1/pleroma/admin/users/tag', { nicknames: accts, tags: ['verified'] }); + callbacks?.onSuccess?.(); + } catch (e) { + callbacks?.onError?.(e); + verifyEffect(accts, false); + } + } + + async function unverify(accts: string[], callbacks?: EntityCallbacks) { + verifyEffect(accts, false); + try { + await api.delete('/api/v1/pleroma/admin/users/tag', { data: { nicknames: accts, tags: ['verified'] } }); + callbacks?.onSuccess?.(); + } catch (e) { + callbacks?.onError?.(e); + verifyEffect(accts, true); + } + } + + return { + verify, + unverify, + }; +} + +function selectIdsForAccts(state: RootState, accts: string[]): string[] { + return accts.map((acct) => { + const account = findEntity( + state, + Entities.ACCOUNTS, + (account) => account.acct === acct, + ); + return account!.id; + }); +} + +export { useVerify }; \ No newline at end of file diff --git a/app/soapbox/features/ui/components/modals/account-moderation-modal/account-moderation-modal.tsx b/app/soapbox/features/ui/components/modals/account-moderation-modal/account-moderation-modal.tsx index 9d837f5cf..6255a11f6 100644 --- a/app/soapbox/features/ui/components/modals/account-moderation-modal/account-moderation-modal.tsx +++ b/app/soapbox/features/ui/components/modals/account-moderation-modal/account-moderation-modal.tsx @@ -1,14 +1,11 @@ import React, { ChangeEventHandler, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; -import { - verifyUser, - unverifyUser, - setBadges as saveBadges, -} from 'soapbox/actions/admin'; +import { setBadges as saveBadges } from 'soapbox/actions/admin'; import { deactivateUserModal, deleteUserModal } from 'soapbox/actions/moderation'; import { useAccount } from 'soapbox/api/hooks'; import { useSuggest } from 'soapbox/api/hooks/admin/useSuggest'; +import { useVerify } from 'soapbox/api/hooks/admin/useVerify'; import Account from 'soapbox/components/account'; import List, { ListItem } from 'soapbox/components/list'; import MissingIndicator from 'soapbox/components/missing-indicator'; @@ -45,6 +42,7 @@ const AccountModerationModal: React.FC = ({ onClose, ac const dispatch = useAppDispatch(); const { suggest, unsuggest } = useSuggest(); + const { verify, unverify } = useVerify(); const { account: ownAccount } = useOwnAccount(); const features = useFeatures(); const { account } = useAccount(accountId); @@ -70,11 +68,11 @@ const AccountModerationModal: React.FC = ({ onClose, ac const { checked } = e.target; const message = checked ? messages.userVerified : messages.userUnverified; - const action = checked ? verifyUser : unverifyUser; + const action = checked ? verify : unverify; - dispatch(action(account.id)) - .then(() => toast.success(intl.formatMessage(message, { acct: account.acct }))) - .catch(() => {}); + action([account.acct], { + onSuccess: () => toast.success(intl.formatMessage(message, { acct: account.acct })), + }); }; const handleSuggestedChange: ChangeEventHandler = (e) => {