From 58cede4808baa4db6cc143b80ef23e8179a8415b Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 18 Nov 2017 19:39:02 +0100 Subject: Profile redirect notes (#5746) * Serialize moved accounts into REST and ActivityPub APIs * Parse federated moved accounts from ActivityPub * Add note about moved accounts to public profiles * Add moved account message to web UI * Fix code style issues --- .../mastodon/features/account/components/header.js | 7 +++- .../features/account_timeline/components/header.js | 3 ++ .../account_timeline/components/moved_note.js | 48 ++++++++++++++++++++++ app/javascript/mastodon/reducers/accounts.js | 5 +++ app/javascript/mastodon/selectors/index.js | 8 +++- 5 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 app/javascript/mastodon/features/account_timeline/components/moved_note.js (limited to 'app/javascript/mastodon') diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js index f0d2d481f..b2399ae9b 100644 --- a/app/javascript/mastodon/features/account/components/header.js +++ b/app/javascript/mastodon/features/account/components/header.js @@ -7,6 +7,7 @@ import Motion from '../../ui/util/optional_motion'; import spring from 'react-motion/lib/spring'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { autoPlayGif, me } from '../../../initial_state'; +import classNames from 'classnames'; const messages = defineMessages({ unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, @@ -102,6 +103,10 @@ export default class Header extends ImmutablePureComponent { } } + if (account.get('moved')) { + actionBtn = ''; + } + if (account.get('locked')) { lockedIcon = ; } @@ -110,7 +115,7 @@ export default class Header extends ImmutablePureComponent { const displayNameHtml = { __html: account.get('display_name_html') }; return ( -
+
diff --git a/app/javascript/mastodon/features/account_timeline/components/header.js b/app/javascript/mastodon/features/account_timeline/components/header.js index 8cf7b92ca..5e251c0e5 100644 --- a/app/javascript/mastodon/features/account_timeline/components/header.js +++ b/app/javascript/mastodon/features/account_timeline/components/header.js @@ -5,6 +5,7 @@ import InnerHeader from '../../account/components/header'; import ActionBar from '../../account/components/action_bar'; import MissingIndicator from '../../../components/missing_indicator'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import MovedNote from './moved_note'; export default class Header extends ImmutablePureComponent { @@ -68,6 +69,8 @@ export default class Header extends ImmutablePureComponent { return (
+ {account.get('moved') && } + { + if (e.button === 0) { + e.preventDefault(); + this.context.router.history.push(`/accounts/${this.props.to.get('id')}`); + } + + e.stopPropagation(); + } + + render () { + const { from, to } = this.props; + const displayNameHtml = { __html: from.get('display_name_html') }; + + return ( +
+
+
+ }} /> +
+ + +
+ +
+
+ ); + } + +} diff --git a/app/javascript/mastodon/reducers/accounts.js b/app/javascript/mastodon/reducers/accounts.js index 8a4d69f26..5891d0fdd 100644 --- a/app/javascript/mastodon/reducers/accounts.js +++ b/app/javascript/mastodon/reducers/accounts.js @@ -59,6 +59,11 @@ const normalizeAccount = (state, account) => { account.display_name_html = emojify(escapeTextContentForBrowser(displayName)); account.note_emojified = emojify(account.note); + if (account.moved) { + state = normalizeAccount(state, account.moved); + account.moved = account.moved.id; + } + return state.set(account.id, fromJS(account)); }; diff --git a/app/javascript/mastodon/selectors/index.js b/app/javascript/mastodon/selectors/index.js index d26d1b727..e47ec5183 100644 --- a/app/javascript/mastodon/selectors/index.js +++ b/app/javascript/mastodon/selectors/index.js @@ -4,14 +4,18 @@ import { List as ImmutableList } from 'immutable'; const getAccountBase = (state, id) => state.getIn(['accounts', id], null); const getAccountCounters = (state, id) => state.getIn(['accounts_counters', id], null); const getAccountRelationship = (state, id) => state.getIn(['relationships', id], null); +const getAccountMoved = (state, id) => state.getIn(['accounts', state.getIn(['accounts', id, 'moved'])]); export const makeGetAccount = () => { - return createSelector([getAccountBase, getAccountCounters, getAccountRelationship], (base, counters, relationship) => { + return createSelector([getAccountBase, getAccountCounters, getAccountRelationship, getAccountMoved], (base, counters, relationship, moved) => { if (base === null) { return null; } - return base.merge(counters).set('relationship', relationship); + return base.merge(counters).withMutations(map => { + map.set('relationship', relationship); + map.set('moved', moved); + }); }); }; -- cgit