|
|
|
@ -22,13 +22,14 @@ import SvgIcon from 'soapbox/components/ui/icon/svg-icon';
|
|
|
|
|
import MovedNote from 'soapbox/features/account-timeline/components/moved-note';
|
|
|
|
|
import ActionButton from 'soapbox/features/ui/components/action-button';
|
|
|
|
|
import SubscriptionButton from 'soapbox/features/ui/components/subscription-button';
|
|
|
|
|
import { useAppDispatch, useFeatures, useOwnAccount } from 'soapbox/hooks';
|
|
|
|
|
import { useAppDispatch, useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks';
|
|
|
|
|
import { normalizeAttachment } from 'soapbox/normalizers';
|
|
|
|
|
import { ChatKeys, useChats } from 'soapbox/queries/chats';
|
|
|
|
|
import { queryClient } from 'soapbox/queries/client';
|
|
|
|
|
import toast from 'soapbox/toast';
|
|
|
|
|
import { Account } from 'soapbox/types/entities';
|
|
|
|
|
import { isDefaultHeader, isRemote } from 'soapbox/utils/accounts';
|
|
|
|
|
import { isDefaultHeader, isLocal, isRemote } from 'soapbox/utils/accounts';
|
|
|
|
|
import { MASTODON, parseVersion } from 'soapbox/utils/features';
|
|
|
|
|
|
|
|
|
|
import type { Menu as MenuType } from 'soapbox/components/dropdown-menu';
|
|
|
|
|
|
|
|
|
@ -71,6 +72,7 @@ const messages = defineMessages({
|
|
|
|
|
userUnendorsed: { id: 'account.unendorse.success', defaultMessage: 'You are no longer featuring @{acct}' },
|
|
|
|
|
profileExternal: { id: 'account.profile_external', defaultMessage: 'View profile on {domain}' },
|
|
|
|
|
header: { id: 'account.header.alt', defaultMessage: 'Profile header' },
|
|
|
|
|
subscribeFeed: { id: 'account.rss_feed', defaultMessage: 'Subscribe to RSS feed' },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
interface IHeader {
|
|
|
|
@ -85,6 +87,8 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
|
|
|
|
const features = useFeatures();
|
|
|
|
|
const ownAccount = useOwnAccount();
|
|
|
|
|
|
|
|
|
|
const { software } = useAppSelector((state) => parseVersion(state.instance.version));
|
|
|
|
|
|
|
|
|
|
const { getOrCreateChatByAccountId } = useChats();
|
|
|
|
|
|
|
|
|
|
const createAndNavigateToChat = useMutation((accountId: string) => {
|
|
|
|
@ -257,6 +261,10 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleRssFeedClick = () => {
|
|
|
|
|
window.open(software === MASTODON ? `${account.url}.rss` : `${account.url}/feed.rss`, '_blank');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleShare = () => {
|
|
|
|
|
navigator.share({
|
|
|
|
|
text: `@${account.acct}`,
|
|
|
|
@ -269,20 +277,43 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
|
|
|
|
const makeMenu = () => {
|
|
|
|
|
const menu: MenuType = [];
|
|
|
|
|
|
|
|
|
|
if (!account || !ownAccount) {
|
|
|
|
|
if (!account) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (features.rssFeeds && isLocal(account)) {
|
|
|
|
|
menu.push({
|
|
|
|
|
text: intl.formatMessage(messages.subscribeFeed),
|
|
|
|
|
action: handleRssFeedClick,
|
|
|
|
|
icon: require('@tabler/icons/rss.svg'),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ('share' in navigator) {
|
|
|
|
|
menu.push({
|
|
|
|
|
text: intl.formatMessage(messages.share, { name: account.username }),
|
|
|
|
|
action: handleShare,
|
|
|
|
|
icon: require('@tabler/icons/upload.svg'),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (features.federating && isRemote(account)) {
|
|
|
|
|
const domain = account.fqn.split('@')[1];
|
|
|
|
|
|
|
|
|
|
menu.push({
|
|
|
|
|
text: intl.formatMessage(messages.profileExternal, { domain }),
|
|
|
|
|
action: () => onProfileExternal(account.url),
|
|
|
|
|
icon: require('@tabler/icons/external-link.svg'),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ownAccount) return menu;
|
|
|
|
|
|
|
|
|
|
if (menu.length) {
|
|
|
|
|
menu.push(null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (account.id === ownAccount?.id) {
|
|
|
|
|
if (account.id === ownAccount.id) {
|
|
|
|
|
menu.push({
|
|
|
|
|
text: intl.formatMessage(messages.edit_profile),
|
|
|
|
|
to: '/settings/profile',
|
|
|
|
@ -435,17 +466,9 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
|
|
|
|
icon: require('@tabler/icons/ban.svg'),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (features.federating) {
|
|
|
|
|
menu.push({
|
|
|
|
|
text: intl.formatMessage(messages.profileExternal, { domain }),
|
|
|
|
|
action: () => onProfileExternal(account.url),
|
|
|
|
|
icon: require('@tabler/icons/external-link.svg'),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ownAccount?.staff) {
|
|
|
|
|
if (ownAccount.staff) {
|
|
|
|
|
menu.push(null);
|
|
|
|
|
|
|
|
|
|
menu.push({
|
|
|
|
@ -463,7 +486,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
|
|
|
|
|
|
|
|
|
if (!account || !ownAccount) return info;
|
|
|
|
|
|
|
|
|
|
if (ownAccount?.id !== account.id && account.relationship?.followed_by) {
|
|
|
|
|
if (ownAccount.id !== account.id && account.relationship?.followed_by) {
|
|
|
|
|
info.push(
|
|
|
|
|
<Badge
|
|
|
|
|
key='followed_by'
|
|
|
|
@ -471,7 +494,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
|
|
|
|
title={<FormattedMessage id='account.follows_you' defaultMessage='Follows you' />}
|
|
|
|
|
/>,
|
|
|
|
|
);
|
|
|
|
|
} else if (ownAccount?.id !== account.id && account.relationship?.blocking) {
|
|
|
|
|
} else if (ownAccount.id !== account.id && account.relationship?.blocking) {
|
|
|
|
|
info.push(
|
|
|
|
|
<Badge
|
|
|
|
|
key='blocked'
|
|
|
|
@ -481,7 +504,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ownAccount?.id !== account.id && account.relationship?.muting) {
|
|
|
|
|
if (ownAccount.id !== account.id && account.relationship?.muting) {
|
|
|
|
|
info.push(
|
|
|
|
|
<Badge
|
|
|
|
|
key='muted'
|
|
|
|
@ -489,7 +512,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
|
|
|
|
title={<FormattedMessage id='account.muted' defaultMessage='Muted' />}
|
|
|
|
|
/>,
|
|
|
|
|
);
|
|
|
|
|
} else if (ownAccount?.id !== account.id && account.relationship?.domain_blocking) {
|
|
|
|
|
} else if (ownAccount.id !== account.id && account.relationship?.domain_blocking) {
|
|
|
|
|
info.push(
|
|
|
|
|
<Badge
|
|
|
|
|
key='domain_blocked'
|
|
|
|
@ -621,7 +644,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
|
|
|
|
{renderMessageButton()}
|
|
|
|
|
{renderShareButton()}
|
|
|
|
|
|
|
|
|
|
{ownAccount && (
|
|
|
|
|
{menu.length > 0 && (
|
|
|
|
|
<Menu>
|
|
|
|
|
<MenuButton
|
|
|
|
|
as={IconButton}
|
|
|
|
|