From 8dc2329b473a4e8fdb9751ad39bb60af92e7253e Mon Sep 17 00:00:00 2001 From: Quaylyn Rimer Date: Sun, 3 Aug 2025 00:12:48 -0600 Subject: [PATCH 1/3] fix: show moved account notice in hover card popup - Add conditional logic to display moved account notice when account.moved is present - Include link to new account with proper formatting - Hide follow/unfollow buttons for moved accounts to prevent confusion - Add localization key 'account.moved_to_short' for hover card context - Style moved notice to match existing hover card design patterns Fixes #35623 --- .../mastodon/components/hover_card_account.tsx | 14 ++++++++++++++ app/javascript/mastodon/locales/en.json | 1 + app/javascript/styles/mastodon/components.scss | 17 +++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/app/javascript/mastodon/components/hover_card_account.tsx b/app/javascript/mastodon/components/hover_card_account.tsx index a5a5e4c9575..67004b59c0d 100644 --- a/app/javascript/mastodon/components/hover_card_account.tsx +++ b/app/javascript/mastodon/components/hover_card_account.tsx @@ -98,6 +98,20 @@ export const HoverCardAccount = forwardRef< /> )} + ) : account.moved ? ( +
+ + @{account.moved.acct} + + ), + }} + /> +
) : ( <>
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 329ac90589e..b29f4ccbe0f 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -58,6 +58,7 @@ "account.media": "Media", "account.mention": "Mention @{name}", "account.moved_to": "{name} has indicated that their new account is now:", + "account.moved_to_short": "This account has moved to {acct}", "account.mute": "Mute @{name}", "account.mute_notifications_short": "Mute notifications", "account.mute_short": "Mute", diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index d6f0087cc67..2b66da007e1 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -11027,6 +11027,23 @@ noscript { font-weight: 500; } + &__moved-notice { + text-align: center; + font-weight: 500; + color: $secondary-text-color; + + a { + color: inherit; + text-decoration: underline; + + &:hover, + &:focus, + &:active { + text-decoration: none; + } + } + } + .display-name { font-size: 15px; line-height: 22px; From 15f6f8a8bc007d8a5a718b77f084666cf295922d Mon Sep 17 00:00:00 2001 From: Quaylyn Rimer Date: Sun, 3 Aug 2025 00:36:01 -0600 Subject: [PATCH 2/3] feat: Add follow new account button to moved account hover cards Shows moved account notice with follow button for new account. Fixes Issue #35623 where follow back linked to old moved accounts. Includes Storybook stories demonstrating the functionality. --- .../components/hover_card_account.stories.tsx | 142 ++++++++++++++++++ .../components/hover_card_account.tsx | 19 ++- .../styles/mastodon/components.scss | 3 + 3 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 app/javascript/mastodon/components/hover_card_account.stories.tsx diff --git a/app/javascript/mastodon/components/hover_card_account.stories.tsx b/app/javascript/mastodon/components/hover_card_account.stories.tsx new file mode 100644 index 00000000000..cc3f23b2179 --- /dev/null +++ b/app/javascript/mastodon/components/hover_card_account.stories.tsx @@ -0,0 +1,142 @@ +import { Map as ImmutableMap } from 'immutable'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { accountFactory, accountFactoryState } from '@/testing/factories'; + +import { HoverCardAccount } from './hover_card_account'; + +const meta = { + title: 'Components/HoverCardAccount', + component: HoverCardAccount, + argTypes: { + accountId: { + type: 'string', + description: 'ID of the account to display in the hover card', + }, + }, + args: { + accountId: '1', + }, + decorators: [ + (Story) => ( +
+

+ Hover card examples - demonstrating Issue #35623 fix for moved accounts +

+ +
+ ), + ], +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +// Mock data for different account states +const regularAccount = accountFactoryState({ + id: '1', + username: 'alice', + acct: 'alice@mastodon.social', + display_name: 'Alice Johnson', + note: 'Frontend developer who loves building amazing user interfaces. Coffee enthusiast ☕', + followers_count: 1250, + following_count: 342, + statuses_count: 1840, + avatar: 'https://picsum.photos/200/200?random=1', + header: 'https://picsum.photos/600/200?random=1', + fields: [ + { name: 'Website', value: 'https://alice.dev', verified_at: null }, + { name: 'Location', value: 'San Francisco, CA', verified_at: null }, + ], +}); + +const movedAccount = accountFactoryState({ + id: '2', + username: 'bob_old', + acct: 'bob_old@mastodon.social', + display_name: 'Bob Smith (Moved)', + note: 'I have moved to a new account. Please follow me there!', + followers_count: 890, + following_count: 156, + statuses_count: 420, + avatar: 'https://picsum.photos/200/200?random=2', + header: 'https://picsum.photos/600/200?random=2', + moved: accountFactory({ + id: '3', + username: 'bob_new', + acct: 'bob_new@social.example', + display_name: 'Bob Smith', + followers_count: 950, + following_count: 180, + statuses_count: 45, + avatar: 'https://picsum.photos/200/200?random=3', + header: 'https://picsum.photos/600/200?random=3', + }), +}); + +const newAccount = accountFactoryState({ + id: '3', + username: 'bob_new', + acct: 'bob_new@social.example', + display_name: 'Bob Smith', + note: 'This is my new account! Thanks for following me here.', + followers_count: 950, + following_count: 180, + statuses_count: 45, + avatar: 'https://picsum.photos/200/200?random=3', + header: 'https://picsum.photos/600/200?random=3', +}); + +export const RegularAccount: Story = { + args: { + accountId: '1', + }, + parameters: { + state: { + accounts: ImmutableMap({ + '1': regularAccount, + }), + relationships: ImmutableMap(), + meta: ImmutableMap({ + locale: 'en', + emoji_style: 'unicode', + }), + }, + }, +}; + +export const MovedAccount: Story = { + args: { + accountId: '2', + }, + parameters: { + state: { + accounts: ImmutableMap({ + '2': movedAccount, + '3': newAccount, + }), + relationships: ImmutableMap(), + meta: ImmutableMap({ + locale: 'en', + emoji_style: 'unicode', + }), + }, + }, +}; + +export const LoadingState: Story = { + args: { + accountId: '999', + }, + parameters: { + state: { + accounts: ImmutableMap(), + relationships: ImmutableMap(), + meta: ImmutableMap({ + locale: 'en', + emoji_style: 'unicode', + }), + }, + }, +}; diff --git a/app/javascript/mastodon/components/hover_card_account.tsx b/app/javascript/mastodon/components/hover_card_account.tsx index 67004b59c0d..a01907ec8af 100644 --- a/app/javascript/mastodon/components/hover_card_account.tsx +++ b/app/javascript/mastodon/components/hover_card_account.tsx @@ -32,6 +32,11 @@ export const HoverCardAccount = forwardRef< const account = useAppSelector((state) => accountId ? state.accounts.get(accountId) : undefined, ); + // Get the moved account data if this account has moved + // This allows us to show proper follow button for the new account + const movedAccount = useAppSelector((state) => + account?.moved ? state.accounts.get(account.moved) : undefined, + ); const suspended = account?.suspended; const hidden = useAppSelector((state) => accountId ? getAccountHidden(state, accountId) : undefined, @@ -99,18 +104,26 @@ export const HoverCardAccount = forwardRef< )}
) : account.moved ? ( + // Issue #35623: Show moved account notice instead of regular content + // This prevents following the old account and provides a link + follow button for the new account
- @{account.moved.acct} + acct: movedAccount ? ( + + @{movedAccount.acct} + ) : ( + @{account.moved} ), }} /> + {/* Follow button that follows the NEW account, not the old one */} + {movedAccount && ( + + )}
) : ( <> diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 2b66da007e1..f1a137bb5ba 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -11031,6 +11031,9 @@ noscript { text-align: center; font-weight: 500; color: $secondary-text-color; + display: flex; + flex-direction: column; + gap: 12px; a { color: inherit; From 7268e979008544478cb9ab5bb1d7be656881dc0f Mon Sep 17 00:00:00 2001 From: Quaylyn Rimer Date: Sun, 3 Aug 2025 00:43:49 -0600 Subject: [PATCH 3/3] fix: show moved account notice in hover card popup - Add conditional logic to display moved account notice when account.moved is present - Include link to new account with proper formatting - Hide follow/unfollow buttons for moved accounts to prevent confusion - Add localization key 'account.moved_to_short' for hover card context - Style moved notice to match existing hover card design patterns Fixes #35623 --- .../components/hover_card_account.stories.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app/javascript/mastodon/components/hover_card_account.stories.tsx b/app/javascript/mastodon/components/hover_card_account.stories.tsx index cc3f23b2179..58c9bb682bf 100644 --- a/app/javascript/mastodon/components/hover_card_account.stories.tsx +++ b/app/javascript/mastodon/components/hover_card_account.stories.tsx @@ -1,4 +1,5 @@ import { Map as ImmutableMap } from 'immutable'; + import type { Meta, StoryObj } from '@storybook/react-vite'; import { accountFactory, accountFactoryState } from '@/testing/factories'; @@ -19,9 +20,16 @@ const meta = { }, decorators: [ (Story) => ( -
+

- Hover card examples - demonstrating Issue #35623 fix for moved accounts + Hover card examples - demonstrating Issue #35623 fix for moved + accounts

@@ -54,7 +62,7 @@ const regularAccount = accountFactoryState({ const movedAccount = accountFactoryState({ id: '2', username: 'bob_old', - acct: 'bob_old@mastodon.social', + acct: 'bob_old@mastodon.social', display_name: 'Bob Smith (Moved)', note: 'I have moved to a new account. Please follow me there!', followers_count: 890,