diff --git a/app/javascript/mastodon/containers/account_container.jsx b/app/javascript/mastodon/containers/account_container.jsx index a134452e77..f171fcc2fe 100644 --- a/app/javascript/mastodon/containers/account_container.jsx +++ b/app/javascript/mastodon/containers/account_container.jsx @@ -13,7 +13,6 @@ import { import { openModal } from '../actions/modal'; import { initMuteModal } from '../actions/mutes'; import Account from '../components/account'; -import { unfollowModal } from '../initial_state'; import { makeGetAccount } from '../selectors'; const messages = defineMessages({ @@ -34,18 +33,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onFollow (account) { if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) { - if (unfollowModal) { - dispatch(openModal({ - modalType: 'CONFIRM', - modalProps: { - message: @{account.get('acct')} }} />, - confirm: intl.formatMessage(messages.unfollowConfirm), - onConfirm: () => dispatch(unfollowAccount(account.get('id'))), - }, - })); - } else { - dispatch(unfollowAccount(account.get('id'))); - } + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: @{account.get('acct')} }} />, + confirm: intl.formatMessage(messages.unfollowConfirm), + onConfirm: () => dispatch(unfollowAccount(account.get('id'))), + }, + })); } else { dispatch(followAccount(account.get('id'))); } diff --git a/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx b/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx index 071dbdbfb7..73fd62841b 100644 --- a/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx +++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx @@ -21,7 +21,6 @@ import { initDomainBlockModal, unblockDomain } from '../../../actions/domain_blo import { openModal } from '../../../actions/modal'; import { initMuteModal } from '../../../actions/mutes'; import { initReport } from '../../../actions/reports'; -import { unfollowModal } from '../../../initial_state'; import { makeGetAccount, getAccountHidden } from '../../../selectors'; import Header from '../components/header'; @@ -47,31 +46,23 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onFollow (account) { if (account.getIn(['relationship', 'following'])) { - if (unfollowModal) { - dispatch(openModal({ - modalType: 'CONFIRM', - modalProps: { - message: @{account.get('acct')} }} />, - confirm: intl.formatMessage(messages.unfollowConfirm), - onConfirm: () => dispatch(unfollowAccount(account.get('id'))), - }, - })); - } else { - dispatch(unfollowAccount(account.get('id'))); - } + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: @{account.get('acct')} }} />, + confirm: intl.formatMessage(messages.unfollowConfirm), + onConfirm: () => dispatch(unfollowAccount(account.get('id'))), + }, + })); } else if (account.getIn(['relationship', 'requested'])) { - if (unfollowModal) { - dispatch(openModal({ - modalType: 'CONFIRM', - modalProps: { - message: @{account.get('acct')} }} />, - confirm: intl.formatMessage(messages.cancelFollowRequestConfirm), - onConfirm: () => dispatch(unfollowAccount(account.get('id'))), - }, - })); - } else { - dispatch(unfollowAccount(account.get('id'))); - } + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: @{account.get('acct')} }} />, + confirm: intl.formatMessage(messages.cancelFollowRequestConfirm), + onConfirm: () => dispatch(unfollowAccount(account.get('id'))), + }, + })); } else { dispatch(followAccount(account.get('id'))); } diff --git a/app/javascript/mastodon/features/directory/components/account_card.jsx b/app/javascript/mastodon/features/directory/components/account_card.jsx index ff1f8a653b..9c5e688120 100644 --- a/app/javascript/mastodon/features/directory/components/account_card.jsx +++ b/app/javascript/mastodon/features/directory/components/account_card.jsx @@ -20,7 +20,7 @@ import { Avatar } from 'mastodon/components/avatar'; import { Button } from 'mastodon/components/button'; import { DisplayName } from 'mastodon/components/display_name'; import { ShortNumber } from 'mastodon/components/short_number'; -import { autoPlayGif, me, unfollowModal } from 'mastodon/initial_state'; +import { autoPlayGif, me } from 'mastodon/initial_state'; import { makeGetAccount } from 'mastodon/selectors'; const messages = defineMessages({ @@ -48,38 +48,30 @@ const makeMapStateToProps = () => { const mapDispatchToProps = (dispatch, { intl }) => ({ onFollow(account) { if (account.getIn(['relationship', 'following'])) { - if (unfollowModal) { - dispatch( - openModal({ - modalType: 'CONFIRM', - modalProps: { - message: ( - @{account.get('acct')} }} - /> - ), - confirm: intl.formatMessage(messages.unfollowConfirm), - onConfirm: () => dispatch(unfollowAccount(account.get('id'))), - } }), - ); - } else { - dispatch(unfollowAccount(account.get('id'))); - } - } else if (account.getIn(['relationship', 'requested'])) { - if (unfollowModal) { - dispatch(openModal({ + dispatch( + openModal({ modalType: 'CONFIRM', modalProps: { - message: @{account.get('acct')} }} />, - confirm: intl.formatMessage(messages.cancelFollowRequestConfirm), + message: ( + @{account.get('acct')} }} + /> + ), + confirm: intl.formatMessage(messages.unfollowConfirm), onConfirm: () => dispatch(unfollowAccount(account.get('id'))), - }, - })); - } else { - dispatch(unfollowAccount(account.get('id'))); - } + } }), + ); + } else if (account.getIn(['relationship', 'requested'])) { + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: @{account.get('acct')} }} />, + confirm: intl.formatMessage(messages.cancelFollowRequestConfirm), + onConfirm: () => dispatch(unfollowAccount(account.get('id'))), + }, + })); } else { dispatch(followAccount(account.get('id'))); } diff --git a/app/javascript/mastodon/features/notifications/components/column_settings.jsx b/app/javascript/mastodon/features/notifications/components/column_settings.jsx index caa1b757a4..fc737c0fe2 100644 --- a/app/javascript/mastodon/features/notifications/components/column_settings.jsx +++ b/app/javascript/mastodon/features/notifications/components/column_settings.jsx @@ -54,6 +54,7 @@ export default class ColumnSettings extends PureComponent { render () { const { settings, pushSettings, onChange, onClear, alertsEnabled, browserSupport, browserPermission, onRequestNotificationPermission, notificationPolicy } = this.props; + const filterAdvancedStr = ; const unreadMarkersShowStr = ; const alertStr = ; const showStr = ; @@ -116,6 +117,16 @@ export default class ColumnSettings extends PureComponent { +
+

+ +

+ +
+ +
+
+

diff --git a/app/javascript/mastodon/features/notifications/containers/filter_bar_container.js b/app/javascript/mastodon/features/notifications/containers/filter_bar_container.js index e448cd26ad..4e0184cef3 100644 --- a/app/javascript/mastodon/features/notifications/containers/filter_bar_container.js +++ b/app/javascript/mastodon/features/notifications/containers/filter_bar_container.js @@ -5,7 +5,7 @@ import FilterBar from '../components/filter_bar'; const makeMapStateToProps = state => ({ selectedFilter: state.getIn(['settings', 'notifications', 'quickFilter', 'active']), - advancedMode: false, + advancedMode: state.getIn(['settings', 'notifications', 'quickFilter', 'advanced']), }); const mapDispatchToProps = (dispatch) => ({ diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js index 596c9ca49f..d8c57a2a0c 100644 --- a/app/javascript/mastodon/initial_state.js +++ b/app/javascript/mastodon/initial_state.js @@ -38,7 +38,6 @@ * @property {string} title * @property {boolean} show_trends * @property {boolean} trends_as_landing_page - * @property {boolean} unfollow_modal * @property {boolean} use_blurhash * @property {boolean=} use_pending_items * @property {string} version @@ -99,7 +98,6 @@ export const source_url = getMeta('source_url'); export const timelinePreview = getMeta('timeline_preview'); export const title = getMeta('title'); export const trendsAsLanding = getMeta('trends_as_landing_page'); -export const unfollowModal = getMeta('unfollow_modal'); export const useBlurhash = getMeta('use_blurhash'); export const usePendingItems = getMeta('use_pending_items'); export const version = getMeta('version'); diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index efda92d213..1134b393a7 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -484,6 +484,8 @@ "notifications.column_settings.admin.sign_up": "New sign-ups:", "notifications.column_settings.alert": "Desktop notifications", "notifications.column_settings.favourite": "Favorites:", + "notifications.column_settings.filter_bar.advanced": "Display all categories", + "notifications.column_settings.filter_bar.category": "Quick filter bar", "notifications.column_settings.follow": "New followers:", "notifications.column_settings.follow_request": "New follow requests:", "notifications.column_settings.mention": "Mentions:", diff --git a/app/models/concerns/user/has_settings.rb b/app/models/concerns/user/has_settings.rb index 8b599dbf96..53100cc097 100644 --- a/app/models/concerns/user/has_settings.rb +++ b/app/models/concerns/user/has_settings.rb @@ -27,10 +27,6 @@ module User::HasSettings settings['default_sensitive'] end - def setting_unfollow_modal - settings['web.unfollow_modal'] - end - def setting_boost_modal settings['web.reblog_modal'] end diff --git a/app/models/user_settings.rb b/app/models/user_settings.rb index 9956b88513..886c5c9c4d 100644 --- a/app/models/user_settings.rb +++ b/app/models/user_settings.rb @@ -31,7 +31,6 @@ class UserSettings setting :disable_swiping, default: false setting :delete_modal, default: true setting :reblog_modal, default: false - setting :unfollow_modal, default: true setting :favourite_modal, default: false setting :reduce_motion, default: false setting :expand_content_warnings, default: false diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 05c5df2cd3..fe6ab5e995 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -31,7 +31,6 @@ class InitialStateSerializer < ActiveModel::Serializer if object.current_account store[:me] = object.current_account.id.to_s - store[:unfollow_modal] = object_account_user.setting_unfollow_modal store[:boost_modal] = object_account_user.setting_boost_modal store[:favourite_modal] = object_account_user.setting_favourite_modal store[:delete_modal] = object_account_user.setting_delete_modal diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml index f7b244ca05..a5ad02a600 100644 --- a/app/views/settings/preferences/appearance/show.html.haml +++ b/app/views/settings/preferences/appearance/show.html.haml @@ -59,7 +59,6 @@ %h4= t 'appearance.confirmation_dialogs' .fields-group - = ff.input :'web.unfollow_modal', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_unfollow_modal') = ff.input :'web.reblog_modal', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_boost_modal') = ff.input :'web.favourite_modal', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_favourite_modal'), glitch_only: true = ff.input :'web.delete_modal', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_delete_modal') diff --git a/spec/features/severed_relationships_spec.rb b/spec/features/severed_relationships_spec.rb new file mode 100644 index 0000000000..b933398a08 --- /dev/null +++ b/spec/features/severed_relationships_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Severed relationships page' do + include ProfileStories + + describe 'GET severed_relationships#index' do + before do + as_a_logged_in_user + + event = Fabricate(:relationship_severance_event) + Fabricate.times(3, :severed_relationship, local_account: bob.account, relationship_severance_event: event) + Fabricate(:account_relationship_severance_event, account: bob.account, relationship_severance_event: event) + end + + it 'returns http success' do + visit severed_relationships_path + + expect(page).to have_title(I18n.t('settings.severed_relationships')) + expect(page).to have_link(href: following_severed_relationship_path(AccountRelationshipSeveranceEvent.first, format: :csv)) + end + end +end diff --git a/spec/requests/severed_relationships_spec.rb b/spec/requests/severed_relationships_spec.rb deleted file mode 100644 index 05a48ca349..0000000000 --- a/spec/requests/severed_relationships_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -describe 'Severed relationships page' do - include RoutingHelper - - describe 'GET severed_relationships#index' do - let(:user) { Fabricate(:user) } - let(:event) { Fabricate(:account_relationship_severance_event, account: user.account) } - - before do - sign_in user - - Fabricate.times(3, :severed_relationship, local_account: user.account, relationship_severance_event: event.relationship_severance_event) - end - - it 'returns http success' do - get severed_relationships_path - - expect(response).to have_http_status(200) - end - end -end diff --git a/spec/services/block_domain_service_spec.rb b/spec/services/block_domain_service_spec.rb index 26f80eaf62..d4f0c042d4 100644 --- a/spec/services/block_domain_service_spec.rb +++ b/spec/services/block_domain_service_spec.rb @@ -19,7 +19,7 @@ RSpec.describe BlockDomainService do bystander.follow!(local_account) end - it 'creates a domain block, suspends remote accounts with appropriate suspension date, records severed relationships', :aggregate_failures do + it 'creates a domain block, suspends remote accounts with appropriate suspension date, records severed relationships and sends notification', :aggregate_failures do subject.call(DomainBlock.create!(domain: 'evil.org', severity: :suspend)) expect(DomainBlock.blocked?('evil.org')).to be true @@ -42,6 +42,9 @@ RSpec.describe BlockDomainService do expect(severed_relationships.count).to eq 2 expect(severed_relationships[0].relationship_severance_event).to eq severed_relationships[1].relationship_severance_event expect(severed_relationships.map { |rel| [rel.account, rel.target_account] }).to contain_exactly([bystander, local_account], [local_account, bad_account]) + + # Sends severed relationships notification + expect(LocalNotificationWorker).to have_enqueued_sidekiq_job(local_account.id, anything, 'AccountRelationshipSeveranceEvent', 'severed_relationships') end end