Change how changes to media attachments are stored for edits (#17696)

* Change how changes to media attachments are stored for edits

Fix not being able to re-order media attachments

* Fix not broadcasting updates when polls/media is changed through ActivityPub

* Various fixes and improvements

* Update app/models/report.rb

Co-authored-by: Claire <claire.github-309c@sitedethib.com>

* Add tracking of media attachment description changes

* Change poll in status edit to have a structure closer to the real one

Co-authored-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
Eugen Rochko 2022-03-09 09:06:17 +01:00 committed by GitHub
parent bd53dd5210
commit d17fb70131
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 190 additions and 125 deletions

View file

@ -63,8 +63,20 @@ class Report < ApplicationRecord
Status.with_discarded.where(id: status_ids)
end
def media_attachments
MediaAttachment.where(status_id: status_ids)
def media_attachments_count
statuses_to_query = []
count = 0
statuses.pluck(:id, :ordered_media_attachment_ids).each do |id, ordered_ids|
if ordered_ids.nil?
statuses_to_query << id
else
count += ordered_ids.size
end
end
count += MediaAttachment.where(status_id: statuses_to_query).count unless statuses_to_query.empty?
count
end
def rules

View file

@ -3,28 +3,29 @@
#
# Table name: statuses
#
# id :bigint(8) not null, primary key
# uri :string
# text :text default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
# in_reply_to_id :bigint(8)
# reblog_of_id :bigint(8)
# url :string
# sensitive :boolean default(FALSE), not null
# visibility :integer default("public"), not null
# spoiler_text :text default(""), not null
# reply :boolean default(FALSE), not null
# language :string
# conversation_id :bigint(8)
# local :boolean
# account_id :bigint(8) not null
# application_id :bigint(8)
# in_reply_to_account_id :bigint(8)
# poll_id :bigint(8)
# deleted_at :datetime
# edited_at :datetime
# trendable :boolean
# id :bigint(8) not null, primary key
# uri :string
# text :text default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
# in_reply_to_id :bigint(8)
# reblog_of_id :bigint(8)
# url :string
# sensitive :boolean default(FALSE), not null
# visibility :integer default("public"), not null
# spoiler_text :text default(""), not null
# reply :boolean default(FALSE), not null
# language :string
# conversation_id :bigint(8)
# local :boolean
# account_id :bigint(8) not null
# application_id :bigint(8)
# in_reply_to_account_id :bigint(8)
# poll_id :bigint(8)
# deleted_at :datetime
# edited_at :datetime
# trendable :boolean
# ordered_media_attachment_ids :bigint(8) is an Array
#
class Status < ApplicationRecord
@ -211,11 +212,14 @@ class Status < ApplicationRecord
public_visibility? || unlisted_visibility?
end
def snapshot!(media_attachments_changed: false, account_id: nil, at_time: nil)
def snapshot!(account_id: nil, at_time: nil)
edits.create!(
text: text,
spoiler_text: spoiler_text,
media_attachments_changed: media_attachments_changed,
sensitive: sensitive,
ordered_media_attachment_ids: ordered_media_attachment_ids || media_attachments.pluck(:id),
media_descriptions: ordered_media_attachments.map(&:description),
poll_options: preloadable_poll&.options,
account_id: account_id || self.account_id,
created_at: at_time || edited_at
)
@ -228,7 +232,7 @@ class Status < ApplicationRecord
alias sign? distributable?
def with_media?
media_attachments.any?
ordered_media_attachments.any?
end
def with_preview_card?
@ -252,6 +256,15 @@ class Status < ApplicationRecord
@emojis = CustomEmoji.from_text(fields.join(' '), account.domain)
end
def ordered_media_attachments
if ordered_media_attachment_ids.nil?
media_attachments
else
map = media_attachments.index_by(&:id)
ordered_media_attachment_ids.map { |media_attachment_id| map[media_attachment_id] }
end
end
def replies_count
status_stat&.replies_count || 0
end

View file

@ -3,17 +3,29 @@
#
# Table name: status_edits
#
# id :bigint(8) not null, primary key
# status_id :bigint(8) not null
# account_id :bigint(8)
# text :text default(""), not null
# spoiler_text :text default(""), not null
# media_attachments_changed :boolean default(FALSE), not null
# created_at :datetime not null
# updated_at :datetime not null
# id :bigint(8) not null, primary key
# status_id :bigint(8) not null
# account_id :bigint(8)
# text :text default(""), not null
# spoiler_text :text default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
# ordered_media_attachment_ids :bigint(8) is an Array
# media_descriptions :text is an Array
# poll_options :string is an Array
# sensitive :boolean
#
class StatusEdit < ApplicationRecord
self.ignored_columns = %w(
media_attachments_changed
)
class PreservedMediaAttachment < ActiveModelSerializers::Model
attributes :media_attachment, :description
delegate :id, :type, :url, :preview_url, :remote_url, :preview_remote_url, :text_url, :meta, :blurhash, to: :media_attachment
end
belongs_to :status
belongs_to :account, optional: true
@ -25,4 +37,17 @@ class StatusEdit < ApplicationRecord
return @emojis if defined?(@emojis)
@emojis = CustomEmoji.from_text([spoiler_text, text].join(' '), status.account.domain)
end
def ordered_media_attachments
return @ordered_media_attachments if defined?(@ordered_media_attachments)
@ordered_media_attachments = begin
if ordered_media_attachment_ids.nil?
[]
else
map = status.media_attachments.index_by(&:id)
ordered_media_attachment_ids.map.with_index { |media_attachment_id, index| PreservedMediaAttachment.new(media_attachment: map[media_attachment_id], description: media_descriptions[index]) }
end
end
end
end