From 41ad817afa5d8b94f1ced0426dcdff4339a604da Mon Sep 17 00:00:00 2001 From: Eugen Rochko <eugen@zeonfederated.com> Date: Mon, 9 May 2022 07:43:08 +0200 Subject: [PATCH 01/16] Change RSS feeds (#18356) * Change RSS feeds - Use date and time for titles instead of ellipsized text - Use full content in body, even when there is a content warning - Use media extensions * Change feed icons and add width and height attributes to custom emojis * Fix custom emoji animate on hover breaking * Fix tests --- app/controllers/accounts_controller.rb | 1 - app/controllers/tags_controller.rb | 1 - app/helpers/application_helper.rb | 4 +- app/helpers/formatting_helper.rb | 26 +++++ app/lib/emoji_formatter.rb | 28 ++++- app/lib/rss/builder.rb | 33 ++++++ app/lib/rss/channel.rb | 49 ++++++++ app/lib/rss/element.rb | 24 ++++ app/lib/rss/item.rb | 45 ++++++++ app/lib/rss/media_content.rb | 29 +++++ app/lib/rss/serializer.rb | 55 --------- app/lib/rss_builder.rb | 130 ---------------------- app/serializers/rss/account_serializer.rb | 28 ----- app/serializers/rss/tag_serializer.rb | 25 ----- app/views/accounts/show.rss.ruby | 37 ++++++ app/views/tags/show.rss.ruby | 36 ++++++ config/locales/en.yml | 5 + spec/lib/emoji_formatter_spec.rb | 6 +- spec/lib/rss/serializer_spec.rb | 56 ---------- 19 files changed, 311 insertions(+), 307 deletions(-) create mode 100644 app/lib/rss/builder.rb create mode 100644 app/lib/rss/channel.rb create mode 100644 app/lib/rss/element.rb create mode 100644 app/lib/rss/item.rb create mode 100644 app/lib/rss/media_content.rb delete mode 100644 app/lib/rss/serializer.rb delete mode 100644 app/lib/rss_builder.rb delete mode 100644 app/serializers/rss/account_serializer.rb delete mode 100644 app/serializers/rss/tag_serializer.rb create mode 100644 app/views/accounts/show.rss.ruby create mode 100644 app/views/tags/show.rss.ruby delete mode 100644 spec/lib/rss/serializer_spec.rb diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index ddd38cbb01..fe7d934dc3 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -44,7 +44,6 @@ class AccountsController < ApplicationController limit = params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE @statuses = filtered_statuses.without_reblogs.limit(limit) @statuses = cache_collection(@statuses, Status) - render xml: RSS::AccountSerializer.render(@account, @statuses, params[:tag]) end format.json do diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index 6616ba107c..b82da8f0cd 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -26,7 +26,6 @@ class TagsController < ApplicationController format.rss do expires_in 0, public: true - render xml: RSS::TagSerializer.render(@tag, @statuses) end format.json do diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 19dc0acd6d..bba7070d0d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -243,7 +243,7 @@ module ApplicationHelper end.values end - def prerender_custom_emojis(html, custom_emojis) - EmojiFormatter.new(html, custom_emojis, animate: prefers_autoplay?).to_s + def prerender_custom_emojis(html, custom_emojis, other_options = {}) + EmojiFormatter.new(html, custom_emojis, other_options.merge(animate: prefers_autoplay?)).to_s end end diff --git a/app/helpers/formatting_helper.rb b/app/helpers/formatting_helper.rb index a58dd608f8..f5b8dbed87 100644 --- a/app/helpers/formatting_helper.rb +++ b/app/helpers/formatting_helper.rb @@ -18,6 +18,32 @@ module FormattingHelper html_aware_format(status.text, status.local?, preloaded_accounts: [status.account] + (status.respond_to?(:active_mentions) ? status.active_mentions.map(&:account) : [])) end + def rss_status_content_format(status) + html = status_content_format(status) + + before_html = begin + if status.spoiler_text? + "<p><strong>#{I18n.t('rss.content_warning', locale: valid_locale_or_nil(status.language))}</strong> #{h(status.spoiler_text)}</p><hr />" + else + '' + end + end.html_safe # rubocop:disable Rails/OutputSafety + + after_html = begin + if status.preloadable_poll + "<p>#{status.preloadable_poll.options.map { |o| "<input type=#{status.preloadable_poll.multiple? ? 'checkbox' : 'radio'} disabled /> #{h(o)}" }.join('<br />')}</p>" + else + '' + end + end.html_safe # rubocop:disable Rails/OutputSafety + + prerender_custom_emojis( + safe_join([before_html, html, after_html]), + status.emojis, + style: 'width: 1.1em; height: 1.1em; object-fit: contain; vertical-align: middle; margin: -.2ex .15em .2ex' + ).to_str + end + def account_bio_format(account) html_aware_format(account.note, account.local?) end diff --git a/app/lib/emoji_formatter.rb b/app/lib/emoji_formatter.rb index f808f3a226..194849c23d 100644 --- a/app/lib/emoji_formatter.rb +++ b/app/lib/emoji_formatter.rb @@ -11,6 +11,7 @@ class EmojiFormatter # @param [Array<CustomEmoji>] custom_emojis # @param [Hash] options # @option options [Boolean] :animate + # @option options [String] :style def initialize(html, custom_emojis, options = {}) raise ArgumentError unless html.html_safe? @@ -85,14 +86,29 @@ class EmojiFormatter def image_for_emoji(shortcode, emoji) original_url, static_url = emoji - if animate? - image_tag(original_url, draggable: false, class: 'emojione', alt: ":#{shortcode}:", title: ":#{shortcode}:") - else - image_tag(original_url, draggable: false, class: 'emojione custom-emoji', alt: ":#{shortcode}:", title: ":#{shortcode}:", data: { original: original_url, static: static_url }) - end + image_tag( + animate? ? original_url : static_url, + image_attributes.merge(alt: ":#{shortcode}:", title: ":#{shortcode}:", data: image_data_attributes(original_url, static_url)) + ) + end + + def image_attributes + { rel: 'emoji', draggable: false, width: 16, height: 16, class: image_class_names, style: image_style } + end + + def image_data_attributes(original_url, static_url) + { original: original_url, static: static_url } unless animate? + end + + def image_class_names + animate? ? 'emojione' : 'emojione custom-emoji' + end + + def image_style + @options[:style] end def animate? - @options[:animate] + @options[:animate] || @options.key?(:style) end end diff --git a/app/lib/rss/builder.rb b/app/lib/rss/builder.rb new file mode 100644 index 0000000000..a9b3f08c5a --- /dev/null +++ b/app/lib/rss/builder.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +class RSS::Builder + attr_reader :dsl + + def self.build + new.tap do |builder| + yield builder.dsl + end.to_xml + end + + def initialize + @dsl = RSS::Channel.new + end + + def to_xml + ('<?xml version="1.0" encoding="UTF-8"?>'.dup << Ox.dump(wrap_in_document, effort: :tolerant)).force_encoding('UTF-8') + end + + private + + def wrap_in_document + Ox::Document.new(version: '1.0').tap do |document| + document << Ox::Element.new('rss').tap do |rss| + rss['version'] = '2.0' + rss['xmlns:webfeeds'] = 'http://webfeeds.org/rss/1.0' + rss['xmlns:media'] = 'http://search.yahoo.com/mrss/' + + rss << @dsl.to_element + end + end + end +end diff --git a/app/lib/rss/channel.rb b/app/lib/rss/channel.rb new file mode 100644 index 0000000000..1dba94e47e --- /dev/null +++ b/app/lib/rss/channel.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +class RSS::Channel < RSS::Element + def initialize + super() + + @root = create_element('channel') + end + + def title(str) + append_element('title', str) + end + + def link(str) + append_element('link', str) + end + + def last_build_date(date) + append_element('lastBuildDate', date.to_formatted_s(:rfc822)) + end + + def image(url, title, link) + append_element('image') do |image| + image << create_element('url', url) + image << create_element('title', title) + image << create_element('link', link) + end + end + + def description(str) + append_element('description', str) + end + + def generator(str) + append_element('generator', str) + end + + def icon(str) + append_element('webfeeds:icon', str) + end + + def logo(str) + append_element('webfeeds:logo', str) + end + + def item(&block) + @root << RSS::Item.with(&block) + end +end diff --git a/app/lib/rss/element.rb b/app/lib/rss/element.rb new file mode 100644 index 0000000000..7142fa0396 --- /dev/null +++ b/app/lib/rss/element.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +class RSS::Element + def self.with(*args, &block) + new(*args).tap(&block).to_element + end + + def create_element(name, content = nil) + Ox::Element.new(name).tap do |element| + yield element if block_given? + element << content if content.present? + end + end + + def append_element(name, content = nil) + @root << create_element(name, content).tap do |element| + yield element if block_given? + end + end + + def to_element + @root + end +end diff --git a/app/lib/rss/item.rb b/app/lib/rss/item.rb new file mode 100644 index 0000000000..c02991ace2 --- /dev/null +++ b/app/lib/rss/item.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +class RSS::Item < RSS::Element + def initialize + super() + + @root = create_element('item') + end + + def title(str) + append_element('title', str) + end + + def link(str) + append_element('guid', str) do |guid| + guid['isPermaLink'] = 'true' + end + + append_element('link', str) + end + + def pub_date(date) + append_element('pubDate', date.to_formatted_s(:rfc822)) + end + + def description(str) + append_element('description', str) + end + + def category(str) + append_element('category', str) + end + + def enclosure(url, type, size) + append_element('enclosure') do |enclosure| + enclosure['url'] = url + enclosure['length'] = size + enclosure['type'] = type + end + end + + def media_content(url, type, size, &block) + @root << RSS::MediaContent.with(url, type, size, &block) + end +end diff --git a/app/lib/rss/media_content.rb b/app/lib/rss/media_content.rb new file mode 100644 index 0000000000..7aefd8b40b --- /dev/null +++ b/app/lib/rss/media_content.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +class RSS::MediaContent < RSS::Element + def initialize(url, type, size) + super() + + @root = create_element('media:content') do |content| + content['url'] = url + content['type'] = type + content['fileSize'] = size + end + end + + def medium(str) + @root['medium'] = str + end + + def rating(str) + append_element('media:rating', str) do |rating| + rating['scheme'] = 'urn:simple' + end + end + + def description(str) + append_element('media:description', str) do |description| + description['type'] = 'plain' + end + end +end diff --git a/app/lib/rss/serializer.rb b/app/lib/rss/serializer.rb deleted file mode 100644 index d44e94221b..0000000000 --- a/app/lib/rss/serializer.rb +++ /dev/null @@ -1,55 +0,0 @@ -# frozen_string_literal: true - -class RSS::Serializer - include FormattingHelper - - private - - def render_statuses(builder, statuses) - statuses.each do |status| - builder.item do |item| - item.title(status_title(status)) - .link(ActivityPub::TagManager.instance.url_for(status)) - .pub_date(status.created_at) - .description(status_description(status)) - - status.ordered_media_attachments.each do |media| - item.enclosure(full_asset_url(media.file.url(:original, false)), media.file.content_type, media.file.size) - end - end - end - end - - def status_title(status) - preview = status.proper.spoiler_text.presence || status.proper.text - - if preview.length > 30 || preview[0, 30].include?("\n") - preview = preview[0, 30] - preview = preview[0, preview.index("\n").presence || 30] + '…' - end - - preview = "#{status.proper.spoiler_text.present? ? 'CW ' : ''}“#{preview}”#{status.proper.sensitive? ? ' (sensitive)' : ''}" - - if status.reblog? - "#{status.account.acct} boosted #{status.reblog.account.acct}: #{preview}" - else - "#{status.account.acct}: #{preview}" - end - end - - def status_description(status) - if status.proper.spoiler_text? - status.proper.spoiler_text - else - html = status_content_format(status.proper).to_str - after_html = '' - - if status.proper.preloadable_poll - poll_options_html = status.proper.preloadable_poll.options.map { |o| "[ ] #{o}" }.join('<br />') - after_html = "<p>#{poll_options_html}</p>" - end - - "#{html}#{after_html}" - end - end -end diff --git a/app/lib/rss_builder.rb b/app/lib/rss_builder.rb deleted file mode 100644 index 63ddba2e8e..0000000000 --- a/app/lib/rss_builder.rb +++ /dev/null @@ -1,130 +0,0 @@ -# frozen_string_literal: true - -class RSSBuilder - class ItemBuilder - def initialize - @item = Ox::Element.new('item') - end - - def title(str) - @item << (Ox::Element.new('title') << str) - - self - end - - def link(str) - @item << Ox::Element.new('guid').tap do |guid| - guid['isPermalink'] = 'true' - guid << str - end - - @item << (Ox::Element.new('link') << str) - - self - end - - def pub_date(date) - @item << (Ox::Element.new('pubDate') << date.to_formatted_s(:rfc822)) - - self - end - - def description(str) - @item << (Ox::Element.new('description') << str) - - self - end - - def enclosure(url, type, size) - @item << Ox::Element.new('enclosure').tap do |enclosure| - enclosure['url'] = url - enclosure['length'] = size - enclosure['type'] = type - end - - self - end - - def to_element - @item - end - end - - def initialize - @document = Ox::Document.new(version: '1.0') - @channel = Ox::Element.new('channel') - - @document << (rss << @channel) - end - - def title(str) - @channel << (Ox::Element.new('title') << str) - - self - end - - def link(str) - @channel << (Ox::Element.new('link') << str) - - self - end - - def image(str) - @channel << Ox::Element.new('image').tap do |image| - image << (Ox::Element.new('url') << str) - image << (Ox::Element.new('title') << '') - image << (Ox::Element.new('link') << '') - end - - @channel << (Ox::Element.new('webfeeds:icon') << str) - - self - end - - def cover(str) - @channel << Ox::Element.new('webfeeds:cover').tap do |cover| - cover['image'] = str - end - - self - end - - def logo(str) - @channel << (Ox::Element.new('webfeeds:logo') << str) - - self - end - - def accent_color(str) - @channel << (Ox::Element.new('webfeeds:accentColor') << str) - - self - end - - def description(str) - @channel << (Ox::Element.new('description') << str) - - self - end - - def item - @channel << ItemBuilder.new.tap do |item| - yield item - end.to_element - - self - end - - def to_xml - ('<?xml version="1.0" encoding="UTF-8"?>' + Ox.dump(@document, effort: :tolerant)).force_encoding('UTF-8') - end - - private - - def rss - Ox::Element.new('rss').tap do |rss| - rss['version'] = '2.0' - rss['xmlns:webfeeds'] = 'http://webfeeds.org/rss/1.0' - end - end -end diff --git a/app/serializers/rss/account_serializer.rb b/app/serializers/rss/account_serializer.rb deleted file mode 100644 index 81e24af0d0..0000000000 --- a/app/serializers/rss/account_serializer.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: true - -class RSS::AccountSerializer < RSS::Serializer - include ActionView::Helpers::NumberHelper - include AccountsHelper - include RoutingHelper - - def render(account, statuses, tag) - builder = RSSBuilder.new - - builder.title("#{display_name(account)} (@#{account.local_username_and_domain})") - .description(account_description(account)) - .link(tag.present? ? short_account_tag_url(account, tag) : short_account_url(account)) - .logo(full_pack_url('media/images/logo.svg')) - .accent_color('2b90d9') - - builder.image(full_asset_url(account.avatar.url(:original))) if account.avatar? - builder.cover(full_asset_url(account.header.url(:original))) if account.header? - - render_statuses(builder, statuses) - - builder.to_xml - end - - def self.render(account, statuses, tag) - new.render(account, statuses, tag) - end -end diff --git a/app/serializers/rss/tag_serializer.rb b/app/serializers/rss/tag_serializer.rb deleted file mode 100644 index e549ac3675..0000000000 --- a/app/serializers/rss/tag_serializer.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -class RSS::TagSerializer < RSS::Serializer - include ActionView::Helpers::NumberHelper - include ActionView::Helpers::SanitizeHelper - include RoutingHelper - - def render(tag, statuses) - builder = RSSBuilder.new - - builder.title("##{tag.name}") - .description(strip_tags(I18n.t('about.about_hashtag_html', hashtag: tag.name))) - .link(tag_url(tag)) - .logo(full_pack_url('media/images/logo.svg')) - .accent_color('2b90d9') - - render_statuses(builder, statuses) - - builder.to_xml - end - - def self.render(tag, statuses) - new.render(tag, statuses) - end -end diff --git a/app/views/accounts/show.rss.ruby b/app/views/accounts/show.rss.ruby new file mode 100644 index 0000000000..73c1c51e07 --- /dev/null +++ b/app/views/accounts/show.rss.ruby @@ -0,0 +1,37 @@ +RSS::Builder.build do |doc| + doc.title(display_name(@account)) + doc.description(I18n.t('rss.descriptions.account', acct: @account.local_username_and_domain)) + doc.link(params[:tag].present? ? short_account_tag_url(@account, params[:tag]) : short_account_url(@account)) + doc.image(full_asset_url(@account.avatar.url(:original)), display_name(@account), params[:tag].present? ? short_account_tag_url(@account, params[:tag]) : short_account_url(@account)) + doc.last_build_date(@statuses.first.created_at) if @statuses.any? + doc.icon(full_asset_url(@account.avatar.url(:original))) + doc.logo(full_pack_url('media/images/logo_transparent_white.svg')) + doc.generator("Mastodon v#{Mastodon::Version.to_s}") + + @statuses.each do |status| + doc.item do |item| + item.title(l(status.created_at)) + item.link(ActivityPub::TagManager.instance.url_for(status)) + item.pub_date(status.created_at) + item.description(rss_status_content_format(status)) + + if status.ordered_media_attachments.first&.audio? + media = status.ordered_media_attachments.first + item.enclosure(full_asset_url(media.file.url(:original, false)), media.file.content_type, media.file.size) + end + + status.ordered_media_attachments.each do |media| + item.media_content(full_asset_url(media.file.url(:original, false)), media.file.content_type, media.file.size) do |media_content| + media_content.medium(media.gifv? ? 'image' : media.type.to_s) + media_content.rating(status.sensitive? ? 'adult' : 'nonadult') + media_content.description(media.description) if media.description.present? + media_content.thumbnail(media.thumbnail.url(:original, false)) if media.thumbnail? + end + end + + status.tags.each do |tag| + item.category(tag.name) + end + end + end +end diff --git a/app/views/tags/show.rss.ruby b/app/views/tags/show.rss.ruby new file mode 100644 index 0000000000..4152ecd24b --- /dev/null +++ b/app/views/tags/show.rss.ruby @@ -0,0 +1,36 @@ +RSS::Builder.build do |doc| + doc.title("##{@tag.name}") + doc.description(I18n.t('rss.descriptions.tag', hashtag: @tag.name)) + doc.link(tag_url(@tag)) + doc.last_build_date(@statuses.first.created_at) if @statuses.any? + doc.icon(full_asset_url(@account.avatar.url(:original))) + doc.logo(full_pack_url('media/images/logo_transparent_white.svg')) + doc.generator("Mastodon v#{Mastodon::Version.to_s}") + + @statuses.each do |status| + doc.item do |item| + item.title(l(status.created_at)) + item.link(ActivityPub::TagManager.instance.url_for(status)) + item.pub_date(status.created_at) + item.description(rss_status_content_format(status)) + + if status.ordered_media_attachments.first&.audio? + media = status.ordered_media_attachments.first + item.enclosure(full_asset_url(media.file.url(:original, false)), media.file.content_type, media.file.size) + end + + status.ordered_media_attachments.each do |media| + item.media_content(full_asset_url(media.file.url(:original, false)), media.file.content_type, media.file.size) do |media_content| + media_content.medium(media.gifv? ? 'image' : media.type.to_s) + media_content.rating(status.sensitive? ? 'adult' : 'nonadult') + media_content.description(media.description) if media.description.present? + media_content.thumbnail(media.thumbnail.url(:original, false)) if media.thumbnail? + end + end + + status.tags.each do |tag| + item.category(tag.name) + end + end + end +end diff --git a/config/locales/en.yml b/config/locales/en.yml index 2c8455d0ae..50e762db72 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1357,6 +1357,11 @@ en: reports: errors: invalid_rules: does not reference valid rules + rss: + content_warning: 'Content warning:' + descriptions: + account: Public posts from @%{acct} + tag: 'Public posts tagged #%{hashtag}' scheduled_statuses: over_daily_limit: You have exceeded the limit of %{limit} scheduled posts for today over_total_limit: You have exceeded the limit of %{limit} scheduled posts diff --git a/spec/lib/emoji_formatter_spec.rb b/spec/lib/emoji_formatter_spec.rb index 129445aa59..e1747bdd9d 100644 --- a/spec/lib/emoji_formatter_spec.rb +++ b/spec/lib/emoji_formatter_spec.rb @@ -24,7 +24,7 @@ RSpec.describe EmojiFormatter do let(:text) { preformat_text(':coolcat: Beep boop') } it 'converts the shortcode to an image tag' do - is_expected.to match(/<img draggable="false" class="emojione custom-emoji" alt=":coolcat:"/) + is_expected.to match(/<img rel="emoji" draggable="false" width="16" height="16" class="emojione custom-emoji" alt=":coolcat:"/) end end @@ -32,7 +32,7 @@ RSpec.describe EmojiFormatter do let(:text) { preformat_text('Beep :coolcat: boop') } it 'converts the shortcode to an image tag' do - is_expected.to match(/Beep <img draggable="false" class="emojione custom-emoji" alt=":coolcat:"/) + is_expected.to match(/Beep <img rel="emoji" draggable="false" width="16" height="16" class="emojione custom-emoji" alt=":coolcat:"/) end end @@ -48,7 +48,7 @@ RSpec.describe EmojiFormatter do let(:text) { preformat_text('Beep boop :coolcat:') } it 'converts the shortcode to an image tag' do - is_expected.to match(/boop <img draggable="false" class="emojione custom-emoji" alt=":coolcat:"/) + is_expected.to match(/boop <img rel="emoji" draggable="false" width="16" height="16" class="emojione custom-emoji" alt=":coolcat:"/) end end end diff --git a/spec/lib/rss/serializer_spec.rb b/spec/lib/rss/serializer_spec.rb deleted file mode 100644 index 1da45d302a..0000000000 --- a/spec/lib/rss/serializer_spec.rb +++ /dev/null @@ -1,56 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -describe RSS::Serializer do - describe '#status_title' do - let(:text) { 'This is a toot' } - let(:spoiler) { '' } - let(:sensitive) { false } - let(:reblog) { nil } - let(:account) { Fabricate(:account) } - let(:status) { Fabricate(:status, account: account, text: text, spoiler_text: spoiler, sensitive: sensitive, reblog: reblog) } - - subject { RSS::Serializer.new.send(:status_title, status) } - - context 'on a toot with long text' do - let(:text) { "This toot's text is longer than the allowed number of characters" } - - it 'truncates toot text appropriately' do - expect(subject).to eq "#{account.acct}: “This toot's text is longer tha…”" - end - end - - context 'on a toot with long text with a newline' do - let(:text) { "This toot's text is longer\nthan the allowed number of characters" } - - it 'truncates toot text appropriately' do - expect(subject).to eq "#{account.acct}: “This toot's text is longer…”" - end - end - - context 'on a toot with a content warning' do - let(:spoiler) { 'long toot' } - - it 'displays spoiler text instead of toot content' do - expect(subject).to eq "#{account.acct}: CW “long toot”" - end - end - - context 'on a toot with sensitive media' do - let(:sensitive) { true } - - it 'displays that the media is sensitive' do - expect(subject).to eq "#{account.acct}: “This is a toot” (sensitive)" - end - end - - context 'on a reblog' do - let(:reblog) { Fabricate(:status, text: 'This is a toot') } - - it 'display that the toot is a reblog' do - expect(subject).to eq "#{account.acct} boosted #{reblog.account.acct}: “This is a toot”" - end - end - end -end From 5cc4d2ed8b81a718e8555b5a4951f74e04fa2517 Mon Sep 17 00:00:00 2001 From: Claire <claire.github-309c@sitedethib.com> Date: Mon, 9 May 2022 23:19:11 +0200 Subject: [PATCH 02/16] Fix redis configuration not being changed by mastodon:setup (#18383) Fixes #18342 --- lib/tasks/mastodon.rake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake index a89af67780..d652468b37 100644 --- a/lib/tasks/mastodon.rake +++ b/lib/tasks/mastodon.rake @@ -8,6 +8,14 @@ namespace :mastodon do prompt = TTY::Prompt.new env = {} + # When the application code gets loaded, it runs `lib/mastodon/redis_configuration.rb`. + # This happens before application environment configuration and sets REDIS_URL etc. + # These variables are then used even when REDIS_HOST etc. are changed, so clear them + # out so they don't interfer with our new configuration. + ENV.delete('REDIS_URL') + ENV.delete('CACHE_REDIS_URL') + ENV.delete('SIDEKIQ_REDIS_URL') + begin prompt.say('Your instance is identified by its domain name. Changing it afterward will break things.') env['LOCAL_DOMAIN'] = prompt.ask('Domain name:') do |q| From 917567567a9a5a79f2a2492de672b0907605aabf Mon Sep 17 00:00:00 2001 From: Claire <claire.github-309c@sitedethib.com> Date: Mon, 9 May 2022 23:20:19 +0200 Subject: [PATCH 03/16] Fix block/mute lists showing a follow button when unblocking a user (#18364) Fixes #601 --- app/javascript/mastodon/components/account.js | 9 ++++++++- app/javascript/mastodon/features/blocks/index.js | 2 +- app/javascript/mastodon/features/mutes/index.js | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/javascript/mastodon/components/account.js b/app/javascript/mastodon/components/account.js index 62b5843a93..af9f119c82 100644 --- a/app/javascript/mastodon/components/account.js +++ b/app/javascript/mastodon/components/account.js @@ -18,6 +18,8 @@ const messages = defineMessages({ unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, mute_notifications: { id: 'account.mute_notifications', defaultMessage: 'Mute notifications from @{name}' }, unmute_notifications: { id: 'account.unmute_notifications', defaultMessage: 'Unmute notifications from @{name}' }, + mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, + block: { id: 'account.block', defaultMessage: 'Block @{name}' }, }); export default @injectIntl @@ -33,6 +35,7 @@ class Account extends ImmutablePureComponent { hidden: PropTypes.bool, actionIcon: PropTypes.string, actionTitle: PropTypes.string, + defaultAction: PropTypes.string, onActionClick: PropTypes.func, }; @@ -61,7 +64,7 @@ class Account extends ImmutablePureComponent { } render () { - const { account, intl, hidden, onActionClick, actionIcon, actionTitle } = this.props; + const { account, intl, hidden, onActionClick, actionIcon, actionTitle, defaultAction } = this.props; if (!account) { return <div />; @@ -105,6 +108,10 @@ class Account extends ImmutablePureComponent { {hidingNotificationsButton} </Fragment> ); + } else if (defaultAction === 'mute') { + buttons = <IconButton icon='volume-off' title={intl.formatMessage(messages.mute, { name: account.get('username') })} onClick={this.handleMute} />; + } else if (defaultAction === 'block') { + buttons = <IconButton icon='lock' title={intl.formatMessage(messages.block, { name: account.get('username') })} onClick={this.handleBlock} />; } else if (!account.get('moved') || following) { buttons = <IconButton icon={following ? 'user-times' : 'user-plus'} title={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={this.handleFollow} active={following} />; } diff --git a/app/javascript/mastodon/features/blocks/index.js b/app/javascript/mastodon/features/blocks/index.js index 7ec1774344..e00f2b60e0 100644 --- a/app/javascript/mastodon/features/blocks/index.js +++ b/app/javascript/mastodon/features/blocks/index.js @@ -69,7 +69,7 @@ class Blocks extends ImmutablePureComponent { bindToDocument={!multiColumn} > {accountIds.map(id => - <AccountContainer key={id} id={id} />, + <AccountContainer key={id} id={id} defaultAction='block' />, )} </ScrollableList> </Column> diff --git a/app/javascript/mastodon/features/mutes/index.js b/app/javascript/mastodon/features/mutes/index.js index c1d50d1940..c21433cc41 100644 --- a/app/javascript/mastodon/features/mutes/index.js +++ b/app/javascript/mastodon/features/mutes/index.js @@ -69,7 +69,7 @@ class Mutes extends ImmutablePureComponent { bindToDocument={!multiColumn} > {accountIds.map(id => - <AccountContainer key={id} id={id} />, + <AccountContainer key={id} id={id} defaultAction='mute' />, )} </ScrollableList> </Column> From 3e20855c52e508ca8759bdf6a9f65ac635056879 Mon Sep 17 00:00:00 2001 From: luzpaz <luzpaz@users.noreply.github.com> Date: Mon, 9 May 2022 22:58:04 -0400 Subject: [PATCH 04/16] Fix typo in source `setted`->`set` (#18385) Found via `codespell -q 3 -S ./CHANGELOG.md,./AUTHORS.md,./config/locales,./app/javascript/mastodon/locales -L ba,keypair,medias,ro` --- .../confirmations_controller_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb index 7b86513bef..569c8322bd 100644 --- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb +++ b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb @@ -22,7 +22,7 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do let(:user) { Fabricate(:user, email: 'local-part@domain', otp_secret: with_otp_secret ? 'oldotpsecret' : nil) } describe 'GET #new' do - context 'when signed in and a new otp secret has been setted in the session' do + context 'when signed in and a new otp secret has been set in the session' do subject do sign_in user, scope: :user get :new, session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } @@ -36,7 +36,7 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do expect(response).to redirect_to('/auth/sign_in') end - it 'redirects if a new otp_secret has not been setted in the session' do + it 'redirects if a new otp_secret has not been set in the session' do sign_in user, scope: :user get :new, session: { challenge_passed_at: Time.now.utc } expect(response).to redirect_to('/settings/otp_authentication') From ac3d6f9a35e3ce5c74300d811ff0ca5f94d60fb6 Mon Sep 17 00:00:00 2001 From: Eugen Rochko <eugen@zeonfederated.com> Date: Tue, 10 May 2022 09:44:35 +0200 Subject: [PATCH 05/16] Add `limited` attribute to accounts in REST API and a warning in web UI (#18344) --- app/javascript/mastodon/actions/accounts.js | 7 +++ app/javascript/mastodon/components/avatar.js | 28 +++++---- .../features/account/components/header.js | 57 ++++++++++--------- .../account_timeline/components/header.js | 8 ++- .../components/limited_account_hint.js | 35 ++++++++++++ .../containers/header_container.js | 3 +- .../features/account_timeline/index.js | 16 ++++-- .../mastodon/features/followers/index.js | 20 +++++-- .../mastodon/features/following/index.js | 20 +++++-- app/javascript/mastodon/reducers/accounts.js | 7 ++- app/javascript/mastodon/selectors/index.js | 8 +++ .../styles/mastodon/components.scss | 9 +++ app/serializers/rest/account_serializer.rb | 7 ++- 13 files changed, 166 insertions(+), 59 deletions(-) create mode 100644 app/javascript/mastodon/features/account_timeline/components/limited_account_hint.js diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js index ce7bb6d5f0..eedf61dc99 100644 --- a/app/javascript/mastodon/actions/accounts.js +++ b/app/javascript/mastodon/actions/accounts.js @@ -77,6 +77,8 @@ export const FOLLOW_REQUEST_REJECT_REQUEST = 'FOLLOW_REQUEST_REJECT_REQUEST'; export const FOLLOW_REQUEST_REJECT_SUCCESS = 'FOLLOW_REQUEST_REJECT_SUCCESS'; export const FOLLOW_REQUEST_REJECT_FAIL = 'FOLLOW_REQUEST_REJECT_FAIL'; +export const ACCOUNT_REVEAL = 'ACCOUNT_REVEAL'; + export function fetchAccount(id) { return (dispatch, getState) => { dispatch(fetchRelationships([id])); @@ -780,3 +782,8 @@ export function unpinAccountFail(error) { error, }; }; + +export const revealAccount = id => ({ + type: ACCOUNT_REVEAL, + id, +}); diff --git a/app/javascript/mastodon/components/avatar.js b/app/javascript/mastodon/components/avatar.js index 570505833f..12ab7d2dfe 100644 --- a/app/javascript/mastodon/components/avatar.js +++ b/app/javascript/mastodon/components/avatar.js @@ -2,11 +2,12 @@ import React from 'react'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { autoPlayGif } from '../initial_state'; +import classNames from 'classnames'; export default class Avatar extends React.PureComponent { static propTypes = { - account: ImmutablePropTypes.map.isRequired, + account: ImmutablePropTypes.map, size: PropTypes.number.isRequired, style: PropTypes.object, inline: PropTypes.bool, @@ -37,15 +38,6 @@ export default class Avatar extends React.PureComponent { const { account, size, animate, inline } = this.props; const { hovering } = this.state; - const src = account.get('avatar'); - const staticSrc = account.get('avatar_static'); - - let className = 'account__avatar'; - - if (inline) { - className = className + ' account__avatar-inline'; - } - const style = { ...this.props.style, width: `${size}px`, @@ -53,15 +45,21 @@ export default class Avatar extends React.PureComponent { backgroundSize: `${size}px ${size}px`, }; - if (hovering || animate) { - style.backgroundImage = `url(${src})`; - } else { - style.backgroundImage = `url(${staticSrc})`; + if (account) { + const src = account.get('avatar'); + const staticSrc = account.get('avatar_static'); + + if (hovering || animate) { + style.backgroundImage = `url(${src})`; + } else { + style.backgroundImage = `url(${staticSrc})`; + } } + return ( <div - className={className} + className={classNames('account__avatar', { 'account__avatar-inline': inline })} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} style={style} diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js index 2830bee29f..8e6b9f0634 100644 --- a/app/javascript/mastodon/features/account/components/header.js +++ b/app/javascript/mastodon/features/account/components/header.js @@ -82,6 +82,7 @@ class Header extends ImmutablePureComponent { onEditAccountNote: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, domain: PropTypes.string.isRequired, + hidden: PropTypes.bool, }; openEditProfile = () => { @@ -123,7 +124,7 @@ class Header extends ImmutablePureComponent { } render () { - const { account, intl, domain } = this.props; + const { account, hidden, intl, domain } = this.props; if (!account) { return null; @@ -267,21 +268,25 @@ class Header extends ImmutablePureComponent { {!suspended && info} </div> - <img src={autoPlayGif ? account.get('header') : account.get('header_static')} alt='' className='parallax' /> + {!(suspended || hidden) && <img src={autoPlayGif ? account.get('header') : account.get('header_static')} alt='' className='parallax' />} </div> <div className='account__header__bar'> <div className='account__header__tabs'> <a className='avatar' href={account.get('url')} rel='noopener noreferrer' target='_blank'> - <Avatar account={account} size={90} /> + <Avatar account={suspended || hidden ? undefined : account} size={90} /> </a> <div className='spacer' /> {!suspended && ( <div className='account__header__tabs__buttons'> - {actionBtn} - {bellBtn} + {!hidden && ( + <React.Fragment> + {actionBtn} + {bellBtn} + </React.Fragment> + )} <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' /> </div> @@ -295,30 +300,30 @@ class Header extends ImmutablePureComponent { </h1> </div> - <div className='account__header__extra'> - <div className='account__header__bio'> - {fields.size > 0 && ( - <div className='account__header__fields'> - {fields.map((pair, i) => ( - <dl key={i}> - <dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} className='translate' /> + {!(suspended || hidden) && ( + <div className='account__header__extra'> + <div className='account__header__bio'> + {fields.size > 0 && ( + <div className='account__header__fields'> + {fields.map((pair, i) => ( + <dl key={i}> + <dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} className='translate' /> - <dd className={`${pair.get('verified_at') ? 'verified' : ''} translate`} title={pair.get('value_plain')}> - {pair.get('verified_at') && <span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}><Icon id='check' className='verified__mark' /></span>} <span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} /> - </dd> - </dl> - ))} - </div> - )} + <dd className={`${pair.get('verified_at') ? 'verified' : ''} translate`} title={pair.get('value_plain')}> + {pair.get('verified_at') && <span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}><Icon id='check' className='verified__mark' /></span>} <span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} /> + </dd> + </dl> + ))} + </div> + )} - {account.get('id') !== me && !suspended && <AccountNoteContainer account={account} />} + {account.get('id') !== me && <AccountNoteContainer account={account} />} - {account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content translate' dangerouslySetInnerHTML={content} />} + {account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content translate' dangerouslySetInnerHTML={content} />} - <div className='account__header__joined'><FormattedMessage id='account.joined' defaultMessage='Joined {date}' values={{ date: intl.formatDate(account.get('created_at'), { year: 'numeric', month: 'short', day: '2-digit' }) }} /></div> - </div> + <div className='account__header__joined'><FormattedMessage id='account.joined' defaultMessage='Joined {date}' values={{ date: intl.formatDate(account.get('created_at'), { year: 'numeric', month: 'short', day: '2-digit' }) }} /></div> + </div> - {!suspended && ( <div className='account__header__extra__links'> <NavLink isActive={this.isStatusesPageActive} activeClassName='active' to={`/@${account.get('acct')}`} title={intl.formatNumber(account.get('statuses_count'))}> <ShortNumber @@ -341,8 +346,8 @@ class Header extends ImmutablePureComponent { /> </NavLink> </div> - )} - </div> + </div> + )} </div> </div> ); diff --git a/app/javascript/mastodon/features/account_timeline/components/header.js b/app/javascript/mastodon/features/account_timeline/components/header.js index 507b6c8956..fab0bc597f 100644 --- a/app/javascript/mastodon/features/account_timeline/components/header.js +++ b/app/javascript/mastodon/features/account_timeline/components/header.js @@ -24,6 +24,7 @@ export default class Header extends ImmutablePureComponent { onAddToList: PropTypes.func.isRequired, hideTabs: PropTypes.bool, domain: PropTypes.string.isRequired, + hidden: PropTypes.bool, }; static contextTypes = { @@ -91,7 +92,7 @@ export default class Header extends ImmutablePureComponent { } render () { - const { account, hideTabs } = this.props; + const { account, hidden, hideTabs } = this.props; if (account === null) { return null; @@ -99,7 +100,7 @@ export default class Header extends ImmutablePureComponent { return ( <div className='account-timeline__header'> - {account.get('moved') && <MovedNote from={account} to={account.get('moved')} />} + {(!hidden && account.get('moved')) && <MovedNote from={account} to={account.get('moved')} />} <InnerHeader account={account} @@ -117,9 +118,10 @@ export default class Header extends ImmutablePureComponent { onAddToList={this.handleAddToList} onEditAccountNote={this.handleEditAccountNote} domain={this.props.domain} + hidden={hidden} /> - {!hideTabs && ( + {!(hideTabs || hidden) && ( <div className='account__section-headline'> <NavLink exact to={`/@${account.get('acct')}`}><FormattedMessage id='account.posts' defaultMessage='Posts' /></NavLink> <NavLink exact to={`/@${account.get('acct')}/with_replies`}><FormattedMessage id='account.posts_with_replies' defaultMessage='Posts and replies' /></NavLink> diff --git a/app/javascript/mastodon/features/account_timeline/components/limited_account_hint.js b/app/javascript/mastodon/features/account_timeline/components/limited_account_hint.js new file mode 100644 index 0000000000..6b025596ca --- /dev/null +++ b/app/javascript/mastodon/features/account_timeline/components/limited_account_hint.js @@ -0,0 +1,35 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { revealAccount } from 'mastodon/actions/accounts'; +import { FormattedMessage } from 'react-intl'; +import Button from 'mastodon/components/button'; + +const mapDispatchToProps = (dispatch, { accountId }) => ({ + + reveal () { + dispatch(revealAccount(accountId)); + }, + +}); + +export default @connect(() => {}, mapDispatchToProps) +class LimitedAccountHint extends React.PureComponent { + + static propTypes = { + accountId: PropTypes.string.isRequired, + reveal: PropTypes.func, + } + + render () { + const { reveal } = this.props; + + return ( + <div className='limited-account-hint'> + <p><FormattedMessage id='limited_account_hint.title' defaultMessage='This profile has been hidden by the moderators of your server.' /></p> + <Button onClick={reveal}><FormattedMessage id='limited_account_hint.action' defaultMessage='Show profile anyway' /></Button> + </div> + ); + } + +} diff --git a/app/javascript/mastodon/features/account_timeline/containers/header_container.js b/app/javascript/mastodon/features/account_timeline/containers/header_container.js index b3f8521cb9..371794dd75 100644 --- a/app/javascript/mastodon/features/account_timeline/containers/header_container.js +++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.js @@ -1,6 +1,6 @@ import React from 'react'; import { connect } from 'react-redux'; -import { makeGetAccount } from '../../../selectors'; +import { makeGetAccount, getAccountHidden } from '../../../selectors'; import Header from '../components/header'; import { followAccount, @@ -33,6 +33,7 @@ const makeMapStateToProps = () => { const mapStateToProps = (state, { accountId }) => ({ account: getAccount(state, accountId), domain: state.getIn(['meta', 'domain']), + hidden: getAccountHidden(state, accountId), }); return mapStateToProps; diff --git a/app/javascript/mastodon/features/account_timeline/index.js b/app/javascript/mastodon/features/account_timeline/index.js index 5122aec4e9..5b592c5a76 100644 --- a/app/javascript/mastodon/features/account_timeline/index.js +++ b/app/javascript/mastodon/features/account_timeline/index.js @@ -16,6 +16,8 @@ import MissingIndicator from 'mastodon/components/missing_indicator'; import TimelineHint from 'mastodon/components/timeline_hint'; import { me } from 'mastodon/initial_state'; import { connectTimeline, disconnectTimeline } from 'mastodon/actions/timelines'; +import LimitedAccountHint from './components/limited_account_hint'; +import { getAccountHidden } from 'mastodon/selectors'; const emptyList = ImmutableList(); @@ -40,6 +42,7 @@ const mapStateToProps = (state, { params: { acct, id }, withReplies = false }) = isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']), hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']), suspended: state.getIn(['accounts', accountId, 'suspended'], false), + hidden: getAccountHidden(state, accountId), blockedBy: state.getIn(['relationships', accountId, 'blocked_by'], false), }; }; @@ -70,6 +73,7 @@ class AccountTimeline extends ImmutablePureComponent { blockedBy: PropTypes.bool, isAccount: PropTypes.bool, suspended: PropTypes.bool, + hidden: PropTypes.bool, remote: PropTypes.bool, remoteUrl: PropTypes.string, multiColumn: PropTypes.bool, @@ -128,7 +132,7 @@ class AccountTimeline extends ImmutablePureComponent { } render () { - const { statusIds, featuredStatusIds, isLoading, hasMore, blockedBy, suspended, isAccount, multiColumn, remote, remoteUrl } = this.props; + const { accountId, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy, suspended, isAccount, hidden, multiColumn, remote, remoteUrl } = this.props; if (!isAccount) { return ( @@ -149,8 +153,12 @@ class AccountTimeline extends ImmutablePureComponent { let emptyMessage; + const forceEmptyState = suspended || blockedBy || hidden; + if (suspended) { emptyMessage = <FormattedMessage id='empty_column.account_suspended' defaultMessage='Account suspended' />; + } else if (hidden) { + emptyMessage = <LimitedAccountHint accountId={accountId} />; } else if (blockedBy) { emptyMessage = <FormattedMessage id='empty_column.account_unavailable' defaultMessage='Profile unavailable' />; } else if (remote && statusIds.isEmpty()) { @@ -166,14 +174,14 @@ class AccountTimeline extends ImmutablePureComponent { <ColumnBackButton multiColumn={multiColumn} /> <StatusList - prepend={<HeaderContainer accountId={this.props.accountId} />} + prepend={<HeaderContainer accountId={this.props.accountId} hideTabs={forceEmptyState} />} alwaysPrepend append={remoteMessage} scrollKey='account_timeline' - statusIds={(suspended || blockedBy) ? emptyList : statusIds} + statusIds={forceEmptyState ? emptyList : statusIds} featuredStatusIds={featuredStatusIds} isLoading={isLoading} - hasMore={hasMore} + hasMore={!forceEmptyState && hasMore} onLoadMore={this.handleLoadMore} emptyMessage={emptyMessage} bindToDocument={!multiColumn} diff --git a/app/javascript/mastodon/features/followers/index.js b/app/javascript/mastodon/features/followers/index.js index 224e74b3dd..5b7f402f8d 100644 --- a/app/javascript/mastodon/features/followers/index.js +++ b/app/javascript/mastodon/features/followers/index.js @@ -19,6 +19,8 @@ import ColumnBackButton from '../../components/column_back_button'; import ScrollableList from '../../components/scrollable_list'; import MissingIndicator from 'mastodon/components/missing_indicator'; import TimelineHint from 'mastodon/components/timeline_hint'; +import LimitedAccountHint from '../account_timeline/components/limited_account_hint'; +import { getAccountHidden } from 'mastodon/selectors'; const mapStateToProps = (state, { params: { acct, id } }) => { const accountId = id || state.getIn(['accounts_map', acct]); @@ -37,6 +39,8 @@ const mapStateToProps = (state, { params: { acct, id } }) => { accountIds: state.getIn(['user_lists', 'followers', accountId, 'items']), hasMore: !!state.getIn(['user_lists', 'followers', accountId, 'next']), isLoading: state.getIn(['user_lists', 'followers', accountId, 'isLoading'], true), + suspended: state.getIn(['accounts', accountId, 'suspended'], false), + hidden: getAccountHidden(state, accountId), blockedBy: state.getIn(['relationships', accountId, 'blocked_by'], false), }; }; @@ -64,6 +68,8 @@ class Followers extends ImmutablePureComponent { isLoading: PropTypes.bool, blockedBy: PropTypes.bool, isAccount: PropTypes.bool, + suspended: PropTypes.bool, + hidden: PropTypes.bool, remote: PropTypes.bool, remoteUrl: PropTypes.string, multiColumn: PropTypes.bool, @@ -101,7 +107,7 @@ class Followers extends ImmutablePureComponent { }, 300, { leading: true }); render () { - const { accountIds, hasMore, blockedBy, isAccount, multiColumn, isLoading, remote, remoteUrl } = this.props; + const { accountId, accountIds, hasMore, blockedBy, isAccount, multiColumn, isLoading, suspended, hidden, remote, remoteUrl } = this.props; if (!isAccount) { return ( @@ -121,7 +127,13 @@ class Followers extends ImmutablePureComponent { let emptyMessage; - if (blockedBy) { + const forceEmptyState = blockedBy || suspended || hidden; + + if (suspended) { + emptyMessage = <FormattedMessage id='empty_column.account_suspended' defaultMessage='Account suspended' />; + } else if (hidden) { + emptyMessage = <LimitedAccountHint accountId={accountId} />; + } else if (blockedBy) { emptyMessage = <FormattedMessage id='empty_column.account_unavailable' defaultMessage='Profile unavailable' />; } else if (remote && accountIds.isEmpty()) { emptyMessage = <RemoteHint url={remoteUrl} />; @@ -137,7 +149,7 @@ class Followers extends ImmutablePureComponent { <ScrollableList scrollKey='followers' - hasMore={hasMore} + hasMore={!forceEmptyState && hasMore} isLoading={isLoading} onLoadMore={this.handleLoadMore} prepend={<HeaderContainer accountId={this.props.accountId} hideTabs />} @@ -146,7 +158,7 @@ class Followers extends ImmutablePureComponent { emptyMessage={emptyMessage} bindToDocument={!multiColumn} > - {blockedBy ? [] : accountIds.map(id => + {forceEmptyState ? [] : accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} />, )} </ScrollableList> diff --git a/app/javascript/mastodon/features/following/index.js b/app/javascript/mastodon/features/following/index.js index aadce1644f..143082d760 100644 --- a/app/javascript/mastodon/features/following/index.js +++ b/app/javascript/mastodon/features/following/index.js @@ -19,6 +19,8 @@ import ColumnBackButton from '../../components/column_back_button'; import ScrollableList from '../../components/scrollable_list'; import MissingIndicator from 'mastodon/components/missing_indicator'; import TimelineHint from 'mastodon/components/timeline_hint'; +import LimitedAccountHint from '../account_timeline/components/limited_account_hint'; +import { getAccountHidden } from 'mastodon/selectors'; const mapStateToProps = (state, { params: { acct, id } }) => { const accountId = id || state.getIn(['accounts_map', acct]); @@ -37,6 +39,8 @@ const mapStateToProps = (state, { params: { acct, id } }) => { accountIds: state.getIn(['user_lists', 'following', accountId, 'items']), hasMore: !!state.getIn(['user_lists', 'following', accountId, 'next']), isLoading: state.getIn(['user_lists', 'following', accountId, 'isLoading'], true), + suspended: state.getIn(['accounts', accountId, 'suspended'], false), + hidden: getAccountHidden(state, accountId), blockedBy: state.getIn(['relationships', accountId, 'blocked_by'], false), }; }; @@ -64,6 +68,8 @@ class Following extends ImmutablePureComponent { isLoading: PropTypes.bool, blockedBy: PropTypes.bool, isAccount: PropTypes.bool, + suspended: PropTypes.bool, + hidden: PropTypes.bool, remote: PropTypes.bool, remoteUrl: PropTypes.string, multiColumn: PropTypes.bool, @@ -101,7 +107,7 @@ class Following extends ImmutablePureComponent { }, 300, { leading: true }); render () { - const { accountIds, hasMore, blockedBy, isAccount, multiColumn, isLoading, remote, remoteUrl } = this.props; + const { accountId, accountIds, hasMore, blockedBy, isAccount, multiColumn, isLoading, suspended, hidden, remote, remoteUrl } = this.props; if (!isAccount) { return ( @@ -121,7 +127,13 @@ class Following extends ImmutablePureComponent { let emptyMessage; - if (blockedBy) { + const forceEmptyState = blockedBy || suspended || hidden; + + if (suspended) { + emptyMessage = <FormattedMessage id='empty_column.account_suspended' defaultMessage='Account suspended' />; + } else if (hidden) { + emptyMessage = <LimitedAccountHint accountId={accountId} />; + } else if (blockedBy) { emptyMessage = <FormattedMessage id='empty_column.account_unavailable' defaultMessage='Profile unavailable' />; } else if (remote && accountIds.isEmpty()) { emptyMessage = <RemoteHint url={remoteUrl} />; @@ -137,7 +149,7 @@ class Following extends ImmutablePureComponent { <ScrollableList scrollKey='following' - hasMore={hasMore} + hasMore={!forceEmptyState && hasMore} isLoading={isLoading} onLoadMore={this.handleLoadMore} prepend={<HeaderContainer accountId={this.props.accountId} hideTabs />} @@ -146,7 +158,7 @@ class Following extends ImmutablePureComponent { emptyMessage={emptyMessage} bindToDocument={!multiColumn} > - {blockedBy ? [] : accountIds.map(id => + {forceEmptyState ? [] : accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} />, )} </ScrollableList> diff --git a/app/javascript/mastodon/reducers/accounts.js b/app/javascript/mastodon/reducers/accounts.js index 530ed8e607..b5589668c1 100644 --- a/app/javascript/mastodon/reducers/accounts.js +++ b/app/javascript/mastodon/reducers/accounts.js @@ -1,4 +1,5 @@ -import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from '../actions/importer'; +import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from 'mastodon/actions/importer'; +import { ACCOUNT_REVEAL } from 'mastodon/actions/accounts'; import { Map as ImmutableMap, fromJS } from 'immutable'; const initialState = ImmutableMap(); @@ -10,6 +11,8 @@ const normalizeAccount = (state, account) => { delete account.following_count; delete account.statuses_count; + account.hidden = state.getIn([account.id, 'hidden']) === false ? false : account.limited; + return state.set(account.id, fromJS(account)); }; @@ -27,6 +30,8 @@ export default function accounts(state = initialState, action) { return normalizeAccount(state, action.account); case ACCOUNTS_IMPORT: return normalizeAccounts(state, action.accounts); + case ACCOUNT_REVEAL: + return state.setIn([action.id, 'hidden'], false); default: return state; } diff --git a/app/javascript/mastodon/selectors/index.js b/app/javascript/mastodon/selectors/index.js index 1e19db65d0..3121774b3d 100644 --- a/app/javascript/mastodon/selectors/index.js +++ b/app/javascript/mastodon/selectors/index.js @@ -175,3 +175,11 @@ export const getAccountGallery = createSelector([ return medias; }); + +export const getAccountHidden = createSelector([ + (state, id) => state.getIn(['accounts', id, 'hidden']), + (state, id) => state.getIn(['relationships', id, 'following']) || state.getIn(['relationships', id, 'requested']), + (state, id) => id === me, +], (hidden, followingOrRequested, isSelf) => { + return hidden && !(isSelf || followingOrRequested); +}); diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index b53648ead1..1a1cec6db2 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -4037,6 +4037,15 @@ a.status-card.compact:hover { vertical-align: middle; } +.limited-account-hint { + p { + color: $secondary-text-color; + font-size: 15px; + font-weight: 500; + margin-bottom: 20px; + } +} + .empty-column-indicator, .error-column, .follow_requests-unlocked_explanation { diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb index 4cf7b253fa..c52a89d872 100644 --- a/app/serializers/rest/account_serializer.rb +++ b/app/serializers/rest/account_serializer.rb @@ -13,6 +13,7 @@ class REST::AccountSerializer < ActiveModel::Serializer has_many :emojis, serializer: REST::CustomEmojiSerializer attribute :suspended, if: :suspended? + attribute :silenced, key: :limited, if: :silenced? class FieldSerializer < ActiveModel::Serializer include FormattingHelper @@ -98,7 +99,11 @@ class REST::AccountSerializer < ActiveModel::Serializer object.suspended? end - delegate :suspended?, to: :object + def silenced + object.silenced? + end + + delegate :suspended?, :silenced?, to: :object def moved_and_not_nested? object.moved? && object.moved_to_account.moved_to_account_id.nil? From 385f6e1f39b2cbf79f24d6c046117a9f9aa3d92f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 May 2022 04:00:31 +0900 Subject: [PATCH 06/16] Bump react-select from 5.3.1 to 5.3.2 (#18382) Bumps [react-select](https://github.com/JedWatson/react-select) from 5.3.1 to 5.3.2. - [Release notes](https://github.com/JedWatson/react-select/releases) - [Changelog](https://github.com/JedWatson/react-select/blob/master/docs/CHANGELOG.md) - [Commits](https://github.com/JedWatson/react-select/compare/react-select@5.3.1...react-select@5.3.2) --- updated-dependencies: - dependency-name: react-select dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 17 ++++------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 01f1d116a2..df42cecdc1 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,7 @@ "react-redux-loading-bar": "^4.0.8", "react-router-dom": "^4.1.1", "react-router-scroll-4": "^1.0.0-beta.1", - "react-select": "^5.3.1", + "react-select": "^5.3.2", "react-sparklines": "^1.7.0", "react-swipeable-views": "^0.14.0", "react-textarea-autosize": "^8.3.3", diff --git a/yarn.lock b/yarn.lock index 358ae7de39..96c4883302 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5139,15 +5139,6 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -9245,10 +9236,10 @@ react-router@^4.3.1: prop-types "^15.6.1" warning "^4.0.1" -react-select@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.3.1.tgz#2cb651b71493e494c56f6b4ce40011669b34bd95" - integrity sha512-Y195MmhDoDAj/8gTDyYZU1Raf7tmZd81wxM6RkFko4pqJ4Xv0/ilqUMtSn+GYkwmSlTWeMlzh+e+t7PJgtuXPw== +react-select@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.3.2.tgz#ecee0d5c59ed4acb7f567f7de3c75a488d93dacb" + integrity sha512-W6Irh7U6Ha7p5uQQ2ZnemoCQ8mcfgOtHfw3wuMzG6FAu0P+CYicgofSLOq97BhjMx8jS+h+wwWdCBeVVZ9VqlQ== dependencies: "@babel/runtime" "^7.12.0" "@emotion/cache" "^11.4.0" From 5bedcdbe870c06d721dc9b160d45abe42b941977 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 May 2022 04:01:16 +0900 Subject: [PATCH 07/16] Bump capybara from 3.36.0 to 3.37.1 (#18376) Bumps [capybara](https://github.com/teamcapybara/capybara) from 3.36.0 to 3.37.1. - [Release notes](https://github.com/teamcapybara/capybara/releases) - [Changelog](https://github.com/teamcapybara/capybara/blob/master/History.md) - [Commits](https://github.com/teamcapybara/capybara/compare/3.36.0...3.37.1) --- updated-dependencies: - dependency-name: capybara dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile | 2 +- Gemfile.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index 1c479e6cb9..08137833e1 100644 --- a/Gemfile +++ b/Gemfile @@ -112,7 +112,7 @@ group :production, :test do end group :test do - gem 'capybara', '~> 3.36' + gem 'capybara', '~> 3.37' gem 'climate_control', '~> 0.2' gem 'faker', '~> 2.20' gem 'microformats', '~> 4.2' diff --git a/Gemfile.lock b/Gemfile.lock index d5aa4df067..3404215f3e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -144,7 +144,7 @@ GEM sshkit (~> 1.3) capistrano-yarn (2.0.2) capistrano (~> 3.0) - capybara (3.36.0) + capybara (3.37.1) addressable matrix mini_mime (>= 0.1.3) @@ -467,7 +467,7 @@ GEM pry (~> 0.13.0) pry-rails (0.3.9) pry (>= 0.10.4) - public_suffix (4.0.6) + public_suffix (4.0.7) puma (5.6.4) nio4r (~> 2.0) pundit (2.2.0) @@ -533,7 +533,7 @@ GEM redis (4.5.1) redis-namespace (1.8.2) redis (>= 3.0.4) - regexp_parser (2.3.1) + regexp_parser (2.4.0) request_store (1.5.1) rack (>= 1.4) responders (3.0.1) @@ -742,7 +742,7 @@ DEPENDENCIES capistrano-rails (~> 1.6) capistrano-rbenv (~> 2.2) capistrano-yarn (~> 2.0) - capybara (~> 3.36) + capybara (~> 3.37) charlock_holmes (~> 0.7.7) chewy (~> 7.2) climate_control (~> 0.2) From 85d0e1b31d330cb8c215ca06b6a6d0c9848ff99e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 May 2022 04:01:51 +0900 Subject: [PATCH 08/16] Bump jest-environment-jsdom from 28.0.2 to 28.1.0 (#18379) Bumps [jest-environment-jsdom](https://github.com/facebook/jest/tree/HEAD/packages/jest-environment-jsdom) from 28.0.2 to 28.1.0. - [Release notes](https://github.com/facebook/jest/releases) - [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/jest/commits/v28.1.0/packages/jest-environment-jsdom) --- updated-dependencies: - dependency-name: jest-environment-jsdom dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 101 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 64 insertions(+), 39 deletions(-) diff --git a/package.json b/package.json index df42cecdc1..ab21a0f2ee 100644 --- a/package.json +++ b/package.json @@ -152,7 +152,7 @@ "eslint-plugin-promise": "~6.0.0", "eslint-plugin-react": "~7.29.4", "jest": "^28.0.3", - "jest-environment-jsdom": "^28.0.2", + "jest-environment-jsdom": "^28.1.0", "prettier": "^2.6.2", "raf": "^3.4.1", "react-intl-translations-manager": "^5.0.3", diff --git a/yarn.lock b/yarn.lock index 96c4883302..084e66f405 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1295,15 +1295,15 @@ slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^28.0.2": - version "28.0.2" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-28.0.2.tgz#a865949d876b2d364b979bbc0a46338ffd23de26" - integrity sha512-IvI7dEfqVEffDYlw9FQfVBt6kXt/OI38V7QUIur0ulOQgzpKYJDVvLzj4B1TVmHWTGW5tcnJdlZ3hqzV6/I9Qg== +"@jest/environment@^28.0.2", "@jest/environment@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-28.1.0.tgz#dedf7d59ec341b9292fcf459fd0ed819eb2e228a" + integrity sha512-S44WGSxkRngzHslhV6RoAExekfF7Qhwa6R5+IYFa81mpcj0YgdBnRSmvHe3SNwOt64yXaE5GG8Y2xM28ii5ssA== dependencies: - "@jest/fake-timers" "^28.0.2" - "@jest/types" "^28.0.2" + "@jest/fake-timers" "^28.1.0" + "@jest/types" "^28.1.0" "@types/node" "*" - jest-mock "^28.0.2" + jest-mock "^28.1.0" "@jest/expect-utils@^28.0.2": version "28.0.2" @@ -1320,17 +1320,17 @@ expect "^28.0.2" jest-snapshot "^28.0.3" -"@jest/fake-timers@^28.0.2": - version "28.0.2" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-28.0.2.tgz#d36e62bc58f39d65ea6adac1ff7749e63aff05f3" - integrity sha512-R75yUv+WeybPa4ZVhX9C+8XN0TKjUoceUX+/QEaDVQGxZZOK50eD74cs7iMDTtpodh00d8iLlc9197vgF6oZjA== +"@jest/fake-timers@^28.0.2", "@jest/fake-timers@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-28.1.0.tgz#ea77878aabd5c5d50e1fc53e76d3226101e33064" + integrity sha512-Xqsf/6VLeAAq78+GNPzI7FZQRf5cCHj1qgQxCjws9n8rKw8r1UYoeaALwBvyuzOkpU3c1I6emeMySPa96rxtIg== dependencies: - "@jest/types" "^28.0.2" + "@jest/types" "^28.1.0" "@sinonjs/fake-timers" "^9.1.1" "@types/node" "*" - jest-message-util "^28.0.2" - jest-mock "^28.0.2" - jest-util "^28.0.2" + jest-message-util "^28.1.0" + jest-mock "^28.1.0" + jest-util "^28.1.0" "@jest/globals@^28.0.3": version "28.0.3" @@ -1448,10 +1448,10 @@ "@types/yargs" "^16.0.0" chalk "^4.0.0" -"@jest/types@^28.0.2": - version "28.0.2" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.0.2.tgz#70b9538c1863fb060b2f438ca008b5563d00c5b4" - integrity sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A== +"@jest/types@^28.0.2", "@jest/types@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.0.tgz#508327a89976cbf9bd3e1cc74641a29fd7dfd519" + integrity sha512-xmEggMPr317MIOjjDoZ4ejCSr9Lpbt/u34+dvc99t7DS8YirW5rwZEhzKPC2BMUFkUhI48qs6qLUSGw5FuL0GA== dependencies: "@jest/schemas" "^28.0.2" "@types/istanbul-lib-coverage" "^2.0.0" @@ -6568,18 +6568,18 @@ jest-each@^28.0.2: jest-util "^28.0.2" pretty-format "^28.0.2" -jest-environment-jsdom@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-28.0.2.tgz#b923f861f4cd896d2ba1971255060e1f413e9a04" - integrity sha512-rQhgV9reB6Id7VPa5jEkKx80Ppa/I6C7vKTMnceBS+d/rt+aTfbxbK/P4HRLMLE8KKsETszPpzYtGgsa8xMg7g== +jest-environment-jsdom@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-28.1.0.tgz#1042cffd0343615c5fac2d2c8da20d1d43b73ef8" + integrity sha512-8n6P4xiDjNVqTWv6W6vJPuQdLx+ZiA3dbYg7YJ+DPzR+9B61K6pMVJrSs2IxfGRG4J7pyAUA5shQ9G0KEun78w== dependencies: - "@jest/environment" "^28.0.2" - "@jest/fake-timers" "^28.0.2" - "@jest/types" "^28.0.2" + "@jest/environment" "^28.1.0" + "@jest/fake-timers" "^28.1.0" + "@jest/types" "^28.1.0" "@types/jsdom" "^16.2.4" "@types/node" "*" - jest-mock "^28.0.2" - jest-util "^28.0.2" + jest-mock "^28.1.0" + jest-util "^28.1.0" jsdom "^19.0.0" jest-environment-node@^28.0.2: @@ -6656,12 +6656,27 @@ jest-message-util@^28.0.2: slash "^3.0.0" stack-utils "^2.0.3" -jest-mock@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-28.0.2.tgz#059b500b34c1dd76474ebcdeccc249fe4dd0249f" - integrity sha512-vfnJ4zXRB0i24jOTGtQJyl26JKsgBKtqRlCnsrORZbG06FToSSn33h2x/bmE8XxqxkLWdZBRo+/65l8Vi3nD+g== +jest-message-util@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.0.tgz#7e8f0b9049e948e7b94c2a52731166774ba7d0af" + integrity sha512-RpA8mpaJ/B2HphDMiDlrAZdDytkmwFqgjDZovM21F35lHGeUeCvYmm6W+sbQ0ydaLpg5bFAUuWG1cjqOl8vqrw== dependencies: - "@jest/types" "^28.0.2" + "@babel/code-frame" "^7.12.13" + "@jest/types" "^28.1.0" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^28.1.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^28.0.2, jest-mock@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-28.1.0.tgz#ccc7cc12a9b330b3182db0c651edc90d163ff73e" + integrity sha512-H7BrhggNn77WhdL7O1apG0Q/iwl0Bdd5E1ydhCJzL3oBLh/UYxAwR3EJLsBZ9XA3ZU4PA3UNw4tQjduBTCTmLw== + dependencies: + "@jest/types" "^28.1.0" "@types/node" "*" jest-pnp-resolver@^1.2.2: @@ -6781,12 +6796,12 @@ jest-snapshot@^28.0.3: pretty-format "^28.0.2" semver "^7.3.5" -jest-util@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.0.2.tgz#8e22cdd6e0549e0a393055f0e2da7eacc334b143" - integrity sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA== +jest-util@^28.0.2, jest-util@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.0.tgz#d54eb83ad77e1dd441408738c5a5043642823be5" + integrity sha512-qYdCKD77k4Hwkose2YBEqQk7PzUf/NSE+rutzceduFveQREeH6b+89Dc9+wjX9dAwHcgdx4yedGA3FQlU/qCTA== dependencies: - "@jest/types" "^28.0.2" + "@jest/types" "^28.1.0" "@types/node" "*" chalk "^4.0.0" ci-info "^3.2.0" @@ -8858,6 +8873,16 @@ pretty-format@^28.0.2: ansi-styles "^5.0.0" react-is "^18.0.0" +pretty-format@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.0.tgz#8f5836c6a0dfdb834730577ec18029052191af55" + integrity sha512-79Z4wWOYCdvQkEoEuSlBhHJqWeZ8D8YRPiPctJFCtvuaClGpiwiQYSCUOE6IEKUbbFukKOTFIUAXE8N4EQTo1Q== + dependencies: + "@jest/schemas" "^28.0.2" + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^18.0.0" + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" From cc9d618428b416f096693e0bb00eaaea8ac61e45 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 May 2022 04:02:08 +0900 Subject: [PATCH 09/16] Bump babel-jest from 28.0.3 to 28.1.0 (#18374) Bumps [babel-jest](https://github.com/facebook/jest/tree/HEAD/packages/babel-jest) from 28.0.3 to 28.1.0. - [Release notes](https://github.com/facebook/jest/releases) - [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/jest/commits/v28.1.0/packages/babel-jest) --- updated-dependencies: - dependency-name: babel-jest dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 76 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index ab21a0f2ee..6396371cac 100644 --- a/package.json +++ b/package.json @@ -145,7 +145,7 @@ "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^12.1.5", "babel-eslint": "^10.1.0", - "babel-jest": "^28.0.3", + "babel-jest": "^28.1.0", "eslint": "^7.32.0", "eslint-plugin-import": "~2.26.0", "eslint-plugin-jsx-a11y": "~6.5.1", diff --git a/yarn.lock b/yarn.lock index 084e66f405..9c44d65549 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1406,22 +1406,22 @@ jest-haste-map "^28.0.2" slash "^3.0.0" -"@jest/transform@^28.0.3": - version "28.0.3" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-28.0.3.tgz#591fb5ebc1d84db5c5f21e1225c7406c35f5eb1e" - integrity sha512-+Y0ikI7SwoW/YbK8t9oKwC70h4X2Gd0OVuz5tctRvSV/EDQU00AAkoqevXgPSSFimUmp/sp7Yl8s/1bExDqOIg== +"@jest/transform@^28.0.3", "@jest/transform@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-28.1.0.tgz#224a3c9ba4cc98e2ff996c0a89a2d59db15c74ce" + integrity sha512-omy2xe5WxlAfqmsTjTPxw+iXRTRnf+NtX0ToG+4S0tABeb4KsKmPUHq5UBuwunHg3tJRwgEQhEp0M/8oiatLEA== dependencies: "@babel/core" "^7.11.6" - "@jest/types" "^28.0.2" + "@jest/types" "^28.1.0" "@jridgewell/trace-mapping" "^0.3.7" babel-plugin-istanbul "^6.1.1" chalk "^4.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.2.9" - jest-haste-map "^28.0.2" + jest-haste-map "^28.1.0" jest-regex-util "^28.0.2" - jest-util "^28.0.2" + jest-util "^28.1.0" micromatch "^4.0.4" pirates "^4.0.4" slash "^3.0.0" @@ -1460,6 +1460,18 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" +"@jest/types@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.0.tgz#508327a89976cbf9bd3e1cc74641a29fd7dfd519" + integrity sha512-xmEggMPr317MIOjjDoZ4ejCSr9Lpbt/u34+dvc99t7DS8YirW5rwZEhzKPC2BMUFkUhI48qs6qLUSGw5FuL0GA== + dependencies: + "@jest/schemas" "^28.0.2" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" @@ -2474,12 +2486,12 @@ babel-eslint@^10.1.0: eslint-visitor-keys "^1.0.0" resolve "^1.12.0" -babel-jest@^28.0.3: - version "28.0.3" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-28.0.3.tgz#843dc170da5b9671d4054ada9fdcd28f85f92a6e" - integrity sha512-S0ADyYdcrt5fp9YldRYWCUHdk1BKt9AkvBkLWBoNAEV9NoWZPIj5+MYhPcGgTS65mfv3a+Ymf2UqgWoAVd41cA== +babel-jest@^28.0.3, babel-jest@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-28.1.0.tgz#95a67f8e2e7c0042e7b3ad3951b8af41a533b5ea" + integrity sha512-zNKk0yhDZ6QUwfxh9k07GII6siNGMJWVUU49gmFj5gfdqDKLqa2RArXOF2CODp4Dr7dLxN2cvAV+667dGJ4b4w== dependencies: - "@jest/transform" "^28.0.3" + "@jest/transform" "^28.1.0" "@types/babel__core" "^7.1.14" babel-plugin-istanbul "^6.1.1" babel-preset-jest "^28.0.2" @@ -6623,6 +6635,25 @@ jest-haste-map@^28.0.2: optionalDependencies: fsevents "^2.3.2" +jest-haste-map@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-28.1.0.tgz#6c1ee2daf1c20a3e03dbd8e5b35c4d73d2349cf0" + integrity sha512-xyZ9sXV8PtKi6NCrJlmq53PyNVHzxmcfXNVvIRHpHmh1j/HChC4pwKgyjj7Z9us19JMw8PpQTJsFWOsIfT93Dw== + dependencies: + "@jest/types" "^28.1.0" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^28.0.2" + jest-util "^28.1.0" + jest-worker "^28.1.0" + micromatch "^4.0.4" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.3.2" + jest-leak-detector@^28.0.2: version "28.0.2" resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-28.0.2.tgz#cbde3d22d09bd690ececdc2ed01c608435328456" @@ -6808,6 +6839,18 @@ jest-util@^28.0.2, jest-util@^28.1.0: graceful-fs "^4.2.9" picomatch "^2.2.3" +jest-util@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.0.tgz#d54eb83ad77e1dd441408738c5a5043642823be5" + integrity sha512-qYdCKD77k4Hwkose2YBEqQk7PzUf/NSE+rutzceduFveQREeH6b+89Dc9+wjX9dAwHcgdx4yedGA3FQlU/qCTA== + dependencies: + "@jest/types" "^28.1.0" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + jest-validate@^28.0.2: version "28.0.2" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-28.0.2.tgz#58bb7e826c054a8bb3b54c05f73758d96cf6dbef" @@ -6852,6 +6895,15 @@ jest-worker@^28.0.2: merge-stream "^2.0.0" supports-color "^8.0.0" +jest-worker@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-28.1.0.tgz#ced54757a035e87591e1208253a6e3aac1a855e5" + integrity sha512-ZHwM6mNwaWBR52Snff8ZvsCTqQsvhCxP/bT1I6T6DAnb6ygkshsyLQIMxFwHpYxht0HOoqt23JlC01viI7T03A== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + jest@^28.0.3: version "28.0.3" resolved "https://registry.yarnpkg.com/jest/-/jest-28.0.3.tgz#92a7d6ee097b61de4ba2db7f3ab723e81a99b32d" From 1dbf9ed6557775b61ca956446962d41b538d51f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 May 2022 04:04:12 +0900 Subject: [PATCH 10/16] Bump i18n-tasks from 1.0.9 to 1.0.10 (#18370) Bumps [i18n-tasks](https://github.com/glebm/i18n-tasks) from 1.0.9 to 1.0.10. - [Release notes](https://github.com/glebm/i18n-tasks/releases) - [Changelog](https://github.com/glebm/i18n-tasks/blob/main/CHANGES.md) - [Commits](https://github.com/glebm/i18n-tasks/compare/v1.0.9...v1.0.10) --- updated-dependencies: - dependency-name: i18n-tasks dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3404215f3e..d29c6711fe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -306,7 +306,7 @@ GEM rainbow (>= 2.0.0) i18n (1.10.0) concurrent-ruby (~> 1.0) - i18n-tasks (1.0.9) + i18n-tasks (1.0.10) activesupport (>= 4.0.2) ast (>= 2.1.0) better_html (~> 1.0) From 1a6ac50f319d940e6d3ed69dda4f245f6e958e14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 May 2022 04:08:27 +0900 Subject: [PATCH 11/16] Bump array-includes from 3.1.4 to 3.1.5 (#18381) Bumps [array-includes](https://github.com/es-shims/array-includes) from 3.1.4 to 3.1.5. - [Release notes](https://github.com/es-shims/array-includes/releases) - [Changelog](https://github.com/es-shims/array-includes/blob/main/CHANGELOG.md) - [Commits](https://github.com/es-shims/array-includes/compare/v3.1.4...v3.1.5) --- updated-dependencies: - dependency-name: array-includes dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 168 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 107 insertions(+), 63 deletions(-) diff --git a/package.json b/package.json index 6396371cac..6c45fa3bee 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@gamestdio/websocket": "^0.3.2", "@github/webauthn-json": "^0.5.7", "@rails/ujs": "^6.1.5", - "array-includes": "^3.1.4", + "array-includes": "^3.1.5", "arrow-key-navigation": "^1.2.0", "autoprefixer": "^9.8.8", "axios": "^0.27.2", diff --git a/yarn.lock b/yarn.lock index 9c44d65549..a2eedf81a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2332,14 +2332,14 @@ array-flatten@^2.1.0: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== -array-includes@^3.1.3, array-includes@^3.1.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9" - integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== +array-includes@^3.1.3, array-includes@^3.1.4, array-includes@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb" + integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + define-properties "^1.1.4" + es-abstract "^1.19.5" get-intrinsic "^1.1.1" is-string "^1.0.7" @@ -3981,12 +3981,13 @@ default-gateway@^4.2.0: execa "^1.0.0" ip-regex "^2.1.0" -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== +define-properties@^1.1.3, define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== dependencies: - object-keys "^1.0.12" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" define-property@^0.2.5: version "0.2.5" @@ -4355,31 +4356,34 @@ error-stack-parser@^2.0.6: dependencies: stackframe "^1.1.1" -es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1, es-abstract@^1.19.0, es-abstract@^1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" - integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== +es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1, es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.5: + version "1.20.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.0.tgz#b2d526489cceca004588296334726329e0a6bfb6" + integrity sha512-URbD8tgRthKD3YcC39vbvSDrX23upXnPcnGAjQfgxXF5ID75YcENawc9ZX/9iTP9ptUyfCLIxTTuMYoRfiOVKA== dependencies: call-bind "^1.0.2" es-to-primitive "^1.2.1" function-bind "^1.1.1" + function.prototype.name "^1.1.5" get-intrinsic "^1.1.1" get-symbol-description "^1.0.0" has "^1.0.3" - has-symbols "^1.0.2" + has-property-descriptors "^1.0.0" + has-symbols "^1.0.3" internal-slot "^1.0.3" is-callable "^1.2.4" - is-negative-zero "^2.0.1" + is-negative-zero "^2.0.2" is-regex "^1.1.4" - is-shared-array-buffer "^1.0.1" + is-shared-array-buffer "^1.0.2" is-string "^1.0.7" - is-weakref "^1.0.1" - object-inspect "^1.11.0" + is-weakref "^1.0.2" + object-inspect "^1.12.0" object-keys "^1.1.1" object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" + regexp.prototype.flags "^1.4.1" + string.prototype.trimend "^1.0.5" + string.prototype.trimstart "^1.0.5" + unbox-primitive "^1.0.2" es-to-primitive@^1.2.1: version "1.2.1" @@ -5241,11 +5245,26 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + gauge@^4.0.3: version "4.0.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" @@ -5483,10 +5502,10 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== +has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== has-flag@^1.0.0: version "1.0.0" @@ -5503,6 +5522,13 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" @@ -5513,6 +5539,11 @@ has-symbols@^1.0.2: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + has-tostringtag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" @@ -6248,10 +6279,10 @@ is-nan@^1.3.2: call-bind "^1.0.0" define-properties "^1.1.3" -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== is-number-object@^1.0.4: version "1.0.5" @@ -6331,10 +6362,12 @@ is-resolvable@^1.0.0: resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== -is-shared-array-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" - integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" is-stream@^1.1.0: version "1.1.0" @@ -6372,12 +6405,12 @@ is-url@^1.2.4: resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== -is-weakref@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.1.tgz#842dba4ec17fa9ac9850df2d6efbc1737274f2a2" - integrity sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ== +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" @@ -7891,10 +7924,10 @@ object-fit-images@^3.2.3: resolved "https://registry.yarnpkg.com/object-fit-images/-/object-fit-images-3.2.4.tgz#6c299d38fdf207746e5d2d46c2877f6f25d15b52" integrity sha512-G+7LzpYfTfqUyrZlfrou/PLLLAPNC52FTy5y1CBywX+1/FkxIloOyQXBmZ3Zxa2AWO+lMF0JTuvqbr7G5e5CWg== -object-inspect@^1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" - integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== +object-inspect@^1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" + integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== object-inspect@^1.9.0: version "1.9.0" @@ -7909,7 +7942,7 @@ object-is@^1.0.1: define-properties "^1.1.3" es-abstract "^1.18.0-next.1" -object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -9573,6 +9606,15 @@ regexp.prototype.flags@^1.3.1: call-bind "^1.0.2" define-properties "^1.1.3" +regexp.prototype.flags@^1.4.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + regexpp@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" @@ -10522,21 +10564,23 @@ string.prototype.matchall@^4.0.6: regexp.prototype.flags "^1.3.1" side-channel "^1.0.4" -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== +string.prototype.trimend@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" + integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" + define-properties "^1.1.4" + es-abstract "^1.19.5" -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== +string.prototype.trimstart@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" + integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" + define-properties "^1.1.4" + es-abstract "^1.19.5" string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" @@ -11097,14 +11141,14 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" unicode-canonical-property-names-ecmascript@^1.0.4: From 2b7bdfa48216be1a9c84b8497ad726d7cb378a42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 May 2022 04:09:31 +0900 Subject: [PATCH 12/16] Bump sidekiq-unique-jobs from 7.1.21 to 7.1.22 (#18375) Bumps [sidekiq-unique-jobs](https://github.com/mhenrixon/sidekiq-unique-jobs) from 7.1.21 to 7.1.22. - [Release notes](https://github.com/mhenrixon/sidekiq-unique-jobs/releases) - [Changelog](https://github.com/mhenrixon/sidekiq-unique-jobs/blob/main/CHANGELOG.md) - [Commits](https://github.com/mhenrixon/sidekiq-unique-jobs/compare/v7.1.21...v7.1.22) --- updated-dependencies: - dependency-name: sidekiq-unique-jobs dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index d29c6711fe..342fe635e3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -611,7 +611,7 @@ GEM rufus-scheduler (~> 3.2) sidekiq (>= 4) tilt (>= 1.4.0) - sidekiq-unique-jobs (7.1.21) + sidekiq-unique-jobs (7.1.22) brpoplpush-redis_script (> 0.1.1, <= 2.0.0) concurrent-ruby (~> 1.0, >= 1.0.5) sidekiq (>= 5.0, < 8.0) From 1d596da25cd53217b82207410e8250014065dac2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 May 2022 04:15:04 +0900 Subject: [PATCH 13/16] Bump jest from 28.0.3 to 28.1.0 (#18377) Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 28.0.3 to 28.1.0. - [Release notes](https://github.com/facebook/jest/releases) - [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/jest/commits/v28.1.0/packages/jest) --- updated-dependencies: - dependency-name: jest dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 538 ++++++++++++++++++++++----------------------------- 2 files changed, 232 insertions(+), 308 deletions(-) diff --git a/package.json b/package.json index 6c45fa3bee..2691a3596c 100644 --- a/package.json +++ b/package.json @@ -151,7 +151,7 @@ "eslint-plugin-jsx-a11y": "~6.5.1", "eslint-plugin-promise": "~6.0.0", "eslint-plugin-react": "~7.29.4", - "jest": "^28.0.3", + "jest": "^28.1.0", "jest-environment-jsdom": "^28.1.0", "prettier": "^2.6.2", "raf": "^3.4.1", diff --git a/yarn.lock b/yarn.lock index a2eedf81a3..750104421d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1248,28 +1248,28 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@jest/console@^28.0.2": - version "28.0.2" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-28.0.2.tgz#d11e8b43ae431ae9b3112656848417ae4008fcad" - integrity sha512-tiRpnMeeyQuuzgL5UNSeiqMwF8UOWPbAE5rzcu/1zyq4oPG2Ox6xm4YCOruwbp10F8odWc+XwVxTyGzMSLMqxA== +"@jest/console@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-28.1.0.tgz#db78222c3d3b0c1db82f1b9de51094c2aaff2176" + integrity sha512-tscn3dlJFGay47kb4qVruQg/XWlmvU0xp3EJOjzzY+sBaI+YgwKcvAmTcyYU7xEiLLIY5HCdWRooAL8dqkFlDA== dependencies: - "@jest/types" "^28.0.2" + "@jest/types" "^28.1.0" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^28.0.2" - jest-util "^28.0.2" + jest-message-util "^28.1.0" + jest-util "^28.1.0" slash "^3.0.0" -"@jest/core@^28.0.3": - version "28.0.3" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-28.0.3.tgz#2b8223914ef6ae16ff740e65235ef8ef49c46d52" - integrity sha512-cCQW06vEZ+5r50SB06pOnSWsOBs7F+lswPYnKKfBz1ncLlj1sMqmvjgam8q40KhlZ8Ut4eNAL2Hvfx4BKIO2FA== +"@jest/core@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-28.1.0.tgz#784a1e6ce5358b46fcbdcfbbd93b1b713ed4ea80" + integrity sha512-/2PTt0ywhjZ4NwNO4bUqD9IVJfmFVhVKGlhvSpmEfUCuxYf/3NHcKmRFI+I71lYzbTT3wMuYpETDCTHo81gC/g== dependencies: - "@jest/console" "^28.0.2" - "@jest/reporters" "^28.0.3" - "@jest/test-result" "^28.0.2" - "@jest/transform" "^28.0.3" - "@jest/types" "^28.0.2" + "@jest/console" "^28.1.0" + "@jest/reporters" "^28.1.0" + "@jest/test-result" "^28.1.0" + "@jest/transform" "^28.1.0" + "@jest/types" "^28.1.0" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" @@ -1277,25 +1277,25 @@ exit "^0.1.2" graceful-fs "^4.2.9" jest-changed-files "^28.0.2" - jest-config "^28.0.3" - jest-haste-map "^28.0.2" - jest-message-util "^28.0.2" + jest-config "^28.1.0" + jest-haste-map "^28.1.0" + jest-message-util "^28.1.0" jest-regex-util "^28.0.2" - jest-resolve "^28.0.3" - jest-resolve-dependencies "^28.0.3" - jest-runner "^28.0.3" - jest-runtime "^28.0.3" - jest-snapshot "^28.0.3" - jest-util "^28.0.2" - jest-validate "^28.0.2" - jest-watcher "^28.0.2" + jest-resolve "^28.1.0" + jest-resolve-dependencies "^28.1.0" + jest-runner "^28.1.0" + jest-runtime "^28.1.0" + jest-snapshot "^28.1.0" + jest-util "^28.1.0" + jest-validate "^28.1.0" + jest-watcher "^28.1.0" micromatch "^4.0.4" - pretty-format "^28.0.2" + pretty-format "^28.1.0" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^28.0.2", "@jest/environment@^28.1.0": +"@jest/environment@^28.1.0": version "28.1.0" resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-28.1.0.tgz#dedf7d59ec341b9292fcf459fd0ed819eb2e228a" integrity sha512-S44WGSxkRngzHslhV6RoAExekfF7Qhwa6R5+IYFa81mpcj0YgdBnRSmvHe3SNwOt64yXaE5GG8Y2xM28ii5ssA== @@ -1305,22 +1305,22 @@ "@types/node" "*" jest-mock "^28.1.0" -"@jest/expect-utils@^28.0.2": - version "28.0.2" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.0.2.tgz#0a055868d225261eac82a12013e2e0735238774d" - integrity sha512-YryfH2zN5c7M8eLtn9oTBRj1sfD+X4cHNXJnTejqCveOS33wADEZUxJ7de5++lRvByNpRpfAnc8zTK7yrUJqgA== +"@jest/expect-utils@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.0.tgz#a5cde811195515a9809b96748ae8bcc331a3538a" + integrity sha512-5BrG48dpC0sB80wpeIX5FU6kolDJI4K0n5BM9a5V38MGx0pyRvUBSS0u2aNTdDzmOrCjhOg8pGs6a20ivYkdmw== dependencies: jest-get-type "^28.0.2" -"@jest/expect@^28.0.3": - version "28.0.3" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-28.0.3.tgz#80e0233bee62586e1112f904d28b904dd1143ef2" - integrity sha512-VEzZr85bqNomgayQkR7hWG5HnbZYWYWagQriZsixhLmOzU6PCpMP61aeVhkCoRrg7ri5f7JDpeTPzDAajIwFHw== +"@jest/expect@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-28.1.0.tgz#2e5a31db692597070932366a1602b5157f0f217c" + integrity sha512-be9ETznPLaHOmeJqzYNIXv1ADEzENuQonIoobzThOYPuK/6GhrWNIJDVTgBLCrz3Am73PyEU2urQClZp0hLTtA== dependencies: - expect "^28.0.2" - jest-snapshot "^28.0.3" + expect "^28.1.0" + jest-snapshot "^28.1.0" -"@jest/fake-timers@^28.0.2", "@jest/fake-timers@^28.1.0": +"@jest/fake-timers@^28.1.0": version "28.1.0" resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-28.1.0.tgz#ea77878aabd5c5d50e1fc53e76d3226101e33064" integrity sha512-Xqsf/6VLeAAq78+GNPzI7FZQRf5cCHj1qgQxCjws9n8rKw8r1UYoeaALwBvyuzOkpU3c1I6emeMySPa96rxtIg== @@ -1332,25 +1332,25 @@ jest-mock "^28.1.0" jest-util "^28.1.0" -"@jest/globals@^28.0.3": - version "28.0.3" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-28.0.3.tgz#70f68a06c863d1c9d14aea151c69b9690e3efeb4" - integrity sha512-q/zXYI6CKtTSIt1WuTHBYizJhH7K8h+xG5PE3C0oawLlPIvUMDYmpj0JX0XsJwPRLCsz/fYXHZVG46AaEhSPmw== +"@jest/globals@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-28.1.0.tgz#a4427d2eb11763002ff58e24de56b84ba79eb793" + integrity sha512-3m7sTg52OTQR6dPhsEQSxAvU+LOBbMivZBwOvKEZ+Rb+GyxVnXi9HKgOTYkx/S99T8yvh17U4tNNJPIEQmtwYw== dependencies: - "@jest/environment" "^28.0.2" - "@jest/expect" "^28.0.3" - "@jest/types" "^28.0.2" + "@jest/environment" "^28.1.0" + "@jest/expect" "^28.1.0" + "@jest/types" "^28.1.0" -"@jest/reporters@^28.0.3": - version "28.0.3" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-28.0.3.tgz#9996189e5552e37fcdffe0f41c07754f5d2ea854" - integrity sha512-xrbIc7J/xwo+D7AY3enAR9ZWYCmJ8XIkstTukTGpKDph0gLl/TJje9jl3dssvE4KJzYqMKiSrnE5Nt68I4fTEg== +"@jest/reporters@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-28.1.0.tgz#5183a28b9b593b6000fa9b89b031c7216b58a9a0" + integrity sha512-qxbFfqap/5QlSpIizH9c/bFCDKsQlM4uAKSOvZrP+nIdrjqre3FmKzpTtYyhsaVcOSNK7TTt2kjm+4BJIjysFA== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^28.0.2" - "@jest/test-result" "^28.0.2" - "@jest/transform" "^28.0.3" - "@jest/types" "^28.0.2" + "@jest/console" "^28.1.0" + "@jest/test-result" "^28.1.0" + "@jest/transform" "^28.1.0" + "@jest/types" "^28.1.0" "@jridgewell/trace-mapping" "^0.3.7" "@types/node" "*" chalk "^4.0.0" @@ -1363,10 +1363,11 @@ istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.1.3" - jest-util "^28.0.2" - jest-worker "^28.0.2" + jest-util "^28.1.0" + jest-worker "^28.1.0" slash "^3.0.0" string-length "^4.0.1" + strip-ansi "^6.0.0" terminal-link "^2.0.0" v8-to-istanbul "^9.0.0" @@ -1386,27 +1387,27 @@ callsites "^3.0.0" graceful-fs "^4.2.9" -"@jest/test-result@^28.0.2": - version "28.0.2" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-28.0.2.tgz#bc8e15a95347e3c2149572ae06a5a6fed939c522" - integrity sha512-4EUqgjq9VzyUiVTvZfI9IRJD6t3NYBNP4f+Eq8Zr93+hkJ0RrGU4OBTw8tfNzidKX+bmuYzn8FxqpxOPIGGCMA== +"@jest/test-result@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-28.1.0.tgz#fd149dee123510dd2fcadbbf5f0020f98ad7f12c" + integrity sha512-sBBFIyoPzrZho3N+80P35A5oAkSKlGfsEFfXFWuPGBsW40UAjCkGakZhn4UQK4iQlW2vgCDMRDOob9FGKV8YoQ== dependencies: - "@jest/console" "^28.0.2" - "@jest/types" "^28.0.2" + "@jest/console" "^28.1.0" + "@jest/types" "^28.1.0" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^28.0.2": - version "28.0.2" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-28.0.2.tgz#7669b7d8ff2aa7a8221b11bb37cce552de81b1bb" - integrity sha512-zhnZ8ydkZQTPL7YucB86eOlD79zPy5EGSUKiR2Iv93RVEDU6OEP33kwDBg70ywOcxeJGDRhyo09q7TafNCBiIg== +"@jest/test-sequencer@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-28.1.0.tgz#ce7294bbe986415b9a30e218c7e705e6ebf2cdf2" + integrity sha512-tZCEiVWlWNTs/2iK9yi6o3AlMfbbYgV4uuZInSVdzZ7ftpHZhCMuhvk2HLYhCZzLgPFQ9MnM1YaxMnh3TILFiQ== dependencies: - "@jest/test-result" "^28.0.2" + "@jest/test-result" "^28.1.0" graceful-fs "^4.2.9" - jest-haste-map "^28.0.2" + jest-haste-map "^28.1.0" slash "^3.0.0" -"@jest/transform@^28.0.3", "@jest/transform@^28.1.0": +"@jest/transform@^28.1.0": version "28.1.0" resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-28.1.0.tgz#224a3c9ba4cc98e2ff996c0a89a2d59db15c74ce" integrity sha512-omy2xe5WxlAfqmsTjTPxw+iXRTRnf+NtX0ToG+4S0tABeb4KsKmPUHq5UBuwunHg3tJRwgEQhEp0M/8oiatLEA== @@ -1448,18 +1449,6 @@ "@types/yargs" "^16.0.0" chalk "^4.0.0" -"@jest/types@^28.0.2", "@jest/types@^28.1.0": - version "28.1.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.0.tgz#508327a89976cbf9bd3e1cc74641a29fd7dfd519" - integrity sha512-xmEggMPr317MIOjjDoZ4ejCSr9Lpbt/u34+dvc99t7DS8YirW5rwZEhzKPC2BMUFkUhI48qs6qLUSGw5FuL0GA== - dependencies: - "@jest/schemas" "^28.0.2" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - "@jest/types@^28.1.0": version "28.1.0" resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.0.tgz#508327a89976cbf9bd3e1cc74641a29fd7dfd519" @@ -2486,7 +2475,7 @@ babel-eslint@^10.1.0: eslint-visitor-keys "^1.0.0" resolve "^1.12.0" -babel-jest@^28.0.3, babel-jest@^28.1.0: +babel-jest@^28.1.0: version "28.1.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-28.1.0.tgz#95a67f8e2e7c0042e7b3ad3951b8af41a533b5ea" integrity sha512-zNKk0yhDZ6QUwfxh9k07GII6siNGMJWVUU49gmFj5gfdqDKLqa2RArXOF2CODp4Dr7dLxN2cvAV+667dGJ4b4w== @@ -4856,16 +4845,16 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" -expect@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/expect/-/expect-28.0.2.tgz#86f0d6fa971bc533faf68d4d103d00f343d6a4b3" - integrity sha512-X0qIuI/zKv98k34tM+uGeOgAC73lhs4vROF9MkPk94C1zujtwv4Cla8SxhWn0G1OwvG9gLLL7RjFBkwGVaZ83w== +expect@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-28.1.0.tgz#10e8da64c0850eb8c39a480199f14537f46e8360" + integrity sha512-qFXKl8Pmxk8TBGfaFKRtcQjfXEnKAs+dmlxdwvukJZorwrAabT7M3h8oLOG01I2utEhkmUTi17CHaPBovZsKdw== dependencies: - "@jest/expect-utils" "^28.0.2" + "@jest/expect-utils" "^28.1.0" jest-get-type "^28.0.2" - jest-matcher-utils "^28.0.2" - jest-message-util "^28.0.2" - jest-util "^28.0.2" + jest-matcher-utils "^28.1.0" + jest-message-util "^28.1.0" + jest-util "^28.1.0" express@^4.17.1, express@^4.18.1: version "4.18.1" @@ -6504,74 +6493,74 @@ jest-changed-files@^28.0.2: execa "^5.0.0" throat "^6.0.1" -jest-circus@^28.0.3: - version "28.0.3" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-28.0.3.tgz#45f77090b4b9fe5c1b84f72816868c9d4c0f57b1" - integrity sha512-HJ3rUCm3A3faSy7KVH5MFCncqJLtrjEFkTPn9UIcs4Kq77+TXqHsOaI+/k73aHe6DJQigLUXq9rCYj3MYFlbIw== +jest-circus@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-28.1.0.tgz#e229f590911bd54d60efaf076f7acd9360296dae" + integrity sha512-rNYfqfLC0L0zQKRKsg4n4J+W1A2fbyGH7Ss/kDIocp9KXD9iaL111glsLu7+Z7FHuZxwzInMDXq+N1ZIBkI/TQ== dependencies: - "@jest/environment" "^28.0.2" - "@jest/expect" "^28.0.3" - "@jest/test-result" "^28.0.2" - "@jest/types" "^28.0.2" + "@jest/environment" "^28.1.0" + "@jest/expect" "^28.1.0" + "@jest/test-result" "^28.1.0" + "@jest/types" "^28.1.0" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" dedent "^0.7.0" is-generator-fn "^2.0.0" - jest-each "^28.0.2" - jest-matcher-utils "^28.0.2" - jest-message-util "^28.0.2" - jest-runtime "^28.0.3" - jest-snapshot "^28.0.3" - jest-util "^28.0.2" - pretty-format "^28.0.2" + jest-each "^28.1.0" + jest-matcher-utils "^28.1.0" + jest-message-util "^28.1.0" + jest-runtime "^28.1.0" + jest-snapshot "^28.1.0" + jest-util "^28.1.0" + pretty-format "^28.1.0" slash "^3.0.0" stack-utils "^2.0.3" throat "^6.0.1" -jest-cli@^28.0.3: - version "28.0.3" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-28.0.3.tgz#4a4e55078ec772e0ea2583dd4c4b38fb306dc556" - integrity sha512-NCPTEONCnhYGo1qzPP4OOcGF04YasM5GZSwQLI1HtEluxa3ct4U65IbZs6DSRt8XN1Rq0jhXwv02m5lHB28Uyg== +jest-cli@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-28.1.0.tgz#cd1d8adb9630102d5ba04a22895f63decdd7ac1f" + integrity sha512-fDJRt6WPRriHrBsvvgb93OxgajHHsJbk4jZxiPqmZbMDRcHskfJBBfTyjFko0jjfprP544hOktdSi9HVgl4VUQ== dependencies: - "@jest/core" "^28.0.3" - "@jest/test-result" "^28.0.2" - "@jest/types" "^28.0.2" + "@jest/core" "^28.1.0" + "@jest/test-result" "^28.1.0" + "@jest/types" "^28.1.0" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.9" import-local "^3.0.2" - jest-config "^28.0.3" - jest-util "^28.0.2" - jest-validate "^28.0.2" + jest-config "^28.1.0" + jest-util "^28.1.0" + jest-validate "^28.1.0" prompts "^2.0.1" yargs "^17.3.1" -jest-config@^28.0.3: - version "28.0.3" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-28.0.3.tgz#9c0556d60d692153a6bc8652974182c22db9244f" - integrity sha512-3gWOEHwGpNhyYOk9vnUMv94x15QcdjACm7A3lERaluwnyD6d1WZWe9RFCShgIXVOHzRfG1hWxsI2U0gKKSGgDQ== +jest-config@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-28.1.0.tgz#fca22ca0760e746fe1ce1f9406f6b307ab818501" + integrity sha512-aOV80E9LeWrmflp7hfZNn/zGA4QKv/xsn2w8QCBP0t0+YqObuCWTSgNbHJ0j9YsTuCO08ZR/wsvlxqqHX20iUA== dependencies: "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^28.0.2" - "@jest/types" "^28.0.2" - babel-jest "^28.0.3" + "@jest/test-sequencer" "^28.1.0" + "@jest/types" "^28.1.0" + babel-jest "^28.1.0" chalk "^4.0.0" ci-info "^3.2.0" deepmerge "^4.2.2" glob "^7.1.3" graceful-fs "^4.2.9" - jest-circus "^28.0.3" - jest-environment-node "^28.0.2" + jest-circus "^28.1.0" + jest-environment-node "^28.1.0" jest-get-type "^28.0.2" jest-regex-util "^28.0.2" - jest-resolve "^28.0.3" - jest-runner "^28.0.3" - jest-util "^28.0.2" - jest-validate "^28.0.2" + jest-resolve "^28.1.0" + jest-runner "^28.1.0" + jest-util "^28.1.0" + jest-validate "^28.1.0" micromatch "^4.0.4" parse-json "^5.2.0" - pretty-format "^28.0.2" + pretty-format "^28.1.0" slash "^3.0.0" strip-json-comments "^3.1.1" @@ -6585,15 +6574,15 @@ jest-diff@^25.2.1: jest-get-type "^25.2.6" pretty-format "^25.5.0" -jest-diff@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.0.2.tgz#a543c90082560cd6cb14c5f28c39e6d4618ad7a6" - integrity sha512-33Rnf821Y54OAloav0PGNWHlbtEorXpjwchnToyyWbec10X74FOW7hGfvrXLGz7xOe2dz0uo9JVFAHHj/2B5pg== +jest-diff@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.1.0.tgz#77686fef899ec1873dbfbf9330e37dd429703269" + integrity sha512-8eFd3U3OkIKRtlasXfiAQfbovgFgRDb0Ngcs2E+FMeBZ4rUezqIaGjuyggJBp+llosQXNEWofk/Sz4Hr5gMUhA== dependencies: chalk "^4.0.0" diff-sequences "^28.0.2" jest-get-type "^28.0.2" - pretty-format "^28.0.2" + pretty-format "^28.1.0" jest-docblock@^28.0.2: version "28.0.2" @@ -6602,16 +6591,16 @@ jest-docblock@^28.0.2: dependencies: detect-newline "^3.0.0" -jest-each@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-28.0.2.tgz#fcf6843e9afe5a3f2d0b1c02aab1f41889d92f1d" - integrity sha512-/W5Wc0b+ipR36kDaLngdVEJ/5UYPOITK7rW0djTlCCQdMuWpCFJweMW4TzAoJ6GiRrljPL8FwiyOSoSHKrda2w== +jest-each@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-28.1.0.tgz#54ae66d6a0a5b1913e9a87588d26c2687c39458b" + integrity sha512-a/XX02xF5NTspceMpHujmOexvJ4GftpYXqr6HhhmKmExtMXsyIN/fvanQlt/BcgFoRKN4OCXxLQKth9/n6OPFg== dependencies: - "@jest/types" "^28.0.2" + "@jest/types" "^28.1.0" chalk "^4.0.0" jest-get-type "^28.0.2" - jest-util "^28.0.2" - pretty-format "^28.0.2" + jest-util "^28.1.0" + pretty-format "^28.1.0" jest-environment-jsdom@^28.1.0: version "28.1.0" @@ -6627,17 +6616,17 @@ jest-environment-jsdom@^28.1.0: jest-util "^28.1.0" jsdom "^19.0.0" -jest-environment-node@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-28.0.2.tgz#bd58e192b8f36a37e52c52fac812bd24b360c0b9" - integrity sha512-o9u5UHZ+NCuIoa44KEF0Behhsz/p1wMm0WumsZfWR1k4IVoWSt3aN0BavSC5dd26VxSGQvkrCnJxxOzhhUEG3Q== +jest-environment-node@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-28.1.0.tgz#6ed2150aa31babba0c488c5b4f4d813a585c68e6" + integrity sha512-gBLZNiyrPw9CSMlTXF1yJhaBgWDPVvH0Pq6bOEwGMXaYNzhzhw2kA/OijNF8egbCgDS0/veRv97249x2CX+udQ== dependencies: - "@jest/environment" "^28.0.2" - "@jest/fake-timers" "^28.0.2" - "@jest/types" "^28.0.2" + "@jest/environment" "^28.1.0" + "@jest/fake-timers" "^28.1.0" + "@jest/types" "^28.1.0" "@types/node" "*" - jest-mock "^28.0.2" - jest-util "^28.0.2" + jest-mock "^28.1.0" + jest-util "^28.1.0" jest-get-type@^25.2.6: version "25.2.6" @@ -6649,25 +6638,6 @@ jest-get-type@^28.0.2: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-28.0.2.tgz#34622e628e4fdcd793d46db8a242227901fcf203" integrity sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA== -jest-haste-map@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-28.0.2.tgz#0c768f43680013cfd2a4471a3ec76c47bfb9e7c6" - integrity sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig== - dependencies: - "@jest/types" "^28.0.2" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^28.0.2" - jest-util "^28.0.2" - jest-worker "^28.0.2" - micromatch "^4.0.4" - walker "^1.0.7" - optionalDependencies: - fsevents "^2.3.2" - jest-haste-map@^28.1.0: version "28.1.0" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-28.1.0.tgz#6c1ee2daf1c20a3e03dbd8e5b35c4d73d2349cf0" @@ -6687,38 +6657,23 @@ jest-haste-map@^28.1.0: optionalDependencies: fsevents "^2.3.2" -jest-leak-detector@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-28.0.2.tgz#cbde3d22d09bd690ececdc2ed01c608435328456" - integrity sha512-UGaSPYtxKXl/YKacq6juRAKmMp1z2os8NaU8PSC+xvNikmu3wF6QFrXrihMM4hXeMr9HuNotBrQZHmzDY8KIBQ== +jest-leak-detector@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-28.1.0.tgz#b65167776a8787443214d6f3f54935a4c73c8a45" + integrity sha512-uIJDQbxwEL2AMMs2xjhZl2hw8s77c3wrPaQ9v6tXJLGaaQ+4QrNJH5vuw7hA7w/uGT/iJ42a83opAqxGHeyRIA== dependencies: jest-get-type "^28.0.2" - pretty-format "^28.0.2" + pretty-format "^28.1.0" -jest-matcher-utils@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.0.2.tgz#eb461af204b6d0f05281e9228094f0ab7e9e8537" - integrity sha512-SxtTiI2qLJHFtOz/bySStCnwCvISAuxQ/grS+74dfTy5AuJw3Sgj9TVUvskcnImTfpzLoMCDJseRaeRrVYbAOA== +jest-matcher-utils@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.1.0.tgz#2ae398806668eeabd293c61712227cb94b250ccf" + integrity sha512-onnax0n2uTLRQFKAjC7TuaxibrPSvZgKTcSCnNUz/tOjJ9UhxNm7ZmPpoQavmTDUjXvUQ8KesWk2/VdrxIFzTQ== dependencies: chalk "^4.0.0" - jest-diff "^28.0.2" + jest-diff "^28.1.0" jest-get-type "^28.0.2" - pretty-format "^28.0.2" - -jest-message-util@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.0.2.tgz#f3cf36be72be4c4c4058cb34bd6673996d26dee3" - integrity sha512-knK7XyojvwYh1XiF2wmVdskgM/uN11KsjcEWWHfnMZNEdwXCrqB4sCBO94F4cfiAwCS8WFV6CDixDwPlMh/wdA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^28.0.2" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^28.0.2" - slash "^3.0.0" - stack-utils "^2.0.3" + pretty-format "^28.1.0" jest-message-util@^28.1.0: version "28.1.0" @@ -6735,7 +6690,7 @@ jest-message-util@^28.1.0: slash "^3.0.0" stack-utils "^2.0.3" -jest-mock@^28.0.2, jest-mock@^28.1.0: +jest-mock@^28.1.0: version "28.1.0" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-28.1.0.tgz#ccc7cc12a9b330b3182db0c651edc90d163ff73e" integrity sha512-H7BrhggNn77WhdL7O1apG0Q/iwl0Bdd5E1ydhCJzL3oBLh/UYxAwR3EJLsBZ9XA3ZU4PA3UNw4tQjduBTCTmLw== @@ -6753,125 +6708,113 @@ jest-regex-util@^28.0.2: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-28.0.2.tgz#afdc377a3b25fb6e80825adcf76c854e5bf47ead" integrity sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw== -jest-resolve-dependencies@^28.0.3: - version "28.0.3" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-28.0.3.tgz#76d8f59f7e76ba36d76a1677eeaaed24560da7e0" - integrity sha512-lCgHMm0/5p0qHemrOzm7kI6JDei28xJwIf7XOEcv1HeAVHnsON8B8jO/woqlU+/GcOXb58ymieYqhk3zjGWnvQ== +jest-resolve-dependencies@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.0.tgz#167becb8bee6e20b5ef4a3a728ec67aef6b0b79b" + integrity sha512-Ue1VYoSZquPwEvng7Uefw8RmZR+me/1kr30H2jMINjGeHgeO/JgrR6wxj2ofkJ7KSAA11W3cOrhNCbj5Dqqd9g== dependencies: jest-regex-util "^28.0.2" - jest-snapshot "^28.0.3" + jest-snapshot "^28.1.0" -jest-resolve@^28.0.3: - version "28.0.3" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-28.0.3.tgz#63f8e6b53e40f265b3ca9116195221dd43e3d16d" - integrity sha512-lfgjd9JhEjpjIN3HLUfdysdK+A7ePQoYmd7WL9DUEWqdnngb1rF56eee6iDXJxl/3eSolpP43VD7VrhjL3NsoQ== +jest-resolve@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-28.1.0.tgz#b1f32748a6cee7d1779c7ef639c0a87078de3d35" + integrity sha512-vvfN7+tPNnnhDvISuzD1P+CRVP8cK0FHXRwPAcdDaQv4zgvwvag2n55/h5VjYcM5UJG7L4TwE5tZlzcI0X2Lhw== dependencies: chalk "^4.0.0" graceful-fs "^4.2.9" - jest-haste-map "^28.0.2" + jest-haste-map "^28.1.0" jest-pnp-resolver "^1.2.2" - jest-util "^28.0.2" - jest-validate "^28.0.2" + jest-util "^28.1.0" + jest-validate "^28.1.0" resolve "^1.20.0" resolve.exports "^1.1.0" slash "^3.0.0" -jest-runner@^28.0.3: - version "28.0.3" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-28.0.3.tgz#a8a409c685ad3081a44b149b2eb04bc4d47faaf9" - integrity sha512-4OsHMjBLtYUWCENucAQ4Za0jGfEbOFi/Fusv6dzUuaweqx8apb4+5p2LR2yvgF4StFulmxyC238tGLftfu+zBA== +jest-runner@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-28.1.0.tgz#aefe2a1e618a69baa0b24a50edc54fdd7e728eaa" + integrity sha512-FBpmuh1HB2dsLklAlRdOxNTTHKFR6G1Qmd80pVDvwbZXTriqjWqjei5DKFC1UlM732KjYcE6yuCdiF0WUCOS2w== dependencies: - "@jest/console" "^28.0.2" - "@jest/environment" "^28.0.2" - "@jest/test-result" "^28.0.2" - "@jest/transform" "^28.0.3" - "@jest/types" "^28.0.2" + "@jest/console" "^28.1.0" + "@jest/environment" "^28.1.0" + "@jest/test-result" "^28.1.0" + "@jest/transform" "^28.1.0" + "@jest/types" "^28.1.0" "@types/node" "*" chalk "^4.0.0" emittery "^0.10.2" graceful-fs "^4.2.9" jest-docblock "^28.0.2" - jest-environment-node "^28.0.2" - jest-haste-map "^28.0.2" - jest-leak-detector "^28.0.2" - jest-message-util "^28.0.2" - jest-resolve "^28.0.3" - jest-runtime "^28.0.3" - jest-util "^28.0.2" - jest-watcher "^28.0.2" - jest-worker "^28.0.2" + jest-environment-node "^28.1.0" + jest-haste-map "^28.1.0" + jest-leak-detector "^28.1.0" + jest-message-util "^28.1.0" + jest-resolve "^28.1.0" + jest-runtime "^28.1.0" + jest-util "^28.1.0" + jest-watcher "^28.1.0" + jest-worker "^28.1.0" source-map-support "0.5.13" throat "^6.0.1" -jest-runtime@^28.0.3: - version "28.0.3" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-28.0.3.tgz#02346a34de0ac61d23bdb0e8c035ad973d7bb087" - integrity sha512-7FtPUmvbZEHLOdjsF6dyHg5Pe4E0DU+f3Vvv8BPzVR7mQA6nFR4clQYLAPyJGnsUvN8WRWn+b5a5SVwnj1WaGg== +jest-runtime@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-28.1.0.tgz#4847dcb2a4eb4b0f9eaf41306897e51fb1665631" + integrity sha512-wNYDiwhdH/TV3agaIyVF0lsJ33MhyujOe+lNTUiolqKt8pchy1Hq4+tDMGbtD5P/oNLA3zYrpx73T9dMTOCAcg== dependencies: - "@jest/environment" "^28.0.2" - "@jest/fake-timers" "^28.0.2" - "@jest/globals" "^28.0.3" + "@jest/environment" "^28.1.0" + "@jest/fake-timers" "^28.1.0" + "@jest/globals" "^28.1.0" "@jest/source-map" "^28.0.2" - "@jest/test-result" "^28.0.2" - "@jest/transform" "^28.0.3" - "@jest/types" "^28.0.2" + "@jest/test-result" "^28.1.0" + "@jest/transform" "^28.1.0" + "@jest/types" "^28.1.0" chalk "^4.0.0" cjs-module-lexer "^1.0.0" collect-v8-coverage "^1.0.0" execa "^5.0.0" glob "^7.1.3" graceful-fs "^4.2.9" - jest-haste-map "^28.0.2" - jest-message-util "^28.0.2" - jest-mock "^28.0.2" + jest-haste-map "^28.1.0" + jest-message-util "^28.1.0" + jest-mock "^28.1.0" jest-regex-util "^28.0.2" - jest-resolve "^28.0.3" - jest-snapshot "^28.0.3" - jest-util "^28.0.2" + jest-resolve "^28.1.0" + jest-snapshot "^28.1.0" + jest-util "^28.1.0" slash "^3.0.0" strip-bom "^4.0.0" -jest-snapshot@^28.0.3: - version "28.0.3" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-28.0.3.tgz#9a768d0c617d070e87c1bd37240f22b344616154" - integrity sha512-nVzAAIlAbrMuvVUrS1YxmAeo1TfSsDDU+K5wv/Ow56MBp+L+Y71ksAbwRp3kGCgZAz4oOXcAMPAwtT9Yh1hlQQ== +jest-snapshot@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-28.1.0.tgz#4b74fa8816707dd10fe9d551c2c258e5a67b53b6" + integrity sha512-ex49M2ZrZsUyQLpLGxQtDbahvgBjlLPgklkqGM0hq/F7W/f8DyqZxVHjdy19QKBm4O93eDp+H5S23EiTbbUmHw== dependencies: "@babel/core" "^7.11.6" "@babel/generator" "^7.7.2" "@babel/plugin-syntax-typescript" "^7.7.2" "@babel/traverse" "^7.7.2" "@babel/types" "^7.3.3" - "@jest/expect-utils" "^28.0.2" - "@jest/transform" "^28.0.3" - "@jest/types" "^28.0.2" + "@jest/expect-utils" "^28.1.0" + "@jest/transform" "^28.1.0" + "@jest/types" "^28.1.0" "@types/babel__traverse" "^7.0.6" "@types/prettier" "^2.1.5" babel-preset-current-node-syntax "^1.0.0" chalk "^4.0.0" - expect "^28.0.2" + expect "^28.1.0" graceful-fs "^4.2.9" - jest-diff "^28.0.2" + jest-diff "^28.1.0" jest-get-type "^28.0.2" - jest-haste-map "^28.0.2" - jest-matcher-utils "^28.0.2" - jest-message-util "^28.0.2" - jest-util "^28.0.2" + jest-haste-map "^28.1.0" + jest-matcher-utils "^28.1.0" + jest-message-util "^28.1.0" + jest-util "^28.1.0" natural-compare "^1.4.0" - pretty-format "^28.0.2" + pretty-format "^28.1.0" semver "^7.3.5" -jest-util@^28.0.2, jest-util@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.0.tgz#d54eb83ad77e1dd441408738c5a5043642823be5" - integrity sha512-qYdCKD77k4Hwkose2YBEqQk7PzUf/NSE+rutzceduFveQREeH6b+89Dc9+wjX9dAwHcgdx4yedGA3FQlU/qCTA== - dependencies: - "@jest/types" "^28.1.0" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - jest-util@^28.1.0: version "28.1.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.0.tgz#d54eb83ad77e1dd441408738c5a5043642823be5" @@ -6884,30 +6827,30 @@ jest-util@^28.1.0: graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-validate@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-28.0.2.tgz#58bb7e826c054a8bb3b54c05f73758d96cf6dbef" - integrity sha512-nr0UOvCTtxP0YPdsk01Gk7e7c0xIiEe2nncAe3pj0wBfUvAykTVrMrdeASlAJnlEQCBuwN/GF4hKoCzbkGNCNw== +jest-validate@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-28.1.0.tgz#8a6821f48432aba9f830c26e28226ad77b9a0e18" + integrity sha512-Lly7CJYih3vQBfjLeANGgBSBJ7pEa18cxpQfQEq2go2xyEzehnHfQTjoUia8xUv4x4J80XKFIDwJJThXtRFQXQ== dependencies: - "@jest/types" "^28.0.2" + "@jest/types" "^28.1.0" camelcase "^6.2.0" chalk "^4.0.0" jest-get-type "^28.0.2" leven "^3.1.0" - pretty-format "^28.0.2" + pretty-format "^28.1.0" -jest-watcher@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-28.0.2.tgz#649fa24df531d4071be5784b6274d494d788c88b" - integrity sha512-uIVJLpQ/5VTGQWBiBatHsi7jrCqHjHl0e0dFHMWzwuIfUbdW/muk0DtSr0fteY2T7QTFylv+7a5Rm8sBKrE12Q== +jest-watcher@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-28.1.0.tgz#aaa7b4164a4e77eeb5f7d7b25ede5e7b4e9c9aaf" + integrity sha512-tNHMtfLE8Njcr2IRS+5rXYA4BhU90gAOwI9frTGOqd+jX0P/Au/JfRSNqsf5nUTcWdbVYuLxS1KjnzILSoR5hA== dependencies: - "@jest/test-result" "^28.0.2" - "@jest/types" "^28.0.2" + "@jest/test-result" "^28.1.0" + "@jest/types" "^28.1.0" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" emittery "^0.10.2" - jest-util "^28.0.2" + jest-util "^28.1.0" string-length "^4.0.1" jest-worker@^26.5.0: @@ -6919,15 +6862,6 @@ jest-worker@^26.5.0: merge-stream "^2.0.0" supports-color "^7.0.0" -jest-worker@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-28.0.2.tgz#75f7e5126541289ba02e9c1a67e46349ddb8141d" - integrity sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - jest-worker@^28.1.0: version "28.1.0" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-28.1.0.tgz#ced54757a035e87591e1208253a6e3aac1a855e5" @@ -6937,14 +6871,14 @@ jest-worker@^28.1.0: merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^28.0.3: - version "28.0.3" - resolved "https://registry.yarnpkg.com/jest/-/jest-28.0.3.tgz#92a7d6ee097b61de4ba2db7f3ab723e81a99b32d" - integrity sha512-uS+T5J3w5xyzd1KSJCGKhCo8WTJXbNl86f5SW11wgssbandJOVLRKKUxmhdFfmKxhPeksl1hHZ0HaA8VBzp7xA== +jest@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-28.1.0.tgz#f420e41c8f2395b9a30445a97189ebb57593d831" + integrity sha512-TZR+tHxopPhzw3c3560IJXZWLNHgpcz1Zh0w5A65vynLGNcg/5pZ+VildAd7+XGOu6jd58XMY/HNn0IkZIXVXg== dependencies: - "@jest/core" "^28.0.3" + "@jest/core" "^28.1.0" import-local "^3.0.2" - jest-cli "^28.0.3" + jest-cli "^28.1.0" js-base64@^2.1.9: version "2.6.4" @@ -8948,16 +8882,6 @@ pretty-format@^27.0.2: ansi-styles "^5.0.0" react-is "^17.0.1" -pretty-format@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.0.2.tgz#6a24d71cbb61a5e5794ba7513fe22101675481bc" - integrity sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw== - dependencies: - "@jest/schemas" "^28.0.2" - ansi-regex "^5.0.1" - ansi-styles "^5.0.0" - react-is "^18.0.0" - pretty-format@^28.1.0: version "28.1.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.0.tgz#8f5836c6a0dfdb834730577ec18029052191af55" From 6545114ac706a56a188fc965649ef79070fd827f Mon Sep 17 00:00:00 2001 From: Claire <claire.github-309c@sitedethib.com> Date: Mon, 9 May 2022 23:20:19 +0200 Subject: [PATCH 14/16] [Glitch] Fix block/mute lists showing a follow button when unblocking a user (#18364) Port 917567567a9a5a79f2a2492de672b0907605aabf to glitch-soc Signed-off-by: Claire <claire.github-309c@sitedethib.com> --- app/javascript/flavours/glitch/components/account.js | 12 ++++++++++-- .../flavours/glitch/features/blocks/index.js | 2 +- .../flavours/glitch/features/mutes/index.js | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/javascript/flavours/glitch/components/account.js b/app/javascript/flavours/glitch/components/account.js index 396a36ea0f..489f607363 100644 --- a/app/javascript/flavours/glitch/components/account.js +++ b/app/javascript/flavours/glitch/components/account.js @@ -16,8 +16,10 @@ const messages = defineMessages({ requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' }, unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, - mute_notifications: { id: 'account.mute_notifications', defaultMessage: 'You are not currently muting notifications from @{name}. Click to mute notifications' }, - unmute_notifications: { id: 'account.unmute_notifications', defaultMessage: 'You are currently muting notifications from @{name}. Click to unmute notifications' }, + mute_notifications: { id: 'account.mute_notifications', defaultMessage: 'Mute notifications from @{name}' }, + unmute_notifications: { id: 'account.unmute_notifications', defaultMessage: 'Unmute notifications from @{name}' }, + mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, + block: { id: 'account.block', defaultMessage: 'Block @{name}' }, }); export default @injectIntl @@ -34,6 +36,7 @@ class Account extends ImmutablePureComponent { small: PropTypes.bool, actionIcon: PropTypes.string, actionTitle: PropTypes.string, + defaultAction: PropTypes.string, onActionClick: PropTypes.func, }; @@ -70,6 +73,7 @@ class Account extends ImmutablePureComponent { onActionClick, actionIcon, actionTitle, + defaultAction, } = this.props; if (!account) { @@ -114,6 +118,10 @@ class Account extends ImmutablePureComponent { {hidingNotificationsButton} </Fragment> ); + } else if (defaultAction === 'mute') { + buttons = <IconButton icon='volume-off' title={intl.formatMessage(messages.mute, { name: account.get('username') })} onClick={this.handleMute} />; + } else if (defaultAction === 'block') { + buttons = <IconButton icon='lock' title={intl.formatMessage(messages.block, { name: account.get('username') })} onClick={this.handleBlock} />; } else if (!account.get('moved') || following) { buttons = <IconButton icon={following ? 'user-times' : 'user-plus'} title={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={this.handleFollow} active={following} />; } diff --git a/app/javascript/flavours/glitch/features/blocks/index.js b/app/javascript/flavours/glitch/features/blocks/index.js index 4d0f58239b..4461bd14d8 100644 --- a/app/javascript/flavours/glitch/features/blocks/index.js +++ b/app/javascript/flavours/glitch/features/blocks/index.js @@ -69,7 +69,7 @@ class Blocks extends ImmutablePureComponent { bindToDocument={!multiColumn} > {accountIds.map(id => - <AccountContainer key={id} id={id} />, + <AccountContainer key={id} id={id} defaultAction='block' />, )} </ScrollableList> </Column> diff --git a/app/javascript/flavours/glitch/features/mutes/index.js b/app/javascript/flavours/glitch/features/mutes/index.js index 9f0d5a43ef..764cbef1a2 100644 --- a/app/javascript/flavours/glitch/features/mutes/index.js +++ b/app/javascript/flavours/glitch/features/mutes/index.js @@ -69,7 +69,7 @@ class Mutes extends ImmutablePureComponent { bindToDocument={!multiColumn} > {accountIds.map(id => - <AccountContainer key={id} id={id} />, + <AccountContainer key={id} id={id} defaultAction='mute' />, )} </ScrollableList> </Column> From 6256a3da46b33312e09e8fbc5d7a64c0ba1662a1 Mon Sep 17 00:00:00 2001 From: Eugen Rochko <eugen@zeonfederated.com> Date: Fri, 26 Nov 2021 05:58:18 +0100 Subject: [PATCH 15/16] [Glitch] Remove Keybase integration Port 4375813ea7e5712cbdcb461dd3a2d77deaf31ed0 to glitch-soc Signed-off-by: Claire <claire.github-309c@sitedethib.com> --- .../features/account/components/header.js | 16 +---- .../account_timeline/components/header.js | 4 +- .../containers/header_container.js | 2 - .../glitch/features/account_timeline/index.js | 6 +- .../glitch/reducers/identity_proofs.js | 25 -------- .../flavours/glitch/reducers/index.js | 2 - .../flavours/glitch/styles/forms.scss | 62 ------------------- 7 files changed, 6 insertions(+), 111 deletions(-) delete mode 100644 app/javascript/flavours/glitch/reducers/identity_proofs.js diff --git a/app/javascript/flavours/glitch/features/account/components/header.js b/app/javascript/flavours/glitch/features/account/components/header.js index 68c6bae8ee..a43c20b5fe 100644 --- a/app/javascript/flavours/glitch/features/account/components/header.js +++ b/app/javascript/flavours/glitch/features/account/components/header.js @@ -115,7 +115,7 @@ class Header extends ImmutablePureComponent { } render () { - const { account, intl, domain, identity_proofs } = this.props; + const { account, intl, domain } = this.props; if (!account) { return null; @@ -301,20 +301,8 @@ class Header extends ImmutablePureComponent { {!suspended && ( <div className='account__header__extra'> <div className='account__header__bio'> - { (fields.size > 0 || identity_proofs.size > 0) && ( + { fields.size > 0 && ( <div className='account__header__fields'> - {identity_proofs.map((proof, i) => ( - <dl key={i}> - <dt dangerouslySetInnerHTML={{ __html: proof.get('provider') }} className='translate' /> - - <dd className='verified'> - <a href={proof.get('proof_url')} target='_blank' rel='noopener noreferrer'><span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(proof.get('updated_at'), dateFormatOptions) })}> - <Icon id='check' className='verified__mark' /> - </span></a> - <a href={proof.get('profile_url')} target='_blank' rel='noopener noreferrer'><span dangerouslySetInnerHTML={{ __html: ' '+proof.get('provider_username') }} className='translate' /></a> - </dd> - </dl> - ))} {fields.map((pair, i) => ( <dl key={i}> <dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} /> diff --git a/app/javascript/flavours/glitch/features/account_timeline/components/header.js b/app/javascript/flavours/glitch/features/account_timeline/components/header.js index d6e607a373..eddad17f5f 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/components/header.js +++ b/app/javascript/flavours/glitch/features/account_timeline/components/header.js @@ -12,7 +12,6 @@ export default class Header extends ImmutablePureComponent { static propTypes = { account: ImmutablePropTypes.map, - identity_proofs: ImmutablePropTypes.list, onFollow: PropTypes.func.isRequired, onBlock: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired, @@ -93,7 +92,7 @@ export default class Header extends ImmutablePureComponent { } render () { - const { account, hideTabs, identity_proofs } = this.props; + const { account, hideTabs } = this.props; if (account === null) { return null; @@ -105,7 +104,6 @@ export default class Header extends ImmutablePureComponent { <InnerHeader account={account} - identity_proofs={identity_proofs} onFollow={this.handleFollow} onBlock={this.handleBlock} onMention={this.handleMention} diff --git a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js index 90e746679d..d5858e1c27 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js +++ b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js @@ -22,7 +22,6 @@ import { blockDomain, unblockDomain } from 'flavours/glitch/actions/domain_block import { initEditAccountNote } from 'flavours/glitch/actions/account_notes'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { unfollowModal } from 'flavours/glitch/util/initial_state'; -import { List as ImmutableList } from 'immutable'; const messages = defineMessages({ unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' }, @@ -35,7 +34,6 @@ const makeMapStateToProps = () => { const mapStateToProps = (state, { accountId }) => ({ account: getAccount(state, accountId), domain: state.getIn(['meta', 'domain']), - identity_proofs: state.getIn(['identity_proofs', accountId], ImmutableList()), }); return mapStateToProps; diff --git a/app/javascript/flavours/glitch/features/account_timeline/index.js b/app/javascript/flavours/glitch/features/account_timeline/index.js index 6d2df5c6f5..90374a86b5 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/index.js +++ b/app/javascript/flavours/glitch/features/account_timeline/index.js @@ -13,7 +13,6 @@ import ColumnBackButton from 'flavours/glitch/components/column_back_button'; import { List as ImmutableList } from 'immutable'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage } from 'react-intl'; -import { fetchAccountIdentityProofs } from '../../actions/identity_proofs'; import MissingIndicator from 'flavours/glitch/components/missing_indicator'; import TimelineHint from 'flavours/glitch/components/timeline_hint'; @@ -77,7 +76,7 @@ class AccountTimeline extends ImmutablePureComponent { const { accountId, withReplies, dispatch } = this.props; dispatch(fetchAccount(accountId)); - dispatch(fetchAccountIdentityProofs(accountId)); + if (!withReplies) { dispatch(expandAccountFeaturedTimeline(accountId)); } @@ -109,10 +108,11 @@ class AccountTimeline extends ImmutablePureComponent { if ((nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) || nextProps.withReplies !== this.props.withReplies) { dispatch(fetchAccount(nextProps.params.accountId)); - dispatch(fetchAccountIdentityProofs(nextProps.params.accountId)); + if (!nextProps.withReplies) { dispatch(expandAccountFeaturedTimeline(nextProps.params.accountId)); } + dispatch(expandAccountTimeline(nextProps.params.accountId, { withReplies: nextProps.params.withReplies })); } } diff --git a/app/javascript/flavours/glitch/reducers/identity_proofs.js b/app/javascript/flavours/glitch/reducers/identity_proofs.js deleted file mode 100644 index 58af0a5faa..0000000000 --- a/app/javascript/flavours/glitch/reducers/identity_proofs.js +++ /dev/null @@ -1,25 +0,0 @@ -import { Map as ImmutableMap, fromJS } from 'immutable'; -import { - IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST, - IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS, - IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL, -} from '../actions/identity_proofs'; - -const initialState = ImmutableMap(); - -export default function identityProofsReducer(state = initialState, action) { - switch(action.type) { - case IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST: - return state.set('isLoading', true); - case IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL: - return state.set('isLoading', false); - case IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS: - return state.update(identity_proofs => identity_proofs.withMutations(map => { - map.set('isLoading', false); - map.set('loaded', true); - map.set(action.accountId, fromJS(action.identity_proofs)); - })); - default: - return state; - } -}; diff --git a/app/javascript/flavours/glitch/reducers/index.js b/app/javascript/flavours/glitch/reducers/index.js index 92348c0c5e..b8aad9fad4 100644 --- a/app/javascript/flavours/glitch/reducers/index.js +++ b/app/javascript/flavours/glitch/reducers/index.js @@ -34,7 +34,6 @@ import conversations from './conversations'; import suggestions from './suggestions'; import pinnedAccountsEditor from './pinned_accounts_editor'; import polls from './polls'; -import identity_proofs from './identity_proofs'; import trends from './trends'; import announcements from './announcements'; import markers from './markers'; @@ -73,7 +72,6 @@ const reducers = { notifications, height_cache, custom_emojis, - identity_proofs, lists, listEditor, listAdder, diff --git a/app/javascript/flavours/glitch/styles/forms.scss b/app/javascript/flavours/glitch/styles/forms.scss index e36fab8fa9..a08ca24f14 100644 --- a/app/javascript/flavours/glitch/styles/forms.scss +++ b/app/javascript/flavours/glitch/styles/forms.scss @@ -1022,68 +1022,6 @@ code { } } -.connection-prompt { - margin-bottom: 25px; - - .fa-link { - background-color: darken($ui-base-color, 4%); - border-radius: 100%; - font-size: 24px; - padding: 10px; - } - - &__column { - align-items: center; - display: flex; - flex: 1; - flex-direction: column; - flex-shrink: 1; - max-width: 50%; - - &-sep { - align-self: center; - flex-grow: 0; - overflow: visible; - position: relative; - z-index: 1; - } - - p { - word-break: break-word; - } - } - - .account__avatar { - margin-bottom: 20px; - } - - &__connection { - background-color: lighten($ui-base-color, 8%); - box-shadow: 0 0 15px rgba($base-shadow-color, 0.2); - border-radius: 4px; - padding: 25px 10px; - position: relative; - text-align: center; - - &::after { - background-color: darken($ui-base-color, 4%); - content: ''; - display: block; - height: 100%; - left: 50%; - position: absolute; - top: 0; - width: 1px; - } - } - - &__row { - align-items: flex-start; - display: flex; - flex-direction: row; - } -} - .input.user_confirm_password, .input.user_website { &:not(.field_with_errors) { From fbef44009dd1ba11e71eb194e6bd6fea5326dddb Mon Sep 17 00:00:00 2001 From: Eugen Rochko <eugen@zeonfederated.com> Date: Tue, 10 May 2022 09:44:35 +0200 Subject: [PATCH 16/16] [Glitch] Add `limited` attribute to accounts in REST API and a warning in web UI Port ac3d6f9a35e3ce5c74300d811ff0ca5f94d60fb6 to glitch-soc Signed-off-by: Claire <claire.github-309c@sitedethib.com> --- .../flavours/glitch/actions/accounts.js | 7 ++++ .../flavours/glitch/components/avatar.js | 26 +++++++------- .../features/account/components/header.js | 25 ++++++++----- .../account_timeline/components/header.js | 8 +++-- .../components/limited_account_hint.js | 35 +++++++++++++++++++ .../containers/header_container.js | 3 +- .../glitch/features/account_timeline/index.js | 16 ++++++--- .../glitch/features/followers/index.js | 18 ++++++++-- .../glitch/features/following/index.js | 18 ++++++++-- .../flavours/glitch/reducers/accounts.js | 7 +++- .../flavours/glitch/selectors/index.js | 8 +++++ .../glitch/styles/components/columns.scss | 9 +++++ 12 files changed, 143 insertions(+), 37 deletions(-) create mode 100644 app/javascript/flavours/glitch/features/account_timeline/components/limited_account_hint.js diff --git a/app/javascript/flavours/glitch/actions/accounts.js b/app/javascript/flavours/glitch/actions/accounts.js index 0cf64e0762..f5871beb3e 100644 --- a/app/javascript/flavours/glitch/actions/accounts.js +++ b/app/javascript/flavours/glitch/actions/accounts.js @@ -88,6 +88,8 @@ export const PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CHANGE = 'PINNED_ACCOUNTS_EDITOR export const PINNED_ACCOUNTS_EDITOR_RESET = 'PINNED_ACCOUNTS_EDITOR_RESET'; +export const ACCOUNT_REVEAL = 'ACCOUNT_REVEAL'; + export function fetchAccount(id) { return (dispatch, getState) => { dispatch(fetchRelationships([id])); @@ -798,6 +800,11 @@ export function unpinAccountFail(error) { }; }; +export const revealAccount = id => ({ + type: ACCOUNT_REVEAL, + id, +}); + export function fetchPinnedAccounts() { return (dispatch, getState) => { dispatch(fetchPinnedAccountsRequest()); diff --git a/app/javascript/flavours/glitch/components/avatar.js b/app/javascript/flavours/glitch/components/avatar.js index c5e9072c4a..6d53a5298d 100644 --- a/app/javascript/flavours/glitch/components/avatar.js +++ b/app/javascript/flavours/glitch/components/avatar.js @@ -1,13 +1,13 @@ -import classNames from 'classnames'; import React from 'react'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { autoPlayGif } from 'flavours/glitch/util/initial_state'; +import classNames from 'classnames'; export default class Avatar extends React.PureComponent { static propTypes = { - account: ImmutablePropTypes.map.isRequired, + account: ImmutablePropTypes.map, className: PropTypes.string, size: PropTypes.number.isRequired, style: PropTypes.object, @@ -45,11 +45,6 @@ export default class Avatar extends React.PureComponent { } = this.props; const { hovering } = this.state; - const src = account.get('avatar'); - const staticSrc = account.get('avatar_static'); - - const computedClass = classNames('account__avatar', { 'account__avatar-inline': inline }, className); - const style = { ...this.props.style, width: `${size}px`, @@ -57,19 +52,24 @@ export default class Avatar extends React.PureComponent { backgroundSize: `${size}px ${size}px`, }; - if (hovering || animate) { - style.backgroundImage = `url(${src})`; - } else { - style.backgroundImage = `url(${staticSrc})`; + if (account) { + const src = account.get('avatar'); + const staticSrc = account.get('avatar_static'); + + if (hovering || animate) { + style.backgroundImage = `url(${src})`; + } else { + style.backgroundImage = `url(${staticSrc})`; + } } return ( <div - className={computedClass} + className={classNames('account__avatar', { 'account__avatar-inline': inline }, className)} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} style={style} - data-avatar-of={`@${account.get('acct')}`} + data-avatar-of={account && `@${account.get('acct')}`} /> ); } diff --git a/app/javascript/flavours/glitch/features/account/components/header.js b/app/javascript/flavours/glitch/features/account/components/header.js index a43c20b5fe..45aba53f74 100644 --- a/app/javascript/flavours/glitch/features/account/components/header.js +++ b/app/javascript/flavours/glitch/features/account/components/header.js @@ -82,6 +82,7 @@ class Header extends ImmutablePureComponent { onEditAccountNote: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, domain: PropTypes.string.isRequired, + hidden: PropTypes.bool, }; openEditProfile = () => { @@ -115,7 +116,7 @@ class Header extends ImmutablePureComponent { } render () { - const { account, intl, domain } = this.props; + const { account, hidden, intl, domain } = this.props; if (!account) { return null; @@ -270,23 +271,29 @@ class Header extends ImmutablePureComponent { {info} </div> - <img src={autoPlayGif ? account.get('header') : account.get('header_static')} alt='' className='parallax' /> + {!(suspended || hidden) && <img src={autoPlayGif ? account.get('header') : account.get('header_static')} alt='' className='parallax' />} </div> <div className='account__header__bar'> <div className='account__header__tabs'> <a className='avatar' href={account.get('url')} rel='noopener noreferrer' target='_blank'> - <Avatar account={account} size={90} /> + <Avatar account={suspended || hidden ? undefined : account} size={90} /> </a> <div className='spacer' /> - <div className='account__header__tabs__buttons'> - {actionBtn} - {bellBtn} + {!suspended && ( + <div className='account__header__tabs__buttons'> + {!hidden && ( + <React.Fragment> + {actionBtn} + {bellBtn} + </React.Fragment> + )} - <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' /> - </div> + <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' /> + </div> + )} </div> <div className='account__header__tabs__name'> @@ -298,7 +305,7 @@ class Header extends ImmutablePureComponent { <AccountNoteContainer account={account} /> - {!suspended && ( + {!(suspended || hidden) && ( <div className='account__header__extra'> <div className='account__header__bio'> { fields.size > 0 && ( diff --git a/app/javascript/flavours/glitch/features/account_timeline/components/header.js b/app/javascript/flavours/glitch/features/account_timeline/components/header.js index eddad17f5f..645ff29ea4 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/components/header.js +++ b/app/javascript/flavours/glitch/features/account_timeline/components/header.js @@ -25,6 +25,7 @@ export default class Header extends ImmutablePureComponent { onAddToList: PropTypes.func.isRequired, hideTabs: PropTypes.bool, domain: PropTypes.string.isRequired, + hidden: PropTypes.bool, }; static contextTypes = { @@ -92,7 +93,7 @@ export default class Header extends ImmutablePureComponent { } render () { - const { account, hideTabs } = this.props; + const { account, hidden, hideTabs } = this.props; if (account === null) { return null; @@ -100,7 +101,7 @@ export default class Header extends ImmutablePureComponent { return ( <div className='account-timeline__header'> - {account.get('moved') && <MovedNote from={account} to={account.get('moved')} />} + {(!hidden && account.get('moved')) && <MovedNote from={account} to={account.get('moved')} />} <InnerHeader account={account} @@ -118,13 +119,14 @@ export default class Header extends ImmutablePureComponent { onAddToList={this.handleAddToList} onEditAccountNote={this.handleEditAccountNote} domain={this.props.domain} + hidden={hidden} /> <ActionBar account={account} /> - {!hideTabs && ( + {!(hideTabs || hidden) && ( <div className='account__section-headline'> <NavLink exact to={`/@${account.get('acct')}`}><FormattedMessage id='account.posts' defaultMessage='Posts' /></NavLink> <NavLink exact to={`/@${account.get('acct')}/with_replies`}><FormattedMessage id='account.posts_with_replies' defaultMessage='Posts with replies' /></NavLink> diff --git a/app/javascript/flavours/glitch/features/account_timeline/components/limited_account_hint.js b/app/javascript/flavours/glitch/features/account_timeline/components/limited_account_hint.js new file mode 100644 index 0000000000..e465c83b47 --- /dev/null +++ b/app/javascript/flavours/glitch/features/account_timeline/components/limited_account_hint.js @@ -0,0 +1,35 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { revealAccount } from 'flavours/glitch/actions/accounts'; +import { FormattedMessage } from 'react-intl'; +import Button from 'flavours/glitch/components/button'; + +const mapDispatchToProps = (dispatch, { accountId }) => ({ + + reveal () { + dispatch(revealAccount(accountId)); + }, + +}); + +export default @connect(() => {}, mapDispatchToProps) +class LimitedAccountHint extends React.PureComponent { + + static propTypes = { + accountId: PropTypes.string.isRequired, + reveal: PropTypes.func, + } + + render () { + const { reveal } = this.props; + + return ( + <div className='limited-account-hint'> + <p><FormattedMessage id='limited_account_hint.title' defaultMessage='This profile has been hidden by the moderators of your server.' /></p> + <Button onClick={reveal}><FormattedMessage id='limited_account_hint.action' defaultMessage='Show profile anyway' /></Button> + </div> + ); + } + +} diff --git a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js index d5858e1c27..3fa7c1448b 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js +++ b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js @@ -1,6 +1,6 @@ import React from 'react'; import { connect } from 'react-redux'; -import { makeGetAccount } from 'flavours/glitch/selectors'; +import { makeGetAccount, getAccountHidden } from 'flavours/glitch/selectors'; import Header from '../components/header'; import { followAccount, @@ -34,6 +34,7 @@ const makeMapStateToProps = () => { const mapStateToProps = (state, { accountId }) => ({ account: getAccount(state, accountId), domain: state.getIn(['meta', 'domain']), + hidden: getAccountHidden(state, accountId), }); return mapStateToProps; diff --git a/app/javascript/flavours/glitch/features/account_timeline/index.js b/app/javascript/flavours/glitch/features/account_timeline/index.js index 90374a86b5..68d558e662 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/index.js +++ b/app/javascript/flavours/glitch/features/account_timeline/index.js @@ -15,6 +15,8 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage } from 'react-intl'; import MissingIndicator from 'flavours/glitch/components/missing_indicator'; import TimelineHint from 'flavours/glitch/components/timeline_hint'; +import LimitedAccountHint from './components/limited_account_hint'; +import { getAccountHidden } from 'flavours/glitch/selectors'; const emptyList = ImmutableList(); @@ -39,6 +41,7 @@ const mapStateToProps = (state, { params: { acct, id }, withReplies = false }) = isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']), hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']), suspended: state.getIn(['accounts', accountId, 'suspended'], false), + hidden: getAccountHidden(state, accountId), }; }; @@ -67,6 +70,7 @@ class AccountTimeline extends ImmutablePureComponent { withReplies: PropTypes.bool, isAccount: PropTypes.bool, suspended: PropTypes.bool, + hidden: PropTypes.bool, remote: PropTypes.bool, remoteUrl: PropTypes.string, multiColumn: PropTypes.bool, @@ -130,7 +134,7 @@ class AccountTimeline extends ImmutablePureComponent { } render () { - const { statusIds, featuredStatusIds, isLoading, hasMore, suspended, isAccount, multiColumn, remote, remoteUrl } = this.props; + const { accountId, statusIds, featuredStatusIds, isLoading, hasMore, suspended, isAccount, hidden, multiColumn, remote, remoteUrl } = this.props; if (!isAccount) { return ( @@ -151,8 +155,12 @@ class AccountTimeline extends ImmutablePureComponent { let emptyMessage; + const forceEmptyState = suspended || hidden; + if (suspended) { emptyMessage = <FormattedMessage id='empty_column.account_suspended' defaultMessage='Account suspended' />; + } else if (hidden) { + emptyMessage = <LimitedAccountHint accountId={accountId} />; } else if (remote && statusIds.isEmpty()) { emptyMessage = <RemoteHint url={remoteUrl} />; } else { @@ -166,14 +174,14 @@ class AccountTimeline extends ImmutablePureComponent { <ProfileColumnHeader onClick={this.handleHeaderClick} multiColumn={multiColumn} /> <StatusList - prepend={<HeaderContainer accountId={this.props.accountId} />} + prepend={<HeaderContainer accountId={this.props.accountId} hideTabs={forceEmptyState} />} alwaysPrepend append={remoteMessage} scrollKey='account_timeline' - statusIds={suspended ? emptyList : statusIds} + statusIds={forceEmptyState ? emptyList : statusIds} featuredStatusIds={featuredStatusIds} isLoading={isLoading} - hasMore={hasMore} + hasMore={!forceEmptyState && hasMore} onLoadMore={this.handleLoadMore} emptyMessage={emptyMessage} bindToDocument={!multiColumn} diff --git a/app/javascript/flavours/glitch/features/followers/index.js b/app/javascript/flavours/glitch/features/followers/index.js index 978436dccc..27a63b3fdd 100644 --- a/app/javascript/flavours/glitch/features/followers/index.js +++ b/app/javascript/flavours/glitch/features/followers/index.js @@ -19,6 +19,8 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import MissingIndicator from 'flavours/glitch/components/missing_indicator'; import ScrollableList from 'flavours/glitch/components/scrollable_list'; import TimelineHint from 'flavours/glitch/components/timeline_hint'; +import LimitedAccountHint from '../account_timeline/components/limited_account_hint'; +import { getAccountHidden } from 'flavours/glitch/selectors'; const mapStateToProps = (state, { params: { acct, id } }) => { const accountId = id || state.getIn(['accounts_map', acct]); @@ -37,6 +39,8 @@ const mapStateToProps = (state, { params: { acct, id } }) => { accountIds: state.getIn(['user_lists', 'followers', accountId, 'items']), hasMore: !!state.getIn(['user_lists', 'followers', accountId, 'next']), isLoading: state.getIn(['user_lists', 'followers', accountId, 'isLoading'], true), + suspended: state.getIn(['accounts', accountId, 'suspended'], false), + hidden: getAccountHidden(state, accountId), }; }; @@ -62,6 +66,8 @@ class Followers extends ImmutablePureComponent { hasMore: PropTypes.bool, isLoading: PropTypes.bool, isAccount: PropTypes.bool, + suspended: PropTypes.bool, + hidden: PropTypes.bool, remote: PropTypes.bool, remoteUrl: PropTypes.string, multiColumn: PropTypes.bool, @@ -107,7 +113,7 @@ class Followers extends ImmutablePureComponent { } render () { - const { accountIds, hasMore, isAccount, multiColumn, isLoading, remote, remoteUrl } = this.props; + const { accountId, accountIds, hasMore, isAccount, multiColumn, isLoading, suspended, hidden, remote, remoteUrl } = this.props; if (!isAccount) { return ( @@ -127,7 +133,13 @@ class Followers extends ImmutablePureComponent { let emptyMessage; - if (remote && accountIds.isEmpty()) { + const forceEmptyState = suspended || hidden; + + if (suspended) { + emptyMessage = <FormattedMessage id='empty_column.account_suspended' defaultMessage='Account suspended' />; + } else if (hidden) { + emptyMessage = <LimitedAccountHint accountId={accountId} />; + } else if (remote && accountIds.isEmpty()) { emptyMessage = <RemoteHint url={remoteUrl} />; } else { emptyMessage = <FormattedMessage id='account.followers.empty' defaultMessage='No one follows this user yet.' />; @@ -141,7 +153,7 @@ class Followers extends ImmutablePureComponent { <ScrollableList scrollKey='followers' - hasMore={hasMore} + hasMore={!forceEmptyState && hasMore} isLoading={isLoading} onLoadMore={this.handleLoadMore} prepend={<HeaderContainer accountId={this.props.accountId} hideTabs />} diff --git a/app/javascript/flavours/glitch/features/following/index.js b/app/javascript/flavours/glitch/features/following/index.js index 446a19894b..aa187bf957 100644 --- a/app/javascript/flavours/glitch/features/following/index.js +++ b/app/javascript/flavours/glitch/features/following/index.js @@ -19,6 +19,8 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import MissingIndicator from 'flavours/glitch/components/missing_indicator'; import ScrollableList from 'flavours/glitch/components/scrollable_list'; import TimelineHint from 'flavours/glitch/components/timeline_hint'; +import LimitedAccountHint from '../account_timeline/components/limited_account_hint'; +import { getAccountHidden } from 'flavours/glitch/selectors'; const mapStateToProps = (state, { params: { acct, id } }) => { const accountId = id || state.getIn(['accounts_map', acct]); @@ -37,6 +39,8 @@ const mapStateToProps = (state, { params: { acct, id } }) => { accountIds: state.getIn(['user_lists', 'following', accountId, 'items']), hasMore: !!state.getIn(['user_lists', 'following', accountId, 'next']), isLoading: state.getIn(['user_lists', 'following', accountId, 'isLoading'], true), + suspended: state.getIn(['accounts', accountId, 'suspended'], false), + hidden: getAccountHidden(state, accountId), }; }; @@ -62,6 +66,8 @@ class Following extends ImmutablePureComponent { hasMore: PropTypes.bool, isLoading: PropTypes.bool, isAccount: PropTypes.bool, + suspended: PropTypes.bool, + hidden: PropTypes.bool, remote: PropTypes.bool, remoteUrl: PropTypes.string, multiColumn: PropTypes.bool, @@ -107,7 +113,7 @@ class Following extends ImmutablePureComponent { } render () { - const { accountIds, hasMore, isAccount, multiColumn, isLoading, remote, remoteUrl } = this.props; + const { accountId, accountIds, hasMore, isAccount, multiColumn, isLoading, suspended, hidden, remote, remoteUrl } = this.props; if (!isAccount) { return ( @@ -127,7 +133,13 @@ class Following extends ImmutablePureComponent { let emptyMessage; - if (remote && accountIds.isEmpty()) { + const forceEmptyState = suspended || hidden; + + if (suspended) { + emptyMessage = <FormattedMessage id='empty_column.account_suspended' defaultMessage='Account suspended' />; + } else if (hidden) { + emptyMessage = <LimitedAccountHint accountId={accountId} />; + } else if (remote && accountIds.isEmpty()) { emptyMessage = <RemoteHint url={remoteUrl} />; } else { emptyMessage = <FormattedMessage id='account.follows.empty' defaultMessage="This user doesn't follow anyone yet." />; @@ -141,7 +153,7 @@ class Following extends ImmutablePureComponent { <ScrollableList scrollKey='following' - hasMore={hasMore} + hasMore={!forceEmptyState && hasMore} isLoading={isLoading} onLoadMore={this.handleLoadMore} prepend={<HeaderContainer accountId={this.props.accountId} hideTabs />} diff --git a/app/javascript/flavours/glitch/reducers/accounts.js b/app/javascript/flavours/glitch/reducers/accounts.js index 530ed8e607..e02a5592ee 100644 --- a/app/javascript/flavours/glitch/reducers/accounts.js +++ b/app/javascript/flavours/glitch/reducers/accounts.js @@ -1,4 +1,5 @@ -import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from '../actions/importer'; +import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from 'flavours/glitch/actions/importer'; +import { ACCOUNT_REVEAL } from 'flavours/glitch/actions/accounts'; import { Map as ImmutableMap, fromJS } from 'immutable'; const initialState = ImmutableMap(); @@ -10,6 +11,8 @@ const normalizeAccount = (state, account) => { delete account.following_count; delete account.statuses_count; + account.hidden = state.getIn([account.id, 'hidden']) === false ? false : account.limited; + return state.set(account.id, fromJS(account)); }; @@ -27,6 +30,8 @@ export default function accounts(state = initialState, action) { return normalizeAccount(state, action.account); case ACCOUNTS_IMPORT: return normalizeAccounts(state, action.accounts); + case ACCOUNT_REVEAL: + return state.setIn([action.id, 'hidden'], false); default: return state; } diff --git a/app/javascript/flavours/glitch/selectors/index.js b/app/javascript/flavours/glitch/selectors/index.js index bb9180d120..99afe53551 100644 --- a/app/javascript/flavours/glitch/selectors/index.js +++ b/app/javascript/flavours/glitch/selectors/index.js @@ -194,3 +194,11 @@ export const getAccountGallery = createSelector([ return medias; }); + +export const getAccountHidden = createSelector([ + (state, id) => state.getIn(['accounts', id, 'hidden']), + (state, id) => state.getIn(['relationships', id, 'following']) || state.getIn(['relationships', id, 'requested']), + (state, id) => id === me, +], (hidden, followingOrRequested, isSelf) => { + return hidden && !(isSelf || followingOrRequested); +}); diff --git a/app/javascript/flavours/glitch/styles/components/columns.scss b/app/javascript/flavours/glitch/styles/components/columns.scss index 96e292d8b6..d52ecf02c6 100644 --- a/app/javascript/flavours/glitch/styles/components/columns.scss +++ b/app/javascript/flavours/glitch/styles/components/columns.scss @@ -560,6 +560,15 @@ } } +.limited-account-hint { + p { + color: $secondary-text-color; + font-size: 15px; + font-weight: 500; + margin-bottom: 20px; + } +} + .empty-column-indicator, .error-column, .follow_requests-unlocked_explanation {