/* eslint-disable jsx-a11y/interactive-supports-focus */ import clsx from 'clsx'; import React, { useCallback, useEffect, useState } from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; import { Link, NavLink } from 'react-router-dom'; import { fetchOwnAccounts, logOut, switchAccount } from 'soapbox/actions/auth'; import { getSettings } from 'soapbox/actions/settings'; import { closeSidebar } from 'soapbox/actions/sidebar'; import { useAccount } from 'soapbox/api/hooks'; import Account from 'soapbox/components/account'; import { Stack, Divider, HStack, Icon, Text } from 'soapbox/components/ui'; import ProfileStats from 'soapbox/features/ui/components/profile-stats'; import { useAppDispatch, useAppSelector, useFeatures, useInstance } from 'soapbox/hooks'; import { makeGetOtherAccounts } from 'soapbox/selectors'; import type { List as ImmutableList } from 'immutable'; import type { Account as AccountEntity } from 'soapbox/normalizers'; const messages = defineMessages({ profile: { id: 'account.profile', defaultMessage: 'Profile' }, preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, followedTags: { id: 'navigation_bar.followed_tags', defaultMessage: 'Followed hashtags' }, logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' }, profileDirectory: { id: 'navigation_bar.profile_directory', defaultMessage: 'Profile directory' }, bookmarks: { id: 'column.bookmarks', defaultMessage: 'Bookmarks' }, lists: { id: 'column.lists', defaultMessage: 'Lists' }, groups: { id: 'column.groups', defaultMessage: 'Groups' }, events: { id: 'column.events', defaultMessage: 'Events' }, developers: { id: 'navigation.developers', defaultMessage: 'Developers' }, dashboard: { id: 'navigation.dashboard', defaultMessage: 'Dashboard' }, drafts: { id: 'navigation.drafts', defaultMessage: 'Drafts' }, addAccount: { id: 'profile_dropdown.add_account', defaultMessage: 'Add an existing account' }, followRequests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, close: { id: 'lightbox.close', defaultMessage: 'Close' }, login: { id: 'account.login', defaultMessage: 'Log in' }, register: { id: 'account.register', defaultMessage: 'Sign up' }, }); interface ISidebarLink { href?: string; to?: string; icon: string; text: string | JSX.Element; onClick: React.EventHandler; } const SidebarLink: React.FC = ({ href, to, icon, text, onClick }) => { const body = (
{text}
); if (to) { return ( {body} ); } return ( {body} ); }; const SidebarMenu: React.FC = (): JSX.Element | null => { const intl = useIntl(); const dispatch = useAppDispatch(); const getOtherAccounts = useCallback(makeGetOtherAccounts(), []); const features = useFeatures(); const me = useAppSelector((state) => state.me); const { account } = useAccount(me || undefined); const otherAccounts: ImmutableList = useAppSelector((state) => getOtherAccounts(state)); const sidebarOpen = useAppSelector((state) => state.sidebar.sidebarOpen); const settings = useAppSelector((state) => getSettings(state)); const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.count()); const draftCount = useAppSelector((state) => state.draft_statuses.size); // const dashboardCount = useAppSelector((state) => state.admin.openReports.count() + state.admin.awaitingApproval.count()); const [sidebarVisible, setSidebarVisible] = useState(sidebarOpen); const [touchStart, setTouchStart] = useState(0); const [touchEnd, setTouchEnd] = useState(0); const instance = useInstance(); const restrictUnauth = instance.pleroma.metadata.restrict_unauthenticated; const containerRef = React.useRef(null); const [switcher, setSwitcher] = React.useState(false); const onClose = () => dispatch(closeSidebar()); const handleClose = () => { setSwitcher(false); onClose(); }; const handleSwitchAccount = (account: AccountEntity): React.MouseEventHandler => (e) => { e.preventDefault(); e.stopPropagation(); dispatch(switchAccount(account.id)); }; const onClickLogOut: React.MouseEventHandler = (e) => { e.preventDefault(); e.stopPropagation(); dispatch(logOut()); }; const handleSwitcherClick: React.MouseEventHandler = (e) => { e.preventDefault(); e.stopPropagation(); setSwitcher((prevState) => (!prevState)); }; const renderAccount = (account: AccountEntity) => (
); const handleOutsideClick: React.MouseEventHandler = (e) => { if ((e.target as HTMLElement).isSameNode(e.currentTarget)) handleClose(); }; const handleKeyDown: React.KeyboardEventHandler = (e) => { if (e.key === 'Escape') handleClose(); }; const handleTouchStart: React.TouchEventHandler = (e) => setTouchStart(e.targetTouches[0].clientX); const handleTouchMove: React.TouchEventHandler = (e) => setTouchEnd(e.targetTouches[0].clientX); const handleTouchEnd = () => { if (touchStart - touchEnd > 100) { handleClose(); } }; useEffect(() => { dispatch(fetchOwnAccounts()); }, []); useEffect(() => { if (sidebarOpen) containerRef.current?.querySelector('a')?.focus(); setTimeout(() => setSidebarVisible(sidebarOpen), sidebarOpen ? 0 : 150); }, [sidebarOpen]); return (
{account ? ( {(account.locked || followRequestsCount > 0) && ( )} {features.bookmarks && ( )} {features.groups && ( )} {features.lists && ( )} {features.events && ( )} {features.profileDirectory && ( )} {draftCount > 0 && ( )} {features.publicTimeline && <> : } onClick={onClose} /> {features.federating && ( } onClick={onClose} /> )} {features.bubbleTimeline && ( } onClick={onClose} /> )} } {features.followedHashtagsList && ( )} {settings.get('isDeveloper') && ( )} {(account.is_admin || account.is_moderator) && ( )} {switcher && (
{otherAccounts.map(account => renderAccount(account))} {intl.formatMessage(messages.addAccount)}
)}
) : ( {features.publicTimeline && !restrictUnauth.timelines.local && <> : } onClick={onClose} /> {features.federating && !restrictUnauth.timelines.federated && ( } onClick={onClose} /> )} {features.bubbleTimeline && !restrictUnauth.timelines.bubble && ( } onClick={onClose} /> )} } )}
); }; export { SidebarMenu as default };