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

View file

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

View file

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

View file

@ -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 {
</label>
</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}
</ColumnHeader>
{stlAlert}
<div className='antenna-setting'>
{antenna.get('list') ? (
<p><FormattedMessage id='antennas.related_list' defaultMessage='This antenna is related to {listTitle}.' values={{ listTitle: antenna.getIn(['list', 'title']) }} /></p>
) : (
{isInsertFeeds && (
<>
<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>
{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.not_related_list' defaultMessage='This antenna is not related list. Posts will appear in home timeline. Open edit page to set list.' /></p>
)}
<NonceProvider nonce={document.querySelector('meta[name=style-nonce]').content} cacheKey='lists'>
<Select
value={{ value: antenna.getIn(['list', 'id']), label: antenna.getIn(['list', 'title']) }}
options={listOptions}
noOptionsMessage={this.noOptionsMessage}
onChange={this.onSelect}
className='column-select__container'
classNamePrefix='column-select'
name='lists'
placeholder={this.props.intl.formatMessage(messages.placeholder)}
defaultOptions
/>
</NonceProvider>
</>
)}
<NonceProvider nonce={document.querySelector('meta[name=style-nonce]').content} cacheKey='lists'>
<Select
value={{ value: antenna.getIn(['list', 'id']), label: antenna.getIn(['list', 'title']) }}
options={listOptions}
noOptionsMessage={this.noOptionsMessage}
onChange={this.onSelect}
className='column-select__container'
classNamePrefix='column-select'
name='lists'
placeholder={this.props.intl.formatMessage(messages.placeholder)}
defaultOptions
/>
</NonceProvider>
{!isStl && (
<>
<h3><FormattedMessage id='antennas.accounts' defaultMessage='{count} accounts' values={{ count: antenna.get('accounts_count') }} /></h3>

View file

@ -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 {
<div className='list-panel'>
<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 />
))}
{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>
);
}

View file

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

View file

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

View file

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

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.
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"