Mastodon/app/javascript/flavours/glitch/hooks/useSearchAccounts.ts
diondiondion 784f0169e2 [Glitch] Implements tag suggestions for collections topic field
Port 8bce0b99d4c426840de7e48165e1b37bbdefa5de to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
2026-03-20 18:15:00 +01:00

83 lines
2.3 KiB
TypeScript

import { useRef, useState } from 'react';
import { useDebouncedCallback } from 'use-debounce';
import { fetchRelationships } from 'flavours/glitch/actions/accounts';
import { importFetchedAccounts } from 'flavours/glitch/actions/importer';
import { apiRequest } from 'flavours/glitch/api';
import type { ApiAccountJSON } from 'flavours/glitch/api_types/accounts';
import { useAppDispatch } from 'flavours/glitch/store';
export function useSearchAccounts({
onSettled,
filterResults,
resetOnInputClear = true,
withRelationships = false,
}: {
onSettled?: (value: string) => void;
filterResults?: (account: ApiAccountJSON) => boolean;
resetOnInputClear?: boolean;
withRelationships?: boolean;
} = {}) {
const dispatch = useAppDispatch();
const [accountIds, setAccountIds] = useState<string[]>([]);
const [loadingState, setLoadingState] = useState<
'idle' | 'loading' | 'error'
>('idle');
const searchRequestRef = useRef<AbortController | null>(null);
const searchAccounts = useDebouncedCallback(
(value: string) => {
if (searchRequestRef.current) {
searchRequestRef.current.abort();
}
if (value.trim().length === 0) {
onSettled?.('');
if (resetOnInputClear) {
setAccountIds([]);
}
return;
}
setLoadingState('loading');
searchRequestRef.current = new AbortController();
void apiRequest<ApiAccountJSON[]>('GET', 'v1/accounts/search', {
signal: searchRequestRef.current.signal,
params: {
q: value,
resolve: true,
},
})
.then((data) => {
const accounts = filterResults ? data.filter(filterResults) : data;
const accountIds = accounts.map((a) => a.id);
dispatch(importFetchedAccounts(accounts));
if (withRelationships) {
dispatch(fetchRelationships(accountIds));
}
setAccountIds(accountIds);
setLoadingState('idle');
onSettled?.(value);
})
.catch(() => {
setLoadingState('error');
onSettled?.(value);
});
},
500,
{ leading: true, trailing: true },
);
return {
searchAccounts,
accountIds,
isLoading: loadingState === 'loading',
isError: loadingState === 'error',
};
}