Fix Collections editor allowing to add the same account multiple times (#39296)

This commit is contained in:
diondiondion 2026-06-05 11:28:28 +02:00 committed by GitHub
parent 0c78d1fd0f
commit 2d2a7ec8d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 40 additions and 28 deletions

View File

@ -208,6 +208,12 @@ export const CollectionAccounts: React.FC<{
const hasItems = editorItems.length > 0; const hasItems = editorItems.length > 0;
const hasMaxItems = editorItems.length === MAX_COLLECTION_ACCOUNT_COUNT; const hasMaxItems = editorItems.length === MAX_COLLECTION_ACCOUNT_COUNT;
const wasAccountAdded = useCallback(
(account: ApiMutedAccountJSON) =>
!!editorItems.find((item) => item.account_id === account.id),
[editorItems],
);
const { const {
accounts: suggestedAccounts, accounts: suggestedAccounts,
isLoading: isLoadingSuggestions, isLoading: isLoadingSuggestions,
@ -217,8 +223,7 @@ export const CollectionAccounts: React.FC<{
withRelationships: true, withRelationships: true,
withDefaultFollows: searchValue === '', withDefaultFollows: searchValue === '',
// Don't suggest accounts that were already added // Don't suggest accounts that were already added
filterResults: (account) => filterResults: (account) => !wasAccountAdded(account),
!editorItems.find((item) => item.account_id === account.id),
}); });
const relationships = useAppSelector((state) => state.relationships); const relationships = useAppSelector((state) => state.relationships);
@ -256,23 +261,25 @@ export const CollectionAccounts: React.FC<{
const addAccountItem = useCallback( const addAccountItem = useCallback(
(item: ApiMutedAccountJSON) => { (item: ApiMutedAccountJSON) => {
dispatch( if (!wasAccountAdded(item)) {
updateCollectionEditorField({ dispatch(
field: 'items', updateCollectionEditorField({
value: [ field: 'items',
...editorItems, value: [
{ ...editorItems,
account_id: item.id, {
state: account_id: item.id,
item.feature_approval.current_user === 'manual' state:
? 'pending' item.feature_approval.current_user === 'manual'
: 'accepted', ? 'pending'
}, : 'accepted',
], },
}), ],
); }),
);
}
}, },
[editorItems, dispatch], [editorItems, wasAccountAdded, dispatch],
); );
const instantRemoveAccountItem = useCallback( const instantRemoveAccountItem = useCallback(
@ -299,13 +306,13 @@ export const CollectionAccounts: React.FC<{
const instantAddAccountItem = useCallback( const instantAddAccountItem = useCallback(
(item: ApiMutedAccountJSON) => { (item: ApiMutedAccountJSON) => {
if (id) { if (id && !wasAccountAdded(item)) {
void dispatch( void dispatch(
addCollectionItem({ collectionId: id, accountId: item.id }), addCollectionItem({ collectionId: id, accountId: item.id }),
); );
} }
}, },
[dispatch, id], [dispatch, id, wasAccountAdded],
); );
const handleRemoveAccountItem = useCallback( const handleRemoveAccountItem = useCallback(

View File

@ -51,7 +51,7 @@ export function useSearchAccounts({
searchRequestRef.current = new AbortController(); searchRequestRef.current = new AbortController();
try { try {
const data = await apiRequest<ApiAccountJSON[]>( const accounts = await apiRequest<ApiAccountJSON[]>(
'GET', 'GET',
'v1/accounts/search', 'v1/accounts/search',
{ {
@ -62,7 +62,6 @@ export function useSearchAccounts({
}, },
}, },
); );
const accounts = filterResults ? data.filter(filterResults) : data;
const accountIds = accounts.map((a) => a.id); const accountIds = accounts.map((a) => a.id);
dispatch(importFetchedAccounts(accounts)); dispatch(importFetchedAccounts(accounts));
if (withRelationships) { if (withRelationships) {
@ -95,6 +94,7 @@ export function useSearchAccounts({
const [defaultAccounts, setDefaultAccounts] = useState< const [defaultAccounts, setDefaultAccounts] = useState<
ApiAccountJSON[] | null ApiAccountJSON[] | null
>(null); >(null);
useEffect(() => { useEffect(() => {
if ( if (
!currentUserId || !currentUserId ||
@ -108,12 +108,11 @@ export function useSearchAccounts({
async function doRequest() { async function doRequest() {
setLoadingState('loading'); setLoadingState('loading');
try { try {
const data = await apiRequest<ApiAccountJSON[]>( const accounts = await apiRequest<ApiAccountJSON[]>(
'GET', 'GET',
`v1/accounts/${currentUserId}/following`, `v1/accounts/${currentUserId}/following`,
{ params: { limit: 40 } }, { params: { limit: 40 } },
); );
const accounts = filterResults ? data.filter(filterResults) : data;
const accountIds = accounts.map((a) => a.id); const accountIds = accounts.map((a) => a.id);
dispatch(importFetchedAccounts(accounts)); dispatch(importFetchedAccounts(accounts));
if (withRelationships) { if (withRelationships) {
@ -137,13 +136,19 @@ export function useSearchAccounts({
withDefaultFollows, withDefaultFollows,
]); ]);
const accountsToReturn =
accounts.length === 0 && withDefaultFollows
? (defaultAccounts ?? [])
: accounts;
const filteredAccounts = filterResults
? accountsToReturn.filter(filterResults)
: accountsToReturn;
return { return {
searchAccounts: startSearch, searchAccounts: startSearch,
resetAccounts, resetAccounts,
accounts: accounts: filteredAccounts,
accounts.length === 0 && withDefaultFollows
? (defaultAccounts ?? [])
: accounts,
isLoading: loadingState === 'loading', isLoading: loadingState === 'loading',
isError: loadingState === 'error', isError: loadingState === 'error',
}; };