mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-17 21:31:43 +01:00
cleanup account switcher
This commit is contained in:
parent
fbbe79f194
commit
ff68b25a41
@ -114,7 +114,7 @@
|
||||
"react-window": "^1.8.11",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"remark-wiki-link": "^2.0.1",
|
||||
"rx-nostr": "^3.4.2",
|
||||
"rx-nostr": "^3.5.0",
|
||||
"rxjs": "^7.8.1",
|
||||
"three": "^0.170.0",
|
||||
"three-spritetext": "^1.9.3",
|
||||
|
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@ -301,8 +301,8 @@ importers:
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1
|
||||
rx-nostr:
|
||||
specifier: ^3.4.2
|
||||
version: 3.4.2
|
||||
specifier: ^3.5.0
|
||||
version: 3.5.0
|
||||
rxjs:
|
||||
specifier: ^7.8.1
|
||||
version: 7.8.1
|
||||
@ -5143,8 +5143,8 @@ packages:
|
||||
run-parallel@1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
|
||||
rx-nostr@3.4.2:
|
||||
resolution: {integrity: sha512-K8SCWyYIE5cd4I8KUfHK207uINyjcU4AY2/G1SlsVEMGbk5IFe28vgqSt87p2JUxzfm4g0/4oWevAlVAERIokw==}
|
||||
rx-nostr@3.5.0:
|
||||
resolution: {integrity: sha512-SFk/WTYKW1GAecyxLKNQlkdedrFfGDeT8nz8wTFriIqd2I6jSV5lm7jBkStcnB4ncDK7GOf4QoLcZfxA+OqaQw==}
|
||||
|
||||
rxjs@7.8.1:
|
||||
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
|
||||
@ -8509,7 +8509,7 @@ snapshots:
|
||||
applesauce-core: 0.0.0-next-20250114214607(typescript@5.7.3)
|
||||
nanoid: 5.0.9
|
||||
nostr-tools: 2.10.4(typescript@5.7.3)
|
||||
rx-nostr: 3.4.2
|
||||
rx-nostr: 3.5.0
|
||||
rxjs: 7.8.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -11950,7 +11950,7 @@ snapshots:
|
||||
dependencies:
|
||||
queue-microtask: 1.2.3
|
||||
|
||||
rx-nostr@3.4.2:
|
||||
rx-nostr@3.5.0:
|
||||
dependencies:
|
||||
nostr-typedef: 0.9.0
|
||||
rxjs: 7.8.1
|
||||
|
3
src/components/layout/context.tsx
Normal file
3
src/components/layout/context.tsx
Normal file
@ -0,0 +1,3 @@
|
||||
import { createContext } from "react";
|
||||
|
||||
export const CollapsedContext = createContext(false);
|
@ -1,5 +1,5 @@
|
||||
import { Suspense } from "react";
|
||||
import { Flex, Spinner } from "@chakra-ui/react";
|
||||
import { Spinner } from "@chakra-ui/react";
|
||||
import { Outlet, ScrollRestoration } from "react-router-dom";
|
||||
|
||||
import DesktopSideNav from "./side-nav";
|
||||
|
@ -1,65 +1,19 @@
|
||||
import { createContext, useState } from "react";
|
||||
import {
|
||||
Flex,
|
||||
FlexProps,
|
||||
IconButton,
|
||||
Menu,
|
||||
MenuButton,
|
||||
MenuDivider,
|
||||
MenuItem,
|
||||
MenuList,
|
||||
Spacer,
|
||||
} from "@chakra-ui/react";
|
||||
import { useState } from "react";
|
||||
import { Flex, FlexProps, IconButton } from "@chakra-ui/react";
|
||||
|
||||
import UserAvatar from "../../user/user-avatar";
|
||||
import useCurrentAccount from "../../../hooks/use-current-account";
|
||||
import accountService from "../../../services/account";
|
||||
import UserName from "../../user/user-name";
|
||||
import UserDnsIdentity from "../../user/user-dns-identity";
|
||||
import { ChevronLeftIcon, ChevronRightIcon, SettingsIcon } from "../../icons";
|
||||
import Plus from "../../icons/plus";
|
||||
import NavItem from "../nav-items/nav-item";
|
||||
import { ChevronLeftIcon, ChevronRightIcon } from "../../icons";
|
||||
import NavItems from "../nav-items";
|
||||
import useRootPadding from "../../../hooks/use-root-padding";
|
||||
|
||||
export const ExpandedContext = createContext(false);
|
||||
|
||||
function UserAccount() {
|
||||
const account = useCurrentAccount()!;
|
||||
|
||||
return (
|
||||
<Menu placement="right" offset={[32, 16]}>
|
||||
<MenuButton
|
||||
as={IconButton}
|
||||
variant="outline"
|
||||
w="12"
|
||||
h="12"
|
||||
borderRadius="50%"
|
||||
icon={<UserAvatar pubkey={account.pubkey} />}
|
||||
/>
|
||||
<MenuList boxShadow="lg">
|
||||
<Flex gap="2" px="2" alignItems="center">
|
||||
<UserAvatar pubkey={account.pubkey} />
|
||||
<Flex direction="column">
|
||||
<UserName pubkey={account.pubkey} fontSize="xl" />
|
||||
<UserDnsIdentity pubkey={account.pubkey} />
|
||||
</Flex>
|
||||
</Flex>
|
||||
<MenuDivider />
|
||||
<MenuItem onClick={() => accountService.logout()}>Logout</MenuItem>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
import AccountSwitcher from "../nav-items/account-switcher";
|
||||
import { CollapsedContext } from "../context";
|
||||
|
||||
export default function DesktopSideNav({ ...props }: Omit<FlexProps, "children">) {
|
||||
const account = useCurrentAccount();
|
||||
const [expanded, setExpanded] = useState(true);
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
|
||||
useRootPadding({ left: expanded ? "var(--chakra-sizes-64)" : "var(--chakra-sizes-16)" });
|
||||
useRootPadding({ left: collapsed ? "var(--chakra-sizes-16)" : "var(--chakra-sizes-64)" });
|
||||
|
||||
return (
|
||||
<ExpandedContext.Provider value={expanded}>
|
||||
<CollapsedContext.Provider value={collapsed}>
|
||||
<Flex
|
||||
direction="column"
|
||||
gap="2"
|
||||
@ -69,7 +23,7 @@ export default function DesktopSideNav({ ...props }: Omit<FlexProps, "children">
|
||||
borderRightWidth={1}
|
||||
pt="calc(var(--chakra-space-2) + var(--safe-top))"
|
||||
pb="calc(var(--chakra-space-2) + var(--safe-bottom))"
|
||||
w={expanded ? "64" : "16"}
|
||||
w={collapsed ? "16" : "64"}
|
||||
position="fixed"
|
||||
left="0"
|
||||
bottom="0"
|
||||
@ -77,27 +31,23 @@ export default function DesktopSideNav({ ...props }: Omit<FlexProps, "children">
|
||||
zIndex="modal"
|
||||
overflowY="auto"
|
||||
overflowX="hidden"
|
||||
overscroll="none"
|
||||
{...props}
|
||||
>
|
||||
<IconButton
|
||||
aria-label={expanded ? "Close" : "Open"}
|
||||
title={expanded ? "Close" : "Open"}
|
||||
aria-label={collapsed ? "Open" : "Close"}
|
||||
title={collapsed ? "Open" : "Close"}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => setExpanded(!expanded)}
|
||||
icon={expanded ? <ChevronLeftIcon boxSize={5} /> : <ChevronRightIcon boxSize={5} />}
|
||||
onClick={() => setCollapsed(!collapsed)}
|
||||
icon={collapsed ? <ChevronRightIcon boxSize={5} /> : <ChevronLeftIcon boxSize={5} />}
|
||||
position="absolute"
|
||||
bottom="4"
|
||||
right="-4"
|
||||
/>
|
||||
{account && <UserAccount />}
|
||||
<NavItem icon={Plus} label="Create new" colorScheme="primary" to="/new" variant="solid" />
|
||||
|
||||
<AccountSwitcher />
|
||||
<NavItems />
|
||||
|
||||
<Spacer />
|
||||
<NavItem label="Settings" icon={SettingsIcon} to="/settings" />
|
||||
</Flex>
|
||||
</ExpandedContext.Provider>
|
||||
</CollapsedContext.Provider>
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
import { Outlet, ScrollRestoration } from "react-router-dom";
|
||||
import { useObservable } from "applesauce-react/hooks";
|
||||
|
||||
import MobileBottomNav from "./bottom-nav";
|
||||
import { ErrorBoundary } from "../../error-boundary";
|
||||
|
@ -1,24 +1,9 @@
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
Button,
|
||||
Drawer,
|
||||
DrawerBody,
|
||||
DrawerContent,
|
||||
DrawerOverlay,
|
||||
DrawerProps,
|
||||
Flex,
|
||||
Text,
|
||||
} from "@chakra-ui/react";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import { Avatar, Drawer, DrawerBody, DrawerContent, DrawerOverlay, DrawerProps, Flex, Text } from "@chakra-ui/react";
|
||||
|
||||
import AccountSwitcher from "../../legacy-layout/account-switcher";
|
||||
import AccountSwitcher from "../nav-items/account-switcher";
|
||||
import useCurrentAccount from "../../../hooks/use-current-account";
|
||||
import NavItems from "../nav-items";
|
||||
import TaskManagerButtons from "../../legacy-layout/task-manager-buttons";
|
||||
import { ExpandedContext } from "../desktop/side-nav";
|
||||
import NavItem from "../nav-items/nav-item";
|
||||
import { SettingsIcon } from "../../icons";
|
||||
import { CollapsedContext } from "../context";
|
||||
|
||||
export default function NavDrawer({ ...props }: Omit<DrawerProps, "children">) {
|
||||
const account = useCurrentAccount();
|
||||
@ -27,7 +12,7 @@ export default function NavDrawer({ ...props }: Omit<DrawerProps, "children">) {
|
||||
<Drawer placement="left" {...props}>
|
||||
<DrawerOverlay />
|
||||
<DrawerContent>
|
||||
<ExpandedContext.Provider value={true}>
|
||||
<CollapsedContext.Provider value={false}>
|
||||
<DrawerBody display="flex" flexDirection="column" px="4" pt="4" overflowY="auto" overflowX="hidden" gap="2">
|
||||
{account ? (
|
||||
<AccountSwitcher />
|
||||
@ -38,16 +23,8 @@ export default function NavDrawer({ ...props }: Omit<DrawerProps, "children">) {
|
||||
</Flex>
|
||||
)}
|
||||
<NavItems />
|
||||
<Box h="2" />
|
||||
{!account && (
|
||||
<Button as={RouterLink} to="/signin" colorScheme="primary" flexShrink={0}>
|
||||
Sign in
|
||||
</Button>
|
||||
)}
|
||||
<NavItem label="Settings" icon={SettingsIcon} to="/settings" />
|
||||
<TaskManagerButtons mt="auto" flexShrink={0} />
|
||||
</DrawerBody>
|
||||
</ExpandedContext.Provider>
|
||||
</CollapsedContext.Provider>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
);
|
||||
|
137
src/components/layout/nav-items/account-switcher.tsx
Normal file
137
src/components/layout/nav-items/account-switcher.tsx
Normal file
@ -0,0 +1,137 @@
|
||||
import { CloseIcon } from "@chakra-ui/icons";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Flex,
|
||||
IconButton,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
|
||||
import { getDisplayName } from "../../../helpers/nostr/profile";
|
||||
import useUserProfile from "../../../hooks/use-user-profile";
|
||||
import accountService from "../../../services/account";
|
||||
import { LogoutIcon } from "../../icons";
|
||||
import UserAvatar from "../../user/user-avatar";
|
||||
import AccountTypeBadge from "../../account-info-badge";
|
||||
import useCurrentAccount from "../../../hooks/use-current-account";
|
||||
import { Account } from "../../../classes/accounts/account";
|
||||
import { useObservable } from "applesauce-react/hooks";
|
||||
import { useContext } from "react";
|
||||
import UserDnsIdentity from "../../user/user-dns-identity";
|
||||
import NavItem from "./nav-item";
|
||||
import LogIn01 from "../../icons/log-in-01";
|
||||
import { CollapsedContext } from "../context";
|
||||
|
||||
function AccountItem({ account, onClick }: { account: Account; onClick?: () => void }) {
|
||||
const pubkey = account.pubkey;
|
||||
const metadata = useUserProfile(pubkey, []);
|
||||
|
||||
const handleClick = () => {
|
||||
accountService.switchAccount(pubkey);
|
||||
if (onClick) onClick();
|
||||
};
|
||||
|
||||
return (
|
||||
<Box display="flex" gap="2" alignItems="center">
|
||||
<Flex flex={1} gap="2" overflow="hidden" alignItems="center">
|
||||
<UserAvatar pubkey={pubkey} size="md" />
|
||||
<Flex direction="column" overflow="hidden" alignItems="flex-start">
|
||||
<Text isTruncated>{getDisplayName(metadata, pubkey)}</Text>
|
||||
<AccountTypeBadge fontSize="0.7em" account={account} />
|
||||
</Flex>
|
||||
</Flex>
|
||||
<ButtonGroup size="sm" variant="ghost">
|
||||
<Button onClick={handleClick} aria-label="Switch account">
|
||||
Switch
|
||||
</Button>
|
||||
<IconButton
|
||||
icon={<CloseIcon />}
|
||||
aria-label="Remove account"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (confirm("Remove this account?")) accountService.removeAccount(pubkey);
|
||||
}}
|
||||
colorScheme="red"
|
||||
/>
|
||||
</ButtonGroup>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default function AccountSwitcher() {
|
||||
const account = useCurrentAccount();
|
||||
const modal = useDisclosure();
|
||||
|
||||
const metadata = useUserProfile(account?.pubkey);
|
||||
const accounts = useObservable(accountService.accounts);
|
||||
|
||||
const otherAccounts = accounts.filter((acc) => acc.pubkey !== account?.pubkey);
|
||||
const collapsed = useContext(CollapsedContext);
|
||||
|
||||
return (
|
||||
<>
|
||||
{account ? (
|
||||
<Flex
|
||||
as="button"
|
||||
gap="2"
|
||||
alignItems="center"
|
||||
onClick={modal.onToggle}
|
||||
flexShrink={0}
|
||||
overflow="hidden"
|
||||
outline="none"
|
||||
>
|
||||
<UserAvatar pubkey={account.pubkey} noProxy size="md" />
|
||||
{!collapsed && (
|
||||
<Flex overflow="hidden" direction="column" w="Full" alignItems="flex-start">
|
||||
<Text whiteSpace="nowrap" fontWeight="bold" fontSize="lg" isTruncated>
|
||||
{getDisplayName(metadata, account.pubkey)}
|
||||
</Text>
|
||||
<UserDnsIdentity pubkey={account.pubkey} />
|
||||
</Flex>
|
||||
)}
|
||||
</Flex>
|
||||
) : (
|
||||
<NavItem label="Login" icon={LogIn01} to="/signin" colorScheme="primary" variant="solid" />
|
||||
)}
|
||||
|
||||
<Modal isOpen={modal.isOpen} onClose={modal.onClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader py="2" px="4">
|
||||
Accounts
|
||||
</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody pb="2" pt="0" px="2" display="flex" flexDirection="column" gap="2">
|
||||
{otherAccounts.map((account) => (
|
||||
<AccountItem key={account.pubkey} account={account} onClick={modal.onClose} />
|
||||
))}
|
||||
<ButtonGroup w="full">
|
||||
<Button as={RouterLink} to="/settings/accounts" w="full" onClick={modal.onClose} variant="link">
|
||||
Manage accounts
|
||||
</Button>
|
||||
<Button
|
||||
leftIcon={<LogoutIcon boxSize={5} />}
|
||||
aria-label="Logout"
|
||||
onClick={() => {
|
||||
accountService.logout(false);
|
||||
}}
|
||||
flexShrink={0}
|
||||
>
|
||||
Logout
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { useMemo } from "react";
|
||||
import { ButtonProps } from "@chakra-ui/react";
|
||||
import { ButtonProps, Spacer } from "@chakra-ui/react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { nip19 } from "nostr-tools";
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
SearchIcon,
|
||||
NotesIcon,
|
||||
LightningIcon,
|
||||
SettingsIcon,
|
||||
} from "../../icons";
|
||||
import useCurrentAccount from "../../../hooks/use-current-account";
|
||||
import PuzzlePiece01 from "../../icons/puzzle-piece-01";
|
||||
@ -22,6 +23,8 @@ import { internalApps, internalTools } from "../../../views/other-stuff/apps";
|
||||
import { App } from "../../../views/other-stuff/component/app-card";
|
||||
import NavItem from "./nav-item";
|
||||
import { QuestionIcon } from "@chakra-ui/icons";
|
||||
import TaskManagerButtons from "../../legacy-layout/task-manager-buttons";
|
||||
import Plus from "../../icons/plus";
|
||||
|
||||
export default function NavItems() {
|
||||
const location = useLocation();
|
||||
@ -91,6 +94,9 @@ export default function NavItems() {
|
||||
|
||||
return (
|
||||
<>
|
||||
{account && account.readonly !== false && (
|
||||
<NavItem icon={Plus} label="Create new" colorScheme="primary" to="/new" variant="solid" />
|
||||
)}
|
||||
<NavItem to="/launchpad" icon={Rocket02} label="Launchpad" />
|
||||
<NavItem to="/" icon={NotesIcon} colorScheme={location.pathname === "/" ? "primary" : "gray"} label="Notes" />
|
||||
<NavItem label="Discover" to="/discovery" icon={PuzzlePiece01} />
|
||||
@ -107,7 +113,10 @@ export default function NavItems() {
|
||||
<NavItem key={app.id} to={app.to} icon={app.icon || QuestionIcon} label={app.title} />
|
||||
))}
|
||||
<NavItem to="/other-stuff" icon={Package} label="More" />
|
||||
<Spacer />
|
||||
<NavItem to="/support" icon={LightningIcon} label="Support" />
|
||||
<NavItem label="Settings" icon={SettingsIcon} to="/settings" />
|
||||
<TaskManagerButtons mt="auto" flexShrink={0} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { useContext } from "react";
|
||||
import { Button, ComponentWithAs, IconButton, IconButtonProps, IconProps } from "@chakra-ui/react";
|
||||
import { To, Link as RouterLink, useLocation } from "react-router-dom";
|
||||
import { Link as RouterLink, useLocation } from "react-router-dom";
|
||||
|
||||
import { ExpandedContext } from "../desktop/side-nav";
|
||||
import { CollapsedContext } from "../context";
|
||||
|
||||
export default function NavItem({
|
||||
to,
|
||||
@ -17,27 +17,10 @@ export default function NavItem({
|
||||
colorScheme?: IconButtonProps["colorScheme"];
|
||||
variant?: IconButtonProps["variant"];
|
||||
}) {
|
||||
const expanded = useContext(ExpandedContext);
|
||||
const collapsed = useContext(CollapsedContext);
|
||||
const location = useLocation();
|
||||
|
||||
if (expanded)
|
||||
return (
|
||||
<Button
|
||||
as={RouterLink}
|
||||
aria-label={label}
|
||||
title={label}
|
||||
leftIcon={<Icon boxSize={5} />}
|
||||
variant={variant || "link"}
|
||||
py="2"
|
||||
justifyContent="flex-start"
|
||||
colorScheme={colorScheme || location.pathname.startsWith(to) ? "primary" : undefined}
|
||||
to={to}
|
||||
flexShrink={0}
|
||||
>
|
||||
{label}
|
||||
</Button>
|
||||
);
|
||||
else
|
||||
if (collapsed)
|
||||
return (
|
||||
<IconButton
|
||||
as={RouterLink}
|
||||
@ -51,4 +34,21 @@ export default function NavItem({
|
||||
colorScheme={colorScheme || location.pathname.startsWith(to) ? "primary" : undefined}
|
||||
/>
|
||||
);
|
||||
else
|
||||
return (
|
||||
<Button
|
||||
as={RouterLink}
|
||||
aria-label={label}
|
||||
title={label}
|
||||
leftIcon={<Icon boxSize={5} />}
|
||||
variant={variant || "link"}
|
||||
p="2"
|
||||
justifyContent="flex-start"
|
||||
colorScheme={colorScheme || location.pathname.startsWith(to) ? "primary" : undefined}
|
||||
to={to}
|
||||
flexShrink={0}
|
||||
>
|
||||
{label}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
@ -1,101 +0,0 @@
|
||||
import { CloseIcon } from "@chakra-ui/icons";
|
||||
import { useNavigate, Link as RouterLink } from "react-router-dom";
|
||||
import { Box, Button, ButtonGroup, Flex, IconButton, Text, useDisclosure } from "@chakra-ui/react";
|
||||
|
||||
import { getDisplayName } from "../../helpers/nostr/profile";
|
||||
import useUserProfile from "../../hooks/use-user-profile";
|
||||
import accountService from "../../services/account";
|
||||
import { AddIcon, ChevronDownIcon, ChevronUpIcon } from "../icons";
|
||||
import UserAvatar from "../user/user-avatar";
|
||||
import AccountTypeBadge from "../account-info-badge";
|
||||
import useCurrentAccount from "../../hooks/use-current-account";
|
||||
import { Account } from "../../classes/accounts/account";
|
||||
import { useObservable } from "applesauce-react/hooks";
|
||||
|
||||
function AccountItem({ account, onClick }: { account: Account; onClick?: () => void }) {
|
||||
const pubkey = account.pubkey;
|
||||
const metadata = useUserProfile(pubkey, []);
|
||||
|
||||
const handleClick = () => {
|
||||
accountService.switchAccount(pubkey);
|
||||
if (onClick) onClick();
|
||||
};
|
||||
|
||||
return (
|
||||
<Box display="flex" gap="2" alignItems="center" cursor="pointer">
|
||||
<Flex as="button" onClick={handleClick} flex={1} gap="2" overflow="hidden" alignItems="center">
|
||||
<UserAvatar pubkey={pubkey} size="md" />
|
||||
<Flex direction="column" overflow="hidden" alignItems="flex-start">
|
||||
<Text isTruncated>{getDisplayName(metadata, pubkey)}</Text>
|
||||
<AccountTypeBadge fontSize="0.7em" account={account} />
|
||||
</Flex>
|
||||
</Flex>
|
||||
<IconButton
|
||||
icon={<CloseIcon />}
|
||||
aria-label="Remove Account"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (confirm("Remove this account?")) accountService.removeAccount(pubkey);
|
||||
}}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default function AccountSwitcher() {
|
||||
const navigate = useNavigate();
|
||||
const account = useCurrentAccount()!;
|
||||
const { isOpen, onToggle, onClose } = useDisclosure();
|
||||
const metadata = useUserProfile(account.pubkey);
|
||||
const accounts = useObservable(accountService.accounts);
|
||||
|
||||
const otherAccounts = accounts.filter((acc) => acc.pubkey !== account?.pubkey);
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="2">
|
||||
<Box
|
||||
as="button"
|
||||
borderRadius="lg"
|
||||
borderWidth={1}
|
||||
display="flex"
|
||||
gap="2"
|
||||
alignItems="center"
|
||||
flexGrow={1}
|
||||
onClick={onToggle}
|
||||
>
|
||||
<UserAvatar pubkey={account.pubkey} noProxy size="md" />
|
||||
<Text whiteSpace="nowrap" fontWeight="bold" fontSize="lg" isTruncated>
|
||||
{getDisplayName(metadata, account.pubkey)}
|
||||
</Text>
|
||||
<Flex ml="auto" alignItems="center" justifyContent="center" aspectRatio={1} h="3rem">
|
||||
{isOpen ? <ChevronUpIcon fontSize="1.5rem" /> : <ChevronDownIcon fontSize="1.5rem" />}
|
||||
</Flex>
|
||||
</Box>
|
||||
{isOpen && (
|
||||
<>
|
||||
{otherAccounts.map((account) => (
|
||||
<AccountItem key={account.pubkey} account={account} onClick={onClose} />
|
||||
))}
|
||||
<ButtonGroup>
|
||||
<Button as={RouterLink} to="/settings/accounts" w="full">
|
||||
Manage
|
||||
</Button>
|
||||
<IconButton
|
||||
icon={<AddIcon boxSize={6} />}
|
||||
aria-label="Add Account"
|
||||
onClick={() => {
|
||||
accountService.logout(false);
|
||||
navigate("/signin", { state: { from: location.pathname } });
|
||||
}}
|
||||
colorScheme="primary"
|
||||
>
|
||||
Add Account
|
||||
</IconButton>
|
||||
</ButtonGroup>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
}
|
@ -6,7 +6,7 @@ import { useObservable } from "applesauce-react/hooks";
|
||||
|
||||
import Plus from "../icons/plus";
|
||||
import useCurrentAccount from "../../hooks/use-current-account";
|
||||
import AccountSwitcher from "./account-switcher";
|
||||
import AccountSwitcher from "../layout/nav-items/account-switcher";
|
||||
import NavItems from "../layout/nav-items";
|
||||
import { PostModalContext } from "../../providers/route/post-modal-provider";
|
||||
import { offlineMode } from "../../services/offline-mode";
|
||||
|
@ -51,7 +51,7 @@ export default function ReactionIconButton({
|
||||
</Suspense>
|
||||
);
|
||||
|
||||
if (useModal) {
|
||||
if (useModal)
|
||||
return (
|
||||
<>
|
||||
<IconButton
|
||||
@ -68,7 +68,7 @@ export default function ReactionIconButton({
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
} else
|
||||
else
|
||||
return (
|
||||
<Popover isLazy isOpen={isOpen} onOpen={open.on} onClose={open.off}>
|
||||
<PopoverTrigger>
|
||||
|
@ -1,27 +1,35 @@
|
||||
html,
|
||||
body {
|
||||
html {
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#root {
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
body,
|
||||
#root {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
body {
|
||||
--safe-top: env(safe-area-inset-top, 0px);
|
||||
--safe-bottom: env(safe-area-inset-bottom, 0px);
|
||||
--safe-right: env(safe-area-inset-right, 0px);
|
||||
--safe-left: env(safe-area-inset-left, 0px);
|
||||
|
||||
/* uncomment this to emulate iphone notch and navbar */
|
||||
/* --safe-top: env(safe-area-inset-top, 30px);
|
||||
--safe-bottom: env(safe-area-inset-bottom, 30px);
|
||||
--safe-right: env(safe-area-inset-right);
|
||||
--safe-left: env(safe-area-inset-left); */
|
||||
/* --safe-top: 30px;
|
||||
--safe-bottom: 30px;
|
||||
--safe-right: env(safe-area-inset-right);
|
||||
--safe-left: env(safe-area-inset-left); */
|
||||
}
|
||||
|
||||
body,
|
||||
#root {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
@ -92,11 +92,7 @@ export default function AccountSettings() {
|
||||
<AccountTypeBadge account={account} ml="4" />
|
||||
|
||||
<ButtonGroup size="sm" ml="auto">
|
||||
<Button
|
||||
onClick={() => accountService.switchAccount(account.pubkey)}
|
||||
colorScheme="primary"
|
||||
variant="ghost"
|
||||
>
|
||||
<Button onClick={() => accountService.switchAccount(account.pubkey)} variant="ghost">
|
||||
Switch
|
||||
</Button>
|
||||
<Button
|
||||
|
Loading…
x
Reference in New Issue
Block a user