diff --git a/src/app/hooks/useExploreServers.ts b/src/app/hooks/useExploreServers.ts index a5e293d4..fd9ce757 100644 --- a/src/app/hooks/useExploreServers.ts +++ b/src/app/hooks/useExploreServers.ts @@ -1,3 +1,4 @@ +import { useCallback, useMemo } from 'react'; import { AccountDataEvent } from '../../types/matrix/accountData'; import { useAccountData } from './useAccountData'; import { useMatrixClient } from './useMatrixClient'; @@ -6,33 +7,37 @@ export type InCinnyExploreServersContent = { servers?: string[]; }; -export type ExploreServerListAction = - | { - type: 'APPEND'; - server: string; - } - | { - type: 'DELETE'; - server: string; - }; - -export const useExploreServers = (): [string[], (action: ExploreServerListAction) => void] => { +export const useExploreServers = (): [ + string[], + (server: string) => Promise, + (server: string) => Promise +] => { const mx = useMatrixClient(); - const userAddedServers = - useAccountData(AccountDataEvent.CinnyExploreServers)?.getContent() - ?.servers ?? []; + const accountData = useAccountData(AccountDataEvent.CinnyExploreServers); + const userAddedServers = useMemo( + () => accountData?.getContent()?.servers ?? [], + [accountData] + ); - const setUserAddedServers = (action: ExploreServerListAction) => { - if (action.type === 'APPEND') { - mx.setAccountData(AccountDataEvent.CinnyExploreServers, { - servers: [...userAddedServers, action.server], - }); - } else if (action.type === 'DELETE') { - mx.setAccountData(AccountDataEvent.CinnyExploreServers, { - servers: userAddedServers.filter((server) => server !== action.server), - }); - } - }; + const addServer = useCallback( + async (server: string) => { + if (userAddedServers.indexOf(server) === -1) { + await mx.setAccountData(AccountDataEvent.CinnyExploreServers, { + servers: [...userAddedServers, server], + }); + } + }, + [mx, userAddedServers] + ); - return [userAddedServers, setUserAddedServers]; + const removeServer = useCallback( + async (server: string) => { + await mx.setAccountData(AccountDataEvent.CinnyExploreServers, { + servers: userAddedServers.filter((addedServer) => server !== addedServer), + }); + }, + [mx, userAddedServers] + ); + + return [userAddedServers, addServer, removeServer]; }; diff --git a/src/app/pages/client/explore/Explore.tsx b/src/app/pages/client/explore/Explore.tsx index f42c6a6a..7d406a2f 100644 --- a/src/app/pages/client/explore/Explore.tsx +++ b/src/app/pages/client/explore/Explore.tsx @@ -14,6 +14,7 @@ import { Overlay, OverlayBackdrop, OverlayCenter, + Spinner, Text, color, config, @@ -45,7 +46,7 @@ export function AddExploreServerPrompt() { const mx = useMatrixClient(); const navigate = useNavigate(); const [dialog, setDialog] = useState(false); - const [, setExploreServers] = useExploreServers(); + const [, addServer] = useExploreServers(); const serverInputRef = useRef(null); const [exploreState] = useAsyncCallback( @@ -64,9 +65,9 @@ export function AddExploreServerPrompt() { if (!server) return; setDialog(false); - setExploreServers({ type: 'APPEND', server }); + addServer(server); navigate(getExploreServerPath(server)); - }, [navigate, setExploreServers]); + }, [navigate, addServer]); return ( <> @@ -157,7 +158,7 @@ export function AddExploreServerPrompt() { type ExploreServerNavItemProps = { server: string; selected: boolean; - onRemove?: (() => void) | null; + onRemove?: (() => Promise) | null; }; export function ExploreServerNavItem({ server, @@ -167,6 +168,15 @@ export function ExploreServerNavItem({ const [hover, setHover] = useState(false); const { hoverProps } = useHover({ onHoverChange: setHover }); const { focusWithinProps } = useFocusWithin({ onFocusWithinChange: setHover }); + const [removeState, removeCallback] = useAsyncCallback( + useCallback(async () => { + if (onRemove !== null) { + await onRemove(); + } + }, [onRemove]) + ); + const removeInProgress = + removeState.status === AsyncStatus.Loading || removeState.status === AsyncStatus.Success; return ( - {onRemove !== null && hover && ( + {onRemove !== null && (hover || removeInProgress) && ( - - + + {removeInProgress ? ( + + ) : ( + + )} )} @@ -209,7 +230,7 @@ export function Explore() { const userServer = userId ? getMxIdServer(userId) : undefined; const featuredServers = clientConfig.featuredCommunities?.servers?.filter((server) => server !== userServer) ?? []; - const [exploreServers, setExploreServers] = useExploreServers(); + const [exploreServers, , removeServer] = useExploreServers(); const featuredSelected = useExploreFeaturedSelected(); const selectedServer = useExploreServer(); @@ -290,7 +311,7 @@ export function Explore() { key={server} server={server} selected={server === selectedServer} - onRemove={() => setExploreServers({ type: 'DELETE', server })} + onRemove={() => removeServer(server)} /> ))}