diff --git a/app/controllers/antennas_controller.rb b/app/controllers/antennas_controller.rb index 802f17b205..9e5aebc75b 100644 --- a/app/controllers/antennas_controller.rb +++ b/app/controllers/antennas_controller.rb @@ -59,7 +59,7 @@ class AntennasController < ApplicationController end def resource_params - params.require(:antenna).permit(:title, :list, :available, :stl, :expires_in, :with_media_only, :ignore_reblog, :keywords_raw, :exclude_keywords_raw, :domains_raw, :exclude_domains_raw, :accounts_raw, :exclude_accounts_raw, :tags_raw, :exclude_tags_raw) + params.require(:antenna).permit(:title, :list, :available, :stl, :expires_in, :with_media_only, :ignore_reblog, :keywords_raw, :exclude_keywords_raw, :domains_raw, :exclude_domains_raw, :accounts_raw, :exclude_accounts_raw, :tags_raw, :exclude_tags_raw).merge({ insert_feeds: true }) end def thin_resource_params diff --git a/app/controllers/api/v1/antennas_controller.rb b/app/controllers/api/v1/antennas_controller.rb index 5b6712b834..c4b00c7784 100644 --- a/app/controllers/api/v1/antennas_controller.rb +++ b/app/controllers/api/v1/antennas_controller.rb @@ -42,6 +42,6 @@ class Api::V1::AntennasController < Api::BaseController end def antenna_params - params.permit(:title, :list_id, :stl, :with_media_only, :ignore_reblog) + params.permit(:title, :list_id, :insert_feeds, :stl, :with_media_only, :ignore_reblog) end end diff --git a/app/javascript/mastodon/actions/antennas.js b/app/javascript/mastodon/actions/antennas.js index 77ba6945e2..8cd1e7d90d 100644 --- a/app/javascript/mastodon/actions/antennas.js +++ b/app/javascript/mastodon/actions/antennas.js @@ -151,10 +151,10 @@ export const createAntennaFail = error => ({ error, }); -export const updateAntenna = (id, title, shouldReset, list_id, stl, with_media_only, ignore_reblog) => (dispatch, getState) => { +export const updateAntenna = (id, title, shouldReset, list_id, stl, with_media_only, ignore_reblog, insert_feeds) => (dispatch, getState) => { dispatch(updateAntennaRequest(id)); - api(getState).put(`/api/v1/antennas/${id}`, { title, list_id, stl, with_media_only, ignore_reblog }).then(({ data }) => { + api(getState).put(`/api/v1/antennas/${id}`, { title, list_id, stl, with_media_only, ignore_reblog, insert_feeds }).then(({ data }) => { dispatch(updateAntennaSuccess(data)); if (shouldReset) { diff --git a/app/javascript/mastodon/features/antenna_setting/index.jsx b/app/javascript/mastodon/features/antenna_setting/index.jsx index ca5eadefcb..25776809b3 100644 --- a/app/javascript/mastodon/features/antenna_setting/index.jsx +++ b/app/javascript/mastodon/features/antenna_setting/index.jsx @@ -128,25 +128,31 @@ class AntennaSetting extends PureComponent { onStlToggle = ({ target }) => { const { dispatch } = this.props; const { id } = this.props.params; - dispatch(updateAntenna(id, undefined, false, undefined, target.checked, undefined, undefined)); + dispatch(updateAntenna(id, undefined, false, undefined, target.checked, undefined, undefined, undefined)); }; onMediaOnlyToggle = ({ target }) => { const { dispatch } = this.props; const { id } = this.props.params; - dispatch(updateAntenna(id, undefined, false, undefined, undefined, target.checked, undefined)); + dispatch(updateAntenna(id, undefined, false, undefined, undefined, target.checked, undefined, undefined)); }; onIgnoreReblogToggle = ({ target }) => { const { dispatch } = this.props; const { id } = this.props.params; - dispatch(updateAntenna(id, undefined, false, undefined, undefined, undefined, target.checked)); + dispatch(updateAntenna(id, undefined, false, undefined, undefined, undefined, target.checked, undefined)); + }; + + onNoInsertFeedsToggle = ({ target }) => { + const { dispatch } = this.props; + const { id } = this.props.params; + dispatch(updateAntenna(id, undefined, false, undefined, undefined, undefined, undefined, target.checked)); }; onSelect = value => { const { dispatch } = this.props; const { id } = this.props.params; - dispatch(updateAntenna(id, undefined, false, value.value, undefined, undefined, undefined)); + dispatch(updateAntenna(id, undefined, false, value.value, undefined, undefined, undefined, undefined)); }; noOptionsMessage = () => this.props.intl.formatMessage(messages.noOptions); @@ -159,6 +165,7 @@ class AntennaSetting extends PureComponent { const isStl = antenna ? antenna.get('stl') : undefined; const isMediaOnly = antenna ? antenna.get('with_media_only') : undefined; const isIgnoreReblog = antenna ? antenna.get('ignore_reblog') : undefined; + const isInsertFeeds = antenna ? antenna.get('insert_feeds') : undefined; if (typeof antenna === 'undefined') { return ( @@ -236,36 +243,42 @@ class AntennaSetting extends PureComponent { +
+ + +
+ {columnSettings} {stlAlert}
- {antenna.get('list') ? ( -

- ) : ( + {isInsertFeeds && ( <> -

- + {antenna.get('list') ? ( +

+ ) : ( +

+ )} + + + - - {!isStl && ( <>

diff --git a/app/javascript/mastodon/features/ui/components/list_panel.jsx b/app/javascript/mastodon/features/ui/components/list_panel.jsx index 8ecf70631b..943ed06d81 100644 --- a/app/javascript/mastodon/features/ui/components/list_panel.jsx +++ b/app/javascript/mastodon/features/ui/components/list_panel.jsx @@ -7,6 +7,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; +import { fetchAntennas } from 'mastodon/actions/antennas'; import { fetchLists } from 'mastodon/actions/lists'; import ColumnLink from './column_link'; @@ -19,8 +20,17 @@ const getOrderedLists = createSelector([state => state.get('lists')], lists => { return lists.toList().filter(item => !!item).sort((a, b) => a.get('title').localeCompare(b.get('title'))).take(8); }); +const getOrderedAntennas = createSelector([state => state.get('antennas')], antennas => { + if (!antennas) { + return antennas; + } + + return antennas.toList().filter(item => !!item && !item.get('insert_feeds')).sort((a, b) => a.get('title').localeCompare(b.get('title'))).take(8); +}); + const mapStateToProps = state => ({ lists: getOrderedLists(state), + antennas: getOrderedAntennas(state), }); class ListPanel extends ImmutablePureComponent { @@ -28,17 +38,20 @@ class ListPanel extends ImmutablePureComponent { static propTypes = { dispatch: PropTypes.func.isRequired, lists: ImmutablePropTypes.list, + antennas: ImmutablePropTypes.list, }; componentDidMount () { const { dispatch } = this.props; dispatch(fetchLists()); + dispatch(fetchAntennas()); } render () { - const { lists } = this.props; + const { lists, antennas } = this.props; + const size = (lists ? lists.size : 0) + (antennas ? antennas.size : 0); - if (!lists || lists.isEmpty()) { + if (size === 0) { return null; } @@ -46,9 +59,12 @@ class ListPanel extends ImmutablePureComponent {

- {lists.map(list => ( + {lists && lists.map(list => ( ))} + {antennas && antennas.take(8 - (lists ? lists.size : 0)).map(antenna => ( + + ))}
); } diff --git a/app/models/antenna.rb b/app/models/antenna.rb index 33ccf817a2..5476a6d149 100644 --- a/app/models/antenna.rb +++ b/app/models/antenna.rb @@ -24,6 +24,7 @@ # exclude_tags :jsonb # stl :boolean default(FALSE), not null # ignore_reblog :boolean default(FALSE), not null +# insert_feeds :boolean default(FALSE), not null # class Antenna < ApplicationRecord include Expireable diff --git a/app/serializers/rest/antenna_serializer.rb b/app/serializers/rest/antenna_serializer.rb index 7f1edd48b9..0d449a2089 100644 --- a/app/serializers/rest/antenna_serializer.rb +++ b/app/serializers/rest/antenna_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class REST::AntennaSerializer < ActiveModel::Serializer - attributes :id, :title, :stl, :with_media_only, :ignore_reblog, :accounts_count, :domains_count, :tags_count, :keywords_count + attributes :id, :title, :stl, :insert_feeds, :with_media_only, :ignore_reblog, :accounts_count, :domains_count, :tags_count, :keywords_count class ListSerializer < ActiveModel::Serializer attributes :id, :title diff --git a/app/workers/feed_insert_worker.rb b/app/workers/feed_insert_worker.rb index c1b7edc90d..7bc046f2e2 100644 --- a/app/workers/feed_insert_worker.rb +++ b/app/workers/feed_insert_worker.rb @@ -9,6 +9,7 @@ class FeedInsertWorker @type = type.to_sym @status = Status.find(status_id) @options = options.symbolize_keys + @antenna = Antenna.find(@options[:antenna_id]) if @options[:antenna_id].present? case @type when :home, :tags @@ -55,17 +56,18 @@ class FeedInsertWorker end def perform_push - case @type - when :home, :tags - FeedManager.instance.push_to_home(@follower, @status, update: update?) - when :list - FeedManager.instance.push_to_list(@list, @status, update: update?) + if @antenna.nil? || @antenna.insert_feeds + case @type + when :home, :tags + FeedManager.instance.push_to_home(@follower, @status, update: update?) + when :list + FeedManager.instance.push_to_list(@list, @status, update: update?) + end end - return if @options[:antenna_id].blank? + return if @antenna.nil? - antenna = Antenna.find(@options[:antenna_id]) - FeedManager.instance.push_to_antenna(antenna, @status, update: update?) if antenna.present? + FeedManager.instance.push_to_antenna(@antenna, @status, update: update?) end def perform_unpush @@ -76,10 +78,9 @@ class FeedInsertWorker FeedManager.instance.unpush_from_list(@list, @status, update: true) end - return if @options[:antenna_id].blank? + return if @antenna.nil? - antenna = Antenna.find(@options[:antenna_id]) - FeedManager.instance.unpush_from_antenna(antenna, @status, update: true) if antenna.present? + FeedManager.instance.unpush_from_antenna(@antenna, @status, update: true) end def perform_notify diff --git a/db/migrate/20230819084858_add_no_insert_feeds_to_antennas.rb b/db/migrate/20230819084858_add_no_insert_feeds_to_antennas.rb new file mode 100644 index 0000000000..a040370507 --- /dev/null +++ b/db/migrate/20230819084858_add_no_insert_feeds_to_antennas.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require Rails.root.join('lib', 'mastodon', 'migration_helpers') + +class AddNoInsertFeedsToAntennas < ActiveRecord::Migration[7.0] + include Mastodon::MigrationHelpers + + disable_ddl_transaction! + + class Antenna < ApplicationRecord + end + + def up + safety_assured do + add_column_with_default :antennas, :insert_feeds, :boolean, default: false, allow_null: false + Antenna.where(insert_feeds: false).update_all(insert_feeds: true) # rubocop:disable Rails/SkipsModelValidations + end + end + + def down + remove_column :antennas, :insert_feeds + end +end diff --git a/db/schema.rb b/db/schema.rb index db17c0b4f6..a2e37dcce1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_08_14_223300) do +ActiveRecord::Schema[7.0].define(version: 2023_08_19_084858) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -308,6 +308,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_14_223300) do t.jsonb "exclude_tags" t.boolean "stl", default: false, null: false t.boolean "ignore_reblog", default: false, null: false + t.boolean "insert_feeds", default: false, null: false t.index ["account_id"], name: "index_antennas_on_account_id" t.index ["any_accounts"], name: "index_antennas_on_any_accounts" t.index ["any_domains"], name: "index_antennas_on_any_domains"