import throttle from 'lodash/throttle'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import { Link } from 'react-router-dom'; import { fetchOwnAccounts, logOut, switchAccount } from 'soapbox/actions/auth'; import Account from 'soapbox/components/account'; import { Menu, MenuButton, MenuDivider, MenuItem, MenuLink, MenuList } from 'soapbox/components/ui'; import { useAppSelector, useFeatures } from 'soapbox/hooks'; import { makeGetAccount } from 'soapbox/selectors'; import ThemeToggle from './theme-toggle'; import type { Account as AccountEntity } from 'soapbox/types/entities'; const messages = defineMessages({ add: { id: 'profile_dropdown.add_account', defaultMessage: 'Add an existing account' }, theme: { id: 'profile_dropdown.theme', defaultMessage: 'Theme' }, logout: { id: 'profile_dropdown.logout', defaultMessage: 'Log out @{acct}' }, }); interface IProfileDropdown { account: AccountEntity } type IMenuItem = { text: string | React.ReactElement | null to?: string toggle?: JSX.Element icon?: string action?: (event: React.MouseEvent) => void } const getAccount = makeGetAccount(); const ProfileDropdown: React.FC = ({ account, children }) => { const dispatch = useDispatch(); const features = useFeatures(); const intl = useIntl(); const authUsers = useAppSelector((state) => state.auth.get('users')); const otherAccounts = useAppSelector((state) => authUsers.map((authUser: any) => getAccount(state, authUser.get('id')))); const handleLogOut = () => { dispatch(logOut()); }; const handleSwitchAccount = (account: AccountEntity) => { return () => { dispatch(switchAccount(account.id)); }; }; const fetchOwnAccountThrottled = throttle(() => { dispatch(fetchOwnAccounts()); }, 2000); const renderAccount = (account: AccountEntity) => { return ( ); }; const menu: IMenuItem[] = React.useMemo(() => { const menu: IMenuItem[] = []; menu.push({ text: renderAccount(account), to: `/@${account.acct}` }); otherAccounts.forEach((otherAccount: AccountEntity) => { if (otherAccount && otherAccount.id !== account.id) { menu.push({ text: renderAccount(otherAccount), action: handleSwitchAccount(otherAccount), }); } }); menu.push({ text: null }); menu.push({ text: intl.formatMessage(messages.theme), toggle: }); menu.push({ text: null }); menu.push({ text: intl.formatMessage(messages.add), to: '/login', icon: require('@tabler/icons/icons/plus.svg'), }); menu.push({ text: intl.formatMessage(messages.logout, { acct: account.acct }), to: '/logout', action: handleLogOut, icon: require('@tabler/icons/icons/logout.svg'), }); return menu; }, [account, authUsers, features]); React.useEffect(() => { fetchOwnAccountThrottled(); }, [account, authUsers]); return ( {children} {menu.map((menuItem, idx) => { if (menuItem.toggle) { return (
{menuItem.text} {menuItem.toggle}
); } else if (!menuItem.text) { return ; } else { const Comp: any = menuItem.action ? MenuItem : MenuLink; const itemProps = menuItem.action ? { onSelect: menuItem.action } : { to: menuItem.to, as: Link }; return ( {menuItem.text} ); } })}
); }; export default ProfileDropdown;