From 0436aa99842e9b17e92c58a81fab1162f037c952 Mon Sep 17 00:00:00 2001 From: Darius Kazemi Date: Sun, 5 May 2019 16:59:04 -0700 Subject: [PATCH] Adding full Article support This creates a new column in the `statuses` table which keeps track of activity_pub_type, so in the case of a Note it will be blank (the default) and it will be a string "Article" if the received remote object is an AP Article. There is now a bunch of special case code in the formatters and sanitizers to handle Articles differently, as well as on the clientside. --- app/javascript/mastodon/components/status.js | 2 +- .../mastodon/components/status_content.js | 21 ++++++++++++++----- .../status/components/detailed_status.js | 2 +- .../styles/mastodon/components.scss | 5 +++++ app/lib/activitypub/activity/create.rb | 3 ++- app/lib/formatter.rb | 1 + app/lib/sanitize_config.rb | 3 +++ app/serializers/rest/status_serializer.rb | 6 +++++- 8 files changed, 34 insertions(+), 9 deletions(-) diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index 9b1035649..9797fe459 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -409,7 +409,7 @@ class Status extends ImmutablePureComponent { return ( -
+
{prepend}
diff --git a/app/javascript/mastodon/components/status_content.js b/app/javascript/mastodon/components/status_content.js index 06f5b4aad..a57cb3abd 100644 --- a/app/javascript/mastodon/components/status_content.js +++ b/app/javascript/mastodon/components/status_content.js @@ -170,6 +170,12 @@ export default class StatusContent extends React.PureComponent { ); + const readArticleButton = ( + + ); + if (status.get('spoiler_text').length > 0) { let mentionsPlaceholder = ''; @@ -185,21 +191,26 @@ export default class StatusContent extends React.PureComponent { mentionsPlaceholder =
{mentionLinks}
; } - return ( + const output = [
}

{mentionsPlaceholder}
- {!hidden && !!status.get('poll') && } -
- ); +
, + ]; + + if (status.get('activity_pub_type') === 'Article' && !this.props.expanded) { + output.push(readArticleButton); + } + + return output; } else if (this.props.onClick) { const output = [
- + {media} diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index ed3bbb0d4..7f3291cac 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -773,6 +773,7 @@ ul, ol { margin-left: 1em; + margin-bottom: 1em; p { margin: 0; @@ -840,6 +841,10 @@ display: block; } } + + .article-type img { + max-width: 95%; + } } .status__content.status__content--collapsed { diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 1e47de2d9..b1c170af0 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -60,7 +60,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity account: @account, text: text_from_content || '', language: detected_language, - spoiler_text: converted_object_type? ? '' : (text_from_summary || ''), + spoiler_text: converted_object_type? ? '' : (text_from_summary || (@object['type'] == 'Article' && text_from_name) || ''), created_at: @object['published'], override_timestamps: @options[:override_timestamps], reply: @object['inReplyTo'].present?, @@ -70,6 +70,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity conversation: conversation_from_uri(@object['conversation']), media_attachment_ids: process_attachments.take(4).map(&:id), poll: process_poll, + activity_pub_type: @object['type'] } end end diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index 9c2c0cd29..1c2066655 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -92,6 +92,7 @@ class Formatter def format_article(text) text = text.gsub(/>\n+<") + text = "#{text}" text.html_safe # rubocop:disable Rails/OutputSafety end diff --git a/app/lib/sanitize_config.rb b/app/lib/sanitize_config.rb index c157fc16a..f50d5f0fa 100644 --- a/app/lib/sanitize_config.rb +++ b/app/lib/sanitize_config.rb @@ -49,6 +49,9 @@ class Sanitize 'rel' => 'nofollow noopener', 'target' => '_blank', }, + 'span' => { + 'class' => 'article-type', + }, }, protocols: { diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index 7d2dc4e82..f96c32ae0 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -4,7 +4,7 @@ class REST::StatusSerializer < ActiveModel::Serializer attributes :id, :created_at, :in_reply_to_id, :in_reply_to_account_id, :sensitive, :spoiler_text, :visibility, :language, :uri, :url, :replies_count, :reblogs_count, - :favourites_count, :local_only + :favourites_count, :local_only, :activity_pub_type attribute :favourited, if: :current_user? attribute :reblogged, if: :current_user? @@ -61,6 +61,10 @@ class REST::StatusSerializer < ActiveModel::Serializer OStatus::TagManager.instance.uri_for(object) end + def activity_pub_type + object.activity_pub_type.to_s + end + def content Formatter.instance.format(object) end