From 3eea7dd0742e26a9d972ae34c5ea4fcdcdce1648 Mon Sep 17 00:00:00 2001 From: Ginger Date: Wed, 24 Sep 2025 10:14:56 -0400 Subject: [PATCH] Apply requested changes --- src/app/hooks/router/useExploreSelected.ts | 2 +- src/app/hooks/useExploreServers.ts | 17 +- src/app/pages/client/explore/Explore.tsx | 347 +++++++++++---------- 3 files changed, 197 insertions(+), 169 deletions(-) diff --git a/src/app/hooks/router/useExploreSelected.ts b/src/app/hooks/router/useExploreSelected.ts index be7615ca..f0ffdc86 100644 --- a/src/app/hooks/router/useExploreSelected.ts +++ b/src/app/hooks/router/useExploreSelected.ts @@ -11,7 +11,7 @@ export const useExploreSelected = (): boolean => { return !!match; }; -export const useExploreFeaturedRooms = (): boolean => { +export const useExploreFeaturedSelected = (): boolean => { const match = useMatch({ path: getExploreFeaturedPath(), caseSensitive: true, diff --git a/src/app/hooks/useExploreServers.ts b/src/app/hooks/useExploreServers.ts index 9e60eda9..fc07653f 100644 --- a/src/app/hooks/useExploreServers.ts +++ b/src/app/hooks/useExploreServers.ts @@ -7,22 +7,22 @@ export type InCinnyExploreServersContent = { servers?: string[]; }; -export const useExploreServers = ( - exclude?: string[] -): [string[], (server: string) => Promise, (server: string) => Promise] => { +export const useExploreServers = (): [ + string[], + (server: string) => Promise, + (server: string) => Promise +] => { const mx = useMatrixClient(); const accountData = useAccountData(AccountDataEvent.CinnyExplore); const userAddedServers = useMemo( - () => - accountData - ?.getContent() - ?.servers?.filter((server) => !exclude?.includes(server)) ?? [], - [exclude, accountData] + () => accountData?.getContent()?.servers ?? [], + [accountData] ); const addServer = useCallback( async (server: string) => { if (userAddedServers.indexOf(server) === -1) { + // @ts-expect-error Custom account data event await mx.setAccountData(AccountDataEvent.CinnyExplore, { servers: [...userAddedServers, server], }); @@ -33,6 +33,7 @@ export const useExploreServers = ( const removeServer = useCallback( async (server: string) => { + // @ts-expect-error Custom account data event await mx.setAccountData(AccountDataEvent.CinnyExplore, { servers: userAddedServers.filter((addedServer) => server !== addedServer), }); diff --git a/src/app/pages/client/explore/Explore.tsx b/src/app/pages/client/explore/Explore.tsx index bec600eb..f1e8b184 100644 --- a/src/app/pages/client/explore/Explore.tsx +++ b/src/app/pages/client/explore/Explore.tsx @@ -32,7 +32,7 @@ import { } from '../../../components/nav'; import { getExploreFeaturedPath, getExploreServerPath } from '../../pathUtils'; import { - useExploreFeaturedRooms, + useExploreFeaturedSelected, useExploreServer, } from '../../../hooks/router/useExploreSelected'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; @@ -44,21 +44,18 @@ import { stopPropagation } from '../../../utils/keyboard'; import { useExploreServers } from '../../../hooks/useExploreServers'; import { useAlive } from '../../../hooks/useAlive'; import { useClientConfig } from '../../../hooks/useClientConfig'; +import { UseStateProvider } from '../../../components/UseStateProvider'; type AddExploreServerPromptProps = { onSubmit: (server: string, save: boolean) => Promise; - header: ReactNode; - children: ReactNode; - selected?: boolean; + open: boolean; + requestClose: () => void; }; export function AddExploreServerPrompt({ onSubmit, - header, - children, - selected = false, + open, + requestClose, }: AddExploreServerPromptProps) { - const mx = useMatrixClient(); - const [dialog, setDialog] = useState(false); const alive = useAlive(); const serverInputRef = useRef(null); @@ -74,13 +71,12 @@ export function AddExploreServerPrompt({ const server = getInputServer(); if (!server) return; - await mx.publicRooms({ server, limit: 1 }); await onSubmit(server, save); if (alive()) { - setDialog(false); + requestClose(); } }, - [alive, onSubmit, mx] + [onSubmit, alive, requestClose] ); const [viewState, handleView] = useAsyncCallback(() => submit(false)); @@ -89,113 +85,91 @@ export function AddExploreServerPrompt({ viewState.status === AsyncStatus.Loading || saveViewState.status === AsyncStatus.Loading; return ( - <> - }> - - setDialog(false), - escapeDeactivates: stopPropagation, - }} - > - -
- {header} - setDialog(false)} radii="300"> - - -
- - Add server name to explore public communities. - - Server Name - - {viewState.status === AsyncStatus.Error && ( - - Failed to load public rooms. Please try again. - - )} - - - - - + }> + + + +
+ + Add Server -
-
-
-
- - setDialog(true)}> - {children} - - - + + + + + + Add server name to explore public communities. + + Server Name + + {viewState.status === AsyncStatus.Error && ( + + Failed to load public rooms. Please try again. + + )} + + + + + + +
+
+
+
); } -type ExploreServerNavItemAction = { - onClick: () => Promise; - icon: IconSrc; - alwaysVisible: boolean; -}; type ExploreServerNavItemProps = { server: string; selected: boolean; icon: IconSrc; - action?: ExploreServerNavItemAction; + after?: (hover: boolean) => ReactNode; }; -export function ExploreServerNavItem({ - server, - selected, - icon, - action, -}: ExploreServerNavItemProps) { +export function ExploreServerNavItem({ server, selected, icon, after }: ExploreServerNavItemProps) { const [hover, setHover] = useState(false); const { hoverProps } = useHover({ onHoverChange: setHover }); const { focusWithinProps } = useFocusWithin({ onFocusWithinChange: setHover }); - const [actionState, actionCallback] = useAsyncCallback( - useCallback(async () => { - await action?.onClick(); - }, [action]) - ); - const actionInProgress = - actionState.status === AsyncStatus.Loading || actionState.status === AsyncStatus.Success; return ( - {action !== undefined && (hover || actionInProgress || action.alwaysVisible) && ( + {/* {action !== undefined && (hover || actionInProgress || action.alwaysVisible) && ( - )} + )} */} + {after && {after(hover)}} ); } @@ -253,10 +228,10 @@ export function Explore() { clientConfig.featuredCommunities?.servers?.filter((server) => server !== userServer) ?? [], [clientConfig, userServer] ); - const [exploreServers, addServer, removeServer] = useExploreServers(featuredServers); + const [exploreServers, addServer, removeServer] = useExploreServers(); const selectedServer = useExploreServer(); - const exploringFeaturedRooms = useExploreFeaturedRooms(); + const exploringFeaturedRooms = useExploreFeaturedSelected(); const exploringUnlistedServer = useMemo( () => !( @@ -268,21 +243,25 @@ export function Explore() { [exploreServers, selectedServer, userServer, featuredServers] ); - const addServerCallback = useCallback( - async (server: string, save: boolean) => { - if (save && server !== userServer && !featuredServers.includes(server) && selectedServer) { - await addServer(server); - } - navigate(getExploreServerPath(server)); - }, - [addServer, navigate, userServer, featuredServers, selectedServer] + const [addServerState, addServerCallback] = useAsyncCallback( + useCallback( + async (server: string, save: boolean) => { + if (save && server !== userServer && !featuredServers.includes(server) && selectedServer) { + await addServer(server); + } + navigate(getExploreServerPath(server)); + }, + [addServer, navigate, userServer, featuredServers, selectedServer] + ) ); - const removeServerCallback = useCallback( - async (server: string) => { - await removeServer(server); - }, - [removeServer] + const [removeServerState, removeServerCallback] = useAsyncCallback( + useCallback( + async (server: string) => { + await removeServer(server); + }, + [removeServer] + ) ); return ( @@ -320,19 +299,7 @@ export function Explore() { - )} - {exploringUnlistedServer && selectedServer !== undefined && ( - addServerCallback(selectedServer, true), - }} /> )} @@ -350,34 +317,94 @@ export function Explore() { icon={Icons.Server} /> ))} - {exploreServers.map((server) => ( + {exploreServers + .filter((server) => !featuredServers.includes(server)) + .map((server) => ( + { + const busy = removeServerState.status === AsyncStatus.Loading; + + if (!(hover || busy)) { + return undefined; + } + + return ( + removeServerCallback(server)} + variant="Background" + fill="None" + size="300" + radii="300" + disabled={busy} + > + {busy ? ( + + ) : ( + + )} + + ); + }} + /> + ))} + {exploringUnlistedServer && selectedServer !== undefined && ( removeServerCallback(server), + after={() => { + const busy = addServerState.status === AsyncStatus.Loading; + + return ( + addServerCallback(selectedServer, true)} + variant="Background" + fill="None" + size="300" + radii="300" + disabled={busy} + > + {busy ? ( + + ) : ( + + )} + + ); }} /> - ))} - Add Server} - > - - - - - - - Add Server - - - - + )} + + {(dialogOpen, setDialogOpen) => ( + <> + + setDialogOpen(true)}> + + + + + + + + Add Server + + + + + + + setDialogOpen(false)} + /> + + )} +