[Glitch] Move account search into hook
Port 7e27ba990e905fd07b1469edeeda8eb0217b3b93 to glitch-soc Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
parent
9eb718836e
commit
8caaffe435
@ -1,12 +1,10 @@
|
|||||||
import { useCallback, useState, useEffect, useRef } from 'react';
|
import { useCallback, useState, useEffect } from 'react';
|
||||||
|
|
||||||
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import { useParams, Link } from 'react-router-dom';
|
import { useParams, Link } from 'react-router-dom';
|
||||||
|
|
||||||
import { useDebouncedCallback } from 'use-debounce';
|
|
||||||
|
|
||||||
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
|
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
|
||||||
import SquigglyArrow from '@/svg-icons/squiggly_arrow.svg?react';
|
import SquigglyArrow from '@/svg-icons/squiggly_arrow.svg?react';
|
||||||
import { fetchRelationships } from 'flavours/glitch/actions/accounts';
|
import { fetchRelationships } from 'flavours/glitch/actions/accounts';
|
||||||
@ -14,14 +12,12 @@ import { showAlertForError } from 'flavours/glitch/actions/alerts';
|
|||||||
import { importFetchedAccounts } from 'flavours/glitch/actions/importer';
|
import { importFetchedAccounts } from 'flavours/glitch/actions/importer';
|
||||||
import { fetchList } from 'flavours/glitch/actions/lists';
|
import { fetchList } from 'flavours/glitch/actions/lists';
|
||||||
import { openModal } from 'flavours/glitch/actions/modal';
|
import { openModal } from 'flavours/glitch/actions/modal';
|
||||||
import { apiRequest } from 'flavours/glitch/api';
|
|
||||||
import { apiFollowAccount } from 'flavours/glitch/api/accounts';
|
import { apiFollowAccount } from 'flavours/glitch/api/accounts';
|
||||||
import {
|
import {
|
||||||
apiGetAccounts,
|
apiGetAccounts,
|
||||||
apiAddAccountToList,
|
apiAddAccountToList,
|
||||||
apiRemoveAccountFromList,
|
apiRemoveAccountFromList,
|
||||||
} from 'flavours/glitch/api/lists';
|
} from 'flavours/glitch/api/lists';
|
||||||
import type { ApiAccountJSON } from 'flavours/glitch/api_types/accounts';
|
|
||||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||||
import { Button } from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
import { Column } from 'flavours/glitch/components/column';
|
import { Column } from 'flavours/glitch/components/column';
|
||||||
@ -35,6 +31,8 @@ import { VerifiedBadge } from 'flavours/glitch/components/verified_badge';
|
|||||||
import { me } from 'flavours/glitch/initial_state';
|
import { me } from 'flavours/glitch/initial_state';
|
||||||
import { useAppDispatch, useAppSelector } from 'flavours/glitch/store';
|
import { useAppDispatch, useAppSelector } from 'flavours/glitch/store';
|
||||||
|
|
||||||
|
import { useSearchAccounts } from './use_search_accounts';
|
||||||
|
|
||||||
export const messages = defineMessages({
|
export const messages = defineMessages({
|
||||||
manageMembers: {
|
manageMembers: {
|
||||||
id: 'column.list_members',
|
id: 'column.list_members',
|
||||||
@ -163,10 +161,23 @@ const ListMembers: React.FC<{
|
|||||||
|
|
||||||
const [searching, setSearching] = useState(false);
|
const [searching, setSearching] = useState(false);
|
||||||
const [accountIds, setAccountIds] = useState<string[]>([]);
|
const [accountIds, setAccountIds] = useState<string[]>([]);
|
||||||
const [searchAccountIds, setSearchAccountIds] = useState<string[]>([]);
|
|
||||||
const [loading, setLoading] = useState(!!id);
|
const [loading, setLoading] = useState(!!id);
|
||||||
const [mode, setMode] = useState<Mode>('remove');
|
const [mode, setMode] = useState<Mode>('remove');
|
||||||
|
|
||||||
|
const {
|
||||||
|
accountIds: searchAccountIds = [],
|
||||||
|
isLoading: loadingSearchResults,
|
||||||
|
searchAccounts: handleSearch,
|
||||||
|
} = useSearchAccounts({
|
||||||
|
onSettled: (value) => {
|
||||||
|
if (value.trim().length === 0) {
|
||||||
|
setSearching(false);
|
||||||
|
} else {
|
||||||
|
setSearching(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (id) {
|
if (id) {
|
||||||
dispatch(fetchList(id));
|
dispatch(fetchList(id));
|
||||||
@ -206,46 +217,6 @@ const ListMembers: React.FC<{
|
|||||||
[accountIds, setAccountIds],
|
[accountIds, setAccountIds],
|
||||||
);
|
);
|
||||||
|
|
||||||
const searchRequestRef = useRef<AbortController | null>(null);
|
|
||||||
|
|
||||||
const handleSearch = useDebouncedCallback(
|
|
||||||
(value: string) => {
|
|
||||||
if (searchRequestRef.current) {
|
|
||||||
searchRequestRef.current.abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.trim().length === 0) {
|
|
||||||
setSearching(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
searchRequestRef.current = new AbortController();
|
|
||||||
|
|
||||||
void apiRequest<ApiAccountJSON[]>('GET', 'v1/accounts/search', {
|
|
||||||
signal: searchRequestRef.current.signal,
|
|
||||||
params: {
|
|
||||||
q: value,
|
|
||||||
resolve: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((data) => {
|
|
||||||
dispatch(importFetchedAccounts(data));
|
|
||||||
setSearchAccountIds(data.map((a) => a.id));
|
|
||||||
setLoading(false);
|
|
||||||
setSearching(true);
|
|
||||||
return '';
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
setSearching(true);
|
|
||||||
setLoading(false);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
500,
|
|
||||||
{ leading: true, trailing: true },
|
|
||||||
);
|
|
||||||
|
|
||||||
let displayedAccountIds: string[];
|
let displayedAccountIds: string[];
|
||||||
|
|
||||||
if (mode === 'add' && searching) {
|
if (mode === 'add' && searching) {
|
||||||
@ -279,7 +250,7 @@ const ListMembers: React.FC<{
|
|||||||
scrollKey='list_members'
|
scrollKey='list_members'
|
||||||
trackScroll={!multiColumn}
|
trackScroll={!multiColumn}
|
||||||
bindToDocument={!multiColumn}
|
bindToDocument={!multiColumn}
|
||||||
isLoading={loading}
|
isLoading={loading || loadingSearchResults}
|
||||||
showLoading={loading && displayedAccountIds.length === 0}
|
showLoading={loading && displayedAccountIds.length === 0}
|
||||||
hasMore={false}
|
hasMore={false}
|
||||||
footer={
|
footer={
|
||||||
|
|||||||
@ -0,0 +1,67 @@
|
|||||||
|
import { useRef, useState } from 'react';
|
||||||
|
|
||||||
|
import { useDebouncedCallback } from 'use-debounce';
|
||||||
|
|
||||||
|
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,
|
||||||
|
}: {
|
||||||
|
onSettled?: (value: string) => void;
|
||||||
|
} = {}) {
|
||||||
|
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?.('');
|
||||||
|
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) => {
|
||||||
|
dispatch(importFetchedAccounts(data));
|
||||||
|
setAccountIds(data.map((a) => a.id));
|
||||||
|
setLoadingState('idle');
|
||||||
|
onSettled?.(value);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setLoadingState('error');
|
||||||
|
onSettled?.(value);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
500,
|
||||||
|
{ leading: true, trailing: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
searchAccounts,
|
||||||
|
accountIds,
|
||||||
|
isLoading: loadingState === 'loading',
|
||||||
|
isError: loadingState === 'error',
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user