mirror of
https://github.com/mastodon/mastodon.git
synced 2026-05-23 09:36:43 -05:00
Remove and move profile code (#38863)
This commit is contained in:
parent
3021cd8002
commit
945ac23910
|
|
@ -4,6 +4,10 @@ import type { FC } from 'react';
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { fetchRelationships } from '@/mastodon/actions/accounts';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import type { AccountRole } from '@/mastodon/models/account';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import {
|
||||
AdminBadge,
|
||||
AutomatedBadge,
|
||||
|
|
@ -11,10 +15,7 @@ import {
|
|||
BlockedBadge,
|
||||
GroupBadge,
|
||||
MutedBadge,
|
||||
} from '@/mastodon/components/badge';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import type { AccountRole } from '@/mastodon/models/account';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
} from '../badge';
|
||||
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
|
|
@ -6,9 +6,6 @@ import { defineMessages, useIntl } from 'react-intl';
|
|||
import classNames from 'classnames';
|
||||
|
||||
import { followAccount } from '@/mastodon/actions/accounts';
|
||||
import { CopyIconButton } from '@/mastodon/components/copy_icon_button';
|
||||
import { FollowButton } from '@/mastodon/components/follow_button';
|
||||
import { IconButton } from '@/mastodon/components/icon_button';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { getAccountHidden } from '@/mastodon/selectors/accounts';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
|
@ -16,6 +13,10 @@ 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 { CopyIconButton } from '../copy_icon_button';
|
||||
import { FollowButton } from '../follow_button';
|
||||
import { IconButton } from '../icon_button';
|
||||
|
||||
import { AccountMenu } from './menu';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
|
@ -7,21 +7,21 @@ import classNames from 'classnames';
|
|||
|
||||
import IconVerified from '@/images/icons/icon_verified.svg?react';
|
||||
import { openModal } from '@/mastodon/actions/modal';
|
||||
import { CustomEmojiProvider } from '@/mastodon/components/emoji/context';
|
||||
import type { EmojiHTMLProps } from '@/mastodon/components/emoji/html';
|
||||
import { EmojiHTML } from '@/mastodon/components/emoji/html';
|
||||
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 { useFieldHtml } from '@/mastodon/features/account_timeline/hooks/useFieldHtml';
|
||||
import { cleanExtraEmojis } from '@/mastodon/features/emoji/normalize';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { useResizeObserver } from '@/mastodon/hooks/useObserver';
|
||||
import type { AccountFieldShape } 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 { useFieldHtml } from '../hooks/useFieldHtml';
|
||||
import { CustomEmojiProvider } from '../emoji/context';
|
||||
import type { EmojiHTMLProps } from '../emoji/html';
|
||||
import { EmojiHTML } from '../emoji/html';
|
||||
import { Icon } from '../icon';
|
||||
import { IconButton } from '../icon_button';
|
||||
import { MiniCard } from '../mini_card';
|
||||
import { useElementHandledLink } from '../status/handled_link';
|
||||
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
|
|
@ -37,6 +37,12 @@ const dateFormatOptions: Intl.DateTimeFormatOptions = {
|
|||
minute: '2-digit',
|
||||
};
|
||||
|
||||
export interface AccountField extends AccountFieldShape {
|
||||
nameHasEmojis: boolean;
|
||||
value_plain: string;
|
||||
valueHasEmojis: boolean;
|
||||
}
|
||||
|
||||
export const AccountHeaderFields: FC<{ accountId: string }> = ({
|
||||
accountId,
|
||||
}) => {
|
||||
|
|
@ -4,9 +4,6 @@ import classNames from 'classnames';
|
|||
import { Helmet } from 'react-helmet';
|
||||
|
||||
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 FollowRequestNoteContainer from '@/mastodon/features/account/containers/follow_request_note_container';
|
||||
import { useLayout } from '@/mastodon/hooks/useLayout';
|
||||
import { useVisibility } from '@/mastodon/hooks/useVisibility';
|
||||
|
|
@ -19,17 +16,20 @@ import type { Account } from '@/mastodon/models/account';
|
|||
import { getAccountHidden } from '@/mastodon/selectors/accounts';
|
||||
import { useAppSelector, useAppDispatch } from '@/mastodon/store';
|
||||
|
||||
import { FamiliarFollowers } from '../../../components/familiar_followers';
|
||||
import { AccountBio } from '../account_bio';
|
||||
import { Avatar } from '../avatar';
|
||||
import { AnimateEmojiProvider } from '../emoji/context';
|
||||
import { FamiliarFollowers } from '../familiar_followers';
|
||||
|
||||
import { AccountName } from './account_name';
|
||||
import { AccountSubscriptionForm } from './account_subscription_form';
|
||||
import { AccountButtons } from './buttons';
|
||||
import { AccountHeaderFields } from './fields';
|
||||
import { MemorialNote } from './memorial_note';
|
||||
import { MovedNote } from './moved_note';
|
||||
import { AccountName } from './name';
|
||||
import { AccountNote } from './note';
|
||||
import { AccountNumberFields } from './number_fields';
|
||||
import classes from './styles.module.scss';
|
||||
import { AccountSubscriptionForm } from './subscription_form';
|
||||
import { AccountTabs } from './tabs';
|
||||
|
||||
const titleFromAccount = (account: Account) => {
|
||||
|
|
@ -21,7 +21,6 @@ import {
|
|||
import { openModal } from '@/mastodon/actions/modal';
|
||||
import { initMuteModal } from '@/mastodon/actions/mutes';
|
||||
import { initReport } from '@/mastodon/actions/reports';
|
||||
import { Dropdown } from '@/mastodon/components/dropdown_menu';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { useIdentity } from '@/mastodon/identity_context';
|
||||
import type { Account } from '@/mastodon/models/account';
|
||||
|
|
@ -40,6 +39,8 @@ 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 { Dropdown } from '../dropdown_menu';
|
||||
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
export const AccountMenu: FC<{ accountId: string }> = ({ accountId }) => {
|
||||
|
|
@ -2,9 +2,10 @@ import { FormattedMessage } from 'react-intl';
|
|||
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { DisplayName } from '@/mastodon/components/display_name';
|
||||
import { AvatarOverlay } from 'mastodon/components/avatar_overlay';
|
||||
import { useAppSelector } from 'mastodon/store';
|
||||
import { useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import { AvatarOverlay } from '../avatar_overlay';
|
||||
import { DisplayName } from '../display_name';
|
||||
|
||||
export const MovedNote: React.FC<{
|
||||
accountId: string;
|
||||
|
|
@ -8,10 +8,6 @@ import classNames from 'classnames';
|
|||
import Overlay from 'react-overlays/esm/Overlay';
|
||||
|
||||
import { showAlert } from '@/mastodon/actions/alerts';
|
||||
import { FollowsYouBadge } from '@/mastodon/components/badge';
|
||||
import { Button } from '@/mastodon/components/button';
|
||||
import { DisplayName } from '@/mastodon/components/display_name';
|
||||
import { Icon } from '@/mastodon/components/icon';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { useRelationship } from '@/mastodon/hooks/useRelationship';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
|
@ -20,6 +16,11 @@ import ContentCopyIcon from '@/material-icons/400-24px/content_copy.svg?react';
|
|||
import HelpIcon from '@/material-icons/400-24px/help.svg?react';
|
||||
import DomainIcon from '@/material-icons/400-24px/language.svg?react';
|
||||
|
||||
import { FollowsYouBadge } from '../badge';
|
||||
import { Button } from '../button';
|
||||
import { DisplayName } from '../display_name';
|
||||
import { Icon } from '../icon';
|
||||
|
||||
import { AccountBadges } from './badges';
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
|
|
@ -5,11 +5,12 @@ import { defineMessages, useIntl } from 'react-intl';
|
|||
|
||||
import { fetchRelationships } from '@/mastodon/actions/accounts';
|
||||
import { openModal } from '@/mastodon/actions/modal';
|
||||
import { Callout } from '@/mastodon/components/callout';
|
||||
import { IconButton } from '@/mastodon/components/icon_button';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
import EditIcon from '@/material-icons/400-24px/edit_square.svg?react';
|
||||
|
||||
import { Callout } from '../callout';
|
||||
import { IconButton } from '../icon_button';
|
||||
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
|
@ -4,15 +4,13 @@ import type { FC } from 'react';
|
|||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import { openModal } from '@/mastodon/actions/modal';
|
||||
import { FormattedDateWrapper } from '@/mastodon/components/formatted_date';
|
||||
import {
|
||||
NumberFields,
|
||||
NumberFieldsItem,
|
||||
} from '@/mastodon/components/number_fields';
|
||||
import { ShortNumber } from '@/mastodon/components/short_number';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { useAppDispatch } from '@/mastodon/store';
|
||||
|
||||
import { FormattedDateWrapper } from '../formatted_date';
|
||||
import { NumberFields, NumberFieldsItem } from '../number_fields';
|
||||
import { ShortNumber } from '../short_number';
|
||||
|
||||
export const AccountNumberFields: FC<{ accountId: string }> = ({
|
||||
accountId,
|
||||
}) => {
|
||||
|
|
@ -8,16 +8,17 @@ import { Link } from 'react-router-dom';
|
|||
|
||||
import { AxiosError } from 'axios';
|
||||
|
||||
import { apiSubscribeByEmail } from 'mastodon/api/accounts';
|
||||
import { apiSubscribeByEmail } from '@/mastodon/api/accounts';
|
||||
import type {
|
||||
ValidationErrorResponse,
|
||||
ValidationError,
|
||||
} from 'mastodon/api_types/errors';
|
||||
import { Button } from 'mastodon/components/button';
|
||||
import { DisplayName } from 'mastodon/components/display_name';
|
||||
import type { FieldStatus } from 'mastodon/components/form_fields';
|
||||
import { TextInputField } from 'mastodon/components/form_fields/text_input_field';
|
||||
import { useAppSelector } from 'mastodon/store';
|
||||
} from '@/mastodon/api_types/errors';
|
||||
import { useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import { Button } from '../button';
|
||||
import { DisplayName } from '../display_name';
|
||||
import type { FieldStatus } from '../form_fields';
|
||||
import { TextInputField } from '../form_fields/text_input_field';
|
||||
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
|
|
@ -4,10 +4,11 @@ import { FormattedMessage } from 'react-intl';
|
|||
|
||||
import type { NavLinkProps } from 'react-router-dom';
|
||||
|
||||
import { TabLink, TabList } from '@/mastodon/components/tab_list';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { useAccountId } from '@/mastodon/hooks/useAccountId';
|
||||
|
||||
import { TabLink, TabList } from '../tab_list';
|
||||
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
const isActive: Required<NavLinkProps>['isActive'] = (match, location) =>
|
||||
|
|
@ -2,10 +2,11 @@ import { useCallback } from 'react';
|
|||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { revealAccount } from 'mastodon/actions/accounts_typed';
|
||||
import { Button } from 'mastodon/components/button';
|
||||
import { domain } from 'mastodon/initial_state';
|
||||
import { useAppDispatch } from 'mastodon/store';
|
||||
import { revealAccount } from '@/mastodon/actions/accounts_typed';
|
||||
import { domain } from '@/mastodon/initial_state';
|
||||
import { useAppDispatch } from '@/mastodon/store';
|
||||
|
||||
import { Button } from './button';
|
||||
|
||||
export const LimitedAccountHint: React.FC<{ accountId: string }> = ({
|
||||
accountId,
|
||||
|
|
@ -8,7 +8,7 @@ import { debounce } from 'lodash';
|
|||
import { TIMELINE_GAP, TIMELINE_PINNED_VIEW_ALL, TIMELINE_SUGGESTIONS } from 'mastodon/actions/timelines';
|
||||
import { RegenerationIndicator } from 'mastodon/components/regeneration_indicator';
|
||||
import { InlineFollowSuggestions } from 'mastodon/features/home_timeline/components/inline_follow_suggestions';
|
||||
import { PinnedShowAllButton } from '@/mastodon/features/account_timeline/v2/pinned_statuses';
|
||||
import { PinnedShowAllButton } from '@/mastodon/features/account_timeline/components/pinned_statuses';
|
||||
|
||||
import { StatusQuoteManager } from '../components/status_quoted';
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { Link } from 'react-router-dom';
|
|||
import { openModal } from '@/mastodon/actions/modal';
|
||||
import { Button } from '@/mastodon/components/button';
|
||||
import { EmptyState } from '@/mastodon/components/empty_state';
|
||||
import { LimitedAccountHint } from '@/mastodon/features/account_timeline/components/limited_account_hint';
|
||||
import { LimitedAccountHint } from '@/mastodon/components/limited_account_hint';
|
||||
import { areCollectionsEnabled } from '@/mastodon/features/collections/utils';
|
||||
import { useCurrentAccountId } from '@/mastodon/hooks/useAccountId';
|
||||
import { useAppDispatch } from '@/mastodon/store';
|
||||
|
|
|
|||
|
|
@ -6,26 +6,26 @@ import { useHistory } from 'react-router';
|
|||
|
||||
import { List as ImmutableList } from 'immutable';
|
||||
|
||||
import AddIcon from '@/material-icons/400-24px/add.svg?react';
|
||||
import { fetchEndorsedAccounts } from 'mastodon/actions/accounts';
|
||||
import { AccountListItem } from 'mastodon/components/account_list_item';
|
||||
import { ColumnBackButton } from 'mastodon/components/column_back_button';
|
||||
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
||||
import { RemoteHint } from 'mastodon/components/remote_hint';
|
||||
import { fetchEndorsedAccounts } from '@/mastodon/actions/accounts';
|
||||
import { AccountHeader } from '@/mastodon/components/account_header';
|
||||
import { AccountListItem } from '@/mastodon/components/account_list_item';
|
||||
import { ColumnBackButton } from '@/mastodon/components/column_back_button';
|
||||
import { LoadingIndicator } from '@/mastodon/components/loading_indicator';
|
||||
import { RemoteHint } from '@/mastodon/components/remote_hint';
|
||||
import {
|
||||
Article,
|
||||
ItemList,
|
||||
Scrollable,
|
||||
} from 'mastodon/components/scrollable_list/components';
|
||||
import type { TruncatedListItemInfo } from 'mastodon/components/truncated_list';
|
||||
import { TruncatedListItems } from 'mastodon/components/truncated_list';
|
||||
import { AccountHeader } from 'mastodon/features/account_timeline/components/account_header';
|
||||
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
|
||||
import Column from 'mastodon/features/ui/components/column';
|
||||
import { useAccount } from 'mastodon/hooks/useAccount';
|
||||
import { useAccountId } from 'mastodon/hooks/useAccountId';
|
||||
import { useAccountVisibility } from 'mastodon/hooks/useAccountVisibility';
|
||||
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
||||
} from '@/mastodon/components/scrollable_list/components';
|
||||
import type { TruncatedListItemInfo } from '@/mastodon/components/truncated_list';
|
||||
import { TruncatedListItems } from '@/mastodon/components/truncated_list';
|
||||
import BundleColumnError from '@/mastodon/features/ui/components/bundle_column_error';
|
||||
import Column from '@/mastodon/features/ui/components/column';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { useAccountId } from '@/mastodon/hooks/useAccountId';
|
||||
import { useAccountVisibility } from '@/mastodon/hooks/useAccountVisibility';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
import AddIcon from '@/material-icons/400-24px/add.svg?react';
|
||||
|
||||
import { useAccountCollections } from '../collections';
|
||||
import { CollectionListItem } from '../collections/components/collection_list_item';
|
||||
|
|
|
|||
|
|
@ -4,23 +4,23 @@ import { FormattedMessage } from 'react-intl';
|
|||
|
||||
import { List as ImmutableList, isList } from 'immutable';
|
||||
|
||||
import { openModal } from 'mastodon/actions/modal';
|
||||
import { expandAccountMediaTimeline } from 'mastodon/actions/timelines';
|
||||
import { ColumnBackButton } from 'mastodon/components/column_back_button';
|
||||
import { RemoteHint } from 'mastodon/components/remote_hint';
|
||||
import ScrollableList from 'mastodon/components/scrollable_list';
|
||||
import { AccountHeader } from 'mastodon/features/account_timeline/components/account_header';
|
||||
import { LimitedAccountHint } from 'mastodon/features/account_timeline/components/limited_account_hint';
|
||||
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
|
||||
import Column from 'mastodon/features/ui/components/column';
|
||||
import { useAccountId } from 'mastodon/hooks/useAccountId';
|
||||
import { useAccountVisibility } from 'mastodon/hooks/useAccountVisibility';
|
||||
import type { MediaAttachment } from 'mastodon/models/media_attachment';
|
||||
import { openModal } from '@/mastodon/actions/modal';
|
||||
import { expandAccountMediaTimeline } from '@/mastodon/actions/timelines';
|
||||
import { AccountHeader } from '@/mastodon/components/account_header';
|
||||
import { ColumnBackButton } from '@/mastodon/components/column_back_button';
|
||||
import { LimitedAccountHint } from '@/mastodon/components/limited_account_hint';
|
||||
import { RemoteHint } from '@/mastodon/components/remote_hint';
|
||||
import ScrollableList from '@/mastodon/components/scrollable_list';
|
||||
import BundleColumnError from '@/mastodon/features/ui/components/bundle_column_error';
|
||||
import Column from '@/mastodon/features/ui/components/column';
|
||||
import { useAccountId } from '@/mastodon/hooks/useAccountId';
|
||||
import { useAccountVisibility } from '@/mastodon/hooks/useAccountVisibility';
|
||||
import type { MediaAttachment } from '@/mastodon/models/media_attachment';
|
||||
import {
|
||||
useAppSelector,
|
||||
useAppDispatch,
|
||||
createAppSelector,
|
||||
} from 'mastodon/store';
|
||||
} from '@/mastodon/store';
|
||||
|
||||
import { MediaItem } from './components/media_item';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
import type { AccountFieldShape } from '@/mastodon/models/account';
|
||||
|
||||
export interface AccountField extends AccountFieldShape {
|
||||
nameHasEmojis: boolean;
|
||||
value_plain: string;
|
||||
valueHasEmojis: boolean;
|
||||
}
|
||||
|
|
@ -13,8 +13,8 @@ import { useOverflowButton } from '@/mastodon/hooks/useOverflow';
|
|||
import { selectAccountFeaturedTags } from '@/mastodon/selectors/accounts';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import { useAccountContext } from './context';
|
||||
import classes from './styles.module.scss';
|
||||
import { useAccountContext } from '../hooks/useAccountContext';
|
||||
import classes from '../styles.module.scss';
|
||||
|
||||
export const FeaturedTags: FC<{ accountId: string }> = ({ accountId }) => {
|
||||
// Fetch tags.
|
||||
|
|
@ -7,14 +7,13 @@ import { useParams } from 'react-router';
|
|||
|
||||
import Overlay from 'react-overlays/esm/Overlay';
|
||||
|
||||
import { AccountTabs } from '@/mastodon/components/account_header/tabs';
|
||||
import { Toggle } from '@/mastodon/components/form_fields';
|
||||
import { Icon } from '@/mastodon/components/icon';
|
||||
import KeyboardArrowDownIcon from '@/material-icons/400-24px/keyboard_arrow_down.svg?react';
|
||||
|
||||
import { AccountTabs } from '../components/tabs';
|
||||
|
||||
import { useAccountContext } from './context';
|
||||
import classes from './styles.module.scss';
|
||||
import { useAccountContext } from '../hooks/useAccountContext';
|
||||
import classes from '../styles.module.scss';
|
||||
|
||||
export const AccountFilters: FC = () => {
|
||||
const { acct } = useParams<{ acct: string }>();
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
import type { FC } from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import type { Relationship } from '@/mastodon/models/relationship';
|
||||
|
||||
export const AccountInfo: FC<{ relationship?: Relationship }> = ({
|
||||
relationship,
|
||||
}) => {
|
||||
if (!relationship) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div className='account__header__info'>
|
||||
{(relationship.followed_by || relationship.requested_by) && (
|
||||
<span className='relationship-tag'>
|
||||
<AccountInfoFollower relationship={relationship} />
|
||||
</span>
|
||||
)}
|
||||
{relationship.blocking && (
|
||||
<span className='relationship-tag'>
|
||||
<FormattedMessage id='account.blocking' defaultMessage='Blocking' />
|
||||
</span>
|
||||
)}
|
||||
{relationship.muting && (
|
||||
<span key='muting' className='relationship-tag'>
|
||||
<FormattedMessage id='account.muting' defaultMessage='Muting' />
|
||||
</span>
|
||||
)}
|
||||
{relationship.domain_blocking && (
|
||||
<span key='domain_blocking' className='relationship-tag'>
|
||||
<FormattedMessage
|
||||
id='account.domain_blocking'
|
||||
defaultMessage='Blocking domain'
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const AccountInfoFollower: FC<{ relationship: Relationship }> = ({
|
||||
relationship,
|
||||
}) => {
|
||||
if (
|
||||
relationship.followed_by &&
|
||||
(relationship.following || relationship.requested)
|
||||
) {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id='account.mutual'
|
||||
defaultMessage='You follow each other'
|
||||
/>
|
||||
);
|
||||
} else if (relationship.followed_by) {
|
||||
return (
|
||||
<FormattedMessage id='account.follows_you' defaultMessage='Follows you' />
|
||||
);
|
||||
} else if (relationship.requested_by) {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id='account.requests_to_follow_you'
|
||||
defaultMessage='Requests to follow you'
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import type { FC } from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import IconPinned from '@/images/icons/icon_pinned.svg?react';
|
||||
import { Badge } from '@/mastodon/components/badge';
|
||||
import { Button } from '@/mastodon/components/button';
|
||||
import { Icon } from '@/mastodon/components/icon';
|
||||
import { StatusHeader } from '@/mastodon/components/status/header';
|
||||
import type { StatusHeaderRenderFn } from '@/mastodon/components/status/header';
|
||||
|
||||
import { useAccountContext } from '../hooks/useAccountContext';
|
||||
import classes from '../styles.module.scss';
|
||||
|
||||
export const renderPinnedStatusHeader: StatusHeaderRenderFn = ({
|
||||
featured,
|
||||
...args
|
||||
}) => {
|
||||
if (!featured) {
|
||||
return <StatusHeader {...args} />;
|
||||
}
|
||||
return (
|
||||
<StatusHeader {...args} className={classes.pinnedStatusHeader}>
|
||||
<Badge
|
||||
className={classes.pinnedBadge}
|
||||
icon={<Icon id='pinned' icon={IconPinned} />}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='account.timeline.pinned'
|
||||
defaultMessage='Pinned'
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</StatusHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export const PinnedShowAllButton: FC = () => {
|
||||
const { onShowAllPinned } = useAccountContext();
|
||||
|
||||
return (
|
||||
<Button
|
||||
onClick={onShowAllPinned}
|
||||
className={classNames(classes.pinnedViewAllButton, 'focusable')}
|
||||
>
|
||||
<Icon id='pinned' icon={IconPinned} />
|
||||
<FormattedMessage
|
||||
id='account.timeline.pinned.view_all'
|
||||
defaultMessage='View all pinned posts'
|
||||
/>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
|
@ -20,7 +20,7 @@ import {
|
|||
createAppSelector,
|
||||
} from '@/mastodon/store';
|
||||
|
||||
import classes from './styles.module.scss';
|
||||
import classes from '../styles.module.scss';
|
||||
|
||||
const MAX_SUGGESTED_TAGS = 3;
|
||||
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
import type { FC, ReactNode } from 'react';
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
|
|
@ -10,7 +9,7 @@ import {
|
|||
import { useStorageState } from '@/mastodon/hooks/useStorage';
|
||||
|
||||
interface AccountTimelineContextValue {
|
||||
accountId: string;
|
||||
accountId: string | null;
|
||||
boosts: boolean;
|
||||
replies: boolean;
|
||||
showAllPinned: boolean;
|
||||
|
|
@ -19,13 +18,20 @@ interface AccountTimelineContextValue {
|
|||
onShowAllPinned: () => void;
|
||||
}
|
||||
|
||||
const AccountTimelineContext =
|
||||
export const AccountTimelineContext =
|
||||
createContext<AccountTimelineContextValue | null>(null);
|
||||
|
||||
export const AccountTimelineProvider: FC<{
|
||||
accountId: string;
|
||||
children: ReactNode;
|
||||
}> = ({ accountId, children }) => {
|
||||
export function useAccountContext() {
|
||||
const values = useContext(AccountTimelineContext);
|
||||
if (!values) {
|
||||
throw new Error(
|
||||
'useAccountFilters must be used within an AccountTimelineProvider',
|
||||
);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
export const useAccountContextValue = (accountId?: string | null) => {
|
||||
const storageOptions = {
|
||||
type: 'local',
|
||||
prefix: 'account-filters',
|
||||
|
|
@ -62,9 +68,9 @@ export const AccountTimelineProvider: FC<{
|
|||
}, []);
|
||||
|
||||
// Memoize the context value to avoid unnecessary re-renders.
|
||||
const value = useMemo(
|
||||
return useMemo(
|
||||
() => ({
|
||||
accountId,
|
||||
accountId: accountId ?? null,
|
||||
boosts,
|
||||
replies,
|
||||
showAllPinned,
|
||||
|
|
@ -82,20 +88,4 @@ export const AccountTimelineProvider: FC<{
|
|||
showAllPinned,
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
<AccountTimelineContext.Provider value={value}>
|
||||
{children}
|
||||
</AccountTimelineContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export function useAccountContext() {
|
||||
const values = useContext(AccountTimelineContext);
|
||||
if (!values) {
|
||||
throw new Error(
|
||||
'useAccountFilters must be used within an AccountTimelineProvider',
|
||||
);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import { useEffect, useMemo } from 'react';
|
||||
|
||||
import { TIMELINE_PINNED_VIEW_ALL } from '@/mastodon/actions/timelines';
|
||||
import {
|
||||
expandTimelineByKey,
|
||||
timelineKey,
|
||||
} from '@/mastodon/actions/timelines_typed';
|
||||
import { selectTimelineByKey } from '@/mastodon/selectors/timelines';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import { useAccountContext } from './useAccountContext';
|
||||
|
||||
export function usePinnedStatusIds({
|
||||
accountId,
|
||||
tagged,
|
||||
forceEmptyState = false,
|
||||
}: {
|
||||
accountId: string;
|
||||
tagged?: string;
|
||||
forceEmptyState?: boolean;
|
||||
}) {
|
||||
const pinnedKey = timelineKey({
|
||||
type: 'account',
|
||||
userId: accountId,
|
||||
tagged,
|
||||
pinned: true,
|
||||
replies: true,
|
||||
});
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
useEffect(() => {
|
||||
dispatch(expandTimelineByKey({ key: pinnedKey }));
|
||||
}, [dispatch, pinnedKey]);
|
||||
|
||||
const pinnedTimeline = useAppSelector((state) =>
|
||||
selectTimelineByKey(state, pinnedKey),
|
||||
);
|
||||
|
||||
const { showAllPinned } = useAccountContext();
|
||||
|
||||
const pinnedTimelineItems = pinnedTimeline?.items; // Make a const to avoid the React Compiler complaining.
|
||||
const pinnedStatusIds = useMemo(() => {
|
||||
if (!pinnedTimelineItems || forceEmptyState) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (pinnedTimelineItems.size <= 1 || showAllPinned) {
|
||||
return pinnedTimelineItems;
|
||||
}
|
||||
return pinnedTimelineItems.slice(0, 1).push(TIMELINE_PINNED_VIEW_ALL);
|
||||
}, [forceEmptyState, pinnedTimelineItems, showAllPinned]);
|
||||
|
||||
return {
|
||||
statusIds: pinnedStatusIds,
|
||||
isLoading: !!pinnedTimeline?.isLoading,
|
||||
showAllPinned,
|
||||
};
|
||||
}
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { List as ImmutableList } from 'immutable';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
|
||||
import { me } from 'mastodon/initial_state';
|
||||
import { normalizeForLookup } from 'mastodon/reducers/accounts_map';
|
||||
import { getAccountHidden } from 'mastodon/selectors/accounts';
|
||||
|
||||
import { lookupAccount, fetchAccount } from '../../actions/accounts';
|
||||
import { expandAccountFeaturedTimeline, expandAccountTimeline, connectTimeline, disconnectTimeline } from '../../actions/timelines';
|
||||
import { ColumnBackButton } from '../../components/column_back_button';
|
||||
import { LoadingIndicator } from '../../components/loading_indicator';
|
||||
import StatusList from '../../components/status_list';
|
||||
import Column from '../ui/components/column';
|
||||
import { RemoteHint } from 'mastodon/components/remote_hint';
|
||||
|
||||
import { AccountHeader } from './components/account_header';
|
||||
import { LimitedAccountHint } from './components/limited_account_hint';
|
||||
import { FeaturedCarousel } from '@/mastodon/components/featured_carousel';
|
||||
|
||||
const emptyList = ImmutableList();
|
||||
|
||||
const mapStateToProps = (state, { params: { acct, id, tagged }, withReplies = false }) => {
|
||||
const accountId = id || state.accounts_map[normalizeForLookup(acct)];
|
||||
|
||||
if (accountId === null) {
|
||||
return {
|
||||
isLoading: false,
|
||||
isAccount: false,
|
||||
statusIds: emptyList,
|
||||
};
|
||||
} else if (!accountId) {
|
||||
return {
|
||||
isLoading: true,
|
||||
statusIds: emptyList,
|
||||
};
|
||||
}
|
||||
|
||||
const path = withReplies ? `${accountId}:with_replies` : `${accountId}${tagged ? `:${tagged}` : ''}`;
|
||||
|
||||
return {
|
||||
accountId,
|
||||
isAccount: !!state.getIn(['accounts', accountId]),
|
||||
statusIds: state.getIn(['timelines', `account:${path}`, 'items'], emptyList),
|
||||
isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']),
|
||||
hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']),
|
||||
suspended: state.getIn(['accounts', accountId, 'suspended'], false),
|
||||
hidden: getAccountHidden(state, accountId),
|
||||
blockedBy: state.getIn(['relationships', accountId, 'blocked_by'], false),
|
||||
};
|
||||
};
|
||||
|
||||
class AccountTimeline extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.shape({
|
||||
acct: PropTypes.string,
|
||||
id: PropTypes.string,
|
||||
tagged: PropTypes.string,
|
||||
}).isRequired,
|
||||
accountId: PropTypes.string,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
statusIds: ImmutablePropTypes.list,
|
||||
isLoading: PropTypes.bool,
|
||||
hasMore: PropTypes.bool,
|
||||
withReplies: PropTypes.bool,
|
||||
blockedBy: PropTypes.bool,
|
||||
isAccount: PropTypes.bool,
|
||||
suspended: PropTypes.bool,
|
||||
hidden: PropTypes.bool,
|
||||
multiColumn: PropTypes.bool,
|
||||
};
|
||||
|
||||
_load () {
|
||||
const { accountId, withReplies, params: { tagged }, dispatch } = this.props;
|
||||
|
||||
dispatch(fetchAccount(accountId));
|
||||
|
||||
if (!withReplies) {
|
||||
dispatch(expandAccountFeaturedTimeline(accountId, { tagged }));
|
||||
}
|
||||
|
||||
dispatch(expandAccountTimeline(accountId, { withReplies, tagged }));
|
||||
|
||||
if (accountId === me) {
|
||||
dispatch(connectTimeline(`account:${me}`));
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
const { params: { acct }, accountId, dispatch } = this.props;
|
||||
|
||||
if (accountId) {
|
||||
this._load();
|
||||
} else {
|
||||
dispatch(lookupAccount(acct));
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps) {
|
||||
const { params: { acct, tagged }, accountId, withReplies, dispatch } = this.props;
|
||||
|
||||
if (prevProps.accountId !== accountId && accountId) {
|
||||
this._load();
|
||||
} else if (prevProps.params.acct !== acct) {
|
||||
dispatch(lookupAccount(acct));
|
||||
} else if (prevProps.params.tagged !== tagged) {
|
||||
if (!withReplies) {
|
||||
dispatch(expandAccountFeaturedTimeline(accountId, { tagged }));
|
||||
}
|
||||
dispatch(expandAccountTimeline(accountId, { withReplies, tagged }));
|
||||
}
|
||||
|
||||
if (prevProps.accountId === me && accountId !== me) {
|
||||
dispatch(disconnectTimeline({ timeline: `account:${me}` }));
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
const { dispatch, accountId } = this.props;
|
||||
|
||||
if (accountId === me) {
|
||||
dispatch(disconnectTimeline({ timeline: `account:${me}` }));
|
||||
}
|
||||
}
|
||||
|
||||
handleLoadMore = maxId => {
|
||||
this.props.dispatch(expandAccountTimeline(this.props.accountId, { maxId, withReplies: this.props.withReplies, tagged: this.props.params.tagged }));
|
||||
};
|
||||
|
||||
render () {
|
||||
const { accountId, statusIds, isLoading, hasMore, blockedBy, suspended, isAccount, hidden, multiColumn, remote, remoteUrl, params: { tagged } } = this.props;
|
||||
|
||||
if (isLoading && statusIds.isEmpty()) {
|
||||
return (
|
||||
<Column>
|
||||
<LoadingIndicator />
|
||||
</Column>
|
||||
);
|
||||
} else if (!isLoading && !isAccount) {
|
||||
return (
|
||||
<BundleColumnError multiColumn={multiColumn} errorType='routing' />
|
||||
);
|
||||
}
|
||||
|
||||
let emptyMessage;
|
||||
|
||||
const forceEmptyState = suspended || blockedBy || hidden;
|
||||
|
||||
if (suspended) {
|
||||
emptyMessage = <FormattedMessage id='empty_column.account_suspended' defaultMessage='Account suspended' />;
|
||||
} else if (hidden) {
|
||||
emptyMessage = <LimitedAccountHint accountId={accountId} />;
|
||||
} else if (blockedBy) {
|
||||
emptyMessage = <FormattedMessage id='empty_column.account_unavailable' defaultMessage='Profile unavailable' />;
|
||||
} else if (remote && statusIds.isEmpty()) {
|
||||
emptyMessage = <RemoteHint accountId={accountId} url={remoteUrl} />;
|
||||
} else {
|
||||
emptyMessage = <FormattedMessage id='empty_column.account_timeline' defaultMessage='No posts found' />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Column>
|
||||
<ColumnBackButton />
|
||||
|
||||
<StatusList
|
||||
prepend={
|
||||
<>
|
||||
<AccountHeader accountId={this.props.accountId} hideTabs={forceEmptyState} tagged={tagged} />
|
||||
{!forceEmptyState && <FeaturedCarousel accountId={this.props.accountId} tagged={tagged} />}
|
||||
</>
|
||||
}
|
||||
alwaysPrepend
|
||||
append={<RemoteHint accountId={accountId} />}
|
||||
scrollKey='account_timeline'
|
||||
statusIds={forceEmptyState ? emptyList : statusIds}
|
||||
isLoading={isLoading}
|
||||
hasMore={!forceEmptyState && hasMore}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={emptyMessage}
|
||||
bindToDocument={!multiColumn}
|
||||
timelineId='account'
|
||||
withCounters
|
||||
/>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(AccountTimeline);
|
||||
|
|
@ -12,8 +12,10 @@ import {
|
|||
expandTimelineByKey,
|
||||
timelineKey,
|
||||
} from '@/mastodon/actions/timelines_typed';
|
||||
import { AccountHeader } from '@/mastodon/components/account_header';
|
||||
import { Column } from '@/mastodon/components/column';
|
||||
import { ColumnBackButton } from '@/mastodon/components/column_back_button';
|
||||
import { LimitedAccountHint } from '@/mastodon/components/limited_account_hint';
|
||||
import { LoadingIndicator } from '@/mastodon/components/loading_indicator';
|
||||
import { RemoteHint } from '@/mastodon/components/remote_hint';
|
||||
import StatusList from '@/mastodon/components/status_list';
|
||||
|
|
@ -26,23 +28,23 @@ import { useAccountVisibility } from '@/mastodon/hooks/useAccountVisibility';
|
|||
import { selectTimelineByKey } from '@/mastodon/selectors/timelines';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import { AccountHeader } from '../components/account_header';
|
||||
import { LimitedAccountHint } from '../components/limited_account_hint';
|
||||
|
||||
import { AccountTimelineProvider, useAccountContext } from './context';
|
||||
import { FeaturedTags } from './featured_tags';
|
||||
import { AccountFilters } from './filters';
|
||||
import { FeaturedTags } from './components/featured_tags';
|
||||
import { AccountFilters } from './components/filters';
|
||||
import { renderPinnedStatusHeader } from './components/pinned_statuses';
|
||||
import { TagSuggestions } from './components/tags_suggestions';
|
||||
import {
|
||||
renderPinnedStatusHeader,
|
||||
usePinnedStatusIds,
|
||||
} from './pinned_statuses';
|
||||
AccountTimelineContext,
|
||||
useAccountContext,
|
||||
useAccountContextValue,
|
||||
} from './hooks/useAccountContext';
|
||||
import { usePinnedStatusIds } from './hooks/usePinned';
|
||||
import classes from './styles.module.scss';
|
||||
import { TagSuggestions } from './tags_suggestions';
|
||||
|
||||
const emptyList = ImmutableList<string>();
|
||||
|
||||
const AccountTimelineV2: FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
|
||||
const AccountTimeline: FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
|
||||
const accountId = useAccountId();
|
||||
const accountContext = useAccountContextValue(accountId);
|
||||
|
||||
// Null means accountId does not exist (e.g. invalid acct). Undefined means loading.
|
||||
if (accountId === null) {
|
||||
|
|
@ -59,13 +61,13 @@ const AccountTimelineV2: FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
|
|||
|
||||
// Add this key to remount the timeline when accountId changes.
|
||||
return (
|
||||
<AccountTimelineProvider accountId={accountId}>
|
||||
<AccountTimelineContext.Provider value={accountContext}>
|
||||
<InnerTimeline
|
||||
accountId={accountId}
|
||||
key={accountId}
|
||||
multiColumn={multiColumn}
|
||||
/>
|
||||
</AccountTimelineProvider>
|
||||
</AccountTimelineContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
@ -183,4 +185,4 @@ const EmptyMessage: FC<{ accountId: string }> = ({ accountId }) => {
|
|||
};
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default AccountTimelineV2;
|
||||
export default AccountTimeline;
|
||||
|
|
@ -2,6 +2,7 @@ import type { FC } from 'react';
|
|||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import type { AccountField } from '@/mastodon/components/account_header/fields';
|
||||
import { Button } from '@/mastodon/components/button';
|
||||
import { EmojiHTML } from '@/mastodon/components/emoji/html';
|
||||
import {
|
||||
|
|
@ -10,7 +11,6 @@ import {
|
|||
ModalShellBody,
|
||||
} from '@/mastodon/components/modal_shell';
|
||||
|
||||
import type { AccountField } from '../common';
|
||||
import { useFieldHtml } from '../hooks/useFieldHtml';
|
||||
|
||||
import classes from './styles.module.scss';
|
||||
|
|
|
|||
|
|
@ -1,110 +0,0 @@
|
|||
import type { FC } from 'react';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import IconPinned from '@/images/icons/icon_pinned.svg?react';
|
||||
import { TIMELINE_PINNED_VIEW_ALL } from '@/mastodon/actions/timelines';
|
||||
import {
|
||||
expandTimelineByKey,
|
||||
timelineKey,
|
||||
} from '@/mastodon/actions/timelines_typed';
|
||||
import { Badge } from '@/mastodon/components/badge';
|
||||
import { Button } from '@/mastodon/components/button';
|
||||
import { Icon } from '@/mastodon/components/icon';
|
||||
import { StatusHeader } from '@/mastodon/components/status/header';
|
||||
import type { StatusHeaderRenderFn } from '@/mastodon/components/status/header';
|
||||
import { selectTimelineByKey } from '@/mastodon/selectors/timelines';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import { useAccountContext } from './context';
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
export function usePinnedStatusIds({
|
||||
accountId,
|
||||
tagged,
|
||||
forceEmptyState = false,
|
||||
}: {
|
||||
accountId: string;
|
||||
tagged?: string;
|
||||
forceEmptyState?: boolean;
|
||||
}) {
|
||||
const pinnedKey = timelineKey({
|
||||
type: 'account',
|
||||
userId: accountId,
|
||||
tagged,
|
||||
pinned: true,
|
||||
replies: true,
|
||||
});
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
useEffect(() => {
|
||||
dispatch(expandTimelineByKey({ key: pinnedKey }));
|
||||
}, [dispatch, pinnedKey]);
|
||||
|
||||
const pinnedTimeline = useAppSelector((state) =>
|
||||
selectTimelineByKey(state, pinnedKey),
|
||||
);
|
||||
|
||||
const { showAllPinned } = useAccountContext();
|
||||
|
||||
const pinnedTimelineItems = pinnedTimeline?.items; // Make a const to avoid the React Compiler complaining.
|
||||
const pinnedStatusIds = useMemo(() => {
|
||||
if (!pinnedTimelineItems || forceEmptyState) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (pinnedTimelineItems.size <= 1 || showAllPinned) {
|
||||
return pinnedTimelineItems;
|
||||
}
|
||||
return pinnedTimelineItems.slice(0, 1).push(TIMELINE_PINNED_VIEW_ALL);
|
||||
}, [forceEmptyState, pinnedTimelineItems, showAllPinned]);
|
||||
|
||||
return {
|
||||
statusIds: pinnedStatusIds,
|
||||
isLoading: !!pinnedTimeline?.isLoading,
|
||||
showAllPinned,
|
||||
};
|
||||
}
|
||||
|
||||
export const renderPinnedStatusHeader: StatusHeaderRenderFn = ({
|
||||
featured,
|
||||
...args
|
||||
}) => {
|
||||
if (!featured) {
|
||||
return <StatusHeader {...args} />;
|
||||
}
|
||||
return (
|
||||
<StatusHeader {...args} className={classes.pinnedStatusHeader}>
|
||||
<Badge
|
||||
className={classes.pinnedBadge}
|
||||
icon={<Icon id='pinned' icon={IconPinned} />}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='account.timeline.pinned'
|
||||
defaultMessage='Pinned'
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</StatusHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export const PinnedShowAllButton: FC = () => {
|
||||
const { onShowAllPinned } = useAccountContext();
|
||||
|
||||
return (
|
||||
<Button
|
||||
onClick={onShowAllPinned}
|
||||
className={classNames(classes.pinnedViewAllButton, 'focusable')}
|
||||
>
|
||||
<Icon id='pinned' icon={IconPinned} />
|
||||
<FormattedMessage
|
||||
id='account.timeline.pinned.view_all'
|
||||
defaultMessage='View all pinned posts'
|
||||
/>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
import type { FC } from 'react';
|
||||
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { RelativeTimestamp } from '@/mastodon/components/relative_timestamp';
|
||||
import type { StatusHeaderProps } from '@/mastodon/components/status/header';
|
||||
import {
|
||||
StatusDisplayName,
|
||||
StatusEditedAt,
|
||||
StatusVisibility,
|
||||
} from '@/mastodon/components/status/header';
|
||||
import type { Account } from '@/mastodon/models/account';
|
||||
|
||||
export const AccountStatusHeader: FC<StatusHeaderProps> = ({
|
||||
status,
|
||||
account,
|
||||
children,
|
||||
avatarSize = 48,
|
||||
wrapperProps,
|
||||
onHeaderClick,
|
||||
}) => {
|
||||
const statusAccount = status.get('account') as Account | undefined;
|
||||
const editedAt = status.get('edited_at') as string;
|
||||
|
||||
return (
|
||||
/* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */
|
||||
<div
|
||||
onClick={onHeaderClick}
|
||||
onAuxClick={onHeaderClick}
|
||||
{...wrapperProps}
|
||||
className='status__info'
|
||||
/* eslint-enable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */
|
||||
>
|
||||
<Link
|
||||
to={`/@${statusAccount?.acct}/${status.get('id') as string}`}
|
||||
className='status__relative-time'
|
||||
>
|
||||
<StatusVisibility visibility={status.get('visibility')} />
|
||||
<RelativeTimestamp timestamp={status.get('created_at') as string} />
|
||||
{editedAt && <StatusEditedAt editedAt={editedAt} />}
|
||||
</Link>
|
||||
|
||||
<StatusDisplayName
|
||||
statusAccount={statusAccount}
|
||||
friendAccount={account}
|
||||
avatarSize={avatarSize}
|
||||
/>
|
||||
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -2,7 +2,7 @@ import type { FC, ReactNode } from 'react';
|
|||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { LimitedAccountHint } from '@/mastodon/features/account_timeline/components/limited_account_hint';
|
||||
import { LimitedAccountHint } from '@/mastodon/components/limited_account_hint';
|
||||
import { useAccountVisibility } from '@/mastodon/hooks/useAccountVisibility';
|
||||
import type { Account } from '@/mastodon/models/account';
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ export function PinnedStatuses () {
|
|||
}
|
||||
|
||||
export function AccountTimeline () {
|
||||
return import('../../account_timeline/v2');
|
||||
return import('../../account_timeline');
|
||||
}
|
||||
|
||||
export function AccountGallery () {
|
||||
|
|
|
|||
|
|
@ -28,12 +28,10 @@
|
|||
"account.block_domain": "Block domain {domain}",
|
||||
"account.block_short": "Block",
|
||||
"account.blocked": "Blocked",
|
||||
"account.blocking": "Blocking",
|
||||
"account.cancel_follow_request": "Cancel follow",
|
||||
"account.copy": "Copy link to profile",
|
||||
"account.direct": "Privately mention @{name}",
|
||||
"account.disable_notifications": "Stop notifying me when @{name} posts",
|
||||
"account.domain_blocking": "Blocking domain",
|
||||
"account.edit_note": "Edit personal note",
|
||||
"account.edit_profile": "Edit profile",
|
||||
"account.edit_profile_short": "Edit",
|
||||
|
|
@ -111,7 +109,6 @@
|
|||
"account.mute_notifications_short": "Mute notifications",
|
||||
"account.mute_short": "Mute",
|
||||
"account.muted": "Muted",
|
||||
"account.muting": "Muting",
|
||||
"account.mutual": "You follow each other",
|
||||
"account.name.copy": "Copy handle",
|
||||
"account.name.help.domain": "{domain} is the server that hosts the user’s profile and posts.",
|
||||
|
|
@ -136,7 +133,6 @@
|
|||
"account.remove_from_followers": "Remove {name} from followers",
|
||||
"account.report": "Report @{name}",
|
||||
"account.requested_follow": "{name} has requested to follow you",
|
||||
"account.requests_to_follow_you": "Requests to follow you",
|
||||
"account.share": "Share @{name}'s profile",
|
||||
"account.show_reblogs": "Show boosts from @{name}",
|
||||
"account.statuses_counter": "{count, plural, one {{counter} post} other {{counter} posts}}",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user