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([