diff --git a/app/javascript/mastodon/components/account_header/buttons.tsx b/app/javascript/mastodon/components/account_header/buttons.tsx index c66ae9b0892..594e27e2bd7 100644 --- a/app/javascript/mastodon/components/account_header/buttons.tsx +++ b/app/javascript/mastodon/components/account_header/buttons.tsx @@ -1,11 +1,13 @@ import { useCallback } from 'react'; import type { FC } from 'react'; -import { defineMessages, useIntl } from 'react-intl'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; -import { BellIcon, BellSlashIcon } from '@phosphor-icons/react'; +import { ChatCircleDotsIcon, UserMinusIcon } from '@phosphor-icons/react'; import { followAccount } from '@/mastodon/actions/accounts'; +import { directCompose } from '@/mastodon/actions/compose'; +import { openModal } from '@/mastodon/actions/modal'; import { useAccount } from '@/mastodon/hooks/useAccount'; import { useFollowReference } from '@/mastodon/hooks/useFollowReference'; import { getAccountHidden } from '@/mastodon/selectors/accounts'; @@ -14,7 +16,7 @@ import { isRedesignEnabled } from '@/mastodon/utils/environment'; import NotificationsIcon from '@/material-icons/400-24px/notifications.svg?react'; import NotificationsActiveIcon from '@/material-icons/400-24px/notifications_active-fill.svg?react'; -import { ToggleIconButton } from '../button/redesign'; +import { Button, IconButton } from '../button/redesign'; import { CopyIconButton, CopyIconButtonLegacy } from '../copy_button'; import { FollowButton } from '../follow_button'; import { IconButton as LegacyIconButton } from '../icon_button'; @@ -71,12 +73,27 @@ const AccountButtonsOther: FC< ); const dispatch = useAppDispatch(); + const handleNotifyToggle = useCallback(() => { if (account) { dispatch(followAccount(account.id, { notify: !relationship?.notifying })); } }, [dispatch, account, relationship]); + const sendDirectMessage = useCallback(() => { + if (account) { + dispatch(directCompose(account)); + } + }, [dispatch, account]); + + const confirmUnfollow = useCallback(() => { + if (account) { + dispatch( + openModal({ modalType: 'CONFIRM_UNFOLLOW', modalProps: { account } }), + ); + } + }, [dispatch, account]); + const reference = useFollowReference('profile'); if (!account) { @@ -86,9 +103,11 @@ const AccountButtonsOther: FC< const isMovedAndUnfollowedAccount = account.moved && !relationship?.following; const isFollowing = relationship?.requested || relationship?.following; + const shouldHideMainFollowButton = isRedesignEnabled() && isFollowing; + return ( <> - {!isMovedAndUnfollowedAccount && ( + {!shouldHideMainFollowButton && !isMovedAndUnfollowedAccount && ( )} - {isFollowing && - (isRedesignEnabled() ? ( - + + + + + + )} + {isFollowing && !isRedesignEnabled() && ( + + )} {!noShare && (isRedesignEnabled() ? ( { - dispatch(directCompose(account)); - }, - }); + if (!relationship?.following) { + items.push(null, { + text: intl.formatMessage(messages.redesignMessage), + action: () => { + dispatch(directCompose(account)); + }, + }); + } } else { items.push( + null, { text: intl.formatMessage(messages.mention), action: () => { @@ -400,6 +410,21 @@ function getMenuItems({ // Timeline options if (relationship?.following && !relationship.muting) { + if (isRedesignEnabled()) { + items.push({ + text: intl.formatMessage( + relationship.notifying + ? messages.disableNotifications + : messages.enableNotifications, + { name: account.username }, + ), + action: () => { + dispatch( + followAccount(account.id, { notify: !relationship.notifying }), + ); + }, + }); + } items.push( { text: intl.formatMessage( diff --git a/app/javascript/mastodon/components/follow_button.tsx b/app/javascript/mastodon/components/follow_button.tsx index ec6c7896c4c..165ddd16e38 100644 --- a/app/javascript/mastodon/components/follow_button.tsx +++ b/app/javascript/mastodon/components/follow_button.tsx @@ -5,6 +5,9 @@ import { useIntl, defineMessages } from 'react-intl'; import classNames from 'classnames'; import { Link } from 'react-router-dom'; +import type { Icon } from '@phosphor-icons/react'; +import { UserMinusIcon, UserPlusIcon } from '@phosphor-icons/react'; + import { useIdentity } from '@/mastodon/identity_context'; import { fetchRelationships, @@ -69,6 +72,7 @@ interface FollowButtonOptions { interface FollowButtonReturn { label: React.ReactNode; + icon: Icon | undefined; onClick: (() => void) | undefined; link: MastodonLocationDescriptor | undefined; disabled: boolean; @@ -163,11 +167,13 @@ export function useFollowButton({ : messages.follow; let label: React.ReactNode; + let icon: Icon | undefined; let disabled = relationship?.blocked_by || account?.suspended || !!account?.moved; if (!signedIn) { label = intl.formatMessage(followMessage); + icon = UserPlusIcon; } else if (accountId === me) { label = intl.formatMessage(messages.editProfile); } else if (!relationship) { @@ -177,6 +183,7 @@ export function useFollowButton({ disabled = false; } else if (relationship.following) { label = intl.formatMessage(messages.unfollow); + icon = UserMinusIcon; disabled = false; } else if (relationship.blocking) { label = intl.formatMessage(messages.unblock); @@ -186,8 +193,10 @@ export function useFollowButton({ disabled = false; } else if (relationship.followed_by && !account?.locked) { label = intl.formatMessage(messages.followBack); + icon = UserPlusIcon; } else { label = intl.formatMessage(followMessage); + icon = UserPlusIcon; } const isMovedAndUnfollowedAccount = @@ -197,6 +206,7 @@ export function useFollowButton({ onClick, link, label, + icon, disabled, following, secondary, @@ -242,22 +252,28 @@ const FollowButtonRedesign: React.FC< FollowButtonOptions & Pick > = ({ accountId, labelLength, withUnmute, reference, ...buttonProps }) => { - const { onClick, link, label, disabled, secondary, hidden } = useFollowButton( - { + const { onClick, link, label, icon, disabled, secondary, hidden } = + useFollowButton({ accountId, labelLength, withUnmute, reference, - }, - ); + }); if (hidden) { return null; } + const leadingIcon = labelLength === 'long' ? icon : undefined; + if (link) { return ( - + {label} ); @@ -266,6 +282,7 @@ const FollowButtonRedesign: React.FC< return (