import classNames from 'classnames'; import { is as ImmutableIs } from 'immutable'; import { throttle } from 'lodash'; import PropTypes from 'prop-types'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { Link, NavLink } from 'react-router-dom'; import { logOut, switchAccount } from 'soapbox/actions/auth'; import { fetchOwnAccounts } from 'soapbox/actions/auth'; import { getSettings } from 'soapbox/actions/settings'; import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import { getFeatures } from 'soapbox/utils/features'; import { closeSidebar } from '../actions/sidebar'; import ThemeToggle from '../features/ui/components/theme_toggle_container'; import { makeGetAccount, makeGetOtherAccounts } from '../selectors'; import { isAdmin, getBaseURL } from '../utils/accounts'; import Avatar from './avatar'; import DisplayName from './display_name'; import Icon from './icon'; import IconButton from './icon_button'; const messages = defineMessages({ followers: { id: 'account.followers', defaultMessage: 'Followers' }, follows: { id: 'account.follows', defaultMessage: 'Follows' }, profile: { id: 'account.profile', defaultMessage: 'Profile' }, invites: { id: 'navigation_bar.invites', defaultMessage: 'Invites' }, preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' }, domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' }, mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' }, filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' }, admin_settings: { id: 'navigation_bar.admin_settings', defaultMessage: 'Admin settings' }, soapbox_config: { id: 'navigation_bar.soapbox_config', defaultMessage: 'Soapbox config' }, import_data: { id: 'navigation_bar.import_data', defaultMessage: 'Import data' }, account_aliases: { id: 'navigation_bar.account_aliases', defaultMessage: 'Account aliases' }, security: { id: 'navigation_bar.security', defaultMessage: 'Security' }, logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' }, lists: { id: 'column.lists', defaultMessage: 'Lists' }, bookmarks: { id: 'column.bookmarks', defaultMessage: 'Bookmarks' }, profileDirectory: { id: 'column.profile_directory', defaultMessage: 'Profile directory' }, header: { id: 'tabs_bar.header', defaultMessage: 'Account Info' }, apps: { id: 'tabs_bar.apps', defaultMessage: 'Apps' }, news: { id: 'tabs_bar.news', defaultMessage: 'News' }, donate: { id: 'donate', defaultMessage: 'Donate' }, donate_crypto: { id: 'donate_crypto', defaultMessage: 'Donate cryptocurrency' }, info: { id: 'column.info', defaultMessage: 'Server information' }, developers: { id: 'navigation.developers', defaultMessage: 'Developers' }, add_account: { id: 'profile_dropdown.add_account', defaultMessage: 'Add an existing account' }, }); const makeMapStateToProps = () => { const getAccount = makeGetAccount(); const getOtherAccounts = makeGetOtherAccounts(); const mapStateToProps = state => { const me = state.get('me'); const account = state.getIn(['accounts', me]); const instance = state.get('instance'); const features = getFeatures(instance); const soapbox = getSoapboxConfig(state); return { account: getAccount(state, me), sidebarOpen: state.get('sidebar').sidebarOpen, donateUrl: state.getIn(['patron', 'instance', 'url']), hasCrypto: typeof soapbox.getIn(['cryptoAddresses', 0, 'ticker']) === 'string', otherAccounts: getOtherAccounts(state), features, instance, settings: getSettings(state), siteTitle: instance.get('title'), baseURL: getBaseURL(account), }; }; return mapStateToProps; }; const mapDispatchToProps = (dispatch, { intl }) => ({ onClose() { dispatch(closeSidebar()); }, onClickLogOut(e) { dispatch(logOut(intl)); e.preventDefault(); }, fetchOwnAccounts() { dispatch(fetchOwnAccounts()); }, switchAccount(account) { dispatch(switchAccount(account.get('id'))); }, }); export default @injectIntl @connect(makeMapStateToProps, mapDispatchToProps) class SidebarMenu extends ImmutablePureComponent { static propTypes = { intl: PropTypes.object.isRequired, account: ImmutablePropTypes.map, otherAccounts: ImmutablePropTypes.list, sidebarOpen: PropTypes.bool, onClose: PropTypes.func.isRequired, settings: PropTypes.object.isRequired, features: PropTypes.object.isRequired, instance: ImmutablePropTypes.map.isRequired, baseURL: PropTypes.string, }; state = { switcher: false, } handleClose = () => { this.setState({ switcher: false }); this.props.onClose(); } handleSwitchAccount = account => { return e => { this.props.switchAccount(account); e.preventDefault(); }; } handleSwitcherClick = e => { this.setState({ switcher: !this.state.switcher }); e.preventDefault(); } fetchOwnAccounts = throttle(() => { this.props.fetchOwnAccounts(); }, 2000); componentDidMount() { this.fetchOwnAccounts(); } componentDidUpdate(prevProps) { const accountChanged = !ImmutableIs(prevProps.account, this.props.account); const otherAccountsChanged = !ImmutableIs(prevProps.otherAccounts, this.props.otherAccounts); if (accountChanged || otherAccountsChanged) { this.fetchOwnAccounts(); } if (this.props.sidebarOpen && !prevProps.sidebarOpen) { document.querySelector('.sidebar-menu__close').focus(); } } renderAccount = account => { return (
); } render() { const { sidebarOpen, intl, account, onClickLogOut, donateUrl, otherAccounts, hasCrypto, settings, features, instance, siteTitle, baseURL } = this.props; const { switcher } = this.state; if (!account) return null; const acct = account.get('acct'); const classes = classNames('sidebar-menu__root', { 'sidebar-menu__root--visible': sidebarOpen, }); return (
{switcher &&
{otherAccounts.map(account => this.renderAccount(account))} {intl.formatMessage(messages.add_account)}
}
{features.federating ? ( {siteTitle} ) : ( )} {features.federating && }
{intl.formatMessage(messages.profile)} {instance.get('invites_enabled') && {intl.formatMessage(messages.invites)} } {donateUrl && {intl.formatMessage(messages.donate)} } {hasCrypto && {intl.formatMessage(messages.donate_crypto)} } {features.lists && {intl.formatMessage(messages.lists)} } {features.bookmarks && {intl.formatMessage(messages.bookmarks)} } {features.profileDirectory && {intl.formatMessage(messages.profileDirectory)} }
{intl.formatMessage(messages.follow_requests)} {intl.formatMessage(messages.blocks)} {features.federating && {intl.formatMessage(messages.domain_blocks)} } {intl.formatMessage(messages.mutes)} {intl.formatMessage(messages.filters)} {isAdmin(account) && {intl.formatMessage(messages.admin_settings)} } {isAdmin(account) && {intl.formatMessage(messages.soapbox_config)} } {features.settingsStore ? ( {intl.formatMessage(messages.preferences)} ) : ( {intl.formatMessage(messages.preferences)} )} {features.importAPI ? ( {intl.formatMessage(messages.import_data)} ) : ( {intl.formatMessage(messages.import_data)} )} {(features.federating && features.accountAliasesAPI) && {intl.formatMessage(messages.account_aliases)} } {features.securityAPI ? ( {intl.formatMessage(messages.security)} ) : ( {intl.formatMessage(messages.security)} )}
{intl.formatMessage(messages.info)}
{(settings.get('isDeveloper')) && ( {intl.formatMessage(messages.developers)} )}
{intl.formatMessage(messages.logout)}
); } }