diff --git a/app/soapbox/actions/accounts.js b/app/soapbox/actions/accounts.js index fe0f5519a..fb1323ee8 100644 --- a/app/soapbox/actions/accounts.js +++ b/app/soapbox/actions/accounts.js @@ -217,7 +217,7 @@ export function fetchAccountFail(id, error) { }; } -export function followAccount(id, reblogs = true) { +export function followAccount(id, options = { reblogs: true }) { return (dispatch, getState) => { if (!isLoggedIn(getState)) return; @@ -226,7 +226,7 @@ export function followAccount(id, reblogs = true) { dispatch(followAccountRequest(id, locked)); - api(getState).post(`/api/v1/accounts/${id}/follow`, { reblogs }).then(response => { + api(getState).post(`/api/v1/accounts/${id}/follow`, options).then(response => { dispatch(followAccountSuccess(response.data, alreadyFollowing)); }).catch(error => { dispatch(followAccountFail(error, locked)); diff --git a/app/soapbox/features/account/components/header.js b/app/soapbox/features/account/components/header.js index 4de9b6580..775f1327b 100644 --- a/app/soapbox/features/account/components/header.js +++ b/app/soapbox/features/account/components/header.js @@ -283,7 +283,21 @@ class Header extends ImmutablePureComponent { }); } - if (features.accountSubscriptions) { + if (features.accountNotifies) { + if (account.getIn(['relationship', 'notifying'])) { + menu.push({ + text: intl.formatMessage(messages.unsubscribe, { name: account.get('username') }), + action: this.props.onNotifyToggle, + icon: require('@tabler/icons/icons/bell.svg'), + }); + } else { + menu.push({ + text: intl.formatMessage(messages.subscribe, { name: account.get('username') }), + action: this.props.onNotifyToggle, + icon: require('@tabler/icons/icons/bell-off.svg'), + }); + } + } else if (features.accountSubscriptions) { if (account.getIn(['relationship', 'subscribing'])) { menu.push({ text: intl.formatMessage(messages.unsubscribe, { name: account.get('username') }), @@ -589,8 +603,8 @@ class Header extends ImmutablePureComponent { } - {features.accountSubscriptions &&
- + {(features.accountNotifies || features.accountSubscriptions) &&
+
}
diff --git a/app/soapbox/features/account_timeline/components/header.js b/app/soapbox/features/account_timeline/components/header.js index 8b244dd33..51120dfcf 100644 --- a/app/soapbox/features/account_timeline/components/header.js +++ b/app/soapbox/features/account_timeline/components/header.js @@ -59,6 +59,10 @@ export default class Header extends ImmutablePureComponent { this.props.onSubscriptionToggle(this.props.account); } + handleNotifyToggle = () => { + this.props.onNotifyToggle(this.props.account); + } + handleMute = () => { this.props.onMute(this.props.account); } @@ -145,6 +149,7 @@ export default class Header extends ImmutablePureComponent { onChat={this.handleChat} onReblogToggle={this.handleReblogToggle} onSubscriptionToggle={this.handleSubscriptionToggle} + onNotifyToggle={this.handleNotifyToggle} onReport={this.handleReport} onMute={this.handleMute} onBlockDomain={this.handleBlockDomain} diff --git a/app/soapbox/features/account_timeline/containers/header_container.js b/app/soapbox/features/account_timeline/containers/header_container.js index 5050db874..ae4dcb067 100644 --- a/app/soapbox/features/account_timeline/containers/header_container.js +++ b/app/soapbox/features/account_timeline/containers/header_container.js @@ -116,9 +116,9 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onReblogToggle(account) { if (account.getIn(['relationship', 'showing_reblogs'])) { - dispatch(followAccount(account.get('id'), false)); + dispatch(followAccount(account.get('id'), { reblogs: false })); } else { - dispatch(followAccount(account.get('id'), true)); + dispatch(followAccount(account.get('id'), { reblogs: true })); } }, @@ -130,6 +130,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } }, + onNotifyToggle(account) { + if (account.getIn(['relationship', 'notifying'])) { + dispatch(followAccount(account.get('id'), { notify: false })); + } else { + dispatch(followAccount(account.get('id'), { notify: true })); + } + }, + onEndorseToggle(account) { if (account.getIn(['relationship', 'endorsed'])) { dispatch(unpinAccount(account.get('id'))); diff --git a/app/soapbox/features/ui/components/subscription_button.js b/app/soapbox/features/ui/components/subscription_button.js index 0cefca3e5..30de7185e 100644 --- a/app/soapbox/features/ui/components/subscription_button.js +++ b/app/soapbox/features/ui/components/subscription_button.js @@ -1,4 +1,5 @@ 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'; @@ -6,6 +7,7 @@ import { defineMessages, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; import { + followAccount, subscribeAccount, unsubscribeAccount, } from 'soapbox/actions/accounts'; @@ -33,6 +35,13 @@ const mapDispatchToProps = (dispatch) => ({ dispatch(subscribeAccount(account.get('id'))); } }, + onNotifyToggle(account) { + if (account.getIn(['relationship', 'notifying'])) { + dispatch(followAccount(account.get('id'), { notify: false })); + } else { + dispatch(followAccount(account.get('id'), { notify: true })); + } + }, }); export default @connect(mapStateToProps, mapDispatchToProps) @@ -41,15 +50,17 @@ class SubscriptionButton extends ImmutablePureComponent { static propTypes = { account: ImmutablePropTypes.map, + features: PropTypes.object.isRequired, }; handleSubscriptionToggle = () => { - this.props.onSubscriptionToggle(this.props.account); + if (this.props.features.accountNotifies) this.props.onNotifyToggle(this.props.account); + else this.props.onSubscriptionToggle(this.props.account); } render() { - const { account, intl } = this.props; - const subscribing = account.getIn(['relationship', 'subscribing']); + const { account, intl, features } = this.props; + const subscribing = features.accountNotifies ? account.getIn(['relationship', 'notifying']) : account.getIn(['relationship', 'subscribing']); const following = account.getIn(['relationship', 'following']); const requested = account.getIn(['relationship', 'requested']); diff --git a/app/soapbox/utils/features.js b/app/soapbox/utils/features.js index fc3dc68ab..4f5456e78 100644 --- a/app/soapbox/utils/features.js +++ b/app/soapbox/utils/features.js @@ -65,6 +65,10 @@ export const getFeatures = createSelector([ resetPasswordAPI: v.software === PLEROMA, exposableReactions: features.includes('exposable_reactions'), accountSubscriptions: v.software === PLEROMA && gte(v.version, '1.0.0'), + accountNotifies: any([ + v.software === MASTODON && gte(v.compatVersion, '3.3.0'), + v.software === PLEROMA && gte(v.version, '2.4.50'), + ]), unrestrictedLists: v.software === PLEROMA, accountByUsername: v.software === PLEROMA, profileDirectory: any([