mirror of
https://github.com/mastodon/mastodon.git
synced 2026-10-21 03:52:40 -05:00
Redesign: Update main actions when visiting the profile of someone you follow (#40809)
This commit is contained in:
@@ -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 && (
|
||||
<FollowButton
|
||||
compact={isRedesignEnabled()}
|
||||
accountId={accountId}
|
||||
@@ -98,39 +117,42 @@ const AccountButtonsOther: FC<
|
||||
reference={reference}
|
||||
/>
|
||||
)}
|
||||
{isFollowing &&
|
||||
(isRedesignEnabled() ? (
|
||||
<ToggleIconButton
|
||||
{isFollowing && isRedesignEnabled() && (
|
||||
<>
|
||||
<Button
|
||||
leadingIcon={ChatCircleDotsIcon}
|
||||
size='sm'
|
||||
icon={relationship.notifying ? BellSlashIcon : BellIcon}
|
||||
active={relationship.notifying}
|
||||
onClick={handleNotifyToggle}
|
||||
variant='solid'
|
||||
color='accent'
|
||||
onClick={sendDirectMessage}
|
||||
>
|
||||
{intl.formatMessage(
|
||||
relationship.notifying
|
||||
? messages.disableNotifications
|
||||
: messages.enableNotifications,
|
||||
{ name: account.username },
|
||||
)}
|
||||
</ToggleIconButton>
|
||||
) : (
|
||||
<LegacyIconButton
|
||||
icon={relationship.notifying ? 'bell' : 'bell-o'}
|
||||
iconComponent={
|
||||
relationship.notifying
|
||||
? NotificationsActiveIcon
|
||||
: NotificationsIcon
|
||||
}
|
||||
active={relationship.notifying}
|
||||
title={intl.formatMessage(
|
||||
relationship.notifying
|
||||
? messages.disableNotifications
|
||||
: messages.enableNotifications,
|
||||
{ name: account.username },
|
||||
)}
|
||||
onClick={handleNotifyToggle}
|
||||
/>
|
||||
))}
|
||||
<FormattedMessage
|
||||
id='account.menu.message'
|
||||
defaultMessage='Message'
|
||||
description='Message refers to a direct message. For languages where this is confusing, "chat" or "direct message" can be used.'
|
||||
/>
|
||||
</Button>
|
||||
<IconButton icon={UserMinusIcon} size='sm' onClick={confirmUnfollow}>
|
||||
<FormattedMessage id='account.unfollow' defaultMessage='Unfollow' />
|
||||
</IconButton>
|
||||
</>
|
||||
)}
|
||||
{isFollowing && !isRedesignEnabled() && (
|
||||
<LegacyIconButton
|
||||
icon={relationship.notifying ? 'bell' : 'bell-o'}
|
||||
iconComponent={
|
||||
relationship.notifying ? NotificationsActiveIcon : NotificationsIcon
|
||||
}
|
||||
active={relationship.notifying}
|
||||
title={intl.formatMessage(
|
||||
relationship.notifying
|
||||
? messages.disableNotifications
|
||||
: messages.enableNotifications,
|
||||
{ name: account.username },
|
||||
)}
|
||||
onClick={handleNotifyToggle}
|
||||
/>
|
||||
)}
|
||||
{!noShare &&
|
||||
(isRedesignEnabled() ? (
|
||||
<CopyIconButton
|
||||
|
||||
@@ -221,6 +221,14 @@ const messages = defineMessages({
|
||||
id: 'status.admin_domain',
|
||||
defaultMessage: 'Open moderation interface for {domain}',
|
||||
},
|
||||
enableNotifications: {
|
||||
id: 'account.notify_me',
|
||||
defaultMessage: 'Notify me about new posts',
|
||||
},
|
||||
disableNotifications: {
|
||||
id: 'account.stop_notifying_me',
|
||||
defaultMessage: 'Stop notifying me about new posts',
|
||||
},
|
||||
languages: {
|
||||
id: 'account.languages',
|
||||
defaultMessage: 'Change subscribed languages',
|
||||
@@ -289,17 +297,19 @@ function getMenuItems({
|
||||
|
||||
// Mention and direct message options
|
||||
if (signedIn && !account.suspended) {
|
||||
items.push(null);
|
||||
if (!account.invalid_handle) {
|
||||
if (isRedesignEnabled()) {
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.redesignMessage),
|
||||
action: () => {
|
||||
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(
|
||||
|
||||
@@ -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<RedesignButtonProps, 'size' | 'color' | 'className'>
|
||||
> = ({ 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 (
|
||||
<RedesignButton as='link' to={link} {...buttonProps}>
|
||||
<RedesignButton
|
||||
as='link'
|
||||
to={link}
|
||||
leadingIcon={leadingIcon}
|
||||
{...buttonProps}
|
||||
>
|
||||
{label}
|
||||
</RedesignButton>
|
||||
);
|
||||
@@ -266,6 +282,7 @@ const FollowButtonRedesign: React.FC<
|
||||
return (
|
||||
<RedesignButton
|
||||
{...buttonProps}
|
||||
leadingIcon={leadingIcon}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
variant={secondary ? 'tonal' : 'solid'}
|
||||
|
||||
@@ -133,12 +133,14 @@
|
||||
"account.node_modal.title": "Add a personal note",
|
||||
"account.note.edit_button": "Edit",
|
||||
"account.note.title": "Personal note (visible only to you)",
|
||||
"account.notify_me": "Notify me about new posts",
|
||||
"account.open_original_page": "Open original page",
|
||||
"account.pending": "Pending",
|
||||
"account.posts": "Posts",
|
||||
"account.requested_follow": "{name} has requested to follow you",
|
||||
"account.share": "Share @{name}'s profile",
|
||||
"account.statuses_counter": "{count, plural, one {{counter} post} other {{counter} posts}}",
|
||||
"account.stop_notifying_me": "Stop notifying me about new posts",
|
||||
"account.timeline.pinned": "Pinned",
|
||||
"account.timeline.pinned.view_all": "View all pinned posts",
|
||||
"account.unblock": "Unblock @{name}",
|
||||
|
||||
Reference in New Issue
Block a user