From 945ac23910dff9e7d901f5faa6ee55292812f032 Mon Sep 17 00:00:00 2001 From: Echo Date: Thu, 30 Apr 2026 15:58:22 +0200 Subject: [PATCH] Remove and move profile code (#38863) --- .../account_header}/badges.tsx | 9 +- .../account_header}/buttons.tsx | 7 +- .../account_header}/fields.tsx | 26 ++- .../account_header/index.tsx} | 12 +- .../account_header}/memorial_note.tsx | 0 .../account_header}/menu.tsx | 3 +- .../account_header}/moved_note.tsx | 7 +- .../account_header/name.tsx} | 9 +- .../account_header}/note.tsx | 5 +- .../account_header}/number_fields.tsx | 10 +- .../account_header}/styles.module.scss | 0 .../account_header/subscription_form.tsx} | 15 +- .../account_header}/tabs.tsx | 3 +- .../components/limited_account_hint.tsx | 9 +- .../mastodon/components/status_list.jsx | 2 +- .../components/empty_message.tsx | 2 +- .../features/account_featured/index.tsx | 32 +-- .../features/account_gallery/index.tsx | 26 +-- .../features/account_timeline/common.ts | 7 - .../{v2 => components}/featured_tags.tsx | 4 +- .../{v2 => components}/filters.tsx | 7 +- .../account_timeline/components/info.tsx | 68 ------ .../components/pinned_statuses.tsx | 55 +++++ .../{v2 => components}/tags_suggestions.tsx | 2 +- .../useAccountContext.ts} | 40 ++-- .../account_timeline/hooks/usePinned.ts | 58 ++++++ .../features/account_timeline/index.jsx | 197 ------------------ .../account_timeline/{v2 => }/index.tsx | 30 +-- .../account_timeline/modals/field_modal.tsx | 2 +- .../{v2 => }/styles.module.scss | 0 .../account_timeline/v2/pinned_statuses.tsx | 110 ---------- .../account_timeline/v2/status_header.tsx | 52 ----- .../features/followers/components/empty.tsx | 2 +- .../features/ui/util/async-components.js | 2 +- app/javascript/mastodon/locales/en.json | 4 - 35 files changed, 248 insertions(+), 569 deletions(-) rename app/javascript/mastodon/{features/account_timeline/components => components/account_header}/badges.tsx (98%) rename app/javascript/mastodon/{features/account_timeline/components => components/account_header}/buttons.tsx (95%) rename app/javascript/mastodon/{features/account_timeline/components => components/account_header}/fields.tsx (93%) rename app/javascript/mastodon/{features/account_timeline/components/account_header.tsx => components/account_header/index.tsx} (94%) rename app/javascript/mastodon/{features/account_timeline/components => components/account_header}/memorial_note.tsx (100%) rename app/javascript/mastodon/{features/account_timeline/components => components/account_header}/menu.tsx (99%) rename app/javascript/mastodon/{features/account_timeline/components => components/account_header}/moved_note.tsx (87%) rename app/javascript/mastodon/{features/account_timeline/components/account_name.tsx => components/account_header/name.tsx} (96%) rename app/javascript/mastodon/{features/account_timeline/components => components/account_header}/note.tsx (93%) rename app/javascript/mastodon/{features/account_timeline/components => components/account_header}/number_fields.tsx (91%) rename app/javascript/mastodon/{features/account_timeline/components => components/account_header}/styles.module.scss (100%) rename app/javascript/mastodon/{features/account_timeline/components/account_subscription_form.tsx => components/account_header/subscription_form.tsx} (92%) rename app/javascript/mastodon/{features/account_timeline/components => components/account_header}/tabs.tsx (95%) rename app/javascript/mastodon/{features/account_timeline => }/components/limited_account_hint.tsx (78%) delete mode 100644 app/javascript/mastodon/features/account_timeline/common.ts rename app/javascript/mastodon/features/account_timeline/{v2 => components}/featured_tags.tsx (96%) rename app/javascript/mastodon/features/account_timeline/{v2 => components}/filters.tsx (95%) delete mode 100644 app/javascript/mastodon/features/account_timeline/components/info.tsx create mode 100644 app/javascript/mastodon/features/account_timeline/components/pinned_statuses.tsx rename app/javascript/mastodon/features/account_timeline/{v2 => components}/tags_suggestions.tsx (98%) rename app/javascript/mastodon/features/account_timeline/{v2/context.tsx => hooks/useAccountContext.ts} (82%) create mode 100644 app/javascript/mastodon/features/account_timeline/hooks/usePinned.ts delete mode 100644 app/javascript/mastodon/features/account_timeline/index.jsx rename app/javascript/mastodon/features/account_timeline/{v2 => }/index.tsx (85%) rename app/javascript/mastodon/features/account_timeline/{v2 => }/styles.module.scss (100%) delete mode 100644 app/javascript/mastodon/features/account_timeline/v2/pinned_statuses.tsx delete mode 100644 app/javascript/mastodon/features/account_timeline/v2/status_header.tsx diff --git a/app/javascript/mastodon/features/account_timeline/components/badges.tsx b/app/javascript/mastodon/components/account_header/badges.tsx similarity index 98% rename from app/javascript/mastodon/features/account_timeline/components/badges.tsx rename to app/javascript/mastodon/components/account_header/badges.tsx index ec8b00f5ac3..401f0d0fb1f 100644 --- a/app/javascript/mastodon/features/account_timeline/components/badges.tsx +++ b/app/javascript/mastodon/components/account_header/badges.tsx @@ -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'; diff --git a/app/javascript/mastodon/features/account_timeline/components/buttons.tsx b/app/javascript/mastodon/components/account_header/buttons.tsx similarity index 95% rename from app/javascript/mastodon/features/account_timeline/components/buttons.tsx rename to app/javascript/mastodon/components/account_header/buttons.tsx index 0c24207b6ab..737a3b9ca5a 100644 --- a/app/javascript/mastodon/features/account_timeline/components/buttons.tsx +++ b/app/javascript/mastodon/components/account_header/buttons.tsx @@ -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({ diff --git a/app/javascript/mastodon/features/account_timeline/components/fields.tsx b/app/javascript/mastodon/components/account_header/fields.tsx similarity index 93% rename from app/javascript/mastodon/features/account_timeline/components/fields.tsx rename to app/javascript/mastodon/components/account_header/fields.tsx index 38e93b100fb..ce2fe9d3225 100644 --- a/app/javascript/mastodon/features/account_timeline/components/fields.tsx +++ b/app/javascript/mastodon/components/account_header/fields.tsx @@ -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, }) => { diff --git a/app/javascript/mastodon/features/account_timeline/components/account_header.tsx b/app/javascript/mastodon/components/account_header/index.tsx similarity index 94% rename from app/javascript/mastodon/features/account_timeline/components/account_header.tsx rename to app/javascript/mastodon/components/account_header/index.tsx index 174f8623652..9222d0eb320 100644 --- a/app/javascript/mastodon/features/account_timeline/components/account_header.tsx +++ b/app/javascript/mastodon/components/account_header/index.tsx @@ -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) => { diff --git a/app/javascript/mastodon/features/account_timeline/components/memorial_note.tsx b/app/javascript/mastodon/components/account_header/memorial_note.tsx similarity index 100% rename from app/javascript/mastodon/features/account_timeline/components/memorial_note.tsx rename to app/javascript/mastodon/components/account_header/memorial_note.tsx diff --git a/app/javascript/mastodon/features/account_timeline/components/menu.tsx b/app/javascript/mastodon/components/account_header/menu.tsx similarity index 99% rename from app/javascript/mastodon/features/account_timeline/components/menu.tsx rename to app/javascript/mastodon/components/account_header/menu.tsx index 366115ee290..936609e91fd 100644 --- a/app/javascript/mastodon/features/account_timeline/components/menu.tsx +++ b/app/javascript/mastodon/components/account_header/menu.tsx @@ -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 }) => { diff --git a/app/javascript/mastodon/features/account_timeline/components/moved_note.tsx b/app/javascript/mastodon/components/account_header/moved_note.tsx similarity index 87% rename from app/javascript/mastodon/features/account_timeline/components/moved_note.tsx rename to app/javascript/mastodon/components/account_header/moved_note.tsx index f2457dedd74..153c206bbc9 100644 --- a/app/javascript/mastodon/features/account_timeline/components/moved_note.tsx +++ b/app/javascript/mastodon/components/account_header/moved_note.tsx @@ -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; diff --git a/app/javascript/mastodon/features/account_timeline/components/account_name.tsx b/app/javascript/mastodon/components/account_header/name.tsx similarity index 96% rename from app/javascript/mastodon/features/account_timeline/components/account_name.tsx rename to app/javascript/mastodon/components/account_header/name.tsx index 9f7dc528ea4..4f2bbcc3178 100644 --- a/app/javascript/mastodon/features/account_timeline/components/account_name.tsx +++ b/app/javascript/mastodon/components/account_header/name.tsx @@ -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'; diff --git a/app/javascript/mastodon/features/account_timeline/components/note.tsx b/app/javascript/mastodon/components/account_header/note.tsx similarity index 93% rename from app/javascript/mastodon/features/account_timeline/components/note.tsx rename to app/javascript/mastodon/components/account_header/note.tsx index 6bd727791ad..d58c37aec94 100644 --- a/app/javascript/mastodon/features/account_timeline/components/note.tsx +++ b/app/javascript/mastodon/components/account_header/note.tsx @@ -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({ diff --git a/app/javascript/mastodon/features/account_timeline/components/number_fields.tsx b/app/javascript/mastodon/components/account_header/number_fields.tsx similarity index 91% rename from app/javascript/mastodon/features/account_timeline/components/number_fields.tsx rename to app/javascript/mastodon/components/account_header/number_fields.tsx index fb6301952f7..50f7f67aabe 100644 --- a/app/javascript/mastodon/features/account_timeline/components/number_fields.tsx +++ b/app/javascript/mastodon/components/account_header/number_fields.tsx @@ -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, }) => { diff --git a/app/javascript/mastodon/features/account_timeline/components/styles.module.scss b/app/javascript/mastodon/components/account_header/styles.module.scss similarity index 100% rename from app/javascript/mastodon/features/account_timeline/components/styles.module.scss rename to app/javascript/mastodon/components/account_header/styles.module.scss diff --git a/app/javascript/mastodon/features/account_timeline/components/account_subscription_form.tsx b/app/javascript/mastodon/components/account_header/subscription_form.tsx similarity index 92% rename from app/javascript/mastodon/features/account_timeline/components/account_subscription_form.tsx rename to app/javascript/mastodon/components/account_header/subscription_form.tsx index e3fc8146e6c..f78077bef76 100644 --- a/app/javascript/mastodon/features/account_timeline/components/account_subscription_form.tsx +++ b/app/javascript/mastodon/components/account_header/subscription_form.tsx @@ -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'; diff --git a/app/javascript/mastodon/features/account_timeline/components/tabs.tsx b/app/javascript/mastodon/components/account_header/tabs.tsx similarity index 95% rename from app/javascript/mastodon/features/account_timeline/components/tabs.tsx rename to app/javascript/mastodon/components/account_header/tabs.tsx index 5fc56f8e3a1..f2f4ebbe278 100644 --- a/app/javascript/mastodon/features/account_timeline/components/tabs.tsx +++ b/app/javascript/mastodon/components/account_header/tabs.tsx @@ -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['isActive'] = (match, location) => diff --git a/app/javascript/mastodon/features/account_timeline/components/limited_account_hint.tsx b/app/javascript/mastodon/components/limited_account_hint.tsx similarity index 78% rename from app/javascript/mastodon/features/account_timeline/components/limited_account_hint.tsx rename to app/javascript/mastodon/components/limited_account_hint.tsx index f06bf574a77..b780e802e5f 100644 --- a/app/javascript/mastodon/features/account_timeline/components/limited_account_hint.tsx +++ b/app/javascript/mastodon/components/limited_account_hint.tsx @@ -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, diff --git a/app/javascript/mastodon/components/status_list.jsx b/app/javascript/mastodon/components/status_list.jsx index 817a9e9ce4b..5e2c960ed15 100644 --- a/app/javascript/mastodon/components/status_list.jsx +++ b/app/javascript/mastodon/components/status_list.jsx @@ -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'; diff --git a/app/javascript/mastodon/features/account_featured/components/empty_message.tsx b/app/javascript/mastodon/features/account_featured/components/empty_message.tsx index e1de024a695..19ced4ce23c 100644 --- a/app/javascript/mastodon/features/account_featured/components/empty_message.tsx +++ b/app/javascript/mastodon/features/account_featured/components/empty_message.tsx @@ -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'; diff --git a/app/javascript/mastodon/features/account_featured/index.tsx b/app/javascript/mastodon/features/account_featured/index.tsx index 439016cf9c3..f6a9288e214 100644 --- a/app/javascript/mastodon/features/account_featured/index.tsx +++ b/app/javascript/mastodon/features/account_featured/index.tsx @@ -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'; diff --git a/app/javascript/mastodon/features/account_gallery/index.tsx b/app/javascript/mastodon/features/account_gallery/index.tsx index 069f1242f70..feba6f454d5 100644 --- a/app/javascript/mastodon/features/account_gallery/index.tsx +++ b/app/javascript/mastodon/features/account_gallery/index.tsx @@ -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'; diff --git a/app/javascript/mastodon/features/account_timeline/common.ts b/app/javascript/mastodon/features/account_timeline/common.ts deleted file mode 100644 index b036530e14d..00000000000 --- a/app/javascript/mastodon/features/account_timeline/common.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { AccountFieldShape } from '@/mastodon/models/account'; - -export interface AccountField extends AccountFieldShape { - nameHasEmojis: boolean; - value_plain: string; - valueHasEmojis: boolean; -} diff --git a/app/javascript/mastodon/features/account_timeline/v2/featured_tags.tsx b/app/javascript/mastodon/features/account_timeline/components/featured_tags.tsx similarity index 96% rename from app/javascript/mastodon/features/account_timeline/v2/featured_tags.tsx rename to app/javascript/mastodon/features/account_timeline/components/featured_tags.tsx index b8061fced43..c4d43bb2b9f 100644 --- a/app/javascript/mastodon/features/account_timeline/v2/featured_tags.tsx +++ b/app/javascript/mastodon/features/account_timeline/components/featured_tags.tsx @@ -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. diff --git a/app/javascript/mastodon/features/account_timeline/v2/filters.tsx b/app/javascript/mastodon/features/account_timeline/components/filters.tsx similarity index 95% rename from app/javascript/mastodon/features/account_timeline/v2/filters.tsx rename to app/javascript/mastodon/features/account_timeline/components/filters.tsx index 2dc8254a201..e24ca642093 100644 --- a/app/javascript/mastodon/features/account_timeline/v2/filters.tsx +++ b/app/javascript/mastodon/features/account_timeline/components/filters.tsx @@ -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 }>(); diff --git a/app/javascript/mastodon/features/account_timeline/components/info.tsx b/app/javascript/mastodon/features/account_timeline/components/info.tsx deleted file mode 100644 index bb99999c41e..00000000000 --- a/app/javascript/mastodon/features/account_timeline/components/info.tsx +++ /dev/null @@ -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 ( -
- {(relationship.followed_by || relationship.requested_by) && ( - - - - )} - {relationship.blocking && ( - - - - )} - {relationship.muting && ( - - - - )} - {relationship.domain_blocking && ( - - - - )} -
- ); -}; - -const AccountInfoFollower: FC<{ relationship: Relationship }> = ({ - relationship, -}) => { - if ( - relationship.followed_by && - (relationship.following || relationship.requested) - ) { - return ( - - ); - } else if (relationship.followed_by) { - return ( - - ); - } else if (relationship.requested_by) { - return ( - - ); - } - return null; -}; diff --git a/app/javascript/mastodon/features/account_timeline/components/pinned_statuses.tsx b/app/javascript/mastodon/features/account_timeline/components/pinned_statuses.tsx new file mode 100644 index 00000000000..11de336002b --- /dev/null +++ b/app/javascript/mastodon/features/account_timeline/components/pinned_statuses.tsx @@ -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 ; + } + return ( + + } + label={ + + } + /> + + ); +}; + +export const PinnedShowAllButton: FC = () => { + const { onShowAllPinned } = useAccountContext(); + + return ( + + ); +}; diff --git a/app/javascript/mastodon/features/account_timeline/v2/tags_suggestions.tsx b/app/javascript/mastodon/features/account_timeline/components/tags_suggestions.tsx similarity index 98% rename from app/javascript/mastodon/features/account_timeline/v2/tags_suggestions.tsx rename to app/javascript/mastodon/features/account_timeline/components/tags_suggestions.tsx index f3ac52ca3bc..555dc6e7c9a 100644 --- a/app/javascript/mastodon/features/account_timeline/v2/tags_suggestions.tsx +++ b/app/javascript/mastodon/features/account_timeline/components/tags_suggestions.tsx @@ -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; diff --git a/app/javascript/mastodon/features/account_timeline/v2/context.tsx b/app/javascript/mastodon/features/account_timeline/hooks/useAccountContext.ts similarity index 82% rename from app/javascript/mastodon/features/account_timeline/v2/context.tsx rename to app/javascript/mastodon/features/account_timeline/hooks/useAccountContext.ts index c95eba37339..46595425bd3 100644 --- a/app/javascript/mastodon/features/account_timeline/v2/context.tsx +++ b/app/javascript/mastodon/features/account_timeline/hooks/useAccountContext.ts @@ -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(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 ( - - {children} - - ); }; - -export function useAccountContext() { - const values = useContext(AccountTimelineContext); - if (!values) { - throw new Error( - 'useAccountFilters must be used within an AccountTimelineProvider', - ); - } - return values; -} diff --git a/app/javascript/mastodon/features/account_timeline/hooks/usePinned.ts b/app/javascript/mastodon/features/account_timeline/hooks/usePinned.ts new file mode 100644 index 00000000000..2ff2c16965e --- /dev/null +++ b/app/javascript/mastodon/features/account_timeline/hooks/usePinned.ts @@ -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, + }; +} diff --git a/app/javascript/mastodon/features/account_timeline/index.jsx b/app/javascript/mastodon/features/account_timeline/index.jsx deleted file mode 100644 index 70e607d5f2d..00000000000 --- a/app/javascript/mastodon/features/account_timeline/index.jsx +++ /dev/null @@ -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 ( - - - - ); - } else if (!isLoading && !isAccount) { - return ( - - ); - } - - let emptyMessage; - - const forceEmptyState = suspended || blockedBy || hidden; - - if (suspended) { - emptyMessage = ; - } else if (hidden) { - emptyMessage = ; - } else if (blockedBy) { - emptyMessage = ; - } else if (remote && statusIds.isEmpty()) { - emptyMessage = ; - } else { - emptyMessage = ; - } - - return ( - - - - - - {!forceEmptyState && } - - } - alwaysPrepend - append={} - scrollKey='account_timeline' - statusIds={forceEmptyState ? emptyList : statusIds} - isLoading={isLoading} - hasMore={!forceEmptyState && hasMore} - onLoadMore={this.handleLoadMore} - emptyMessage={emptyMessage} - bindToDocument={!multiColumn} - timelineId='account' - withCounters - /> - - ); - } - -} - -export default connect(mapStateToProps)(AccountTimeline); diff --git a/app/javascript/mastodon/features/account_timeline/v2/index.tsx b/app/javascript/mastodon/features/account_timeline/index.tsx similarity index 85% rename from app/javascript/mastodon/features/account_timeline/v2/index.tsx rename to app/javascript/mastodon/features/account_timeline/index.tsx index 693813bdbe9..ce1e99a45fa 100644 --- a/app/javascript/mastodon/features/account_timeline/v2/index.tsx +++ b/app/javascript/mastodon/features/account_timeline/index.tsx @@ -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(); -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 ( - + - + ); }; @@ -183,4 +185,4 @@ const EmptyMessage: FC<{ accountId: string }> = ({ accountId }) => { }; // eslint-disable-next-line import/no-default-export -export default AccountTimelineV2; +export default AccountTimeline; diff --git a/app/javascript/mastodon/features/account_timeline/modals/field_modal.tsx b/app/javascript/mastodon/features/account_timeline/modals/field_modal.tsx index d2b05703c2f..baf0c70f762 100644 --- a/app/javascript/mastodon/features/account_timeline/modals/field_modal.tsx +++ b/app/javascript/mastodon/features/account_timeline/modals/field_modal.tsx @@ -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'; diff --git a/app/javascript/mastodon/features/account_timeline/v2/styles.module.scss b/app/javascript/mastodon/features/account_timeline/styles.module.scss similarity index 100% rename from app/javascript/mastodon/features/account_timeline/v2/styles.module.scss rename to app/javascript/mastodon/features/account_timeline/styles.module.scss diff --git a/app/javascript/mastodon/features/account_timeline/v2/pinned_statuses.tsx b/app/javascript/mastodon/features/account_timeline/v2/pinned_statuses.tsx deleted file mode 100644 index 78dad724782..00000000000 --- a/app/javascript/mastodon/features/account_timeline/v2/pinned_statuses.tsx +++ /dev/null @@ -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 ; - } - return ( - - } - label={ - - } - /> - - ); -}; - -export const PinnedShowAllButton: FC = () => { - const { onShowAllPinned } = useAccountContext(); - - return ( - - ); -}; diff --git a/app/javascript/mastodon/features/account_timeline/v2/status_header.tsx b/app/javascript/mastodon/features/account_timeline/v2/status_header.tsx deleted file mode 100644 index 5f0ff886857..00000000000 --- a/app/javascript/mastodon/features/account_timeline/v2/status_header.tsx +++ /dev/null @@ -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 = ({ - 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 */ -
- - - - {editedAt && } - - - - - {children} -
- ); -}; diff --git a/app/javascript/mastodon/features/followers/components/empty.tsx b/app/javascript/mastodon/features/followers/components/empty.tsx index 3fb92c1061e..edb675e80ae 100644 --- a/app/javascript/mastodon/features/followers/components/empty.tsx +++ b/app/javascript/mastodon/features/followers/components/empty.tsx @@ -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'; diff --git a/app/javascript/mastodon/features/ui/util/async-components.js b/app/javascript/mastodon/features/ui/util/async-components.js index f976604a4ef..a6685587e92 100644 --- a/app/javascript/mastodon/features/ui/util/async-components.js +++ b/app/javascript/mastodon/features/ui/util/async-components.js @@ -77,7 +77,7 @@ export function PinnedStatuses () { } export function AccountTimeline () { - return import('../../account_timeline/v2'); + return import('../../account_timeline'); } export function AccountGallery () { diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 8019566ef6f..7e49de02bfe 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -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}}",