Add insert_feeds config to antenna

This commit is contained in:
KMY 2023-08-19 18:12:30 +09:00
parent 5c758b344c
commit 45a39f1ec3
10 changed files with 100 additions and 45 deletions

View file

@ -59,7 +59,7 @@ class AntennasController < ApplicationController
end end
def resource_params 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 end
def thin_resource_params def thin_resource_params

View file

@ -42,6 +42,6 @@ class Api::V1::AntennasController < Api::BaseController
end end
def antenna_params 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
end end

View file

@ -151,10 +151,10 @@ export const createAntennaFail = error => ({
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)); 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)); dispatch(updateAntennaSuccess(data));
if (shouldReset) { if (shouldReset) {

View file

@ -128,25 +128,31 @@ class AntennaSetting extends PureComponent {
onStlToggle = ({ target }) => { onStlToggle = ({ target }) => {
const { dispatch } = this.props; const { dispatch } = this.props;
const { id } = this.props.params; 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 }) => { onMediaOnlyToggle = ({ target }) => {
const { dispatch } = this.props; const { dispatch } = this.props;
const { id } = this.props.params; 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 }) => { onIgnoreReblogToggle = ({ target }) => {
const { dispatch } = this.props; const { dispatch } = this.props;
const { id } = this.props.params; 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 => { onSelect = value => {
const { dispatch } = this.props; const { dispatch } = this.props;
const { id } = this.props.params; 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); noOptionsMessage = () => this.props.intl.formatMessage(messages.noOptions);
@ -159,6 +165,7 @@ class AntennaSetting extends PureComponent {
const isStl = antenna ? antenna.get('stl') : undefined; const isStl = antenna ? antenna.get('stl') : undefined;
const isMediaOnly = antenna ? antenna.get('with_media_only') : undefined; const isMediaOnly = antenna ? antenna.get('with_media_only') : undefined;
const isIgnoreReblog = antenna ? antenna.get('ignore_reblog') : undefined; const isIgnoreReblog = antenna ? antenna.get('ignore_reblog') : undefined;
const isInsertFeeds = antenna ? antenna.get('insert_feeds') : undefined;
if (typeof antenna === 'undefined') { if (typeof antenna === 'undefined') {
return ( return (
@ -236,20 +243,24 @@ class AntennaSetting extends PureComponent {
</label> </label>
</div> </div>
<div className='setting-toggle'>
<Toggle id={`antenna-${id}-noinsertfeeds`} defaultChecked={isInsertFeeds} onChange={this.onNoInsertFeedsToggle} />
<label htmlFor={`antenna-${id}-noinsertfeeds`} className='setting-toggle__label'>
<FormattedMessage id='antennas.insert_feeds' defaultMessage='Insert to feeds' />
</label>
</div>
{columnSettings} {columnSettings}
</ColumnHeader> </ColumnHeader>
{stlAlert} {stlAlert}
<div className='antenna-setting'> <div className='antenna-setting'>
{isInsertFeeds && (
<>
{antenna.get('list') ? ( {antenna.get('list') ? (
<p><FormattedMessage id='antennas.related_list' defaultMessage='This antenna is related to {listTitle}.' values={{ listTitle: antenna.getIn(['list', 'title']) }} /></p> <p><FormattedMessage id='antennas.related_list' defaultMessage='This antenna is related to {listTitle}.' values={{ listTitle: antenna.getIn(['list', 'title']) }} /></p>
) : ( ) : (
<>
<p><FormattedMessage id='antennas.not_related_list' defaultMessage='This antenna is not related list. Posts will appear in home timeline. Open edit page to set list.' /></p> <p><FormattedMessage id='antennas.not_related_list' defaultMessage='This antenna is not related list. Posts will appear in home timeline. Open edit page to set list.' /></p>
<button type='button' className='text-btn column-header__setting-btn' tabIndex={0} onClick={this.handleEditAntennaClick}>
<Icon id='pencil' /> <FormattedMessage id='anntennas.edit' defaultMessage='Edit antenna' />
</button>
</>
)} )}
<NonceProvider nonce={document.querySelector('meta[name=style-nonce]').content} cacheKey='lists'> <NonceProvider nonce={document.querySelector('meta[name=style-nonce]').content} cacheKey='lists'>
@ -265,6 +276,8 @@ class AntennaSetting extends PureComponent {
defaultOptions defaultOptions
/> />
</NonceProvider> </NonceProvider>
</>
)}
{!isStl && ( {!isStl && (
<> <>

View file

@ -7,6 +7,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { fetchAntennas } from 'mastodon/actions/antennas';
import { fetchLists } from 'mastodon/actions/lists'; import { fetchLists } from 'mastodon/actions/lists';
import ColumnLink from './column_link'; 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); 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 => ({ const mapStateToProps = state => ({
lists: getOrderedLists(state), lists: getOrderedLists(state),
antennas: getOrderedAntennas(state),
}); });
class ListPanel extends ImmutablePureComponent { class ListPanel extends ImmutablePureComponent {
@ -28,17 +38,20 @@ class ListPanel extends ImmutablePureComponent {
static propTypes = { static propTypes = {
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
lists: ImmutablePropTypes.list, lists: ImmutablePropTypes.list,
antennas: ImmutablePropTypes.list,
}; };
componentDidMount () { componentDidMount () {
const { dispatch } = this.props; const { dispatch } = this.props;
dispatch(fetchLists()); dispatch(fetchLists());
dispatch(fetchAntennas());
} }
render () { 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; return null;
} }
@ -46,9 +59,12 @@ class ListPanel extends ImmutablePureComponent {
<div className='list-panel'> <div className='list-panel'>
<hr /> <hr />
{lists.map(list => ( {lists && lists.map(list => (
<ColumnLink icon='list-ul' key={list.get('id')} strict text={list.get('title')} to={`/lists/${list.get('id')}`} transparent /> <ColumnLink icon='list-ul' key={list.get('id')} strict text={list.get('title')} to={`/lists/${list.get('id')}`} transparent />
))} ))}
{antennas && antennas.take(8 - (lists ? lists.size : 0)).map(antenna => (
<ColumnLink icon='wifi' key={antenna.get('id')} strict text={antenna.get('title')} to={`/antennast/${antenna.get('id')}`} transparent />
))}
</div> </div>
); );
} }

View file

@ -24,6 +24,7 @@
# exclude_tags :jsonb # exclude_tags :jsonb
# stl :boolean default(FALSE), not null # stl :boolean default(FALSE), not null
# ignore_reblog :boolean default(FALSE), not null # ignore_reblog :boolean default(FALSE), not null
# insert_feeds :boolean default(FALSE), not null
# #
class Antenna < ApplicationRecord class Antenna < ApplicationRecord
include Expireable include Expireable

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class REST::AntennaSerializer < ActiveModel::Serializer 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 class ListSerializer < ActiveModel::Serializer
attributes :id, :title attributes :id, :title

View file

@ -9,6 +9,7 @@ class FeedInsertWorker
@type = type.to_sym @type = type.to_sym
@status = Status.find(status_id) @status = Status.find(status_id)
@options = options.symbolize_keys @options = options.symbolize_keys
@antenna = Antenna.find(@options[:antenna_id]) if @options[:antenna_id].present?
case @type case @type
when :home, :tags when :home, :tags
@ -55,17 +56,18 @@ class FeedInsertWorker
end end
def perform_push def perform_push
if @antenna.nil? || @antenna.insert_feeds
case @type case @type
when :home, :tags when :home, :tags
FeedManager.instance.push_to_home(@follower, @status, update: update?) FeedManager.instance.push_to_home(@follower, @status, update: update?)
when :list when :list
FeedManager.instance.push_to_list(@list, @status, update: update?) FeedManager.instance.push_to_list(@list, @status, update: update?)
end 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?)
FeedManager.instance.push_to_antenna(antenna, @status, update: update?) if antenna.present?
end end
def perform_unpush def perform_unpush
@ -76,10 +78,9 @@ class FeedInsertWorker
FeedManager.instance.unpush_from_list(@list, @status, update: true) FeedManager.instance.unpush_from_list(@list, @status, update: true)
end 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)
FeedManager.instance.unpush_from_antenna(antenna, @status, update: true) if antenna.present?
end end
def perform_notify def perform_notify

View file

@ -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

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # 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 # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -308,6 +308,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_14_223300) do
t.jsonb "exclude_tags" t.jsonb "exclude_tags"
t.boolean "stl", default: false, null: false t.boolean "stl", default: false, null: false
t.boolean "ignore_reblog", 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 ["account_id"], name: "index_antennas_on_account_id"
t.index ["any_accounts"], name: "index_antennas_on_any_accounts" t.index ["any_accounts"], name: "index_antennas_on_any_accounts"
t.index ["any_domains"], name: "index_antennas_on_any_domains" t.index ["any_domains"], name: "index_antennas_on_any_domains"