mirror of
https://github.com/mastodon/mastodon.git
synced 2026-04-25 16:05:44 -05:00
Profile redesign: Remove feature flag (#38513)
Some checks are pending
Check i18n / check-i18n (push) Waiting to run
Chromatic / Check for relevant changes (push) Waiting to run
Chromatic / Run Chromatic (push) Blocked by required conditions
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (ruby) (push) Waiting to run
Crowdin / Upload translations / upload-translations (push) Waiting to run
Check formatting / lint (push) Waiting to run
CSS Linting / lint (push) Waiting to run
JavaScript Linting / lint (push) Waiting to run
Ruby Linting / lint (push) Waiting to run
JavaScript Testing / test (push) Waiting to run
Historical data migration test / test (14-alpine) (push) Waiting to run
Historical data migration test / test (15-alpine) (push) Waiting to run
Historical data migration test / test (16-alpine) (push) Waiting to run
Historical data migration test / test (17-alpine) (push) Waiting to run
Ruby Testing / build (production) (push) Waiting to run
Ruby Testing / build (test) (push) Waiting to run
Ruby Testing / test (.ruby-version) (push) Blocked by required conditions
Ruby Testing / test (3.3) (push) Blocked by required conditions
Ruby Testing / test (3.4) (push) Blocked by required conditions
Ruby Testing / End to End testing (.ruby-version) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.3) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.4) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:8.19.2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, opensearchproject/opensearch:2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.3, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.4, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Blocked by required conditions
Some checks are pending
Check i18n / check-i18n (push) Waiting to run
Chromatic / Check for relevant changes (push) Waiting to run
Chromatic / Run Chromatic (push) Blocked by required conditions
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (ruby) (push) Waiting to run
Crowdin / Upload translations / upload-translations (push) Waiting to run
Check formatting / lint (push) Waiting to run
CSS Linting / lint (push) Waiting to run
JavaScript Linting / lint (push) Waiting to run
Ruby Linting / lint (push) Waiting to run
JavaScript Testing / test (push) Waiting to run
Historical data migration test / test (14-alpine) (push) Waiting to run
Historical data migration test / test (15-alpine) (push) Waiting to run
Historical data migration test / test (16-alpine) (push) Waiting to run
Historical data migration test / test (17-alpine) (push) Waiting to run
Ruby Testing / build (production) (push) Waiting to run
Ruby Testing / build (test) (push) Waiting to run
Ruby Testing / test (.ruby-version) (push) Blocked by required conditions
Ruby Testing / test (3.3) (push) Blocked by required conditions
Ruby Testing / test (3.4) (push) Blocked by required conditions
Ruby Testing / End to End testing (.ruby-version) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.3) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.4) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:8.19.2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, opensearchproject/opensearch:2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.3, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.4, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Blocked by required conditions
This commit is contained in:
parent
159d710bc1
commit
ca5c0a144a
|
|
@ -6,7 +6,6 @@ import classNames from 'classnames';
|
|||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { useIdentity } from '@/mastodon/identity_context';
|
||||
import { isServerFeatureEnabled } from '@/mastodon/utils/environment';
|
||||
import {
|
||||
fetchRelationships,
|
||||
followAccount,
|
||||
|
|
@ -171,23 +170,10 @@ export const FollowButton: React.FC<{
|
|||
'button--compact': compact,
|
||||
});
|
||||
|
||||
if (isServerFeatureEnabled('profile_redesign')) {
|
||||
return (
|
||||
<Link to='/profile/edit' className={buttonClasses}>
|
||||
{label}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<a
|
||||
href='/settings/profile'
|
||||
target='_blank'
|
||||
rel='noopener'
|
||||
className={buttonClasses}
|
||||
>
|
||||
<Link to='/profile/edit' className={buttonClasses}>
|
||||
{label}
|
||||
</a>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import { useHistory } from 'react-router';
|
|||
import { List as ImmutableList } from 'immutable';
|
||||
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { isServerFeatureEnabled } from '@/mastodon/utils/environment';
|
||||
import { fetchEndorsedAccounts } from 'mastodon/actions/accounts';
|
||||
import { fetchFeaturedTags } from 'mastodon/actions/featured_tags';
|
||||
import { Account } from 'mastodon/components/account';
|
||||
|
|
@ -49,11 +48,7 @@ const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({
|
|||
|
||||
const history = useHistory();
|
||||
useEffect(() => {
|
||||
if (
|
||||
account &&
|
||||
!account.show_featured &&
|
||||
isServerFeatureEnabled('profile_redesign')
|
||||
) {
|
||||
if (account && !account.show_featured) {
|
||||
history.push(`/@${account.acct}`);
|
||||
}
|
||||
}, [account, history]);
|
||||
|
|
@ -111,8 +106,7 @@ const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({
|
|||
);
|
||||
}
|
||||
|
||||
const noTags =
|
||||
featuredTags.isEmpty() || isServerFeatureEnabled('profile_redesign');
|
||||
const noTags = featuredTags.isEmpty();
|
||||
|
||||
if (
|
||||
noTags &&
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import { FormattedMessage } from 'react-intl';
|
|||
|
||||
import { List as ImmutableList, isList } from 'immutable';
|
||||
|
||||
import { isServerFeatureEnabled } from '@/mastodon/utils/environment';
|
||||
import { openModal } from 'mastodon/actions/modal';
|
||||
import { expandAccountMediaTimeline } from 'mastodon/actions/timelines';
|
||||
import { ColumnBackButton } from 'mastodon/components/column_back_button';
|
||||
|
|
@ -27,8 +26,6 @@ import { MediaItem } from './components/media_item';
|
|||
|
||||
const emptyList = ImmutableList<MediaAttachment>();
|
||||
|
||||
const redesignEnabled = isServerFeatureEnabled('profile_redesign');
|
||||
|
||||
const selectGalleryTimeline = createAppSelector(
|
||||
[
|
||||
(_state, accountId?: string | null) => accountId,
|
||||
|
|
@ -58,7 +55,7 @@ const selectGalleryTimeline = createAppSelector(
|
|||
|
||||
const { show_media, show_media_replies } = account;
|
||||
// If the account disabled showing media, don't display anything.
|
||||
if (!show_media && redesignEnabled) {
|
||||
if (!show_media) {
|
||||
return {
|
||||
items,
|
||||
hasMore: false,
|
||||
|
|
@ -67,7 +64,7 @@ const selectGalleryTimeline = createAppSelector(
|
|||
};
|
||||
}
|
||||
|
||||
const withReplies = show_media_replies && redesignEnabled;
|
||||
const withReplies = show_media_replies;
|
||||
const timeline = timelines.get(
|
||||
`account:${accountId}:media${withReplies ? ':with_replies' : ''}`,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,4 @@
|
|||
import type { AccountFieldShape } from '@/mastodon/models/account';
|
||||
import { isServerFeatureEnabled } from '@/mastodon/utils/environment';
|
||||
|
||||
export function isRedesignEnabled() {
|
||||
return isServerFeatureEnabled('profile_redesign');
|
||||
}
|
||||
|
||||
export interface AccountField extends AccountFieldShape {
|
||||
nameHasEmojis: boolean;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import { openModal } from '@/mastodon/actions/modal';
|
|||
import { AccountBio } from '@/mastodon/components/account_bio';
|
||||
import { Avatar } from '@/mastodon/components/avatar';
|
||||
import { AnimateEmojiProvider } from '@/mastodon/components/emoji/context';
|
||||
import { AccountNote } from '@/mastodon/features/account/components/account_note';
|
||||
import FollowRequestNoteContainer from '@/mastodon/features/account/containers/follow_request_note_container';
|
||||
import { useLayout } from '@/mastodon/hooks/useLayout';
|
||||
import { useVisibility } from '@/mastodon/hooks/useVisibility';
|
||||
|
|
@ -20,15 +19,12 @@ import type { Account } from '@/mastodon/models/account';
|
|||
import { getAccountHidden } from '@/mastodon/selectors/accounts';
|
||||
import { useAppSelector, useAppDispatch } from '@/mastodon/store';
|
||||
|
||||
import { isRedesignEnabled } from '../common';
|
||||
|
||||
import { AccountName } from './account_name';
|
||||
import { AccountSubscriptionForm } from './account_subscription_form';
|
||||
import { AccountBadges } from './badges';
|
||||
import { AccountButtons } from './buttons';
|
||||
import { FamiliarFollowers } from './familiar_followers';
|
||||
import { AccountHeaderFields } from './fields';
|
||||
import { AccountInfo } from './info';
|
||||
import { MemorialNote } from './memorial_note';
|
||||
import { MovedNote } from './moved_note';
|
||||
import { AccountNote as AccountNoteRedesign } from './note';
|
||||
|
|
@ -52,8 +48,6 @@ export const AccountHeader: React.FC<{
|
|||
accountId: string;
|
||||
hideTabs?: boolean;
|
||||
}> = ({ accountId, hideTabs }) => {
|
||||
const isRedesign = isRedesignEnabled();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const account = useAppSelector((state) => state.accounts.get(accountId));
|
||||
const relationship = useAppSelector((state) =>
|
||||
|
|
@ -120,13 +114,9 @@ export const AccountHeader: React.FC<{
|
|||
<div
|
||||
className={classNames(
|
||||
'account__header__image',
|
||||
isRedesign && redesignClasses.header,
|
||||
redesignClasses.header,
|
||||
)}
|
||||
>
|
||||
{me !== account.id && relationship && !isRedesign && (
|
||||
<AccountInfo relationship={relationship} />
|
||||
)}
|
||||
|
||||
{!suspendedOrHidden && (
|
||||
<img
|
||||
src={autoPlayGif ? account.header : account.header_static}
|
||||
|
|
@ -139,13 +129,13 @@ export const AccountHeader: React.FC<{
|
|||
<div
|
||||
className={classNames(
|
||||
'account__header__bar',
|
||||
isRedesign && redesignClasses.barWrapper,
|
||||
redesignClasses.barWrapper,
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
'account__header__tabs',
|
||||
isRedesign && redesignClasses.avatarWrapper,
|
||||
redesignClasses.avatarWrapper,
|
||||
)}
|
||||
>
|
||||
<a
|
||||
|
|
@ -157,33 +147,24 @@ export const AccountHeader: React.FC<{
|
|||
>
|
||||
<Avatar
|
||||
account={suspendedOrHidden ? undefined : account}
|
||||
size={isRedesign ? 80 : 92}
|
||||
size={80}
|
||||
/>
|
||||
</a>
|
||||
|
||||
{!isRedesign && (
|
||||
<AccountButtons
|
||||
accountId={accountId}
|
||||
className='account__header__buttons--desktop'
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={classNames(
|
||||
'account__header__tabs__name',
|
||||
isRedesign && redesignClasses.nameWrapper,
|
||||
redesignClasses.nameWrapper,
|
||||
)}
|
||||
>
|
||||
<AccountName accountId={accountId} />
|
||||
{isRedesign && (
|
||||
<AccountButtons
|
||||
accountId={accountId}
|
||||
className={redesignClasses.buttonsDesktop}
|
||||
noShare={!isMe || 'share' in navigator}
|
||||
forceMenu={'share' in navigator}
|
||||
/>
|
||||
)}
|
||||
<AccountButtons
|
||||
accountId={accountId}
|
||||
className={redesignClasses.buttonsDesktop}
|
||||
noShare={!isMe || 'share' in navigator}
|
||||
forceMenu={'share' in navigator}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<AccountBadges accountId={accountId} />
|
||||
|
|
@ -192,31 +173,19 @@ export const AccountHeader: React.FC<{
|
|||
<FamiliarFollowers accountId={accountId} />
|
||||
)}
|
||||
|
||||
{!isRedesign && (
|
||||
<AccountButtons
|
||||
className='account__header__buttons--mobile'
|
||||
accountId={accountId}
|
||||
noShare
|
||||
/>
|
||||
)}
|
||||
|
||||
{!suspendedOrHidden && (
|
||||
<div className='account__header__extra'>
|
||||
<div className='account__header__bio'>
|
||||
{me &&
|
||||
account.id !== me &&
|
||||
(isRedesign ? (
|
||||
<AccountNoteRedesign accountId={accountId} />
|
||||
) : (
|
||||
<AccountNote accountId={accountId} />
|
||||
))}
|
||||
{me && account.id !== me && (
|
||||
<AccountNoteRedesign accountId={accountId} />
|
||||
)}
|
||||
|
||||
<AccountBio
|
||||
showDropdown
|
||||
accountId={accountId}
|
||||
className={classNames(
|
||||
'account__header__content',
|
||||
isRedesign && redesignClasses.bio,
|
||||
redesignClasses.bio,
|
||||
)}
|
||||
/>
|
||||
|
||||
|
|
@ -231,20 +200,18 @@ export const AccountHeader: React.FC<{
|
|||
</div>
|
||||
)}
|
||||
|
||||
{isRedesign && (
|
||||
<AccountButtons
|
||||
className={classNames(
|
||||
redesignClasses.buttonsMobile,
|
||||
!isIntersecting && redesignClasses.buttonsMobileIsStuck,
|
||||
)}
|
||||
accountId={accountId}
|
||||
noShare
|
||||
/>
|
||||
)}
|
||||
<AccountButtons
|
||||
className={classNames(
|
||||
redesignClasses.buttonsMobile,
|
||||
!isIntersecting && redesignClasses.buttonsMobileIsStuck,
|
||||
)}
|
||||
accountId={accountId}
|
||||
noShare
|
||||
/>
|
||||
</div>
|
||||
</AnimateEmojiProvider>
|
||||
|
||||
{!hideTabs && !hidden && <AccountTabs acct={account.acct} />}
|
||||
{!hideTabs && !hidden && <AccountTabs />}
|
||||
<div ref={observedRef} />
|
||||
|
||||
<Helmet>
|
||||
|
|
|
|||
|
|
@ -14,10 +14,6 @@ import { useAppSelector } from '@/mastodon/store';
|
|||
import AtIcon from '@/material-icons/400-24px/alternate_email.svg?react';
|
||||
import HelpIcon from '@/material-icons/400-24px/help.svg?react';
|
||||
import DomainIcon from '@/material-icons/400-24px/language.svg?react';
|
||||
import LockIcon from '@/material-icons/400-24px/lock.svg?react';
|
||||
|
||||
import { DomainPill } from '../../account/components/domain_pill';
|
||||
import { isRedesignEnabled } from '../common';
|
||||
|
||||
import classes from './redesign.module.scss';
|
||||
|
||||
|
|
@ -34,7 +30,6 @@ const messages = defineMessages({
|
|||
});
|
||||
|
||||
export const AccountName: FC<{ accountId: string }> = ({ accountId }) => {
|
||||
const intl = useIntl();
|
||||
const account = useAccount(accountId);
|
||||
const me = useAppSelector((state) => state.meta.get('me') as string);
|
||||
const localDomain = useAppSelector(
|
||||
|
|
@ -47,32 +42,6 @@ export const AccountName: FC<{ accountId: string }> = ({ accountId }) => {
|
|||
|
||||
const [username = '', domain = localDomain] = account.acct.split('@');
|
||||
|
||||
if (!isRedesignEnabled()) {
|
||||
return (
|
||||
<h1>
|
||||
<DisplayName account={account} variant='simple' />
|
||||
<small>
|
||||
<span>
|
||||
@{username}
|
||||
<span className='invisible'>@{domain}</span>
|
||||
</span>
|
||||
<DomainPill
|
||||
username={username}
|
||||
domain={domain}
|
||||
isSelf={me === account.id}
|
||||
/>
|
||||
{account.locked && (
|
||||
<Icon
|
||||
id='lock'
|
||||
icon={LockIcon}
|
||||
aria-label={intl.formatMessage(messages.lockedInfo)}
|
||||
/>
|
||||
)}
|
||||
</small>
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classes.name}>
|
||||
<h1>
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ import { useAccount } from '@/mastodon/hooks/useAccount';
|
|||
import type { AccountRole } from '@/mastodon/models/account';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import { isRedesignEnabled } from '../common';
|
||||
|
||||
import classes from './redesign.module.scss';
|
||||
|
||||
export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
|
||||
|
|
@ -46,9 +44,6 @@ export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
|
|||
return null;
|
||||
}
|
||||
|
||||
const isRedesign = isRedesignEnabled();
|
||||
const className = isRedesign ? classes.badge : '';
|
||||
|
||||
const domain = account.acct.includes('@')
|
||||
? account.acct.split('@')[1]
|
||||
: localDomain;
|
||||
|
|
@ -58,7 +53,7 @@ export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
|
|||
<AdminBadge
|
||||
key={role.id}
|
||||
label={role.name}
|
||||
className={className}
|
||||
className={classes.badge}
|
||||
domain={`(${domain})`}
|
||||
roleId={role.id}
|
||||
/>,
|
||||
|
|
@ -68,8 +63,8 @@ export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
|
|||
<Badge
|
||||
key={role.id}
|
||||
label={role.name}
|
||||
className={className}
|
||||
domain={isRedesign ? `(${domain})` : domain}
|
||||
className={classes.badge}
|
||||
domain={`(${domain})`}
|
||||
roleId={role.id}
|
||||
/>,
|
||||
);
|
||||
|
|
@ -77,17 +72,17 @@ export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
|
|||
});
|
||||
|
||||
if (account.bot) {
|
||||
badges.push(<AutomatedBadge key='bot-badge' className={className} />);
|
||||
badges.push(<AutomatedBadge key='bot-badge' className={classes.badge} />);
|
||||
}
|
||||
if (account.group) {
|
||||
badges.push(<GroupBadge key='group-badge' className={className} />);
|
||||
badges.push(<GroupBadge key='group-badge' className={classes.badge} />);
|
||||
}
|
||||
if (isRedesign && relationship) {
|
||||
if (relationship) {
|
||||
if (relationship.blocking) {
|
||||
badges.push(
|
||||
<BlockedBadge
|
||||
key='blocking'
|
||||
className={classNames(className, classes.badgeBlocked)}
|
||||
className={classNames(classes.badge, classes.badgeBlocked)}
|
||||
/>,
|
||||
);
|
||||
}
|
||||
|
|
@ -95,7 +90,7 @@ export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
|
|||
badges.push(
|
||||
<BlockedBadge
|
||||
key='domain-blocking'
|
||||
className={classNames(className, classes.badgeBlocked)}
|
||||
className={classNames(classes.badge, classes.badgeBlocked)}
|
||||
domain={domain}
|
||||
label={
|
||||
<FormattedMessage
|
||||
|
|
@ -110,7 +105,7 @@ export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
|
|||
badges.push(
|
||||
<MutedBadge
|
||||
key='muted-badge'
|
||||
className={classNames(className, classes.badgeMuted)}
|
||||
className={classNames(classes.badge, classes.badgeMuted)}
|
||||
expiresAt={relationship.muting_expires_at}
|
||||
/>,
|
||||
);
|
||||
|
|
@ -136,5 +131,5 @@ export const PinnedBadge: FC = () => (
|
|||
|
||||
function isAdminBadge(role: AccountRole) {
|
||||
const name = role.name.toLowerCase();
|
||||
return isRedesignEnabled() && (name === 'admin' || name === 'owner');
|
||||
return name === 'admin' || name === 'owner';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,6 @@ import NotificationsIcon from '@/material-icons/400-24px/notifications.svg?react
|
|||
import NotificationsActiveIcon from '@/material-icons/400-24px/notifications_active-fill.svg?react';
|
||||
import ShareIcon from '@/material-icons/400-24px/share.svg?react';
|
||||
|
||||
import { isRedesignEnabled } from '../common';
|
||||
|
||||
import { AccountMenu } from './menu';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
|
@ -97,7 +95,6 @@ const AccountButtonsOther: FC<
|
|||
accountId={accountId}
|
||||
className='account__header__follow-button'
|
||||
labelLength='long'
|
||||
withUnmute={!isRedesignEnabled()}
|
||||
/>
|
||||
)}
|
||||
{isFollowing && (
|
||||
|
|
|
|||
|
|
@ -1,68 +1,30 @@
|
|||
import { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { defineMessage, FormattedMessage, useIntl } from 'react-intl';
|
||||
import { defineMessage, useIntl } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import IconVerified from '@/images/icons/icon_verified.svg?react';
|
||||
import { openModal } from '@/mastodon/actions/modal';
|
||||
import { AccountFields } from '@/mastodon/components/account_fields';
|
||||
import { CustomEmojiProvider } from '@/mastodon/components/emoji/context';
|
||||
import type { EmojiHTMLProps } from '@/mastodon/components/emoji/html';
|
||||
import { EmojiHTML } from '@/mastodon/components/emoji/html';
|
||||
import { FormattedDateWrapper } from '@/mastodon/components/formatted_date';
|
||||
import { Icon } from '@/mastodon/components/icon';
|
||||
import { IconButton } from '@/mastodon/components/icon_button';
|
||||
import { MiniCard } from '@/mastodon/components/mini_card';
|
||||
import { useElementHandledLink } from '@/mastodon/components/status/handled_link';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { useResizeObserver } from '@/mastodon/hooks/useObserver';
|
||||
import type { Account } from '@/mastodon/models/account';
|
||||
import { useAppDispatch } from '@/mastodon/store';
|
||||
import MoreIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||
|
||||
import { cleanExtraEmojis } from '../../emoji/normalize';
|
||||
import type { AccountField } from '../common';
|
||||
import { isRedesignEnabled } from '../common';
|
||||
import { useFieldHtml } from '../hooks/useFieldHtml';
|
||||
|
||||
import classes from './redesign.module.scss';
|
||||
|
||||
export const AccountHeaderFields: FC<{ accountId: string }> = ({
|
||||
accountId,
|
||||
}) => {
|
||||
const account = useAccount(accountId);
|
||||
|
||||
if (!account) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isRedesignEnabled()) {
|
||||
return <RedesignAccountHeaderFields account={account} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='account__header__fields'>
|
||||
<dl>
|
||||
<dt>
|
||||
<FormattedMessage id='account.joined_short' defaultMessage='Joined' />
|
||||
</dt>
|
||||
<dd>
|
||||
<FormattedDateWrapper
|
||||
value={account.created_at}
|
||||
year='numeric'
|
||||
month='short'
|
||||
day='2-digit'
|
||||
/>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<AccountFields fields={account.fields} emojis={account.emojis} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const verifyMessage = defineMessage({
|
||||
id: 'account.link_verified_on',
|
||||
defaultMessage: 'Ownership of this link was checked on {date}',
|
||||
|
|
@ -75,13 +37,22 @@ const dateFormatOptions: Intl.DateTimeFormatOptions = {
|
|||
minute: '2-digit',
|
||||
};
|
||||
|
||||
const RedesignAccountHeaderFields: FC<{ account: Account }> = ({ account }) => {
|
||||
export const AccountHeaderFields: FC<{ accountId: string }> = ({
|
||||
accountId,
|
||||
}) => {
|
||||
const account = useAccount(accountId);
|
||||
|
||||
const emojis = useMemo(
|
||||
() => cleanExtraEmojis(account.emojis),
|
||||
[account.emojis],
|
||||
() => cleanExtraEmojis(account?.emojis),
|
||||
[account?.emojis],
|
||||
);
|
||||
const accountFields = account?.fields;
|
||||
const fields: AccountField[] = useMemo(() => {
|
||||
const fields = account.fields.toJS();
|
||||
const fields = accountFields?.toJS();
|
||||
if (!fields) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!emojis) {
|
||||
return fields.map((field) => ({
|
||||
...field,
|
||||
|
|
@ -102,10 +73,10 @@ const RedesignAccountHeaderFields: FC<{ account: Account }> = ({ account }) => {
|
|||
field.value_plain?.includes(`:${code}:`),
|
||||
),
|
||||
}));
|
||||
}, [account.fields, emojis]);
|
||||
}, [accountFields, emojis]);
|
||||
|
||||
const htmlHandlers = useElementHandledLink({
|
||||
hashtagAccountId: account.id,
|
||||
hashtagAccountId: account?.id,
|
||||
});
|
||||
|
||||
const { wrapperRef } = useColumnWrap();
|
||||
|
|
|
|||
|
|
@ -40,8 +40,6 @@ import PersonRemoveIcon from '@/material-icons/400-24px/person_remove.svg?react'
|
|||
import ReportIcon from '@/material-icons/400-24px/report.svg?react';
|
||||
import ShareIcon from '@/material-icons/400-24px/share.svg?react';
|
||||
|
||||
import { isRedesignEnabled } from '../common';
|
||||
|
||||
import classes from './redesign.module.scss';
|
||||
|
||||
export const AccountMenu: FC<{ accountId: string }> = ({ accountId }) => {
|
||||
|
|
@ -63,19 +61,9 @@ export const AccountMenu: FC<{ accountId: string }> = ({ accountId }) => {
|
|||
return [];
|
||||
}
|
||||
|
||||
if (isRedesignEnabled()) {
|
||||
return redesignMenuItems({
|
||||
account,
|
||||
signedIn: !isMe && signedIn,
|
||||
permissions,
|
||||
intl,
|
||||
relationship,
|
||||
dispatch,
|
||||
});
|
||||
}
|
||||
return currentMenuItems({
|
||||
return redesignMenuItems({
|
||||
account,
|
||||
signedIn,
|
||||
signedIn: !isMe && signedIn,
|
||||
permissions,
|
||||
intl,
|
||||
relationship,
|
||||
|
|
@ -178,270 +166,6 @@ const messages = defineMessages({
|
|||
},
|
||||
});
|
||||
|
||||
function currentMenuItems({
|
||||
account,
|
||||
signedIn,
|
||||
permissions,
|
||||
intl,
|
||||
relationship,
|
||||
dispatch,
|
||||
}: MenuItemsParams): MenuItem[] {
|
||||
const items: MenuItem[] = [];
|
||||
const isRemote = account.acct !== account.username;
|
||||
|
||||
if (signedIn && !account.suspended) {
|
||||
items.push(
|
||||
{
|
||||
text: intl.formatMessage(messages.mention, {
|
||||
name: account.username,
|
||||
}),
|
||||
action: () => {
|
||||
dispatch(mentionCompose(account));
|
||||
},
|
||||
},
|
||||
{
|
||||
text: intl.formatMessage(messages.direct, {
|
||||
name: account.username,
|
||||
}),
|
||||
action: () => {
|
||||
dispatch(directCompose(account));
|
||||
},
|
||||
},
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
if (isRemote) {
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.openOriginalPage),
|
||||
href: account.url,
|
||||
});
|
||||
|
||||
if (signedIn) {
|
||||
items.push(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!signedIn) {
|
||||
return items;
|
||||
}
|
||||
|
||||
if (relationship?.following) {
|
||||
// Timeline options
|
||||
if (!relationship.muting) {
|
||||
if (relationship.showing_reblogs) {
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.hideReblogs, {
|
||||
name: account.username,
|
||||
}),
|
||||
action: () => {
|
||||
dispatch(followAccount(account.id, { reblogs: false }));
|
||||
},
|
||||
});
|
||||
} else {
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.showReblogs, {
|
||||
name: account.username,
|
||||
}),
|
||||
action: () => {
|
||||
dispatch(followAccount(account.id, { reblogs: true }));
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
items.push(
|
||||
{
|
||||
text: intl.formatMessage(messages.languages),
|
||||
action: () => {
|
||||
dispatch(
|
||||
openModal({
|
||||
modalType: 'SUBSCRIBED_LANGUAGES',
|
||||
modalProps: {
|
||||
accountId: account.id,
|
||||
},
|
||||
}),
|
||||
);
|
||||
},
|
||||
},
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
items.push(
|
||||
{
|
||||
text: intl.formatMessage(
|
||||
relationship.endorsed ? messages.unendorse : messages.endorse,
|
||||
),
|
||||
action: () => {
|
||||
if (relationship.endorsed) {
|
||||
dispatch(unpinAccount(account.id));
|
||||
} else {
|
||||
dispatch(pinAccount(account.id));
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
text: intl.formatMessage(messages.add_or_remove_from_list),
|
||||
action: () => {
|
||||
dispatch(
|
||||
openModal({
|
||||
modalType: 'LIST_ADDER',
|
||||
modalProps: {
|
||||
accountId: account.id,
|
||||
},
|
||||
}),
|
||||
);
|
||||
},
|
||||
},
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
if (relationship?.followed_by) {
|
||||
const handleRemoveFromFollowers = () => {
|
||||
dispatch(
|
||||
openModal({
|
||||
modalType: 'CONFIRM',
|
||||
modalProps: {
|
||||
title: intl.formatMessage(messages.confirmRemoveFromFollowersTitle),
|
||||
message: intl.formatMessage(
|
||||
messages.confirmRemoveFromFollowersMessage,
|
||||
{ name: <strong>{account.acct}</strong> },
|
||||
),
|
||||
confirm: intl.formatMessage(
|
||||
messages.confirmRemoveFromFollowersButton,
|
||||
),
|
||||
onConfirm: () => {
|
||||
void dispatch(
|
||||
removeAccountFromFollowers({ accountId: account.id }),
|
||||
);
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.removeFromFollowers, {
|
||||
name: account.username,
|
||||
}),
|
||||
action: handleRemoveFromFollowers,
|
||||
dangerous: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (relationship?.muting) {
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.unmute, {
|
||||
name: account.username,
|
||||
}),
|
||||
action: () => {
|
||||
dispatch(unmuteAccount(account.id));
|
||||
},
|
||||
});
|
||||
} else {
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.mute, {
|
||||
name: account.username,
|
||||
}),
|
||||
action: () => {
|
||||
dispatch(initMuteModal(account));
|
||||
},
|
||||
dangerous: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (relationship?.blocking) {
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.unblock, {
|
||||
name: account.username,
|
||||
}),
|
||||
action: () => {
|
||||
dispatch(unblockAccount(account.id));
|
||||
},
|
||||
});
|
||||
} else {
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.block, {
|
||||
name: account.username,
|
||||
}),
|
||||
action: () => {
|
||||
dispatch(blockAccount(account.id));
|
||||
},
|
||||
dangerous: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (!account.suspended) {
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.report, {
|
||||
name: account.username,
|
||||
}),
|
||||
action: () => {
|
||||
dispatch(initReport(account));
|
||||
},
|
||||
dangerous: true,
|
||||
});
|
||||
}
|
||||
|
||||
const remoteDomain = isRemote ? account.acct.split('@')[1] : null;
|
||||
if (remoteDomain) {
|
||||
items.push(null);
|
||||
|
||||
if (relationship?.domain_blocking) {
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.unblockDomain, {
|
||||
domain: remoteDomain,
|
||||
}),
|
||||
action: () => {
|
||||
dispatch(unblockDomain(remoteDomain));
|
||||
},
|
||||
});
|
||||
} else {
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.blockDomain, {
|
||||
domain: remoteDomain,
|
||||
}),
|
||||
action: () => {
|
||||
dispatch(initDomainBlockModal(account));
|
||||
},
|
||||
dangerous: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS ||
|
||||
(isRemote &&
|
||||
(permissions & PERMISSION_MANAGE_FEDERATION) ===
|
||||
PERMISSION_MANAGE_FEDERATION)
|
||||
) {
|
||||
items.push(null);
|
||||
if ((permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS) {
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.admin_account, {
|
||||
name: account.username,
|
||||
}),
|
||||
href: `/admin/accounts/${account.id}`,
|
||||
});
|
||||
}
|
||||
if (
|
||||
isRemote &&
|
||||
(permissions & PERMISSION_MANAGE_FEDERATION) ===
|
||||
PERMISSION_MANAGE_FEDERATION
|
||||
) {
|
||||
items.push({
|
||||
text: intl.formatMessage(messages.admin_domain, {
|
||||
domain: remoteDomain,
|
||||
}),
|
||||
href: `/admin/instances/${remoteDomain}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
const redesignMessages = defineMessages({
|
||||
share: { id: 'account.menu.share', defaultMessage: 'Share…' },
|
||||
copy: { id: 'account.menu.copy', defaultMessage: 'Copy link' },
|
||||
|
|
|
|||
|
|
@ -3,13 +3,6 @@ import type { FC } from 'react';
|
|||
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
FollowersCounter,
|
||||
FollowingCounter,
|
||||
StatusesCounter,
|
||||
} from '@/mastodon/components/counters';
|
||||
import { FormattedDateWrapper } from '@/mastodon/components/formatted_date';
|
||||
import {
|
||||
NumberFields,
|
||||
|
|
@ -18,54 +11,9 @@ import {
|
|||
import { ShortNumber } from '@/mastodon/components/short_number';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
|
||||
import { isRedesignEnabled } from '../common';
|
||||
|
||||
const LegacyNumberFields: FC<{ accountId: string }> = ({ accountId }) => {
|
||||
const intl = useIntl();
|
||||
const account = useAccount(accountId);
|
||||
|
||||
if (!account) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='account__header__extra__links'>
|
||||
<NavLink
|
||||
to={`/@${account.acct}`}
|
||||
title={intl.formatNumber(account.statuses_count)}
|
||||
>
|
||||
<ShortNumber
|
||||
value={account.statuses_count}
|
||||
renderer={StatusesCounter}
|
||||
/>
|
||||
</NavLink>
|
||||
|
||||
<NavLink
|
||||
exact
|
||||
to={`/@${account.acct}/following`}
|
||||
title={intl.formatNumber(account.following_count)}
|
||||
>
|
||||
<ShortNumber
|
||||
value={account.following_count}
|
||||
renderer={FollowingCounter}
|
||||
/>
|
||||
</NavLink>
|
||||
|
||||
<NavLink
|
||||
exact
|
||||
to={`/@${account.acct}/followers`}
|
||||
title={intl.formatNumber(account.followers_count)}
|
||||
>
|
||||
<ShortNumber
|
||||
value={account.followers_count}
|
||||
renderer={FollowersCounter}
|
||||
/>
|
||||
</NavLink>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const RedesignNumberFields: FC<{ accountId: string }> = ({ accountId }) => {
|
||||
export const AccountNumberFields: FC<{ accountId: string }> = ({
|
||||
accountId,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const account = useAccount(accountId);
|
||||
const createdThisYear = useMemo(
|
||||
|
|
@ -125,7 +73,3 @@ const RedesignNumberFields: FC<{ accountId: string }> = ({ accountId }) => {
|
|||
</NumberFields>
|
||||
);
|
||||
};
|
||||
|
||||
export const AccountNumberFields = isRedesignEnabled()
|
||||
? RedesignNumberFields
|
||||
: LegacyNumberFields;
|
||||
|
|
|
|||
|
|
@ -8,40 +8,13 @@ import { NavLink } from 'react-router-dom';
|
|||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { useAccountId } from '@/mastodon/hooks/useAccountId';
|
||||
|
||||
import { isRedesignEnabled } from '../common';
|
||||
|
||||
import classes from './redesign.module.scss';
|
||||
|
||||
export const AccountTabs: FC<{ acct: string }> = ({ acct }) => {
|
||||
if (isRedesignEnabled()) {
|
||||
return <RedesignTabs />;
|
||||
}
|
||||
return (
|
||||
<div className='account__section-headline'>
|
||||
<NavLink exact to={`/@${acct}/featured`}>
|
||||
<FormattedMessage id='account.featured' defaultMessage='Featured' />
|
||||
</NavLink>
|
||||
<NavLink exact to={`/@${acct}`}>
|
||||
<FormattedMessage id='account.posts' defaultMessage='Posts' />
|
||||
</NavLink>
|
||||
<NavLink exact to={`/@${acct}/with_replies`}>
|
||||
<FormattedMessage
|
||||
id='account.posts_with_replies'
|
||||
defaultMessage='Posts and replies'
|
||||
/>
|
||||
</NavLink>
|
||||
<NavLink exact to={`/@${acct}/media`}>
|
||||
<FormattedMessage id='account.media' defaultMessage='Media' />
|
||||
</NavLink>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const isActive: Required<NavLinkProps>['isActive'] = (match, location) =>
|
||||
match?.url === location.pathname ||
|
||||
(!!match?.url && location.pathname.startsWith(`${match.url}/tagged/`));
|
||||
|
||||
const RedesignTabs: FC = () => {
|
||||
export const AccountTabs: FC = () => {
|
||||
const accountId = useAccountId();
|
||||
const account = useAccount(accountId);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export const AccountFilters: FC = () => {
|
|||
}
|
||||
return (
|
||||
<>
|
||||
<AccountTabs acct={acct} />
|
||||
<AccountTabs />
|
||||
<div className={classes.filtersWrapper}>
|
||||
<FilterDropdown />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import type { StatusHeaderRenderFn } from '@/mastodon/components/status/header';
|
|||
import { selectTimelineByKey } from '@/mastodon/selectors/timelines';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import { isRedesignEnabled } from '../common';
|
||||
import { PinnedBadge } from '../components/badges';
|
||||
|
||||
import { useAccountContext } from './context';
|
||||
|
|
@ -88,10 +87,6 @@ export const renderPinnedStatusHeader: StatusHeaderRenderFn = ({
|
|||
export const PinnedShowAllButton: FC = () => {
|
||||
const { onShowAllPinned } = useAccountContext();
|
||||
|
||||
if (!isRedesignEnabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
onClick={onShowAllPinned}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import { identityContextPropShape, withIdentity } from 'mastodon/identity_contex
|
|||
import { layoutFromWindow } from 'mastodon/is_mobile';
|
||||
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||
import { checkAnnualReport } from '@/mastodon/reducers/slices/annual_report';
|
||||
import { isServerFeatureEnabled } from '@/mastodon/utils/environment';
|
||||
|
||||
import { uploadCompose, resetCompose, changeComposeSpoilerness } from '../../actions/compose';
|
||||
import { clearHeight } from '../../actions/height_cache';
|
||||
|
|
@ -182,20 +181,6 @@ class SwitchingColumnsArea extends PureComponent {
|
|||
rootRedirect = '/about';
|
||||
}
|
||||
|
||||
const profileRedesignRoutes = [];
|
||||
if (isServerFeatureEnabled('profile_redesign')) {
|
||||
profileRedesignRoutes.push(
|
||||
<WrappedRoute key="edit" path='/profile/edit' component={AccountEdit} content={children} />,
|
||||
<WrappedRoute key="featured_tags" path='/profile/featured_tags' component={AccountEditFeaturedTags} content={children} />
|
||||
)
|
||||
} else {
|
||||
// If profile editing is not enabled, redirect to the home timeline as the current editing pages are outside React Router.
|
||||
profileRedesignRoutes.push(
|
||||
<Redirect key="edit-redirect" from='/profile/edit' to='/' exact />,
|
||||
<Redirect key="featured-tags-redirect" from='/profile/featured_tags' to='/' exact />,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ColumnsContextProvider multiColumn={!singleColumn}>
|
||||
<ColumnsArea ref={this.setRef} singleColumn={singleColumn}>
|
||||
|
|
@ -242,7 +227,8 @@ class SwitchingColumnsArea extends PureComponent {
|
|||
<WrappedRoute path='/search' component={Search} content={children} />
|
||||
<WrappedRoute path={['/publish', '/statuses/new']} component={Compose} content={children} />
|
||||
|
||||
{...profileRedesignRoutes}
|
||||
<WrappedRoute path='/profile/edit' component={AccountEdit} content={children} />
|
||||
<WrappedRoute path='/profile/featured_tags' component={AccountEditFeaturedTags} content={children} />
|
||||
|
||||
<WrappedRoute path={['/@:acct', '/accounts/:id']} exact component={AccountTimeline} content={children} />
|
||||
<WrappedRoute path={['/@:acct/featured', '/accounts/:id/featured']} component={AccountFeatured} content={children} />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import { isServerFeatureEnabled } from '@/mastodon/utils/environment';
|
||||
|
||||
export function EmojiPicker () {
|
||||
return import('../../emoji/emoji_picker');
|
||||
}
|
||||
|
|
@ -79,10 +77,7 @@ export function PinnedStatuses () {
|
|||
}
|
||||
|
||||
export function AccountTimeline () {
|
||||
if (isServerFeatureEnabled('profile_redesign')) {
|
||||
return import('../../account_timeline/v2');
|
||||
}
|
||||
return import('../../account_timeline');
|
||||
return import('../../account_timeline/v2');
|
||||
}
|
||||
|
||||
export function AccountGallery () {
|
||||
|
|
|
|||
|
|
@ -122,7 +122,6 @@
|
|||
"account.note.title": "Personal note (visible only to you)",
|
||||
"account.open_original_page": "Open original page",
|
||||
"account.posts": "Posts",
|
||||
"account.posts_with_replies": "Posts and replies",
|
||||
"account.remove_from_followers": "Remove {name} from followers",
|
||||
"account.report": "Report @{name}",
|
||||
"account.requested_follow": "{name} has requested to follow you",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export function isProduction() {
|
|||
else return import.meta.env.PROD;
|
||||
}
|
||||
|
||||
export type ServerFeatures = 'fasp' | 'collections' | 'profile_redesign';
|
||||
export type ServerFeatures = 'fasp' | 'collections';
|
||||
|
||||
export function isServerFeatureEnabled(feature: ServerFeatures) {
|
||||
return initialState?.features.includes(feature) ?? false;
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Account notes', :inline_jobs, :js, :streaming do
|
||||
include ProfileStories
|
||||
|
||||
let(:email) { 'test@example.com' }
|
||||
let(:password) { 'password' }
|
||||
let(:confirmed_at) { Time.zone.now }
|
||||
let(:finished_onboarding) { true }
|
||||
|
||||
let!(:other_account) { Fabricate(:account) }
|
||||
let(:note_text) { 'This is a personal note' }
|
||||
|
||||
before { as_a_logged_in_user }
|
||||
|
||||
it 'can be written and viewed' do
|
||||
visit_profile(other_account)
|
||||
|
||||
fill_in frontend_translations('account_note.placeholder'), with: note_text
|
||||
|
||||
# This is a bit awkward since there is no button to save the change
|
||||
# The easiest way is to send ctrl+enter ourselves
|
||||
find_field(class: 'account__header__account-note__content').send_keys [:control, :enter]
|
||||
|
||||
expect(page)
|
||||
.to have_css('.account__header__account-note__content', text: note_text)
|
||||
|
||||
# Navigate back and forth and ensure the comment is still here
|
||||
visit root_url
|
||||
visit_profile(other_account)
|
||||
|
||||
expect(AccountNote.find_by(account: bob.account, target_account: other_account).comment)
|
||||
.to eq note_text
|
||||
|
||||
expect(page)
|
||||
.to have_css('.account__header__account-note__content', text: note_text)
|
||||
end
|
||||
|
||||
def visit_profile(account)
|
||||
visit short_account_path(account)
|
||||
|
||||
expect(page)
|
||||
.to have_css('div.app-holder')
|
||||
.and have_css('form.compose-form')
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue
Block a user