Convert ActionButton to TSX
This commit is contained in:
parent
870f78e413
commit
8dc7cc8794
8 changed files with 174 additions and 198 deletions
|
@ -3,7 +3,7 @@ import { Link, useHistory } from 'react-router-dom';
|
|||
|
||||
import HoverRefWrapper from 'soapbox/components/hover_ref_wrapper';
|
||||
import VerificationBadge from 'soapbox/components/verification_badge';
|
||||
import ActionButton from 'soapbox/features/ui/components/action_button';
|
||||
import ActionButton from 'soapbox/features/ui/components/action-button';
|
||||
import { useAppSelector, useOnScreen } from 'soapbox/hooks';
|
||||
import { getAcct } from 'soapbox/utils/accounts';
|
||||
import { displayFqn } from 'soapbox/utils/state';
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
updateProfileHoverCard,
|
||||
} from 'soapbox/actions/profile_hover_card';
|
||||
import Badge from 'soapbox/components/badge';
|
||||
import ActionButton from 'soapbox/features/ui/components/action_button';
|
||||
import ActionButton from 'soapbox/features/ui/components/action-button';
|
||||
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
|
||||
import { UserPanel } from 'soapbox/features/ui/util/async-components';
|
||||
import { useAppSelector, useAppDispatch } from 'soapbox/hooks';
|
||||
|
|
|
@ -16,7 +16,7 @@ import Badge from 'soapbox/components/badge';
|
|||
import StillImage from 'soapbox/components/still_image';
|
||||
import { HStack, IconButton, Menu, MenuButton, MenuItem, MenuList, MenuLink, MenuDivider } from 'soapbox/components/ui';
|
||||
import SvgIcon from 'soapbox/components/ui/icon/svg-icon';
|
||||
import ActionButton from 'soapbox/features/ui/components/action_button';
|
||||
import ActionButton from 'soapbox/features/ui/components/action-button';
|
||||
import {
|
||||
isLocal,
|
||||
isRemote,
|
||||
|
|
|
@ -12,7 +12,7 @@ import DisplayName from 'soapbox/components/display_name';
|
|||
import Permalink from 'soapbox/components/permalink';
|
||||
import RelativeTimestamp from 'soapbox/components/relative_timestamp';
|
||||
import { Text } from 'soapbox/components/ui';
|
||||
import ActionButton from 'soapbox/features/ui/components/action_button';
|
||||
import ActionButton from 'soapbox/features/ui/components/action-button';
|
||||
import { makeGetAccount } from 'soapbox/selectors';
|
||||
import { shortNumberFormat } from 'soapbox/utils/numbers';
|
||||
import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types';
|
||||
|
@ -82,4 +82,4 @@ class AccountCard extends ImmutablePureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
|||
import Avatar from 'soapbox/components/avatar';
|
||||
import DisplayName from 'soapbox/components/display_name';
|
||||
import Permalink from 'soapbox/components/permalink';
|
||||
import ActionButton from 'soapbox/features/ui/components/action_button';
|
||||
import ActionButton from 'soapbox/features/ui/components/action-button';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
import { makeGetAccount } from 'soapbox/selectors';
|
||||
|
||||
|
|
168
app/soapbox/features/ui/components/action-button.tsx
Normal file
168
app/soapbox/features/ui/components/action-button.tsx
Normal file
|
@ -0,0 +1,168 @@
|
|||
import React from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import {
|
||||
followAccount,
|
||||
unfollowAccount,
|
||||
blockAccount,
|
||||
unblockAccount,
|
||||
muteAccount,
|
||||
unmuteAccount,
|
||||
} from 'soapbox/actions/accounts';
|
||||
import { openModal } from 'soapbox/actions/modals';
|
||||
import { Button } from 'soapbox/components/ui';
|
||||
import { useAppSelector, useFeatures } from 'soapbox/hooks';
|
||||
|
||||
import type { Account as AccountEntity } from 'soapbox/types/entities';
|
||||
|
||||
const messages = defineMessages({
|
||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
||||
remote_follow: { id: 'account.remote_follow', defaultMessage: 'Remote follow' },
|
||||
requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' },
|
||||
requested_small: { id: 'account.requested_small', defaultMessage: 'Awaiting approval' },
|
||||
unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
|
||||
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
|
||||
edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' },
|
||||
blocked: { id: 'account.blocked', defaultMessage: 'Blocked' },
|
||||
});
|
||||
|
||||
interface IAccount {
|
||||
account: AccountEntity
|
||||
small?: boolean
|
||||
}
|
||||
|
||||
const ActionButton = ({ account, small }: IAccount) => {
|
||||
const dispatch = useDispatch();
|
||||
const features = useFeatures();
|
||||
const intl = useIntl();
|
||||
|
||||
const me = useAppSelector((state) => state.me);
|
||||
|
||||
const handleFollow = () => {
|
||||
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
|
||||
dispatch(unfollowAccount(account.get('id')));
|
||||
} else {
|
||||
dispatch(followAccount(account.get('id')));
|
||||
}
|
||||
};
|
||||
|
||||
const handleBlock = () => {
|
||||
if (account.getIn(['relationship', 'blocking'])) {
|
||||
dispatch(unblockAccount(account.get('id')));
|
||||
} else {
|
||||
dispatch(blockAccount(account.get('id')));
|
||||
}
|
||||
};
|
||||
|
||||
const handleMute = () => {
|
||||
if (account.getIn(['relationship', 'muting'])) {
|
||||
dispatch(unmuteAccount(account.get('id')));
|
||||
} else {
|
||||
dispatch(muteAccount(account.get('id')));
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemoteFollow = () => {
|
||||
dispatch(openModal('UNAUTHORIZED', {
|
||||
action: 'FOLLOW',
|
||||
account: account.get('id'),
|
||||
ap_id: account.get('url'),
|
||||
}));
|
||||
};
|
||||
|
||||
const empty = <></>;
|
||||
|
||||
if (!me) {
|
||||
// Remote follow
|
||||
if (features.remoteInteractionsAPI) {
|
||||
return (
|
||||
<Button
|
||||
onClick={handleRemoteFollow}
|
||||
icon={require('@tabler/icons/icons/plus.svg')}
|
||||
text={intl.formatMessage(messages.follow)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<form method='POST' action='/main/ostatus'>
|
||||
<input type='hidden' name='nickname' value={account.get('acct')} />
|
||||
<input type='hidden' name='profile' value='' />
|
||||
<Button text={intl.formatMessage(messages.remote_follow)} type='submit' />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
if (me !== account.get('id')) {
|
||||
const isFollowing = account.getIn(['relationship', 'following']);
|
||||
const blockedBy = account.getIn(['relationship', 'blocked_by']) as boolean;
|
||||
|
||||
if (!account.get('relationship')) {
|
||||
// Wait until the relationship is loaded
|
||||
return empty;
|
||||
} else if (account.getIn(['relationship', 'requested'])) {
|
||||
// Awaiting acceptance
|
||||
return (
|
||||
<Button
|
||||
size='sm'
|
||||
theme='secondary'
|
||||
text={small ? intl.formatMessage(messages.requested_small) : intl.formatMessage(messages.requested)}
|
||||
onClick={handleFollow}
|
||||
/>
|
||||
);
|
||||
} else if (!account.getIn(['relationship', 'blocking']) && !account.getIn(['relationship', 'muting'])) {
|
||||
// Follow & Unfollow
|
||||
return (
|
||||
<Button
|
||||
size='sm'
|
||||
disabled={blockedBy}
|
||||
theme={isFollowing ? 'secondary' : 'primary'}
|
||||
icon={blockedBy ? require('@tabler/icons/icons/ban.svg') : (!isFollowing && require('@tabler/icons/icons/plus.svg'))}
|
||||
onClick={handleFollow}
|
||||
>
|
||||
{isFollowing ? (
|
||||
intl.formatMessage(messages.unfollow)
|
||||
) : (
|
||||
intl.formatMessage(blockedBy ? messages.blocked : messages.follow)
|
||||
)}
|
||||
</Button>
|
||||
);
|
||||
} else if (account.getIn(['relationship', 'blocking'])) {
|
||||
// Unblock
|
||||
return (
|
||||
<Button
|
||||
theme='danger'
|
||||
size='sm'
|
||||
text={intl.formatMessage(messages.unblock, { name: account.get('username') })}
|
||||
onClick={handleBlock}
|
||||
/>
|
||||
);
|
||||
} else if (account.getIn(['relationship', 'muting'])) {
|
||||
// Unmute
|
||||
return (
|
||||
<Button
|
||||
theme='danger'
|
||||
size='sm'
|
||||
text={intl.formatMessage(messages.unmute, { name: account.get('username') })}
|
||||
onClick={handleMute}
|
||||
/>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Edit profile
|
||||
return (
|
||||
<Button
|
||||
theme='secondary'
|
||||
size='sm'
|
||||
text={intl.formatMessage(messages.edit_profile)}
|
||||
to='/settings/profile'
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return empty;
|
||||
};
|
||||
|
||||
export default ActionButton;
|
|
@ -1,180 +0,0 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import {
|
||||
followAccount,
|
||||
unfollowAccount,
|
||||
blockAccount,
|
||||
unblockAccount,
|
||||
muteAccount,
|
||||
unmuteAccount,
|
||||
} from 'soapbox/actions/accounts';
|
||||
import { openModal } from 'soapbox/actions/modals';
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import { Button } from 'soapbox/components/ui';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
|
||||
const messages = defineMessages({
|
||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
||||
remote_follow: { id: 'account.remote_follow', defaultMessage: 'Remote follow' },
|
||||
requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' },
|
||||
requested_small: { id: 'account.requested_small', defaultMessage: 'Awaiting approval' },
|
||||
unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
|
||||
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
|
||||
edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' },
|
||||
blocked: { id: 'account.blocked', defaultMessage: 'Blocked' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const me = state.get('me');
|
||||
const instance = state.get('instance');
|
||||
|
||||
return {
|
||||
me,
|
||||
features: getFeatures(instance),
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onFollow(account) {
|
||||
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
|
||||
dispatch(unfollowAccount(account.get('id')));
|
||||
} else {
|
||||
dispatch(followAccount(account.get('id')));
|
||||
}
|
||||
},
|
||||
|
||||
onBlock(account) {
|
||||
if (account.getIn(['relationship', 'blocking'])) {
|
||||
dispatch(unblockAccount(account.get('id')));
|
||||
} else {
|
||||
dispatch(blockAccount(account.get('id')));
|
||||
}
|
||||
},
|
||||
|
||||
onMute(account) {
|
||||
if (account.getIn(['relationship', 'muting'])) {
|
||||
dispatch(unmuteAccount(account.get('id')));
|
||||
} else {
|
||||
dispatch(muteAccount(account.get('id')));
|
||||
}
|
||||
},
|
||||
|
||||
onOpenUnauthorizedModal(account) {
|
||||
dispatch(openModal('UNAUTHORIZED', {
|
||||
action: 'FOLLOW',
|
||||
account: account.get('id'),
|
||||
ap_id: account.get('url'),
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
||||
export default @connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class ActionButton extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
onFollow: PropTypes.func.isRequired,
|
||||
onBlock: PropTypes.func.isRequired,
|
||||
onOpenUnauthorizedModal: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
small: PropTypes.bool,
|
||||
features: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
small: false,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener('resize', this.handleResize, { passive: true });
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('resize', this.handleResize);
|
||||
}
|
||||
|
||||
handleFollow = () => {
|
||||
this.props.onFollow(this.props.account);
|
||||
}
|
||||
|
||||
handleBlock = () => {
|
||||
this.props.onBlock(this.props.account);
|
||||
}
|
||||
|
||||
handleMute = () => {
|
||||
this.props.onMute(this.props.account);
|
||||
}
|
||||
|
||||
handleRemoteFollow = () => {
|
||||
this.props.onOpenUnauthorizedModal(this.props.account);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { account, intl, me, small, features } = this.props;
|
||||
const empty = <></>;
|
||||
|
||||
if (!me) {
|
||||
// Remote follow
|
||||
if (features.remoteInteractionsAPI) {
|
||||
return (<Button
|
||||
className='button--follow'
|
||||
onClick={this.handleRemoteFollow}
|
||||
>
|
||||
{intl.formatMessage(messages.follow)}
|
||||
<Icon src={require('@tabler/icons/icons/plus.svg')} />
|
||||
</Button>);
|
||||
}
|
||||
|
||||
return (<form method='POST' action='/main/ostatus'>
|
||||
<input type='hidden' name='nickname' value={account.get('acct')} />
|
||||
<input type='hidden' name='profile' value='' />
|
||||
<Button className='logo-button' text={intl.formatMessage(messages.remote_follow)} click='submit' />
|
||||
</form>);
|
||||
}
|
||||
|
||||
if (me !== account.get('id')) {
|
||||
const isFollowing = account.getIn(['relationship', 'following']);
|
||||
const blockedBy = account.getIn(['relationship', 'blocked_by']);
|
||||
|
||||
if (!account.get('relationship')) { // Wait until the relationship is loaded
|
||||
return empty;
|
||||
} else if (account.getIn(['relationship', 'requested'])) {
|
||||
// Awaiting acceptance
|
||||
return <Button size='sm' theme='secondary' text={small ? intl.formatMessage(messages.requested_small) : intl.formatMessage(messages.requested)} onClick={this.handleFollow} />;
|
||||
} else if (!account.getIn(['relationship', 'blocking']) && !account.getIn(['relationship', 'muting'])) {
|
||||
// Follow & Unfollow
|
||||
return (<Button
|
||||
size='sm'
|
||||
disabled={blockedBy}
|
||||
theme={isFollowing ? 'secondary' : 'primary'}
|
||||
icon={blockedBy ? require('@tabler/icons/icons/ban.svg') : (!isFollowing && require('@tabler/icons/icons/plus.svg'))}
|
||||
onClick={this.handleFollow}
|
||||
>
|
||||
{isFollowing ? (
|
||||
intl.formatMessage(messages.unfollow)
|
||||
) : (
|
||||
intl.formatMessage(blockedBy ? messages.blocked : messages.follow)
|
||||
)}
|
||||
</Button>);
|
||||
} else if (account.getIn(['relationship', 'blocking'])) {
|
||||
// Unblock
|
||||
return <Button theme='danger' size='sm' text={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.handleBlock} />;
|
||||
} else if (account.getIn(['relationship', 'muting'])) {
|
||||
// Unmute
|
||||
return <Button theme='danger' size='sm' text={intl.formatMessage(messages.unmute, { name: account.get('username') })} onClick={this.handleMute} />;
|
||||
}
|
||||
} else {
|
||||
// Edit profile
|
||||
return <Button theme='secondary' size='sm' text={intl.formatMessage(messages.edit_profile)} to='/settings/profile' />;
|
||||
}
|
||||
return empty;
|
||||
}
|
||||
|
||||
}
|
|
@ -114,18 +114,6 @@ a.button {
|
|||
}
|
||||
}
|
||||
|
||||
.button--follow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.svg-icon {
|
||||
margin: 0 0 0 6px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.button--welcome {
|
||||
.emojione {
|
||||
margin: -1px 6px 0 -4px;
|
||||
|
|
Loading…
Reference in a new issue