From 6331ed16e5953e3a006896c6df07b0f82cfd2350 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 9 Feb 2017 20:25:39 +0100 Subject: [PATCH] Fix #614 - extra reply-boolean on statuses to account for cases when replied-to status is not in the system at time of distribution; fix #607 - reset privacy settings to defaults when cancelling replies --- .../components/reducers/compose.jsx | 9 +++++++- app/channels/application_cable/channel.rb | 22 ------------------- app/channels/application_cable/connection.rb | 22 ------------------- app/channels/hashtag_channel.rb | 13 ----------- app/channels/public_channel.rb | 11 ---------- app/channels/timeline_channel.rb | 7 ------ app/lib/feed_manager.rb | 19 +++------------- app/models/status.rb | 13 ++++++----- app/services/process_feed_service.rb | 3 ++- .../20170209184350_add_reply_to_statuses.rb | 10 +++++++++ db/schema.rb | 3 ++- 11 files changed, 32 insertions(+), 100 deletions(-) delete mode 100644 app/channels/application_cable/channel.rb delete mode 100644 app/channels/application_cable/connection.rb delete mode 100644 app/channels/hashtag_channel.rb delete mode 100644 app/channels/public_channel.rb delete mode 100644 app/channels/timeline_channel.rb create mode 100644 db/migrate/20170209184350_add_reply_to_statuses.rb diff --git a/app/assets/javascripts/components/reducers/compose.jsx b/app/assets/javascripts/components/reducers/compose.jsx index 1b903ed44..042a2c67d 100644 --- a/app/assets/javascripts/components/reducers/compose.jsx +++ b/app/assets/javascripts/components/reducers/compose.jsx @@ -81,11 +81,16 @@ function appendMedia(state, media) { }; function removeMedia(state, mediaId) { - const media = state.get('media_attachments').find(item => item.get('id') === mediaId); + const media = state.get('media_attachments').find(item => item.get('id') === mediaId); + const prevSize = state.get('media_attachments').size; return state.withMutations(map => { map.update('media_attachments', list => list.filterNot(item => item.get('id') === mediaId)); map.update('text', text => text.replace(media.get('text_url'), '').trim()); + + if (prevSize === 1) { + map.update('sensitive', false); + } }); }; @@ -126,6 +131,8 @@ export default function compose(state = initialState, action) { return state.withMutations(map => { map.set('in_reply_to', null); map.set('text', ''); + map.set('unlisted', state.get('default_privacy') === 'unlisted'); + map.set('private', state.get('default_privacy') === 'private'); }); case COMPOSE_SUBMIT_REQUEST: return state.set('is_submitting', true); diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb deleted file mode 100644 index 344511cae..000000000 --- a/app/channels/application_cable/channel.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -module ApplicationCable - class Channel < ActionCable::Channel::Base - protected - - def hydrate_status(encoded_message) - message = Oj.load(encoded_message) - - return [nil, message] if message['event'] == 'delete' - - status_json = Oj.load(message['payload']) - status = Status.find(status_json['id']) - - [status, message] - end - - def filter?(status) - !status.nil? && FeedManager.instance.filter?(:public, status, current_user.account) - end - end -end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb deleted file mode 100644 index 33f9aa429..000000000 --- a/app/channels/application_cable/connection.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -module ApplicationCable - class Connection < ActionCable::Connection::Base - identified_by :current_user - - def connect - self.current_user = find_verified_user - end - - protected - - def find_verified_user - catch :warden do - verified_user = env['warden'].user - return verified_user if verified_user - end - - reject_unauthorized_connection - end - end -end diff --git a/app/channels/hashtag_channel.rb b/app/channels/hashtag_channel.rb deleted file mode 100644 index 4470a0e99..000000000 --- a/app/channels/hashtag_channel.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -class HashtagChannel < ApplicationCable::Channel - def subscribed - tag = params[:tag].downcase - - stream_from "timeline:hashtag:#{tag}", lambda { |encoded_message| - status, message = hydrate_status(encoded_message) - next if filter?(status) - transmit message - } - end -end diff --git a/app/channels/public_channel.rb b/app/channels/public_channel.rb deleted file mode 100644 index 9ef9e5dd7..000000000 --- a/app/channels/public_channel.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -class PublicChannel < ApplicationCable::Channel - def subscribed - stream_from 'timeline:public', lambda { |encoded_message| - status, message = hydrate_status(encoded_message) - next if filter?(status) - transmit message - } - end -end diff --git a/app/channels/timeline_channel.rb b/app/channels/timeline_channel.rb deleted file mode 100644 index 7b8d63ef5..000000000 --- a/app/channels/timeline_channel.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -class TimelineChannel < ApplicationCable::Channel - def subscribed - stream_from "timeline:#{current_user.account_id}" - end -end diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 7069026e3..f0928a945 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -16,8 +16,6 @@ class FeedManager filter_from_home?(status, receiver) elsif timeline_type == :mentions filter_from_mentions?(status, receiver) - elsif timeline_type == :public - filter_from_public?(status, receiver) else false end @@ -89,7 +87,9 @@ class FeedManager def filter_from_home?(status, receiver) should_filter = false - if status.reply? && !status.in_reply_to_account_id.nil? # Filter out if it's a reply + if status.reply? && status.in_reply_to_id.nil? + should_filter = true + elsif status.reply? && !status.in_reply_to_account_id.nil? # Filter out if it's a reply should_filter = !receiver.following?(status.in_reply_to_account) # and I'm not following the person it's a reply to should_filter &&= !(receiver.id == status.in_reply_to_account_id) # and it's not a reply to me should_filter &&= !(status.account_id == status.in_reply_to_account_id) # and it's not a self-reply @@ -115,17 +115,4 @@ class FeedManager should_filter end - - def filter_from_public?(status, receiver) - should_filter = receiver.blocking?(status.account) - should_filter ||= receiver.blocking?(status.mentions.includes(:account).map(&:account)) - - if status.reply? && !status.in_reply_to_account_id.nil? - should_filter ||= receiver.blocking?(status.in_reply_to_account) - elsif status.reblog? - should_filter ||= receiver.blocking?(status.reblog.account) - end - - should_filter - end end diff --git a/app/models/status.rb b/app/models/status.rb index 6ef0b2bdd..c6690c312 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -39,6 +39,10 @@ class Status < ApplicationRecord cache_associated :account, :application, :media_attachments, :tags, :stream_entry, mentions: :account, reblog: [:account, :application, :stream_entry, :tags, :media_attachments, mentions: :account], thread: :account + def reply? + super || !in_reply_to_id.nil? + end + def local? uri.nil? end @@ -47,10 +51,6 @@ class Status < ApplicationRecord !reblog_of_id.nil? end - def reply? - !in_reply_to_id.nil? - end - def verb reblog? ? :share : :post end @@ -105,7 +105,7 @@ class Status < ApplicationRecord def as_public_timeline(account = nil, local_only = false) query = joins('LEFT OUTER JOIN accounts ON statuses.account_id = accounts.id') .where(visibility: :public) - .where('(statuses.in_reply_to_id IS NULL OR statuses.in_reply_to_account_id = statuses.account_id)') + .where('(statuses.reply = false OR statuses.in_reply_to_account_id = statuses.account_id)') .where('statuses.reblog_of_id IS NULL') query = query.where('accounts.domain IS NULL') if local_only @@ -176,8 +176,9 @@ class Status < ApplicationRecord text.strip! spoiler_text&.strip! + self.reply = !(in_reply_to_id.nil? && thread.nil?) unless attributes[:reply] self.reblog = reblog.reblog if reblog? && reblog.reblog? - self.in_reply_to_account_id = (thread.account_id == account_id && thread.reply? ? thread.in_reply_to_account_id : thread.account_id) if reply? + self.in_reply_to_account_id = (thread.account_id == account_id && thread.reply? ? thread.in_reply_to_account_id : thread.account_id) if reply? && !thread.nil? self.visibility = (account.locked? ? :private : :public) if visibility.nil? end diff --git a/app/services/process_feed_service.rb b/app/services/process_feed_service.rb index 46656de3d..c411e3e82 100644 --- a/app/services/process_feed_service.rb +++ b/app/services/process_feed_service.rb @@ -105,7 +105,8 @@ class ProcessFeedService < BaseService account: account, text: content(entry), spoiler_text: content_warning(entry), - created_at: published(entry) + created_at: published(entry), + reply: thread?(entry) ) if thread?(entry) diff --git a/db/migrate/20170209184350_add_reply_to_statuses.rb b/db/migrate/20170209184350_add_reply_to_statuses.rb new file mode 100644 index 000000000..c5074728b --- /dev/null +++ b/db/migrate/20170209184350_add_reply_to_statuses.rb @@ -0,0 +1,10 @@ +class AddReplyToStatuses < ActiveRecord::Migration[5.0] + def up + add_column :statuses, :reply, :boolean, nil: false, default: false + Status.update_all('reply = (in_reply_to_id IS NOT NULL)') + end + + def down + remove_column :statuses, :reply + end +end diff --git a/db/schema.rb b/db/schema.rb index 28a578aa2..86a05ebe6 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.define(version: 20170205175257) do +ActiveRecord::Schema.define(version: 20170209184350) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -197,6 +197,7 @@ ActiveRecord::Schema.define(version: 20170205175257) do t.integer "in_reply_to_account_id" t.integer "application_id" t.text "spoiler_text", default: "", null: false + t.boolean "reply", default: false t.index ["account_id"], name: "index_statuses_on_account_id", using: :btree t.index ["in_reply_to_id"], name: "index_statuses_on_in_reply_to_id", using: :btree t.index ["reblog_of_id"], name: "index_statuses_on_reblog_of_id", using: :btree