diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 2a075f1e1..b6f7bf3ef 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -22,6 +22,11 @@ class AccountsController < ApplicationController format.rss do expires_in 1.minute, public: true + if @account&.user&.setting_norss == true + @statuses = [] + next + end + limit = params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE @statuses = filtered_statuses.without_reblogs.without_local_only.limit(limit) @statuses = cache_collection(@statuses, Status) diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb index 6d9a46502..3aea517a8 100644 --- a/app/controllers/settings/preferences_controller.rb +++ b/app/controllers/settings/preferences_controller.rb @@ -47,6 +47,7 @@ class Settings::PreferencesController < Settings::BaseController :setting_disable_swiping, :setting_system_font_ui, :setting_noindex, + :setting_norss, :setting_theme, :setting_aggregate_reblogs, :setting_show_application, diff --git a/app/controllers/statuses_cleanup_controller.rb b/app/controllers/statuses_cleanup_controller.rb index be234cdcb..74c5676ce 100644 --- a/app/controllers/statuses_cleanup_controller.rb +++ b/app/controllers/statuses_cleanup_controller.rb @@ -26,7 +26,7 @@ class StatusesCleanupController < ApplicationController end def resource_params - params.require(:account_statuses_cleanup_policy).permit(:enabled, :min_status_age, :keep_direct, :keep_pinned, :keep_polls, :keep_media, :keep_self_fav, :keep_self_bookmark, :min_favs, :min_reblogs) + params.require(:account_statuses_cleanup_policy).permit(:enabled, :min_status_age, :keep_direct, :keep_pinned, :keep_polls, :keep_media, :keep_self_fav, :keep_local, :keep_self_bookmark, :min_favs, :min_reblogs) end def set_body_classes diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index 4712c2e50..02f1472f5 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -535,7 +535,7 @@ class Status extends ImmutablePureComponent { onCollapsedToggle={this.handleCollapsedToggle} /> - {media} + {status.get('activity_pub_type') === 'Article' ? null : media} diff --git a/app/javascript/mastodon/components/status_content.js b/app/javascript/mastodon/components/status_content.js index 9d1367536..03ec7d9a0 100644 --- a/app/javascript/mastodon/components/status_content.js +++ b/app/javascript/mastodon/components/status_content.js @@ -276,7 +276,7 @@ class StatusContent extends React.PureComponent { {mentionsPlaceholder} -
+
{!hidden && poll} {!hidden && translateButton}
diff --git a/app/javascript/mastodon/features/compose/components/poll_form.js b/app/javascript/mastodon/features/compose/components/poll_form.js index ede29b8a0..695ee4888 100644 --- a/app/javascript/mastodon/features/compose/components/poll_form.js +++ b/app/javascript/mastodon/features/compose/components/poll_form.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import Toggle from 'react-toggle'; import IconButton from 'mastodon/components/icon_button'; import Icon from 'mastodon/components/icon'; import AutosuggestInput from 'mastodon/components/autosuggest_input'; @@ -155,6 +156,12 @@ class PollForm extends ImmutablePureComponent { +
+ + + + +
diff --git a/app/javascript/mastodon/features/report/category.js b/app/javascript/mastodon/features/report/category.js index c6c0a506f..c319e9242 100644 --- a/app/javascript/mastodon/features/report/category.js +++ b/app/javascript/mastodon/features/report/category.js @@ -42,7 +42,7 @@ class Category extends React.PureComponent { switch(category) { case 'dislike': - onNextStep('thanks'); + onNextStep('statuses'); break; case 'violation': onNextStep('rules'); diff --git a/app/javascript/mastodon/features/status/components/detailed_status.js b/app/javascript/mastodon/features/status/components/detailed_status.js index 2332c0eb0..43b4da498 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.js +++ b/app/javascript/mastodon/features/status/components/detailed_status.js @@ -279,7 +279,7 @@ class DetailedStatus extends ImmutablePureComponent { onTranslate={this.handleTranslate} /> - {media} + {status.get('activity_pub_type') === 'Article' ? null : media}
diff --git a/app/javascript/mastodon/features/ui/components/link_footer.js b/app/javascript/mastodon/features/ui/components/link_footer.js index 7d0db7bae..8b007ba08 100644 --- a/app/javascript/mastodon/features/ui/components/link_footer.js +++ b/app/javascript/mastodon/features/ui/components/link_footer.js @@ -94,7 +94,6 @@ class LinkFooter extends React.PureComponent { {' · '} - {' · '}

); diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 4f12b051b..ebaba42e5 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -449,6 +449,7 @@ "poll.vote": "Vote", "poll.voted": "You voted for this answer", "poll.votes": "{votes, plural, one {# vote} other {# votes}}", + "poll.is_multiple": "Multiple choice", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "privacy.change": "Change post privacy", diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 94fcca6f9..3ffe7afb6 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -980,6 +980,11 @@ } } + .article-type { + display: inline-block; + margin-top: 10px; + } + .article-type img { max-width: 95%; } @@ -4215,6 +4220,21 @@ a.status-card.compact:hover { } } +// Hometown: Styling for toggle for multiple choice polls +.is-multiple-toggle { + display: block; + line-height: 24px; + padding-left: 10px; +} + +.is-multiple-toggle__label { + color: $inverted-text-color; + display: inline-block; + margin-bottom: 14px; + margin-left: 8px; + vertical-align: middle; +} + .setting-toggle { display: block; line-height: 24px; diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 2658405e4..25d3e809f 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -165,6 +165,15 @@ class ActivityPub::Activity::Create < ActivityPub::Activity handler = Handler.new(proc) Ox.sax_parse(handler, @object['content']) handler.srcs.each do |src| + # Handle images where the src is formatted as "/foo/bar.png" + # we assume that the `url` field is populated which lets us infer + # the protocol and domain of the _original_ article, as though + # we were looking at it via a web browser + if src[0] == '/' && !@object['url'].nil? + site = Addressable::URI.parse(@object['url']).site + src = site + src + end + if skip_download? @object['content'].gsub!(src, '') next diff --git a/app/lib/settings/scoped_settings.rb b/app/lib/settings/scoped_settings.rb index 1e18d6d46..4eeb8ed8c 100644 --- a/app/lib/settings/scoped_settings.rb +++ b/app/lib/settings/scoped_settings.rb @@ -5,6 +5,7 @@ module Settings DEFAULTING_TO_UNSCOPED = %w( theme noindex + norss ).freeze def initialize(object) diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb index 70f9bc81d..d529de5a9 100644 --- a/app/lib/user_settings_decorator.rb +++ b/app/lib/user_settings_decorator.rb @@ -31,6 +31,7 @@ class UserSettingsDecorator user.settings['disable_swiping'] = disable_swiping_preference if change?('setting_disable_swiping') user.settings['system_font_ui'] = system_font_ui_preference if change?('setting_system_font_ui') user.settings['noindex'] = noindex_preference if change?('setting_noindex') + user.settings['norss'] = norss_preference if change?('setting_norss') user.settings['theme'] = theme_preference if change?('setting_theme') user.settings['aggregate_reblogs'] = aggregate_reblogs_preference if change?('setting_aggregate_reblogs') user.settings['show_application'] = show_application_preference if change?('setting_show_application') @@ -102,6 +103,10 @@ class UserSettingsDecorator boolean_cast_setting 'setting_noindex' end + def norss_preference + boolean_cast_setting 'setting_norss' + end + def show_application_preference boolean_cast_setting 'setting_show_application' end diff --git a/app/models/account_statuses_cleanup_policy.rb b/app/models/account_statuses_cleanup_policy.rb index 49adc6ad0..088388002 100644 --- a/app/models/account_statuses_cleanup_policy.rb +++ b/app/models/account_statuses_cleanup_policy.rb @@ -14,6 +14,7 @@ # keep_media :boolean default(FALSE), not null # keep_self_fav :boolean default(TRUE), not null # keep_self_bookmark :boolean default(TRUE), not null +# keep_local :boolean default(TRUE), not null # min_favs :integer # min_reblogs :integer # created_at :datetime not null @@ -66,6 +67,7 @@ class AccountStatusesCleanupPolicy < ApplicationRecord scope.merge!(without_poll_scope) if keep_polls? scope.merge!(without_media_scope) if keep_media? scope.merge!(without_self_fav_scope) if keep_self_fav? + scope.merge!(without_local_scope) if keep_local? scope.merge!(without_self_bookmark_scope) if keep_self_bookmark? scope.reorder(id: :asc).limit(limit) @@ -148,6 +150,10 @@ class AccountStatusesCleanupPolicy < ApplicationRecord Status.where(Status.arel_table[:id].lteq(max_id)) end + def without_local_scope + Status.where(local_only: false) + end + def without_self_fav_scope Status.where('NOT EXISTS (SELECT * FROM favourites fav WHERE fav.account_id = statuses.account_id AND fav.status_id = statuses.id)') end diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 431d33bcd..06835312f 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -27,6 +27,7 @@ class Form::AdminSettings show_domain_blocks show_domain_blocks_rationale noindex + norss require_invite_text media_cache_retention_period content_cache_retention_period @@ -48,6 +49,7 @@ class Form::AdminSettings trends trendable_by_default noindex + norss require_invite_text ).freeze diff --git a/app/models/user.rb b/app/models/user.rb index 56b72b098..29aff60ec 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -132,7 +132,7 @@ class User < ApplicationRecord has_many :session_activations, dependent: :destroy delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :delete_modal, - :reduce_motion, :system_font_ui, :noindex, :theme, :display_media, + :reduce_motion, :system_font_ui, :noindex, :norss, :theme, :display_media, :expand_spoilers, :default_language, :aggregate_reblogs, :show_application, :advanced_layout, :use_blurhash, :use_pending_items, :trends, :crop_images, :disable_swiping, :default_federation, :always_send_emails, diff --git a/app/serializers/rest/preferences_serializer.rb b/app/serializers/rest/preferences_serializer.rb index 874bd990d..e8f719716 100644 --- a/app/serializers/rest/preferences_serializer.rb +++ b/app/serializers/rest/preferences_serializer.rb @@ -4,6 +4,7 @@ class REST::PreferencesSerializer < ActiveModel::Serializer attribute :posting_default_privacy, key: 'posting:default:visibility' attribute :posting_default_sensitive, key: 'posting:default:sensitive' attribute :posting_default_language, key: 'posting:default:language' + attribute :posting_default_federation, key: 'posting:default:federation' attribute :reading_default_sensitive_media, key: 'reading:expand:media' attribute :reading_default_sensitive_text, key: 'reading:expand:spoilers' @@ -27,4 +28,8 @@ class REST::PreferencesSerializer < ActiveModel::Serializer def reading_default_sensitive_text object.user.setting_expand_spoilers end + + def posting_default_federation + object.user.setting_default_federation + end end diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index e8fd27e10..f19a7878b 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -5,7 +5,8 @@ - if @account.user_prefers_noindex? %meta{ name: 'robots', content: 'noindex, noarchive' }/ - %link{ rel: 'alternate', type: 'application/rss+xml', href: @rss_url }/ + - if !@account.user&.setting_norss + %link{ rel: 'alternate', type: 'application/rss+xml', href: @rss_url }/ %link{ rel: 'alternate', type: 'application/activity+json', href: ActivityPub::TagManager.instance.uri_for(@account) }/ - @account.fields.select(&:verifiable?).each do |field| diff --git a/app/views/settings/preferences/other/show.html.haml b/app/views/settings/preferences/other/show.html.haml index 086308594..92734ec7d 100644 --- a/app/views/settings/preferences/other/show.html.haml +++ b/app/views/settings/preferences/other/show.html.haml @@ -10,6 +10,9 @@ .fields-group = f.input :setting_noindex, as: :boolean, wrapper: :with_label + .fields-group + = f.input :setting_norss, as: :boolean, wrapper: :with_label + .fields-group = f.input :setting_aggregate_reblogs, as: :boolean, wrapper: :with_label, recommended: true diff --git a/app/views/statuses_cleanup/show.html.haml b/app/views/statuses_cleanup/show.html.haml index 59de4b5aa..07b1071ba 100644 --- a/app/views/statuses_cleanup/show.html.haml +++ b/app/views/statuses_cleanup/show.html.haml @@ -34,6 +34,10 @@ .fields-row__column.fields-row__column-6.fields-group = f.input :keep_media, wrapper: :with_label, label: t('statuses_cleanup.keep_media'), hint: t('statuses_cleanup.keep_media_hint') + .fields-row + .fields-row__column.fields-row__column-6.fields-group + = f.input :keep_local, wrapper: :with_label, label: t('statuses_cleanup.keep_local'), hint: t('statuses_cleanup.keep_local_hint') + %h4= t('statuses_cleanup.interaction_exceptions') .fields-row diff --git a/config/locales/en.yml b/config/locales/en.yml index 59e8e4311..493c48f15 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1497,6 +1497,8 @@ en: interaction_exceptions_explanation: Note that there is no guarantee for posts to be deleted if they go below the favourite or boost threshold after having once gone over them. keep_direct: Keep direct messages keep_direct_hint: Doesn't delete any of your direct messages + keep_local: Keep local-only messages + keep_local_hint: Doesn't delete any of your local-only posts keep_media: Keep posts with media attachments keep_media_hint: Doesn't delete any of your posts that have media attachments keep_pinned: Keep pinned posts diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 2653e473e..331199c29 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -194,7 +194,7 @@ en: setting_auto_play_gif: Auto-play animated GIFs setting_boost_modal: Show confirmation dialog before boosting setting_crop_images: Crop images in non-expanded posts to 16x9 - setting_default_federation: Allow my posts to reach other instances by default + setting_default_federation: Allow my posts to reach other servers by default setting_default_language: Posting language setting_default_privacy: Posting privacy setting_default_sensitive: Always mark media as sensitive @@ -207,6 +207,7 @@ en: setting_expand_spoilers: Always expand posts marked with content warnings setting_hide_network: Hide your social graph setting_noindex: Opt-out of search engine indexing + setting_norss: Opt-out of an RSS feed for your public posts setting_reduce_motion: Reduce motion in animations setting_show_application: Disclose application used to send posts setting_system_font_ui: Use system's default font diff --git a/config/settings.yml b/config/settings.yml index 653db436e..cd1de06b4 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -30,6 +30,7 @@ defaults: &defaults show_application: true system_font_ui: false noindex: false + norss: false theme: 'default' aggregate_reblogs: true advanced_layout: false diff --git a/db/migrate/20221202035831_add_keep_local_to_account_statuses_cleanup_policies.rb b/db/migrate/20221202035831_add_keep_local_to_account_statuses_cleanup_policies.rb new file mode 100644 index 000000000..9bd268ea7 --- /dev/null +++ b/db/migrate/20221202035831_add_keep_local_to_account_statuses_cleanup_policies.rb @@ -0,0 +1,6 @@ +class AddKeepLocalToAccountStatusesCleanupPolicies < ActiveRecord::Migration[6.1] + def change + add_column :account_statuses_cleanup_policies, :keep_local, :boolean + change_column_default :account_statuses_cleanup_policies, :keep_local, false + end +end diff --git a/db/schema.rb b/db/schema.rb index 11559ea47..be959dff6 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: 2022_11_04_133904) do +ActiveRecord::Schema.define(version: 2022_12_02_035831) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -116,6 +116,7 @@ ActiveRecord::Schema.define(version: 2022_11_04_133904) do t.integer "min_reblogs" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false + t.boolean "keep_local", default: true, null: false t.index ["account_id"], name: "index_account_statuses_cleanup_policies_on_account_id" end diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 1be61b92b..4caaa7f4c 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -5,7 +5,7 @@ module Mastodon module_function def major - 2 + 4 end def minor @@ -21,7 +21,7 @@ module Mastodon end def suffix - '+4.0.0' + '+hometown-1.1.0' end def to_a diff --git a/lib/sanitize_ext/sanitize_config.rb b/lib/sanitize_ext/sanitize_config.rb index 9cdd08d62..dd58264ed 100644 --- a/lib/sanitize_ext/sanitize_config.rb +++ b/lib/sanitize_ext/sanitize_config.rb @@ -86,9 +86,6 @@ class Sanitize 'rel' => 'nofollow noopener noreferrer', 'target' => '_blank', }, - 'span' => { - 'class' => 'article-type', - }, }, protocols: {