Merge branch 'remote-follow-feature' into 'develop'

ActionButton: put remote follow behind feature detection

See merge request soapbox-pub/soapbox-fe!1381
This commit is contained in:
Alex Gleason 2022-05-14 18:39:50 +00:00
commit a6396dd4c5
2 changed files with 59 additions and 28 deletions

View file

@ -30,13 +30,21 @@ const messages = defineMessages({
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
}); });
interface iActionButton { interface IActionButton {
/** Target account for the action. */
account: AccountEntity account: AccountEntity
/** Type of action to prioritize, eg on Blocks and Mutes pages. */
actionType?: 'muting' | 'blocking' actionType?: 'muting' | 'blocking'
/** Displays shorter text on the "Awaiting approval" button. */
small?: boolean small?: boolean
} }
const ActionButton = ({ account, actionType, small }: iActionButton) => { /**
* Circumstantial action button (usually "Follow") to display on accounts.
* May say "Unblock" or something else, depending on the relationship and
* `actionType` prop.
*/
const ActionButton: React.FC<IActionButton> = ({ account, actionType, small }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const features = useFeatures(); const features = useFeatures();
const intl = useIntl(); const intl = useIntl();
@ -45,40 +53,41 @@ const ActionButton = ({ account, actionType, small }: iActionButton) => {
const handleFollow = () => { const handleFollow = () => {
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) { if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
dispatch(unfollowAccount(account.get('id'))); dispatch(unfollowAccount(account.id));
} else { } else {
dispatch(followAccount(account.get('id'))); dispatch(followAccount(account.id));
} }
}; };
const handleBlock = () => { const handleBlock = () => {
if (account.getIn(['relationship', 'blocking'])) { if (account.getIn(['relationship', 'blocking'])) {
dispatch(unblockAccount(account.get('id'))); dispatch(unblockAccount(account.id));
} else { } else {
dispatch(blockAccount(account.get('id'))); dispatch(blockAccount(account.id));
} }
}; };
const handleMute = () => { const handleMute = () => {
if (account.getIn(['relationship', 'muting'])) { if (account.getIn(['relationship', 'muting'])) {
dispatch(unmuteAccount(account.get('id'))); dispatch(unmuteAccount(account.id));
} else { } else {
dispatch(muteAccount(account.get('id'))); dispatch(muteAccount(account.id));
} }
}; };
const handleRemoteFollow = () => { const handleRemoteFollow = () => {
dispatch(openModal('UNAUTHORIZED', { dispatch(openModal('UNAUTHORIZED', {
action: 'FOLLOW', action: 'FOLLOW',
account: account.get('id'), account: account.id,
ap_id: account.get('url'), ap_id: account.url,
})); }));
}; };
/** Handles actionType='muting' */
const mutingAction = () => { const mutingAction = () => {
const isMuted = account.getIn(['relationship', 'muting']); const isMuted = account.getIn(['relationship', 'muting']);
const messageKey = isMuted ? messages.unmute : messages.mute; const messageKey = isMuted ? messages.unmute : messages.mute;
const text = intl.formatMessage(messageKey, { name: account.get('username') }); const text = intl.formatMessage(messageKey, { name: account.username });
return ( return (
<Button <Button
@ -90,10 +99,11 @@ const ActionButton = ({ account, actionType, small }: iActionButton) => {
); );
}; };
/** Handles actionType='blocking' */
const blockingAction = () => { const blockingAction = () => {
const isBlocked = account.getIn(['relationship', 'blocking']); const isBlocked = account.getIn(['relationship', 'blocking']);
const messageKey = isBlocked ? messages.unblock : messages.block; const messageKey = isBlocked ? messages.unblock : messages.block;
const text = intl.formatMessage(messageKey, { name: account.get('username') }); const text = intl.formatMessage(messageKey, { name: account.username });
return ( return (
<Button <Button
@ -105,10 +115,9 @@ const ActionButton = ({ account, actionType, small }: iActionButton) => {
); );
}; };
const empty = <></>; /** Render a remote follow button, depending on features. */
const renderRemoteFollow = () => {
if (!me) { // Remote follow through the API.
// Remote follow
if (features.remoteInteractionsAPI) { if (features.remoteInteractionsAPI) {
return ( return (
<Button <Button
@ -117,18 +126,34 @@ const ActionButton = ({ account, actionType, small }: iActionButton) => {
text={intl.formatMessage(messages.follow)} text={intl.formatMessage(messages.follow)}
/> />
); );
// Pleroma's classic remote follow form.
} else if (features.pleromaRemoteFollow) {
return (
<form method='POST' action='/main/ostatus'>
<input type='hidden' name='nickname' value={account.acct} />
<input type='hidden' name='profile' value='' />
<Button text={intl.formatMessage(messages.remote_follow)} type='submit' />
</form>
);
} }
return ( return null;
<form method='POST' action='/main/ostatus'> };
<input type='hidden' name='nickname' value={account.get('acct')} />
<input type='hidden' name='profile' value='' /> /** Render remote follow if federating, otherwise hide the button. */
<Button text={intl.formatMessage(messages.remote_follow)} type='submit' /> const renderLoggedOut = () => {
</form> if (features.federating) {
); return renderRemoteFollow();
}
return null;
};
if (!me) {
return renderLoggedOut();
} }
if (me !== account.get('id')) { if (me !== account.id) {
const isFollowing = account.getIn(['relationship', 'following']); const isFollowing = account.getIn(['relationship', 'following']);
const blockedBy = account.getIn(['relationship', 'blocked_by']) as boolean; const blockedBy = account.getIn(['relationship', 'blocked_by']) as boolean;
@ -140,9 +165,9 @@ const ActionButton = ({ account, actionType, small }: iActionButton) => {
} }
} }
if (!account.get('relationship')) { if (account.relationship.isEmpty()) {
// Wait until the relationship is loaded // Wait until the relationship is loaded
return empty; return null;
} else if (account.getIn(['relationship', 'requested'])) { } else if (account.getIn(['relationship', 'requested'])) {
// Awaiting acceptance // Awaiting acceptance
return ( return (
@ -176,7 +201,7 @@ const ActionButton = ({ account, actionType, small }: iActionButton) => {
<Button <Button
theme='danger' theme='danger'
size='sm' size='sm'
text={intl.formatMessage(messages.unblock, { name: account.get('username') })} text={intl.formatMessage(messages.unblock, { name: account.username })}
onClick={handleBlock} onClick={handleBlock}
/> />
); );
@ -193,7 +218,7 @@ const ActionButton = ({ account, actionType, small }: iActionButton) => {
); );
} }
return empty; return null;
}; };
export default ActionButton; export default ActionButton;

View file

@ -356,6 +356,12 @@ const getInstanceFeatures = (instance: Instance) => {
*/ */
paginatedContext: v.software === TRUTHSOCIAL, paginatedContext: v.software === TRUTHSOCIAL,
/**
* Displays a form to follow a user when logged out.
* @see POST /main/ostatus
*/
pleromaRemoteFollow: v.software === PLEROMA,
/** /**
* Can add polls to statuses. * Can add polls to statuses.
* @see POST /api/v1/statuses * @see POST /api/v1/statuses