diff --git a/app/controllers/settings/account_subscribes_controller.rb b/app/controllers/settings/account_subscribes_controller.rb index 4ca838ac3cb96f40e3e35047de6396af3e16be6f..e21badd4ec0a9694ea4f028942c1744965562692 100644 --- a/app/controllers/settings/account_subscribes_controller.rb +++ b/app/controllers/settings/account_subscribes_controller.rb @@ -3,28 +3,20 @@ class Settings::AccountSubscribesController < Settings::BaseController layout 'admin' before_action :authenticate_user! + before_action :set_lists, only: [:index, :new, :edit, :update] before_action :set_account_subscribings, only: :index + before_action :set_account_subscribing, only: [:edit, :update, :destroy] - class AccountInput - include ActiveModel::Model - include ActiveModel::Attributes - - attribute :acct, :string + def index end - def index - @account_input = AccountInput.new + def new + @form_account_subscribing = Form::AccountSubscribe.new end def create - acct = account_subscribe_params[:acct].strip - acct = acct[1..-1] if acct.start_with?("@") - - begin - target_account = AccountSubscribeService.new.call(current_account, acct) - rescue - target_account = nil - end + @form_account_subscribing = Form::AccountSubscribe.new(account_subscribe_params) + target_account = AccountSubscribeService.new.call(current_account, @form_account_subscribing.acct, @form_account_subscribing.show_reblogs, @form_account_subscribing.list_id) if target_account redirect_to settings_account_subscribes_path @@ -35,21 +27,48 @@ class Settings::AccountSubscribesController < Settings::BaseController end end + def edit; end + + def update + if @account_subscribing.update(account_subscribe_params.merge(account: current_account)) + redirect_to settings_account_subscribes_path + else + render action: :edit + end + end + def destroy - target_account = current_account.active_subscribes.find(params[:id]).target_account - UnsubscribeAccountService.new.call(current_account, target_account) + UnsubscribeAccountService.new.call(current_account, @account_subscribing.target_account) redirect_to settings_account_subscribes_path end private + def set_account_subscribing + @account_subscribing = current_account.active_subscribes.find(params[:id]) + @form_account_subscribing = Form::AccountSubscribe.new(id: @account_subscribing.id, acct: @account_subscribing.target_account.acct, show_reblogs: @account_subscribing.show_reblogs, list_id: @account_subscribing.list_id) + end + def set_account_subscribings - @account_subscribings = current_account.active_subscribes.order(:updated_at).reject(&:new_record?).map do |subscribing| - {id: subscribing.id, acct: subscribing.target_account.acct} - end + @account_subscribings = current_account.active_subscribes.order('list_id NULLS FIRST', :updated_at).reject(&:new_record?) + end + + def set_lists + @lists = List.where(account: current_account).all end def account_subscribe_params - params.require(:account_input).permit(:acct) + new_params = resource_params.permit!.to_h + + if resource_params[:list_id] == '-1' + list = List.find_or_create_by!({ account: current_account, title: new_params[:acct] }) + new_params.merge!({list_id: list.id}) + end + + new_params + end + + def resource_params + params.require(:form_account_subscribe).permit(:acct, :show_reblogs, :list_id) end end diff --git a/app/controllers/settings/follow_tags_controller.rb b/app/controllers/settings/follow_tags_controller.rb index 776a4850426e1fd94a04397b3c15354f06dd4984..a42c00c347f4d358b267cb8bf516b6fd817a736a 100644 --- a/app/controllers/settings/follow_tags_controller.rb +++ b/app/controllers/settings/follow_tags_controller.rb @@ -4,13 +4,18 @@ class Settings::FollowTagsController < Settings::BaseController layout 'admin' before_action :authenticate_user! + before_action :set_lists, only: [:index, :new, :edit, :update] before_action :set_follow_tags, only: :index - before_action :set_follow_tag, except: [:index, :create] + before_action :set_follow_tag, only: [:edit, :update, :destroy] def index @follow_tag = FollowTag.new end + def new + @follow_tag = current_account.follow_tags.build + end + def create @follow_tag = current_account.follow_tags.new(follow_tag_params) @@ -23,6 +28,16 @@ class Settings::FollowTagsController < Settings::BaseController end end + def edit; end + + def update + if @follow_tag.update(follow_tag_params) + redirect_to settings_follow_tag_path + else + render action: :edit + end + end + def destroy @follow_tag.destroy! redirect_to settings_follow_tags_path @@ -35,10 +50,25 @@ class Settings::FollowTagsController < Settings::BaseController end def set_follow_tags - @follow_tags = current_account.follow_tags.order(:updated_at).reject(&:new_record?) + @follow_tags = current_account.follow_tags.order('list_id NULLS FIRST', :updated_at).reject(&:new_record?) + end + + def set_lists + @lists = List.where(account: current_account).all end def follow_tag_params - params.require(:follow_tag).permit(:name) + new_params = resource_params.permit!.to_h + + if resource_params[:list_id] == '-1' + list = List.find_or_create_by!({ account: current_account, title: new_params[:name] }) + new_params.merge!({list_id: list.id}) + end + + new_params + end + + def resource_params + params.require(:follow_tag).permit(:name, :list_id) end end diff --git a/app/javascript/mastodon/features/subscribing/index.js b/app/javascript/mastodon/features/subscribing/index.js index 6067e88e49189755eb751ce522f87a507dd99279..7c63ef30773a45b8aacc50ef76afc0ed0fc69fab 100644 --- a/app/javascript/mastodon/features/subscribing/index.js +++ b/app/javascript/mastodon/features/subscribing/index.js @@ -54,7 +54,7 @@ class Subscribing extends ImmutablePureComponent { } handleLoadMore = debounce(() => { - this.props.dispatch(expandSubscribing()); + this.props.dispatch(expandSubscribing(this.props.params.accountId)); }, 300, { leading: true }); render () { diff --git a/app/models/account_subscribe.rb b/app/models/account_subscribe.rb index e6663c61c745a484fbd0a9d3a3610ffcd9a3ed65..46776feac8722b88edad8019ff95b798d717f422 100644 --- a/app/models/account_subscribe.rb +++ b/app/models/account_subscribe.rb @@ -5,6 +5,7 @@ # id :bigint(8) not null, primary key # account_id :bigint(8) # target_account_id :bigint(8) +# show_reblogs :boolean default(TRUE), not null # created_at :datetime not null # updated_at :datetime not null # list_id :bigint(8) @@ -22,12 +23,32 @@ class AccountSubscribe < ApplicationRecord scope :recent, -> { reorder(id: :desc) } scope :subscribed_lists, ->(account) { AccountSubscribe.where(target_account_id: account.id).where.not(list_id: nil).select(:list_id).uniq } + scope :home, -> { where(list_id: nil) } + scope :list, -> { where.not(list_id: nil) } + scope :with_reblog, ->(reblog) { where(show_reblogs: true) if reblog } after_create :increment_cache_counters after_destroy :decrement_cache_counters + attr_accessor :acct + + def acct=(val) + return if val.nil? + + target_account = ResolveAccountService.new.call(acct, skip_webfinger: true) + target_account ||= ResolveAccountService.new.call(acct, skip_webfinger: false) + end + + def acct + target_account&.acct + end + private + def home? + list_id.nil? + end + def increment_cache_counters account&.increment_count!(:subscribing_count) end diff --git a/app/models/concerns/account_interactions.rb b/app/models/concerns/account_interactions.rb index d4006ac76749173499326b498d0ddb1e731c148c..44a2060b15e73971c40d0cbc8a97da8d606786fc 100644 --- a/app/models/concerns/account_interactions.rb +++ b/app/models/concerns/account_interactions.rb @@ -161,8 +161,8 @@ module AccountInteractions block&.destroy end - def subscribe!(other_account) - rel = active_subscribes.find_or_create_by!(target_account: other_account) + def subscribe!(other_account, show_reblogs = true, list_id = nil) + rel = active_subscribes.find_or_create_by!(target_account: other_account, show_reblogs: show_reblogs, list_id: list_id) remove_potential_friendship(other_account) @@ -221,8 +221,8 @@ module AccountInteractions account_pins.where(target_account: account).exists? end - def subscribing?(other_account) - active_subscribes.where(target_account: other_account).exists? + def subscribing?(other_account, list_id = nil) + active_subscribes.where(target_account: other_account, list_id: list_id).exists? end def followers_for_local_distribution @@ -232,9 +232,10 @@ module AccountInteractions end def subscribers_for_local_distribution - subscribers.local - .joins(:user) - .where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago) + AccountSubscribe.home + .joins(account: :user) + .where(target_account_id: id) + .where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago) end def lists_for_local_distribution @@ -242,6 +243,13 @@ module AccountInteractions .where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago) end + def list_subscribers_for_local_distribution + AccountSubscribe.list + .joins(account: :user) + .where(target_account_id: id) + .where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago) + end + private def remove_potential_friendship(other_account, mutual = false) diff --git a/app/models/follow_tag.rb b/app/models/follow_tag.rb index 90b428b7455628dc62b7c9df8009f94b9060bdcf..25ed799f9898669b02b703bcbdb028fb5ffb4234 100644 --- a/app/models/follow_tag.rb +++ b/app/models/follow_tag.rb @@ -21,6 +21,9 @@ class FollowTag < ApplicationRecord validates :name, presence: true, on: :create validates :account_id, uniqueness: { scope: [:tag_id, :list_id] } + scope :home, -> { where(list_id: nil) } + scope :list, -> { where.not(list_id: nil) } + def name=(str) self.tag = Tag.find_or_create_by_names(str.strip)&.first end diff --git a/app/models/form/account_subscribe.rb b/app/models/form/account_subscribe.rb new file mode 100644 index 0000000000000000000000000000000000000000..664ac914edc855d7def1f96e144a46ab8535e457 --- /dev/null +++ b/app/models/form/account_subscribe.rb @@ -0,0 +1,13 @@ +class Form::AccountSubscribe + include ActiveModel::Model + include ActiveModel::Attributes + + attribute :id, :integer + attribute :acct, :string + attribute :show_reblogs, :boolean, default: true + attribute :list_id, :integer + + def acct=(val) + super(val.to_s.strip.gsub(/\A@/, '')) + end +end diff --git a/app/services/account_subscribe_service.rb b/app/services/account_subscribe_service.rb index 05e10953e98f1500ed3ed1f3a73a7a64acf1ee23..d70f62789011a3383932e2207e5613b5ca4a620e 100644 --- a/app/services/account_subscribe_service.rb +++ b/app/services/account_subscribe_service.rb @@ -4,25 +4,29 @@ class AccountSubscribeService < BaseService # Subscribe a remote user # @param [Account] source_account From which to subscribe # @param [String, Account] uri User URI to subscribe in the form of username@domain (or account record) - def call(source_account, target_account) - begin - target_account = ResolveAccountService.new.call(target_account, skip_webfinger: true) - target_account ||= ResolveAccountService.new.call(target_account, skip_webfinger: false) - rescue - target_account = nil + def call(source_account, target_acct, show_reblogs = true, list_id = nil) + if target_acct.class.name == 'Account' + target_account = target_acct + else + begin + target_account = ResolveAccountService.new.call(target_acct, skip_webfinger: true) + target_account ||= ResolveAccountService.new.call(target_acct, skip_webfinger: false) + rescue + target_account = nil + end end raise ActiveRecord::RecordNotFound if target_account.nil? || target_account.id == source_account.id || target_account.suspended? raise Mastodon::NotPermittedError if target_account.blocking?(source_account) || source_account.blocking?(target_account) || (!target_account.local? && target_account.ostatus?) || source_account.domain_blocking?(target_account.domain) - if source_account.subscribing?(target_account) + if source_account.subscribing?(target_account, list_id) return end ActivityTracker.increment('activity:interactions') - subscribe = source_account.subscribe!(target_account) - MergeWorker.perform_async(target_account.id, source_account.id, true) + subscribe = source_account.subscribe!(target_account, show_reblogs, list_id) + MergeWorker.perform_async(target_account.id, source_account.id, true) if list_id.nil? subscribe end end diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index db4a37e4549f31607dbc5a29f1c06dc7ea2618cc..e03ed4ab787430137bfc0b7baaab1656ff7b7459 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -26,12 +26,13 @@ class FanOutOnWriteService < BaseService end deliver_to_domain_subscribers(status) + deliver_to_subscribers(status) + deliver_to_subscribers_lists(status) return if status.reblog? deliver_to_hashtags(status) deliver_to_hashtag_followers(status) - deliver_to_subscribers(status) deliver_to_keyword_subscribers(status) end @@ -55,9 +56,19 @@ class FanOutOnWriteService < BaseService def deliver_to_subscribers(status) Rails.logger.debug "Delivering status #{status.id} to subscribers" - status.account.subscribers_for_local_distribution.select(:id).reorder(nil).find_in_batches do |subscribings| + status.account.subscribers_for_local_distribution.with_reblog(status.reblog?).select(:id, :account_id).reorder(nil).find_in_batches do |subscribings| FeedInsertWorker.push_bulk(subscribings) do |subscribing| - [status.id, subscribing.id, :home] + [status.id, subscribing.account_id, :home] + end + end + end + + def deliver_to_subscribers_lists(status) + Rails.logger.debug "Delivering status #{status.id} to subscribers lists" + + status.account.list_subscribers_for_local_distribution.with_reblog(status.reblog?).select(:id, :list_id).reorder(nil).find_in_batches do |subscribings| + FeedInsertWorker.push_bulk(subscribings) do |subscribing| + [status.id, subscribing.list_id, :list] end end end @@ -158,11 +169,22 @@ class FanOutOnWriteService < BaseService def deliver_to_hashtag_followers(status) Rails.logger.debug "Delivering status #{status.id} to hashtag followers" - FeedInsertWorker.push_bulk(FollowTag.where(tag: status.tags).pluck(:account_id).uniq) do |follower| + deliver_to_hashtag_followers_home(status) + deliver_to_hashtag_followers_list(status) + end + + def deliver_to_hashtag_followers_home(status) + FeedInsertWorker.push_bulk(FollowTag.home.where(tag: status.tags).pluck(:account_id).uniq) do |follower| [status.id, follower, :home] end end + def deliver_to_hashtag_followers_list(status) + FeedInsertWorker.push_bulk(FollowTag.list.where(tag: status.tags).pluck(:list_id).uniq) do |list_id| + [status.id, list_id, :list] + end + end + def deliver_to_public(status) Rails.logger.debug "Delivering status #{status.id} to public timeline" diff --git a/app/views/settings/account_subscribes/_fields.html.haml b/app/views/settings/account_subscribes/_fields.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..1662dc86c6d81c38da4533302671cc095dede96f --- /dev/null +++ b/app/views/settings/account_subscribes/_fields.html.haml @@ -0,0 +1,11 @@ +.fields-group + = f.input :acct, wrapper: :with_label + +.fields-group + = f.input :show_reblogs, as: :boolean, wrapper: :with_label + +.fields-group + = f.label :list_id + = f.collection_select :list_id, home_list_new(@lists), :first, :last + +%hr.spacer/ diff --git a/app/views/settings/account_subscribes/edit.html.haml b/app/views/settings/account_subscribes/edit.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..25a329099e171cdabd8d0f1bdf795c800defdf8e --- /dev/null +++ b/app/views/settings/account_subscribes/edit.html.haml @@ -0,0 +1,9 @@ +- content_for :page_title do + = t('account_subscribes.edit.title') + += simple_form_for @form_account_subscribing, url: settings_account_subscribe_path(@form_account_subscribing.id), method: :put do |f| + = render 'shared/error_messages', object: @form_account_subscribing + = render 'fields', f: f + + .actions + = f.button :button, t('generic.save_changes'), type: :submit diff --git a/app/views/settings/account_subscribes/index.html.haml b/app/views/settings/account_subscribes/index.html.haml index 0cbb8aab51d439dc019b529227f9ed062c3dc01a..e3bf6af8f20dd01ffa615d55fec2c57ad6847a41 100644 --- a/app/views/settings/account_subscribes/index.html.haml +++ b/app/views/settings/account_subscribes/index.html.haml @@ -5,21 +5,32 @@ %hr.spacer/ -= simple_form_for :account_input, url: settings_account_subscribes_path do |f| +.table-wrapper + %table.table + %thead + %tr + %th= t('simple_form.labels.form_account_subscribe.acct') + %th.nowrap= t('simple_form.labels.form_account_subscribe.reblog') + %th.nowrap= t('simple_form.labels.form_account_subscribe.timeline') + %th.nowrap + %tbody + - @account_subscribings.each do |account_subscribe| + %tr + %td + = fa_icon 'user' + = account_subscribe.target_account.acct + %td.nowrap + - if account_subscribe.show_reblogs + = fa_icon('check') + %td.nowrap + - if account_subscribe.list_id + = fa_icon 'list-ul' + = account_subscribe.list&.title + - else + = fa_icon 'home' + = t 'lists.home' + %td.nowrap + = table_link_to 'pencil', t('account_subscribes.edit.title'), edit_settings_account_subscribe_path(account_subscribe) + = table_link_to 'trash', t('filters.index.delete'), settings_account_subscribe_path(account_subscribe), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') } - .fields-group - = f.input :acct, wrapper: :with_block_label, hint: false - - .actions - = f.button :button, t('account_subscribes.add_new'), type: :submit - -%hr.spacer/ - -- @account_subscribings.each do |account_subscribing| - .directory__tag - %div - %h4 - = fa_icon 'user' - = account_subscribing[:acct] - %small - = table_link_to 'trash', t('filters.index.delete'), settings_account_subscribe_path(account_subscribing), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') } += link_to t('account_subscribes.new.title'), new_settings_account_subscribe_path, class: 'button' diff --git a/app/views/settings/account_subscribes/new.html.haml b/app/views/settings/account_subscribes/new.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..194da0dac48c92dba8b004cffbfc66d505988cd2 --- /dev/null +++ b/app/views/settings/account_subscribes/new.html.haml @@ -0,0 +1,9 @@ +- content_for :page_title do + = t('account_subscribes.new.title') + += simple_form_for @form_account_subscribing, url: settings_account_subscribes_path do |f| + = render 'shared/error_messages', object: @form_account_subscribing + = render 'fields', f: f + + .actions + = f.button :button, t('account_subscribes.new.title'), type: :submit diff --git a/app/views/settings/domain_subscribes/index.html.haml b/app/views/settings/domain_subscribes/index.html.haml index 7602eff3f334b3b5f182c3aab966a62d2e5c498a..762cf89d6594bbde625befa89f982ace11c9c20d 100644 --- a/app/views/settings/domain_subscribes/index.html.haml +++ b/app/views/settings/domain_subscribes/index.html.haml @@ -27,7 +27,7 @@ = domain_subscribe.list&.title - else = fa_icon 'home' - = t 'domain_subscribes.home' + = t 'lists.home' %td.nowrap = table_link_to 'pencil', t('domain_subscribes.edit.title'), edit_settings_domain_subscribe_path(domain_subscribe) = table_link_to 'trash', t('filters.index.delete'), settings_domain_subscribe_path(domain_subscribe), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') } diff --git a/app/views/settings/follow_tags/_fields.html.haml b/app/views/settings/follow_tags/_fields.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..a6612fc5e31f9cdf68dc6aa9e583e6008f2f96b5 --- /dev/null +++ b/app/views/settings/follow_tags/_fields.html.haml @@ -0,0 +1,8 @@ +.fields-group + = f.input :name, wrapper: :with_label + +.fields-group + = f.label :list_id + = f.collection_select :list_id, home_list_new(@lists), :first, :last + +%hr.spacer/ diff --git a/app/views/settings/follow_tags/edit.html.haml b/app/views/settings/follow_tags/edit.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..3b3c73d949fa520ada4aba817ee36a5de963e872 --- /dev/null +++ b/app/views/settings/follow_tags/edit.html.haml @@ -0,0 +1,9 @@ +- content_for :page_title do + = t('follow_tags.edit.title') + += simple_form_for @follow_tag, url: settings_follow_tag_path(@follow_tag), method: :put do |f| + = render 'shared/error_messages', object: @follow_tag + = render 'fields', f: f + + .actions + = f.button :button, t('generic.save_changes'), type: :submit diff --git a/app/views/settings/follow_tags/index.html.haml b/app/views/settings/follow_tags/index.html.haml index 18fce3987213badc75c3676b55dccd61e5c2998e..c26bc7e370556028d8ab6ed6060c0adff0157497 100644 --- a/app/views/settings/follow_tags/index.html.haml +++ b/app/views/settings/follow_tags/index.html.haml @@ -5,22 +5,28 @@ %hr.spacer/ -= simple_form_for @follow_tag, url: settings_follow_tags_path do |f| - = render 'shared/error_messages', object: @follow_tag +.table-wrapper + %table.table + %thead + %tr + %th= t('simple_form.labels.follow_tag.name') + %th.nowrap= t('simple_form.labels.follow_tag.timeline') + %th.nowrap + %tbody + - @follow_tags.each do |follow_tag| + %tr + %td + = fa_icon 'hashtag' + = follow_tag.name + %td.nowrap + - if follow_tag.list_id + = fa_icon 'list-ul' + = follow_tag.list&.title + - else + = fa_icon 'home' + = t 'lists.home' + %td.nowrap + = table_link_to 'pencil', t('follow_tags.edit.title'), edit_settings_follow_tag_path(follow_tag) + = table_link_to 'trash', t('filters.index.delete'), settings_follow_tag_path(follow_tag), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') } - .fields-group - = f.input :name, wrapper: :with_block_label, hint: false - - .actions - = f.button :button, t('follow_tags.add_new'), type: :submit - -%hr.spacer/ - -- @follow_tags.each do |follow_tag| - .directory__tag{ class: params[:tag] == follow_tag.name ? 'active' : nil } - %div - %h4 - = fa_icon 'hashtag' - = follow_tag.name - %small - = table_link_to 'trash', t('filters.index.delete'), settings_follow_tag_path(follow_tag), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') } += link_to t('follow_tags.new.title'), new_settings_follow_tag_path, class: 'button' diff --git a/app/views/settings/follow_tags/new.html.haml b/app/views/settings/follow_tags/new.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..095ab4ed2399ae6045050af7d0481be53a835873 --- /dev/null +++ b/app/views/settings/follow_tags/new.html.haml @@ -0,0 +1,9 @@ +- content_for :page_title do + = t('follow_tags.new.title') + += simple_form_for @follow_tag, url: settings_follow_tags_path do |f| + = render 'shared/error_messages', object: @follow_tag + = render 'fields', f: f + + .actions + = f.button :button, t('follow_tags.new.title'), type: :submit diff --git a/config/locales/en.yml b/config/locales/en.yml index bf01a12f6751a0cebdc300d034912c5bac962c8c..835034b192782c02677e1eb9dadd6e7c11812d71 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -84,7 +84,11 @@ en: unfollow: Unfollow account_subscribes: add_new: Add - hint_html: "<strong>What are account subscription?</strong> Insert public posts from the specified account into the home timeline. Posts received by the server (federated timeline) are targets. You cannot subscribe if you are following." + edit: + title: Edit + hint_html: "<strong>What are account subscription?</strong> Insert public posts from the specified account into the home or list timeline. Posts received by the server (federated timeline) are targets." + new: + title: Add new account subscription admin: account_actions: action: Perform action @@ -719,7 +723,6 @@ en: title: Edit exclude_reblog: Exclude hint_html: "<strong>What are domain subscription?</strong> Insert public posts from the specified domain into the home or list timeline. Posts received by the server (federated timeline) are targets." - home: Home include_reblog: Include new: title: Add new domain subscription @@ -785,8 +788,12 @@ en: new: title: Add new filter follow_tags: - add_new: Add new - hint_html: "<strong>What are follow hashtags?</strong> They are a collection of hashtags you follow. From the posts with hashtags received by the server, the one with the hashtag specified here is inserted into the home timeline." + add_new: Add + edit: + title: Edit + hint_html: "<strong>What are follow hashtags?</strong> They are a collection of hashtags you follow. From the posts with hashtags received by the server, the one with the hashtag specified here is inserted into the home or list timeline." + new: + title: Add new hashtag follow footer: developers: Developers more: More… @@ -869,8 +876,7 @@ en: duplicate: The same content has already been registered limit: You have reached the maximum number of "Keyword subscribes" that can be registered regexp: "Regular expression error: %{message}" - hint_html: "<strong>What is a keyword subscribes?</strong> Inserts a public post that matches one of the specified words or a regular expression into the home timeline. Posts received by the server (federated timeline) are targets." - home: Home + hint_html: "<strong>What is a keyword subscribes?</strong> Inserts a public post that matches one of the specified words or a regular expression into the home or list timeline. Posts received by the server (federated timeline) are targets." ignorecase: enabled: Ignore disabled: Sensitive @@ -887,6 +893,7 @@ en: add_new: Add new list errors: limit: You have reached the maximum amount of lists + home: Home media_attachments: validations: images_and_video: Cannot attach a video to a status that already contains images diff --git a/config/locales/ja.yml b/config/locales/ja.yml index b020d5ddcf75e8f6c826eb92e186b17011e87d62..adbb6c27056aaec0ba585e32df67f50b7df4c579 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -80,7 +80,11 @@ ja: unfollow: フォãƒãƒ¼è§£é™¤ account_subscribes: add_new: è¿½åŠ - hint_html: "<strong>アカウントã®è³¼èªã¨ã¯ä½•ã§ã™ã‹ï¼Ÿ</strong> 指定ã—ãŸã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®å…¬é–‹æŠ•ç¨¿ã‚’ãƒ›ãƒ¼ãƒ ã‚¿ã‚¤ãƒ ãƒ©ã‚¤ãƒ³ã«æŒ¿å…¥ã—ã¾ã™ã€‚サーãƒãŒå—ã‘å–ã£ã¦ã„る投稿(連åˆã‚¿ã‚¤ãƒ ライン)ãŒå¯¾è±¡ã§ã™ã€‚フォãƒãƒ¼ã—ã¦ã„ã‚‹å ´åˆã¯è³¼èªã§ãã¾ã›ã‚“。" + edit: + title: 編集 + hint_html: "<strong>アカウントã®è³¼èªã¨ã¯ä½•ã§ã™ã‹ï¼Ÿ</strong> 指定ã—ãŸã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®å…¬é–‹æŠ•稿をホームタイムラインã¾ãŸã¯ãƒªã‚¹ãƒˆã«æŒ¿å…¥ã—ã¾ã™ã€‚サーãƒãŒå—ã‘å–ã£ã¦ã„る投稿(連åˆã‚¿ã‚¤ãƒ ライン)ãŒå¯¾è±¡ã§ã™ã€‚" + new: + title: æ–°è¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆè³¼èªã‚’è¿½åŠ admin: account_actions: action: アクションを実行 @@ -694,7 +698,6 @@ ja: title: 編集 exclude_reblog: å«ã‚ãªã„ hint_html: "<strong>ドメインã®è³¼èªã¨ã¯ä½•ã§ã™ã‹ï¼Ÿ</strong> 指定ã—ãŸãƒ‰ãƒ¡ã‚¤ãƒ³ã®å…¬é–‹æŠ•稿をホームタイムラインã¾ãŸã¯ãƒªã‚¹ãƒˆã«æŒ¿å…¥ã—ã¾ã™ã€‚サーãƒãŒå—ã‘å–ã£ã¦ã„る投稿(連åˆã‚¿ã‚¤ãƒ ライン)ãŒå¯¾è±¡ã§ã™ã€‚" - home: ホームinclude_reblog: å«ã‚ã‚‹ new: title: æ–°è¦ãƒ‰ãƒ¡ã‚¤ãƒ³è³¼èªã‚’è¿½åŠ @@ -744,7 +747,11 @@ ja: hint_html: "<strong>注目ã®ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ã¨ã¯ï¼Ÿ</strong>プãƒãƒ•ィールページã«ç›®ç«‹ã¤å½¢ã§è¡¨ç¤ºã•れã€ãã®ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ã®ã¤ã„ãŸã‚ãªãŸã®å…¬é–‹æŠ•稿ã ã‘を抽出ã—ã¦é–²è¦§ã§ãるよã†ã«ã—ã¾ã™ã€‚クリエイティブãªä»•事や長期的ãªãƒ—ãƒã‚¸ã‚§ã‚¯ãƒˆã‚’追ã†ã®ã«å„ªã‚ŒãŸæ©Ÿèƒ½ã§ã™ã€‚" follow_tags: add_new: è¿½åŠ - hint_html: "<strong>ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ã®ãƒ•ã‚©ãƒãƒ¼ã¨ã¯ä½•ã§ã™ã‹ï¼Ÿ</strong> ãれらã¯ã‚ãªãŸãŒãƒ•ã‚©ãƒãƒ¼ã™ã‚‹ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ã®ã‚³ãƒ¬ã‚¯ã‚·ãƒ§ãƒ³ã§ã™ã€‚サーãƒãŒå—ã‘å–ã£ãŸãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ä»˜ãã®æŠ•ç¨¿ã®ä¸ã‹ã‚‰ã€ã“ã“ã§æŒ‡å®šã—ãŸãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ã®ã¤ã„ãŸæŠ•ç¨¿ã‚’ãƒ›ãƒ¼ãƒ ã‚¿ã‚¤ãƒ ãƒ©ã‚¤ãƒ³ã«æŒ¿å…¥ã—ã¾ã™ã€‚" + edit: + title: 編集 + hint_html: "<strong>ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ã®ãƒ•ã‚©ãƒãƒ¼ã¨ã¯ä½•ã§ã™ã‹ï¼Ÿ</strong> ãれらã¯ã‚ãªãŸãŒãƒ•ã‚©ãƒãƒ¼ã™ã‚‹ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ã®ã‚³ãƒ¬ã‚¯ã‚·ãƒ§ãƒ³ã§ã™ã€‚サーãƒãŒå—ã‘å–ã£ãŸãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ä»˜ãã®æŠ•ç¨¿ã®ä¸ã‹ã‚‰ã€ã“ã“ã§æŒ‡å®šã—ãŸãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ã®ã¤ã„ãŸæŠ•ç¨¿ã‚’ãƒ›ãƒ¼ãƒ ã‚¿ã‚¤ãƒ ãƒ©ã‚¤ãƒ³ã¾ãŸã¯ãƒªã‚¹ãƒˆã«æŒ¿å…¥ã—ã¾ã™ã€‚" + new: + title: ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ã®ãƒ•ã‚©ãƒãƒ¼ã‚’è¿½åŠ filters: contexts: home: ホームタイムライン @@ -842,8 +849,7 @@ ja: duplicate: æ—¢ã«åŒã˜å†…容ãŒç™»éŒ²ã•れã¦ã„ã¾ã™ limit: ã‚ーワード購èªã®ç™»éŒ²å¯èƒ½æ•°ã®ä¸Šé™ã«é”ã—ã¾ã—㟠regexp: "æ£è¦è¡¨ç¾ã«èª¤ã‚ŠãŒã‚りã¾ã™: %{message}" - hint_html: "<strong>ã‚ーワードã®è³¼èªã¨ã¯ä½•ã§ã™ã‹ï¼Ÿ</strong> 指定ã—ãŸå˜èªžã®ã„ãšã‚Œã‹ã€ã¾ãŸã¯æ£è¦è¡¨ç¾ã«ä¸€è‡´ã™ã‚‹å…¬é–‹æŠ•ç¨¿ã‚’ãƒ›ãƒ¼ãƒ ã‚¿ã‚¤ãƒ ãƒ©ã‚¤ãƒ³ã«æŒ¿å…¥ã—ã¾ã™ã€‚サーãƒãŒå—ã‘å–ã£ã¦ã„る投稿(連åˆã‚¿ã‚¤ãƒ ライン)ãŒå¯¾è±¡ã§ã™ã€‚" - home: ホーム+ hint_html: "<strong>ã‚ーワードã®è³¼èªã¨ã¯ä½•ã§ã™ã‹ï¼Ÿ</strong> 指定ã—ãŸå˜èªžã®ã„ãšã‚Œã‹ã€ã¾ãŸã¯æ£è¦è¡¨ç¾ã«ä¸€è‡´ã™ã‚‹å…¬é–‹æŠ•稿をホームタイムラインã¾ãŸã¯ãƒªã‚¹ãƒˆã«æŒ¿å…¥ã—ã¾ã™ã€‚サーãƒãŒå—ã‘å–ã£ã¦ã„る投稿(連åˆã‚¿ã‚¤ãƒ ライン)ãŒå¯¾è±¡ã§ã™ã€‚" ignorecase: enabled: 無視 disabled: 区別 @@ -860,6 +866,7 @@ ja: add_new: æ–°ã—ã„ãƒªã‚¹ãƒˆã‚’è¿½åŠ errors: limit: リストã®ä¸Šé™ã«é”ã—ã¾ã—㟠+ home: ホームmedia_attachments: validations: images_and_video: æ—¢ã«ç”»åƒãŒè¿½åŠ ã•れã¦ã„ã‚‹ãŸã‚ã€å‹•ç”»ã‚’è¿½åŠ ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 4f0d2b8878e4bc6b4b8170d20def79a01f302fd6..0bbb8d755caa7df8f43d3f3265db95b1af52ce27 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -52,6 +52,11 @@ en: exclude_reblog: Exclude boosted posts from subscription featured_tag: name: 'You might want to use one of these:' + follow_tag: + name: Specify the name of the hashtag without '#' you want to follow + form_account_subscribe: + acct: Specify the username@domain of the account you want to subscribe + show_reblogs: Show boosted posts from subscription form_challenge: current_password: You are entering a secure area imports: @@ -76,8 +81,6 @@ en: value: Content account_alias: acct: Handle of the old account - account_input: - acct: Account account_migration: acct: Handle of the new account account_warning_preset: @@ -157,6 +160,16 @@ en: reblog: Boost featured_tag: name: Hashtag + follow_tag: + list_id: Target timeline + name: Tag name + timeline: Timeline + form_account_subscribe: + acct: Account + list_id: Target timeline + reblog: Boost + show_reblogs: Show boost + timeline: Timeline interactions: must_be_follower: Block notifications from non-followers must_be_following: Block notifications from people you don't follow diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index 165a0da033f531f89c2537fef0024f407e6ae494..1a29511a99bb3d275d1bcf81a73d0cabd11ad04d 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -52,6 +52,11 @@ ja: exclude_reblog: ブーストã•ã‚ŒãŸæŠ•ç¨¿ã‚’è³¼èªã‹ã‚‰é™¤å¤–ã—ã¾ã™ featured_tag: name: 'ã“れらを使ã†ã¨ã„ã„ã‹ã‚‚ã—れã¾ã›ã‚“:' + follow_tag: + name: フォãƒãƒ¼ã—ãŸã„ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ã‚’ '#' 抜ãã§æŒ‡å®šã—ã¾ã™ + form_account_subscribe: + acct: è³¼èªã—ãŸã„アカウントを username@domain å½¢å¼ã§æŒ‡å®šã—ã¾ã™ + show_reblogs: ブーストã•ã‚ŒãŸæŠ•ç¨¿ã‚’è³¼èªã«å«ã‚ã¾ã™ form_challenge: current_password: ã‚»ã‚ュリティ上é‡è¦ãªã‚¨ãƒªã‚¢ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã„ã¾ã™ imports: @@ -76,8 +81,6 @@ ja: value: 内容 account_alias: acct: 引ã£è¶Šã—å…ƒã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ ID - account_input: - acct: アカウント (account@domain.tld) account_migration: acct: 引ã£è¶Šã—å…ˆã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ ID account_warning_preset: @@ -160,7 +163,15 @@ ja: featured_tag: name: ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚° follow_tag: + list_id: 対象タイムライン name: ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚° + timeline: タイムライン + form_account_subscribe: + acct: アカウント + list_id: 対象タイムライン + reblog: ブースト + show_reblogs: ブーストを表示 + timeline: タイムライン interactions: must_be_follower: フォãƒãƒ¯ãƒ¼ä»¥å¤–ã‹ã‚‰ã®é€šçŸ¥ã‚’ブãƒãƒƒã‚¯ must_be_following: フォãƒãƒ¼ã—ã¦ã„ãªã„ユーザーã‹ã‚‰ã®é€šçŸ¥ã‚’ブãƒãƒƒã‚¯ diff --git a/config/navigation.rb b/config/navigation.rb index 2cb2cdc3f7e56c0da5c659b42c204a44c3628f4b..53e2fc51eaa514a3078dd30cf0c72c25db372d93 100644 --- a/config/navigation.rb +++ b/config/navigation.rb @@ -19,10 +19,10 @@ SimpleNavigation::Configuration.run do |navigation| n.item :follow_and_subscriptions, safe_join([fa_icon('users fw'), t('settings.follow_and_subscriptions')]), relationships_url, if: -> { current_user.functional? } do |s| s.item :relationships, safe_join([fa_icon('users fw'), t('settings.relationships')]), relationships_url, highlights_on: %r{/relationships} - s.item :follow_tags, safe_join([fa_icon('hashtag fw'), t('settings.follow_tags')]), settings_follow_tags_url - s.item :account_subscribes, safe_join([fa_icon('users fw'), t('settings.account_subscribes')]), settings_account_subscribes_url - s.item :domain_subscribes, safe_join([fa_icon('server fw'), t('settings.domain_subscribes')]), settings_domain_subscribes_url - s.item :keyword_subscribes, safe_join([fa_icon('search fw'), t('settings.keyword_subscribes')]), settings_keyword_subscribes_url + s.item :follow_tags, safe_join([fa_icon('hashtag fw'), t('settings.follow_tags')]), settings_follow_tags_url, highlights_on: %r{/follow_tags} + s.item :account_subscribes, safe_join([fa_icon('users fw'), t('settings.account_subscribes')]), settings_account_subscribes_url, highlights_on: %r{/account_subscribes} + s.item :domain_subscribes, safe_join([fa_icon('server fw'), t('settings.domain_subscribes')]), settings_domain_subscribes_url, highlights_on: %r{/domain_subscribes} + s.item :keyword_subscribes, safe_join([fa_icon('search fw'), t('settings.keyword_subscribes')]), settings_keyword_subscribes_url, highlights_on: %r{/keyword_subscribes} end n.item :filters, safe_join([fa_icon('filter fw'), t('filters.index.title')]), filters_path, highlights_on: %r{/filters}, if: -> { current_user.functional? } diff --git a/config/routes.rb b/config/routes.rb index b514f7c4f4dd0abb922aa5792a53116d5f3e6a53..6fd33e9e0d7444bf7850a8964e28fe4c516b77ad 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -155,8 +155,8 @@ Rails.application.routes.draw do resources :sessions, only: [:destroy] resources :featured_tags, only: [:index, :create, :destroy] resources :favourite_tags, only: [:index, :create, :destroy] - resources :follow_tags, only: [:index, :create, :destroy] - resources :account_subscribes, only: [:index, :create, :destroy] + resources :follow_tags, except: [:show] + resources :account_subscribes, except: [:show] resources :domain_subscribes, except: [:show] resources :keyword_subscribes, except: [:show] end diff --git a/db/migrate/20200105023325_add_show_reblogs_to_account_subscribe.rb b/db/migrate/20200105023325_add_show_reblogs_to_account_subscribe.rb new file mode 100644 index 0000000000000000000000000000000000000000..c364fd2f968829454fc7e6a5b40e0564b44abd74 --- /dev/null +++ b/db/migrate/20200105023325_add_show_reblogs_to_account_subscribe.rb @@ -0,0 +1,17 @@ +require Rails.root.join('lib', 'mastodon', 'migration_helpers') + +class AddShowReblogsToAccountSubscribe < ActiveRecord::Migration[5.2] + include Mastodon::MigrationHelpers + + disable_ddl_transaction! + + def up + safety_assured do + add_column_with_default :account_subscribes, :show_reblogs, :boolean, default: true, allow_null: false + end + end + + def down + remove_column :account_subscribes, :show_reblogs + end +end diff --git a/db/schema.rb b/db/schema.rb index cc8a6eae1add656ec4ca7af5e12de147f52e3148..7ae9e0e7d70761c60e93518bfb1fc8de7e257fc8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -108,6 +108,7 @@ ActiveRecord::Schema.define(version: 2020_01_19_112504) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.bigint "list_id" + t.boolean "show_reblogs", default: true, null: false t.index ["account_id"], name: "index_account_subscribes_on_account_id" t.index ["list_id"], name: "index_account_subscribes_on_list_id" t.index ["target_account_id"], name: "index_account_subscribes_on_target_account_id" @@ -318,6 +319,27 @@ ActiveRecord::Schema.define(version: 2020_01_19_112504) do t.index ["list_id"], name: "index_domain_subscribes_on_list_id" end + create_table "domains", force: :cascade do |t| + t.string "domain", default: "", null: false + t.string "title", default: "", null: false + t.string "short_description", default: "", null: false + t.string "email", default: "", null: false + t.string "version", default: "", null: false + t.string "thumbnail_remote_url", default: "", null: false + t.string "languages", array: true + t.boolean "registrations" + t.boolean "approval_required" + t.bigint "contact_account_id" + t.string "software", default: "", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "thumbnail_file_name" + t.string "thumbnail_content_type" + t.integer "thumbnail_file_size" + t.datetime "thumbnail_updated_at" + t.index ["contact_account_id"], name: "index_domains_on_contact_account_id" + end + create_table "email_domain_blocks", force: :cascade do |t| t.string "domain", default: "", null: false t.datetime "created_at", null: false @@ -892,6 +914,7 @@ ActiveRecord::Schema.define(version: 2020_01_19_112504) do add_foreign_key "custom_filters", "accounts", on_delete: :cascade add_foreign_key "domain_subscribes", "accounts", on_delete: :cascade add_foreign_key "domain_subscribes", "lists", on_delete: :cascade + add_foreign_key "domains", "accounts", column: "contact_account_id" add_foreign_key "favourite_tags", "accounts", on_delete: :cascade add_foreign_key "favourite_tags", "tags", on_delete: :cascade add_foreign_key "favourites", "accounts", name: "fk_5eb6c2b873", on_delete: :cascade