From 0e1302587a2e2f0d528cd205151a94a8c037b405 Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 13 Jun 2022 11:35:54 -0400 Subject: [PATCH] Improve subscription button on header --- .../actions/__tests__/accounts.test.ts | 10 +- app/soapbox/actions/accounts.js | 5 +- .../features/account/components/header.js | 26 +---- .../ui/components/subscription-button.tsx | 105 ++++++++++++++++++ .../ui/components/subscription_button.js | 83 -------------- app/soapbox/utils/features.ts | 1 + 6 files changed, 121 insertions(+), 109 deletions(-) create mode 100644 app/soapbox/features/ui/components/subscription-button.tsx delete mode 100644 app/soapbox/features/ui/components/subscription_button.js diff --git a/app/soapbox/actions/__tests__/accounts.test.ts b/app/soapbox/actions/__tests__/accounts.test.ts index b02469527..2ea60bd80 100644 --- a/app/soapbox/actions/__tests__/accounts.test.ts +++ b/app/soapbox/actions/__tests__/accounts.test.ts @@ -435,10 +435,14 @@ describe('followAccount()', () => { skipLoading: true, }, ]; - await store.dispatch(followAccount(id)); - const actions = store.getActions(); - expect(actions).toEqual(expectedActions); + try { + await store.dispatch(followAccount(id)); + } catch (e) { + const actions = store.getActions(); + expect(actions).toEqual(expectedActions); + expect(e).toEqual(new Error('Network Error')); + } }); }); }); diff --git a/app/soapbox/actions/accounts.js b/app/soapbox/actions/accounts.js index 5cc0008a4..63314a6b1 100644 --- a/app/soapbox/actions/accounts.js +++ b/app/soapbox/actions/accounts.js @@ -240,7 +240,10 @@ export function followAccount(id, options = { reblogs: true }) { return api(getState) .post(`/api/v1/accounts/${id}/follow`, options) .then(response => dispatch(followAccountSuccess(response.data, alreadyFollowing))) - .catch(error => dispatch(followAccountFail(error, locked))); + .catch(error => { + dispatch(followAccountFail(error, locked)); + throw error; + }); }; } diff --git a/app/soapbox/features/account/components/header.js b/app/soapbox/features/account/components/header.js index b76a156a5..d90fd0f39 100644 --- a/app/soapbox/features/account/components/header.js +++ b/app/soapbox/features/account/components/header.js @@ -17,6 +17,7 @@ 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 SubscriptionButton from 'soapbox/features/ui/components/subscription-button'; import { isLocal, isRemote, @@ -250,22 +251,6 @@ class Header extends ImmutablePureComponent { }); } - if (features.accountSubscriptions) { - if (account.relationship?.subscribing) { - menu.push({ - text: intl.formatMessage(messages.unsubscribe, { name: account.get('username') }), - action: this.props.onSubscriptionToggle, - icon: require('@tabler/icons/icons/bell.svg'), - }); - } else { - menu.push({ - text: intl.formatMessage(messages.subscribe, { name: account.get('username') }), - action: this.props.onSubscriptionToggle, - icon: require('@tabler/icons/icons/bell-off.svg'), - }); - } - } - if (features.lists) { menu.push({ text: intl.formatMessage(messages.add_or_remove_from_list), @@ -476,7 +461,7 @@ class Header extends ImmutablePureComponent { } + title={} />, ); } @@ -578,11 +563,6 @@ class Header extends ImmutablePureComponent { const menu = this.makeMenu(); const header = account.get('header', ''); - // NOTE: Removing Subscription element - // {features.accountSubscriptions &&
- // - //
} - return (
@@ -618,6 +598,8 @@ class Header extends ImmutablePureComponent {
+ + {me && ( { + const dispatch = useAppDispatch(); + const features = useFeatures(); + const intl = useIntl(); + + const following = account.relationship?.following; + const requested = account.relationship?.requested; + const isSubscribed = features.accountNotifies ? + account.relationship?.notifying : + account.relationship?.subscribing; + const title = isSubscribed ? + intl.formatMessage(messages.unsubscribe, { name: account.get('username') }) : + intl.formatMessage(messages.subscribe, { name: account.get('username') }); + + const onSubscribeSuccess = () => + dispatch(snackbar.success(intl.formatMessage(messages.subscribeSuccess))); + + const onSubscribeFailure = () => + dispatch(snackbar.error(intl.formatMessage(messages.subscribeFailure))); + + const onUnsubscribeSuccess = () => + dispatch(snackbar.success(intl.formatMessage(messages.unsubscribeSuccess))); + + const onUnsubscribeFailure = () => + dispatch(snackbar.error(intl.formatMessage(messages.unsubscribeFailure))); + + const onNotifyToggle = () => { + if (account.relationship?.notifying) { + dispatch(followAccount(account.get('id'), { notify: false } as any)) + ?.then(() => onUnsubscribeSuccess()) + .catch(() => onUnsubscribeFailure()); + } else { + dispatch(followAccount(account.get('id'), { notify: true } as any)) + ?.then(() => onSubscribeSuccess()) + .catch(() => onSubscribeFailure()); + } + }; + + const onSubscriptionToggle = () => { + if (account.relationship?.subscribing) { + dispatch(unsubscribeAccount(account.get('id'))) + ?.then(() => onUnsubscribeSuccess()) + .catch(() => onUnsubscribeFailure()); + } else { + dispatch(subscribeAccount(account.get('id'))) + ?.then(() => onSubscribeSuccess()) + .catch(() => onSubscribeFailure()); + } + }; + + const handleToggle = () => { + if (features.accountNotifies) { + onNotifyToggle(); + } else { + onSubscriptionToggle(); + } + }; + + if (!features.accountSubscriptions) { + return null; + } + + if (requested || following) { + return ( + + ); + } + + return null; +}; + +export default SubscriptionButton; diff --git a/app/soapbox/features/ui/components/subscription_button.js b/app/soapbox/features/ui/components/subscription_button.js deleted file mode 100644 index a908ca335..000000000 --- a/app/soapbox/features/ui/components/subscription_button.js +++ /dev/null @@ -1,83 +0,0 @@ -import classNames from 'classnames'; -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, - subscribeAccount, - unsubscribeAccount, -} from 'soapbox/actions/accounts'; -import Icon from 'soapbox/components/icon'; -import { Button } from 'soapbox/components/ui'; - -const messages = defineMessages({ - subscribe: { id: 'account.subscribe', defaultMessage: 'Subscribe to notifications from @{name}' }, - unsubscribe: { id: 'account.unsubscribe', defaultMessage: 'Unsubscribe to notifications from @{name}' }, - subscribed: { id: 'account.subscribed', defaultMessage: 'Subscribed' }, -}); - -const mapStateToProps = state => { - const me = state.get('me'); - return { - me, - }; -}; - -const mapDispatchToProps = (dispatch) => ({ - onSubscriptionToggle(account) { - if (account.relationship?.subscribing) { - dispatch(unsubscribeAccount(account.get('id'))); - } else { - dispatch(subscribeAccount(account.get('id'))); - } - }, - onNotifyToggle(account) { - if (account.relationship?.notifying) { - dispatch(followAccount(account.get('id'), { notify: false })); - } else { - dispatch(followAccount(account.get('id'), { notify: true })); - } - }, -}); - -export default @connect(mapStateToProps, mapDispatchToProps) -@injectIntl -class SubscriptionButton extends ImmutablePureComponent { - - static propTypes = { - account: ImmutablePropTypes.record, - features: PropTypes.object.isRequired, - }; - - handleSubscriptionToggle = () => { - if (this.props.features.accountNotifies) this.props.onNotifyToggle(this.props.account); - else this.props.onSubscriptionToggle(this.props.account); - } - - render() { - const { account, intl, features } = this.props; - const subscribing = features.accountNotifies ? account.relationship?.notifying : account.relationship?.subscribing; - const following = account.relationship?.following; - const requested = account.relationship?.requested; - - if (requested || following) { - return ( - - ); - } - - return null; - } - -} diff --git a/app/soapbox/utils/features.ts b/app/soapbox/utils/features.ts index 8f8a65cc1..8c3f3636c 100644 --- a/app/soapbox/utils/features.ts +++ b/app/soapbox/utils/features.ts @@ -126,6 +126,7 @@ const getInstanceFeatures = (instance: Instance) => { accountNotifies: any([ v.software === MASTODON && gte(v.compatVersion, '3.3.0'), v.software === PLEROMA && gte(v.version, '2.4.50'), + v.software === TRUTHSOCIAL, ]), /**