mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-11-05 15:00:30 +03:00
Use consistent "bookmark" wording in code and UI
This commit is contained in:
parent
53612f4641
commit
c45cb62e2d
6 changed files with 129 additions and 173 deletions
43
src/app/hooks/useBookmarkedServers.ts
Normal file
43
src/app/hooks/useBookmarkedServers.ts
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { useCallback, useMemo } from 'react';
|
||||||
|
import { AccountDataEvent } from '../../types/matrix/accountData';
|
||||||
|
import { useAccountData } from './useAccountData';
|
||||||
|
import { useMatrixClient } from './useMatrixClient';
|
||||||
|
|
||||||
|
export type InCinnyBookmarkedServersContent = {
|
||||||
|
servers?: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useBookmarkedServers = (): [
|
||||||
|
string[],
|
||||||
|
(server: string) => Promise<void>,
|
||||||
|
(server: string) => Promise<void>
|
||||||
|
] => {
|
||||||
|
const mx = useMatrixClient();
|
||||||
|
const accountData = useAccountData(AccountDataEvent.CinnyBookmarkedServers);
|
||||||
|
const bookmarkedServers = useMemo(
|
||||||
|
() => accountData?.getContent<InCinnyBookmarkedServersContent>()?.servers ?? [],
|
||||||
|
[accountData]
|
||||||
|
);
|
||||||
|
|
||||||
|
const addServerBookmark = useCallback(
|
||||||
|
async (server: string) => {
|
||||||
|
if (bookmarkedServers.indexOf(server) === -1) {
|
||||||
|
await mx.setAccountData(AccountDataEvent.CinnyBookmarkedServers, {
|
||||||
|
servers: [...bookmarkedServers, server],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[mx, bookmarkedServers]
|
||||||
|
);
|
||||||
|
|
||||||
|
const removeServerBookmark = useCallback(
|
||||||
|
async (server: string) => {
|
||||||
|
await mx.setAccountData(AccountDataEvent.CinnyBookmarkedServers, {
|
||||||
|
servers: bookmarkedServers.filter((addedServer) => server !== addedServer),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[mx, bookmarkedServers]
|
||||||
|
);
|
||||||
|
|
||||||
|
return [bookmarkedServers, addServerBookmark, removeServerBookmark];
|
||||||
|
};
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
import { useCallback, useMemo } from 'react';
|
|
||||||
import { AccountDataEvent } from '../../types/matrix/accountData';
|
|
||||||
import { useAccountData } from './useAccountData';
|
|
||||||
import { useMatrixClient } from './useMatrixClient';
|
|
||||||
|
|
||||||
export type InCinnyExploreServersContent = {
|
|
||||||
servers?: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useExploreServers = (): [
|
|
||||||
string[],
|
|
||||||
(server: string) => Promise<void>,
|
|
||||||
(server: string) => Promise<void>
|
|
||||||
] => {
|
|
||||||
const mx = useMatrixClient();
|
|
||||||
const accountData = useAccountData(AccountDataEvent.CinnyExplore);
|
|
||||||
const userAddedServers = useMemo(
|
|
||||||
() => accountData?.getContent<InCinnyExploreServersContent>()?.servers ?? [],
|
|
||||||
[accountData]
|
|
||||||
);
|
|
||||||
|
|
||||||
const addServer = useCallback(
|
|
||||||
async (server: string) => {
|
|
||||||
if (userAddedServers.indexOf(server) === -1) {
|
|
||||||
await mx.setAccountData(AccountDataEvent.CinnyExplore, {
|
|
||||||
servers: [...userAddedServers, server],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[mx, userAddedServers]
|
|
||||||
);
|
|
||||||
|
|
||||||
const removeServer = useCallback(
|
|
||||||
async (server: string) => {
|
|
||||||
await mx.setAccountData(AccountDataEvent.CinnyExplore, {
|
|
||||||
servers: userAddedServers.filter((addedServer) => server !== addedServer),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[mx, userAddedServers]
|
|
||||||
);
|
|
||||||
|
|
||||||
return [userAddedServers, addServer, removeServer];
|
|
||||||
};
|
|
||||||
|
|
@ -41,21 +41,21 @@ import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
|
||||||
import { useNavToActivePathMapper } from '../../../hooks/useNavToActivePathMapper';
|
import { useNavToActivePathMapper } from '../../../hooks/useNavToActivePathMapper';
|
||||||
import { PageNav, PageNavContent, PageNavHeader } from '../../../components/page';
|
import { PageNav, PageNavContent, PageNavHeader } from '../../../components/page';
|
||||||
import { stopPropagation } from '../../../utils/keyboard';
|
import { stopPropagation } from '../../../utils/keyboard';
|
||||||
import { useExploreServers } from '../../../hooks/useExploreServers';
|
import { useBookmarkedServers } from '../../../hooks/useBookmarkedServers';
|
||||||
import { useAlive } from '../../../hooks/useAlive';
|
import { useAlive } from '../../../hooks/useAlive';
|
||||||
|
|
||||||
type AddExploreServerPromptProps = {
|
type ExploreServerPromptProps = {
|
||||||
onSubmit: (server: string, save: boolean) => Promise<void>;
|
onSubmit: (server: string, save: boolean) => Promise<void>;
|
||||||
header: ReactNode;
|
header: ReactNode;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
selected?: boolean;
|
selected?: boolean;
|
||||||
};
|
};
|
||||||
export function AddExploreServerPrompt({
|
export function ExploreServerPrompt({
|
||||||
onSubmit,
|
onSubmit,
|
||||||
header,
|
header,
|
||||||
children,
|
children,
|
||||||
selected = false,
|
selected = false,
|
||||||
}: AddExploreServerPromptProps) {
|
}: ExploreServerPromptProps) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
const [dialog, setDialog] = useState(false);
|
const [dialog, setDialog] = useState(false);
|
||||||
const alive = useAlive();
|
const alive = useAlive();
|
||||||
|
|
@ -68,13 +68,13 @@ export function AddExploreServerPrompt({
|
||||||
return server || undefined;
|
return server || undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const submit = useCallback(
|
const handleSubmit = useCallback(
|
||||||
async (save: boolean) => {
|
async (saveBookmark: boolean) => {
|
||||||
const server = getInputServer();
|
const server = getInputServer();
|
||||||
if (!server) return;
|
if (!server) return;
|
||||||
|
|
||||||
await mx.publicRooms({ server, limit: 1 });
|
await mx.publicRooms({ server, limit: 1 });
|
||||||
await onSubmit(server, save);
|
await onSubmit(server, saveBookmark);
|
||||||
if (alive()) {
|
if (alive()) {
|
||||||
setDialog(false);
|
setDialog(false);
|
||||||
}
|
}
|
||||||
|
|
@ -82,10 +82,12 @@ export function AddExploreServerPrompt({
|
||||||
[alive, onSubmit, mx]
|
[alive, onSubmit, mx]
|
||||||
);
|
);
|
||||||
|
|
||||||
const [viewState, handleView] = useAsyncCallback(() => submit(false));
|
const [viewState, handleView] = useAsyncCallback(() => handleSubmit(false));
|
||||||
const [saveViewState, handleSaveView] = useAsyncCallback(() => submit(true));
|
const [saveViewState, handleSaveView] = useAsyncCallback(() => handleSubmit(true));
|
||||||
const busy =
|
const busy =
|
||||||
viewState.status === AsyncStatus.Loading || saveViewState.status === AsyncStatus.Loading;
|
viewState.status === AsyncStatus.Loading || saveViewState.status === AsyncStatus.Loading;
|
||||||
|
const failed =
|
||||||
|
viewState.status === AsyncStatus.Error || saveViewState.status === AsyncStatus.Error;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -113,20 +115,19 @@ export function AddExploreServerPrompt({
|
||||||
<Icon src={Icons.Cross} />
|
<Icon src={Icons.Cross} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Header>
|
</Header>
|
||||||
<Box style={{ padding: config.space.S400 }} direction="Column" gap="400">
|
<Box as="form" style={{ padding: config.space.S400 }} direction="Column" gap="400">
|
||||||
<Text priority="400">Add server name to explore public communities.</Text>
|
<Text priority="400">Add server name to explore public communities.</Text>
|
||||||
<Box direction="Column" gap="100">
|
<Box direction="Column" gap="100">
|
||||||
<Text size="L400">Server Name</Text>
|
<Text size="L400">Server Name</Text>
|
||||||
<Input ref={serverInputRef} name="serverInput" variant="Background" required />
|
<Input ref={serverInputRef} name="serverInput" variant="Background" required />
|
||||||
{viewState.status === AsyncStatus.Error && (
|
{failed && (
|
||||||
<Text style={{ color: color.Critical.Main }} size="T300">
|
<Text style={{ color: color.Critical.Main }} size="T300">
|
||||||
Failed to load public rooms. Please try again.
|
Failed to load public rooms. Please try again.
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
</Box>
|
|
||||||
<Box direction="Column" gap="200">
|
<Box direction="Column" gap="200">
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="button"
|
||||||
onClick={handleView}
|
onClick={handleView}
|
||||||
variant="Secondary"
|
variant="Secondary"
|
||||||
fill="Soft"
|
fill="Soft"
|
||||||
|
|
@ -151,10 +152,11 @@ export function AddExploreServerPrompt({
|
||||||
}
|
}
|
||||||
disabled={busy}
|
disabled={busy}
|
||||||
>
|
>
|
||||||
<Text size="B400">Save & View</Text>
|
<Text size="B400">Bookmark & View</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
</Box>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</FocusTrap>
|
</FocusTrap>
|
||||||
</OverlayCenter>
|
</OverlayCenter>
|
||||||
|
|
@ -171,6 +173,7 @@ export function AddExploreServerPrompt({
|
||||||
type ExploreServerNavItemAction = {
|
type ExploreServerNavItemAction = {
|
||||||
onClick: () => Promise<void>;
|
onClick: () => Promise<void>;
|
||||||
icon: IconSrc;
|
icon: IconSrc;
|
||||||
|
filled?: boolean;
|
||||||
alwaysVisible: boolean;
|
alwaysVisible: boolean;
|
||||||
};
|
};
|
||||||
type ExploreServerNavItemProps = {
|
type ExploreServerNavItemProps = {
|
||||||
|
|
@ -222,16 +225,17 @@ export function ExploreServerNavItem({
|
||||||
<NavItemOptions>
|
<NavItemOptions>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={actionCallback}
|
onClick={actionCallback}
|
||||||
variant="Background"
|
variant={selected ? 'Background' : 'Surface'}
|
||||||
fill="None"
|
fill="None"
|
||||||
|
outlined={action.alwaysVisible}
|
||||||
size="300"
|
size="300"
|
||||||
radii="300"
|
radii="300"
|
||||||
disabled={actionInProgress}
|
disabled={actionInProgress}
|
||||||
>
|
>
|
||||||
{actionInProgress ? (
|
{actionInProgress ? (
|
||||||
<Spinner variant="Secondary" fill="Solid" size="200" />
|
<Spinner variant="Secondary" fill="Solid" size="50" />
|
||||||
) : (
|
) : (
|
||||||
<Icon size="50" src={action.icon} />
|
<Icon size="50" src={action.icon} filled={action.filled} />
|
||||||
)}
|
)}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</NavItemOptions>
|
</NavItemOptions>
|
||||||
|
|
@ -246,7 +250,7 @@ export function Explore() {
|
||||||
useNavToActivePathMapper('explore');
|
useNavToActivePathMapper('explore');
|
||||||
const userId = mx.getUserId();
|
const userId = mx.getUserId();
|
||||||
const userServer = userId ? getMxIdServer(userId) : undefined;
|
const userServer = userId ? getMxIdServer(userId) : undefined;
|
||||||
const [exploreServers, addServer, removeServer] = useExploreServers();
|
const [bookmarkedServers, addServerBookmark, removeServerBookmark] = useBookmarkedServers();
|
||||||
|
|
||||||
const selectedServer = useExploreServer();
|
const selectedServer = useExploreServer();
|
||||||
const exploringFeaturedRooms = useExploreFeaturedRooms();
|
const exploringFeaturedRooms = useExploreFeaturedRooms();
|
||||||
|
|
@ -255,26 +259,26 @@ export function Explore() {
|
||||||
!(
|
!(
|
||||||
selectedServer === undefined ||
|
selectedServer === undefined ||
|
||||||
selectedServer === userServer ||
|
selectedServer === userServer ||
|
||||||
exploreServers.includes(selectedServer)
|
bookmarkedServers.includes(selectedServer)
|
||||||
),
|
),
|
||||||
[exploreServers, selectedServer, userServer]
|
[bookmarkedServers, selectedServer, userServer]
|
||||||
);
|
);
|
||||||
|
|
||||||
const addServerCallback = useCallback(
|
const viewServerCallback = useCallback(
|
||||||
async (server: string, save: boolean) => {
|
async (server: string, saveBookmark: boolean) => {
|
||||||
if (save && server !== userServer && selectedServer) {
|
if (saveBookmark && server !== userServer && selectedServer) {
|
||||||
await addServer(server);
|
await addServerBookmark(server);
|
||||||
}
|
}
|
||||||
navigate(getExploreServerPath(server));
|
navigate(getExploreServerPath(server));
|
||||||
},
|
},
|
||||||
[addServer, navigate, userServer, selectedServer]
|
[addServerBookmark, navigate, userServer, selectedServer]
|
||||||
);
|
);
|
||||||
|
|
||||||
const removeServerCallback = useCallback(
|
const removeServerBookmarkCallback = useCallback(
|
||||||
async (server: string) => {
|
async (server: string) => {
|
||||||
await removeServer(server);
|
await removeServerBookmark(server);
|
||||||
},
|
},
|
||||||
[removeServer]
|
[removeServerBookmark]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -319,11 +323,11 @@ export function Explore() {
|
||||||
<ExploreServerNavItem
|
<ExploreServerNavItem
|
||||||
server={selectedServer}
|
server={selectedServer}
|
||||||
selected
|
selected
|
||||||
icon={Icons.Server}
|
icon={Icons.Eye}
|
||||||
action={{
|
action={{
|
||||||
alwaysVisible: true,
|
alwaysVisible: true,
|
||||||
icon: Icons.Plus,
|
icon: Icons.Bookmark,
|
||||||
onClick: () => addServerCallback(selectedServer, true),
|
onClick: () => viewServerCallback(selectedServer, true),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
@ -331,10 +335,10 @@ export function Explore() {
|
||||||
<NavCategory>
|
<NavCategory>
|
||||||
<NavCategoryHeader>
|
<NavCategoryHeader>
|
||||||
<Text size="O400" style={{ paddingLeft: config.space.S200 }}>
|
<Text size="O400" style={{ paddingLeft: config.space.S200 }}>
|
||||||
Servers
|
Bookmarks
|
||||||
</Text>
|
</Text>
|
||||||
</NavCategoryHeader>
|
</NavCategoryHeader>
|
||||||
{exploreServers.map((server) => (
|
{bookmarkedServers.map((server) => (
|
||||||
<ExploreServerNavItem
|
<ExploreServerNavItem
|
||||||
key={server}
|
key={server}
|
||||||
server={server}
|
server={server}
|
||||||
|
|
@ -342,13 +346,14 @@ export function Explore() {
|
||||||
icon={Icons.Server}
|
icon={Icons.Server}
|
||||||
action={{
|
action={{
|
||||||
alwaysVisible: false,
|
alwaysVisible: false,
|
||||||
icon: Icons.Minus,
|
icon: Icons.Bookmark,
|
||||||
onClick: () => removeServerCallback(server),
|
filled: true,
|
||||||
|
onClick: () => removeServerBookmarkCallback(server),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<AddExploreServerPrompt
|
<ExploreServerPrompt
|
||||||
onSubmit={addServerCallback}
|
onSubmit={viewServerCallback}
|
||||||
header={<Text size="H4">Add Server</Text>}
|
header={<Text size="H4">Add Server</Text>}
|
||||||
>
|
>
|
||||||
<Box as="span" grow="Yes" alignItems="Center" gap="200">
|
<Box as="span" grow="Yes" alignItems="Center" gap="200">
|
||||||
|
|
@ -361,7 +366,7 @@ export function Explore() {
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</AddExploreServerPrompt>
|
</ExploreServerPrompt>
|
||||||
</NavCategory>
|
</NavCategory>
|
||||||
</Box>
|
</Box>
|
||||||
</PageNavContent>
|
</PageNavContent>
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ function ServerCard({ serverName, onExplore }: ServerCardProps) {
|
||||||
</Box>
|
</Box>
|
||||||
<Button onClick={onExplore} variant="Secondary" fill="Soft" size="300">
|
<Button onClick={onExplore} variant="Secondary" fill="Soft" size="300">
|
||||||
<Text size="B300" truncate>
|
<Text size="B300" truncate>
|
||||||
Explore
|
Explore Rooms
|
||||||
</Text>
|
</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</CardBase>
|
</CardBase>
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ import { stopPropagation } from '../../../utils/keyboard';
|
||||||
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
|
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
|
||||||
import { BackRouteHandler } from '../../../components/BackRouteHandler';
|
import { BackRouteHandler } from '../../../components/BackRouteHandler';
|
||||||
import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
|
import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
|
||||||
import { useExploreServers } from '../../../hooks/useExploreServers';
|
import { useBookmarkedServers } from '../../../hooks/useBookmarkedServers';
|
||||||
|
|
||||||
const useServerSearchParams = (searchParams: URLSearchParams): ExploreServerPathSearchParams =>
|
const useServerSearchParams = (searchParams: URLSearchParams): ExploreServerPathSearchParams =>
|
||||||
useMemo(
|
useMemo(
|
||||||
|
|
@ -352,7 +352,6 @@ export function PublicRooms() {
|
||||||
const allRooms = useAtomValue(allRoomsAtom);
|
const allRooms = useAtomValue(allRoomsAtom);
|
||||||
const { navigateSpace, navigateRoom } = useRoomNavigate();
|
const { navigateSpace, navigateRoom } = useRoomNavigate();
|
||||||
const screenSize = useScreenSizeContext();
|
const screenSize = useScreenSizeContext();
|
||||||
const [menuAnchor, setMenuAnchor] = useState<RectCords>();
|
|
||||||
|
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const serverSearchParams = useServerSearchParams(searchParams);
|
const serverSearchParams = useServerSearchParams(searchParams);
|
||||||
|
|
@ -361,9 +360,9 @@ export function PublicRooms() {
|
||||||
const searchInputRef = useRef<HTMLInputElement>(null);
|
const searchInputRef = useRef<HTMLInputElement>(null);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const roomTypeFilters = useRoomTypeFilters();
|
const roomTypeFilters = useRoomTypeFilters();
|
||||||
const [exploreServers, addServer, removeServer] = useExploreServers();
|
const [bookmarkedServers, addServerBookmark, removeServerBookmark] = useBookmarkedServers();
|
||||||
const isUserHomeserver = server && server === userServer;
|
const isUserHomeserver = server !== undefined && server === userServer;
|
||||||
const isBookmarkedServer = server && exploreServers.includes(server);
|
const isBookmarkedServer = server !== undefined && bookmarkedServers.includes(server);
|
||||||
|
|
||||||
const currentLimit: number = useMemo(() => {
|
const currentLimit: number = useMemo(() => {
|
||||||
const limitParam = serverSearchParams.limit;
|
const limitParam = serverSearchParams.limit;
|
||||||
|
|
@ -476,22 +475,17 @@ export function PublicRooms() {
|
||||||
explore({ instance: instanceId, since: undefined });
|
explore({ instance: instanceId, since: undefined });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOpenMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
const [bookmarkActionState, handleBookmarkAction] = useAsyncCallback(
|
||||||
setMenuAnchor(evt.currentTarget.getBoundingClientRect());
|
|
||||||
};
|
|
||||||
|
|
||||||
const [menuActionState, handleMenuAction] = useAsyncCallback(
|
|
||||||
useCallback(
|
useCallback(
|
||||||
async (action: (server: string) => Promise<unknown>) => {
|
async (action: (server: string) => Promise<unknown>) => {
|
||||||
if (!server) return;
|
if (!server) return;
|
||||||
|
|
||||||
setMenuAnchor(undefined);
|
|
||||||
await action(server);
|
await action(server);
|
||||||
},
|
},
|
||||||
[server]
|
[server]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
const menuActionBusy = menuActionState.status === AsyncStatus.Loading;
|
const bookmarkActionLoading = bookmarkActionState.status === AsyncStatus.Loading;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
|
|
@ -546,69 +540,26 @@ export function PublicRooms() {
|
||||||
offset={4}
|
offset={4}
|
||||||
tooltip={
|
tooltip={
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<Text>More Options</Text>
|
<Text>{isBookmarkedServer ? 'Remove Bookmark' : 'Add Bookmark'}</Text>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{(triggerRef) =>
|
{(triggerRef) =>
|
||||||
!isUserHomeserver && (
|
!isUserHomeserver && (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={handleOpenMenu}
|
onClick={() =>
|
||||||
|
handleBookmarkAction(
|
||||||
|
isBookmarkedServer ? removeServerBookmark : addServerBookmark
|
||||||
|
)
|
||||||
|
}
|
||||||
ref={triggerRef}
|
ref={triggerRef}
|
||||||
aria-pressed={!!menuAnchor}
|
disabled={bookmarkActionLoading}
|
||||||
>
|
>
|
||||||
<Icon size="400" src={Icons.VerticalDots} filled={!!menuAnchor} />
|
<Icon size="400" src={Icons.Bookmark} filled={isBookmarkedServer} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
<PopOut
|
|
||||||
anchor={menuAnchor}
|
|
||||||
position="Bottom"
|
|
||||||
align="End"
|
|
||||||
content={
|
|
||||||
<FocusTrap
|
|
||||||
focusTrapOptions={{
|
|
||||||
initialFocus: false,
|
|
||||||
returnFocusOnDeactivate: false,
|
|
||||||
onDeactivate: () => setMenuAnchor(undefined),
|
|
||||||
clickOutsideDeactivates: true,
|
|
||||||
isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
|
|
||||||
isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
|
|
||||||
escapeDeactivates: stopPropagation,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Menu style={{ maxWidth: toRem(160), width: '100vw' }}>
|
|
||||||
<Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
|
|
||||||
<MenuItem
|
|
||||||
onClick={() =>
|
|
||||||
handleMenuAction(isBookmarkedServer ? removeServer : addServer)
|
|
||||||
}
|
|
||||||
variant={isBookmarkedServer ? 'Critical' : 'Primary'}
|
|
||||||
fill="None"
|
|
||||||
size="300"
|
|
||||||
after={
|
|
||||||
menuActionBusy ? (
|
|
||||||
<Spinner fill="Solid" variant="Secondary" size="200" />
|
|
||||||
) : (
|
|
||||||
<Icon
|
|
||||||
size="100"
|
|
||||||
src={isBookmarkedServer ? Icons.Delete : Icons.Plus}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
radii="300"
|
|
||||||
disabled={menuActionBusy}
|
|
||||||
>
|
|
||||||
<Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
|
|
||||||
{isBookmarkedServer ? 'Remove Server' : 'Add Server'}
|
|
||||||
</Text>
|
|
||||||
</MenuItem>
|
|
||||||
</Box>
|
|
||||||
</Menu>
|
|
||||||
</FocusTrap>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ export enum AccountDataEvent {
|
||||||
IgnoredUserList = 'm.ignored_user_list',
|
IgnoredUserList = 'm.ignored_user_list',
|
||||||
|
|
||||||
CinnySpaces = 'in.cinny.spaces',
|
CinnySpaces = 'in.cinny.spaces',
|
||||||
CinnyExplore = 'in.cinny.explore',
|
CinnyBookmarkedServers = 'in.cinny.bookmarked_servers',
|
||||||
|
|
||||||
ElementRecentEmoji = 'io.element.recent_emoji',
|
ElementRecentEmoji = 'io.element.recent_emoji',
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue