Merge branch 'master' into glitch-soc/merge-upstream
Conflicts: - README.md - app/helpers/statuses_helper.rb Upstream moved account helpers to their own file, we had extra helpers there, moved too. - app/lib/sanitize_config.rb - app/models/user.rb - app/serializers/initial_state_serializer.rb - config/locales/simple_form.en.yml - spec/lib/sanitize_config_spec.rb
This commit is contained in:
		
						commit
						41a98b6543
					
				| 
						 | 
					@ -1,2 +1,3 @@
 | 
				
			||||||
VAGRANT=true
 | 
					VAGRANT=true
 | 
				
			||||||
LOCAL_DOMAIN=mastodon.local
 | 
					LOCAL_DOMAIN=mastodon.local
 | 
				
			||||||
 | 
					BIND=0.0.0.0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					daysUntilStale: 120
 | 
				
			||||||
 | 
					daysUntilClose: 7
 | 
				
			||||||
 | 
					exemptLabels:
 | 
				
			||||||
 | 
					  - security
 | 
				
			||||||
 | 
					staleLabel: wontfix
 | 
				
			||||||
 | 
					markComment: >
 | 
				
			||||||
 | 
					  This issue has been automatically marked as stale because it has not had
 | 
				
			||||||
 | 
					  recent activity. It will be closed if no further activity occurs. Thank you
 | 
				
			||||||
 | 
					  for your contributions.
 | 
				
			||||||
 | 
					only: pulls
 | 
				
			||||||
							
								
								
									
										2
									
								
								Gemfile
								
								
								
								
							
							
						
						
									
										2
									
								
								Gemfile
								
								
								
								
							| 
						 | 
					@ -137,7 +137,7 @@ group :development do
 | 
				
			||||||
  gem 'letter_opener', '~> 1.7'
 | 
					  gem 'letter_opener', '~> 1.7'
 | 
				
			||||||
  gem 'letter_opener_web', '~> 1.3'
 | 
					  gem 'letter_opener_web', '~> 1.3'
 | 
				
			||||||
  gem 'memory_profiler'
 | 
					  gem 'memory_profiler'
 | 
				
			||||||
  gem 'rubocop', '~> 0.74', require: false
 | 
					  gem 'rubocop', '~> 0.75', require: false
 | 
				
			||||||
  gem 'rubocop-rails', '~> 2.3', require: false
 | 
					  gem 'rubocop-rails', '~> 2.3', require: false
 | 
				
			||||||
  gem 'brakeman', '~> 4.6', require: false
 | 
					  gem 'brakeman', '~> 4.6', require: false
 | 
				
			||||||
  gem 'bundler-audit', '~> 0.6', require: false
 | 
					  gem 'bundler-audit', '~> 0.6', require: false
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										22
									
								
								Gemfile.lock
								
								
								
								
							
							
						
						
									
										22
									
								
								Gemfile.lock
								
								
								
								
							| 
						 | 
					@ -184,17 +184,17 @@ GEM
 | 
				
			||||||
    connection_pool (2.2.2)
 | 
					    connection_pool (2.2.2)
 | 
				
			||||||
    crack (0.4.3)
 | 
					    crack (0.4.3)
 | 
				
			||||||
      safe_yaml (~> 1.0.0)
 | 
					      safe_yaml (~> 1.0.0)
 | 
				
			||||||
    crass (1.0.4)
 | 
					    crass (1.0.5)
 | 
				
			||||||
    css_parser (1.7.0)
 | 
					    css_parser (1.7.0)
 | 
				
			||||||
      addressable
 | 
					      addressable
 | 
				
			||||||
    debug_inspector (0.0.3)
 | 
					    debug_inspector (0.0.3)
 | 
				
			||||||
    derailed_benchmarks (1.4.0)
 | 
					    derailed_benchmarks (1.4.1)
 | 
				
			||||||
      benchmark-ips (~> 2)
 | 
					      benchmark-ips (~> 2)
 | 
				
			||||||
      get_process_mem (~> 0)
 | 
					      get_process_mem (~> 0)
 | 
				
			||||||
      heapy (~> 0)
 | 
					      heapy (~> 0)
 | 
				
			||||||
      memory_profiler (~> 0)
 | 
					      memory_profiler (~> 0)
 | 
				
			||||||
      rack (>= 1)
 | 
					      rack (>= 1)
 | 
				
			||||||
      rake (> 10, < 13)
 | 
					      rake (> 10, < 14)
 | 
				
			||||||
      ruby-statistics (>= 2.1)
 | 
					      ruby-statistics (>= 2.1)
 | 
				
			||||||
      thor (~> 0.19)
 | 
					      thor (~> 0.19)
 | 
				
			||||||
    devise (4.7.1)
 | 
					    devise (4.7.1)
 | 
				
			||||||
| 
						 | 
					@ -358,7 +358,7 @@ GEM
 | 
				
			||||||
      activesupport (>= 4)
 | 
					      activesupport (>= 4)
 | 
				
			||||||
      railties (>= 4)
 | 
					      railties (>= 4)
 | 
				
			||||||
      request_store (~> 1.0)
 | 
					      request_store (~> 1.0)
 | 
				
			||||||
    loofah (2.2.3)
 | 
					    loofah (2.3.1)
 | 
				
			||||||
      crass (~> 1.0.2)
 | 
					      crass (~> 1.0.2)
 | 
				
			||||||
      nokogiri (>= 1.5.9)
 | 
					      nokogiri (>= 1.5.9)
 | 
				
			||||||
    mail (2.7.1)
 | 
					    mail (2.7.1)
 | 
				
			||||||
| 
						 | 
					@ -399,7 +399,7 @@ GEM
 | 
				
			||||||
      concurrent-ruby (~> 1.0, >= 1.0.2)
 | 
					      concurrent-ruby (~> 1.0, >= 1.0.2)
 | 
				
			||||||
      sidekiq (>= 3.5)
 | 
					      sidekiq (>= 3.5)
 | 
				
			||||||
      statsd-ruby (~> 1.4, >= 1.4.0)
 | 
					      statsd-ruby (~> 1.4, >= 1.4.0)
 | 
				
			||||||
    oj (3.9.1)
 | 
					    oj (3.9.2)
 | 
				
			||||||
    omniauth (1.9.0)
 | 
					    omniauth (1.9.0)
 | 
				
			||||||
      hashie (>= 3.4.6, < 3.7.0)
 | 
					      hashie (>= 3.4.6, < 3.7.0)
 | 
				
			||||||
      rack (>= 1.6.2, < 3)
 | 
					      rack (>= 1.6.2, < 3)
 | 
				
			||||||
| 
						 | 
					@ -428,7 +428,7 @@ GEM
 | 
				
			||||||
    parallel (1.17.0)
 | 
					    parallel (1.17.0)
 | 
				
			||||||
    parallel_tests (2.29.2)
 | 
					    parallel_tests (2.29.2)
 | 
				
			||||||
      parallel
 | 
					      parallel
 | 
				
			||||||
    parser (2.6.4.0)
 | 
					    parser (2.6.5.0)
 | 
				
			||||||
      ast (~> 2.4.0)
 | 
					      ast (~> 2.4.0)
 | 
				
			||||||
    parslet (1.8.2)
 | 
					    parslet (1.8.2)
 | 
				
			||||||
    pastel (0.7.3)
 | 
					    pastel (0.7.3)
 | 
				
			||||||
| 
						 | 
					@ -464,7 +464,7 @@ GEM
 | 
				
			||||||
    rack-attack (6.1.0)
 | 
					    rack-attack (6.1.0)
 | 
				
			||||||
      rack (>= 1.0, < 3)
 | 
					      rack (>= 1.0, < 3)
 | 
				
			||||||
    rack-cors (1.0.3)
 | 
					    rack-cors (1.0.3)
 | 
				
			||||||
    rack-protection (2.0.5)
 | 
					    rack-protection (2.0.7)
 | 
				
			||||||
      rack
 | 
					      rack
 | 
				
			||||||
    rack-proxy (0.6.5)
 | 
					    rack-proxy (0.6.5)
 | 
				
			||||||
      rack
 | 
					      rack
 | 
				
			||||||
| 
						 | 
					@ -560,7 +560,7 @@ GEM
 | 
				
			||||||
      rspec-core (~> 3.0, >= 3.0.0)
 | 
					      rspec-core (~> 3.0, >= 3.0.0)
 | 
				
			||||||
      sidekiq (>= 2.4.0)
 | 
					      sidekiq (>= 2.4.0)
 | 
				
			||||||
    rspec-support (3.8.0)
 | 
					    rspec-support (3.8.0)
 | 
				
			||||||
    rubocop (0.74.0)
 | 
					    rubocop (0.75.1)
 | 
				
			||||||
      jaro_winkler (~> 1.5.1)
 | 
					      jaro_winkler (~> 1.5.1)
 | 
				
			||||||
      parallel (~> 1.10)
 | 
					      parallel (~> 1.10)
 | 
				
			||||||
      parser (>= 2.6)
 | 
					      parser (>= 2.6)
 | 
				
			||||||
| 
						 | 
					@ -593,7 +593,7 @@ GEM
 | 
				
			||||||
      rufus-scheduler (~> 3.2)
 | 
					      rufus-scheduler (~> 3.2)
 | 
				
			||||||
      sidekiq (>= 3)
 | 
					      sidekiq (>= 3)
 | 
				
			||||||
      tilt (>= 1.4.0)
 | 
					      tilt (>= 1.4.0)
 | 
				
			||||||
    sidekiq-unique-jobs (6.0.13)
 | 
					    sidekiq-unique-jobs (6.0.15)
 | 
				
			||||||
      concurrent-ruby (~> 1.0, >= 1.0.5)
 | 
					      concurrent-ruby (~> 1.0, >= 1.0.5)
 | 
				
			||||||
      sidekiq (>= 4.0, < 7.0)
 | 
					      sidekiq (>= 4.0, < 7.0)
 | 
				
			||||||
      thor (~> 0)
 | 
					      thor (~> 0)
 | 
				
			||||||
| 
						 | 
					@ -617,7 +617,7 @@ GEM
 | 
				
			||||||
    sshkit (1.20.0)
 | 
					    sshkit (1.20.0)
 | 
				
			||||||
      net-scp (>= 1.1.2)
 | 
					      net-scp (>= 1.1.2)
 | 
				
			||||||
      net-ssh (>= 2.8.0)
 | 
					      net-ssh (>= 2.8.0)
 | 
				
			||||||
    stackprof (0.2.12)
 | 
					    stackprof (0.2.13)
 | 
				
			||||||
    statsd-ruby (1.4.0)
 | 
					    statsd-ruby (1.4.0)
 | 
				
			||||||
    stoplight (2.1.3)
 | 
					    stoplight (2.1.3)
 | 
				
			||||||
    streamio-ffmpeg (3.0.2)
 | 
					    streamio-ffmpeg (3.0.2)
 | 
				
			||||||
| 
						 | 
					@ -782,7 +782,7 @@ DEPENDENCIES
 | 
				
			||||||
  rqrcode (~> 0.10)
 | 
					  rqrcode (~> 0.10)
 | 
				
			||||||
  rspec-rails (~> 3.8)
 | 
					  rspec-rails (~> 3.8)
 | 
				
			||||||
  rspec-sidekiq (~> 3.0)
 | 
					  rspec-sidekiq (~> 3.0)
 | 
				
			||||||
  rubocop (~> 0.74)
 | 
					  rubocop (~> 0.75)
 | 
				
			||||||
  rubocop-rails (~> 2.3)
 | 
					  rubocop-rails (~> 2.3)
 | 
				
			||||||
  ruby-progressbar (~> 1.10)
 | 
					  ruby-progressbar (~> 1.10)
 | 
				
			||||||
  sanitize (~> 5.1)
 | 
					  sanitize (~> 5.1)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@ class ActivityPub::InboxesController < ActivityPub::BaseController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  before_action :skip_unknown_actor_delete
 | 
					  before_action :skip_unknown_actor_delete
 | 
				
			||||||
  before_action :require_signature!
 | 
					  before_action :require_signature!
 | 
				
			||||||
 | 
					  skip_before_action :authenticate_user!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def create
 | 
					  def create
 | 
				
			||||||
    upgrade_account
 | 
					    upgrade_account
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,6 +60,7 @@ class Settings::PreferencesController < Settings::BaseController
 | 
				
			||||||
      :setting_use_blurhash,
 | 
					      :setting_use_blurhash,
 | 
				
			||||||
      :setting_use_pending_items,
 | 
					      :setting_use_pending_items,
 | 
				
			||||||
      :setting_trends,
 | 
					      :setting_trends,
 | 
				
			||||||
 | 
					      :setting_crop_images,
 | 
				
			||||||
      notification_emails: %i(follow follow_request reblog favourite mention digest report pending_account trending_tag),
 | 
					      notification_emails: %i(follow follow_request reblog favourite mention digest report pending_account trending_tag),
 | 
				
			||||||
      interactions: %i(must_be_follower must_be_following must_be_following_dm)
 | 
					      interactions: %i(must_be_follower must_be_following must_be_following_dm)
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,112 @@
 | 
				
			||||||
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module AccountsHelper
 | 
				
			||||||
 | 
					  def display_name(account, **options)
 | 
				
			||||||
 | 
					    if options[:custom_emojify]
 | 
				
			||||||
 | 
					      Formatter.instance.format_display_name(account, options)
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      account.display_name.presence || account.username
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def acct(account)
 | 
				
			||||||
 | 
					    if account.local?
 | 
				
			||||||
 | 
					      "@#{account.acct}@#{Rails.configuration.x.local_domain}"
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      "@#{account.acct}"
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def account_action_button(account)
 | 
				
			||||||
 | 
					    if user_signed_in?
 | 
				
			||||||
 | 
					      if account.id == current_user.account_id
 | 
				
			||||||
 | 
					        link_to settings_profile_url, class: 'button logo-button' do
 | 
				
			||||||
 | 
					          safe_join([svg_logo, t('settings.edit_profile')])
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      elsif current_account.following?(account) || current_account.requested?(account)
 | 
				
			||||||
 | 
					        link_to account_unfollow_path(account), class: 'button logo-button button--destructive', data: { method: :post } do
 | 
				
			||||||
 | 
					          safe_join([svg_logo, t('accounts.unfollow')])
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      elsif !(account.memorial? || account.moved?)
 | 
				
			||||||
 | 
					        link_to account_follow_path(account), class: "button logo-button#{account.blocking?(current_account) ? ' disabled' : ''}", data: { method: :post } do
 | 
				
			||||||
 | 
					          safe_join([svg_logo, t('accounts.follow')])
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    elsif !(account.memorial? || account.moved?)
 | 
				
			||||||
 | 
					      link_to account_remote_follow_path(account), class: 'button logo-button modal-button', target: '_new' do
 | 
				
			||||||
 | 
					        safe_join([svg_logo, t('accounts.follow')])
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def minimal_account_action_button(account)
 | 
				
			||||||
 | 
					    if user_signed_in?
 | 
				
			||||||
 | 
					      return if account.id == current_user.account_id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if current_account.following?(account) || current_account.requested?(account)
 | 
				
			||||||
 | 
					        link_to account_unfollow_path(account), class: 'icon-button active', data: { method: :post }, title: t('accounts.unfollow') do
 | 
				
			||||||
 | 
					          fa_icon('user-times fw')
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      elsif !(account.memorial? || account.moved?)
 | 
				
			||||||
 | 
					        link_to account_follow_path(account), class: "icon-button#{account.blocking?(current_account) ? ' disabled' : ''}", data: { method: :post }, title: t('accounts.follow') do
 | 
				
			||||||
 | 
					          fa_icon('user-plus fw')
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    elsif !(account.memorial? || account.moved?)
 | 
				
			||||||
 | 
					      link_to account_remote_follow_path(account), class: 'icon-button modal-button', target: '_new', title: t('accounts.follow') do
 | 
				
			||||||
 | 
					        fa_icon('user-plus fw')
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def account_badge(account, all: false)
 | 
				
			||||||
 | 
					    if account.bot?
 | 
				
			||||||
 | 
					      content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles')
 | 
				
			||||||
 | 
					    elsif (Setting.show_staff_badge && account.user_staff?) || all
 | 
				
			||||||
 | 
					      content_tag(:div, class: 'roles') do
 | 
				
			||||||
 | 
					        if all && !account.user_staff?
 | 
				
			||||||
 | 
					          content_tag(:div, t('admin.accounts.roles.user'), class: 'account-role')
 | 
				
			||||||
 | 
					        elsif account.user_admin?
 | 
				
			||||||
 | 
					          content_tag(:div, t('accounts.roles.admin'), class: 'account-role admin')
 | 
				
			||||||
 | 
					        elsif account.user_moderator?
 | 
				
			||||||
 | 
					          content_tag(:div, t('accounts.roles.moderator'), class: 'account-role moderator')
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def hide_followers_count?(account)
 | 
				
			||||||
 | 
					    Setting.hide_followers_count || account.user&.setting_hide_followers_count
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def account_description(account)
 | 
				
			||||||
 | 
					    prepend_stats = [
 | 
				
			||||||
 | 
					      [
 | 
				
			||||||
 | 
					        number_to_human(account.statuses_count, strip_insignificant_zeros: true),
 | 
				
			||||||
 | 
					        I18n.t('accounts.posts', count: account.statuses_count),
 | 
				
			||||||
 | 
					      ].join(' '),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      [
 | 
				
			||||||
 | 
					        number_to_human(account.following_count, strip_insignificant_zeros: true),
 | 
				
			||||||
 | 
					        I18n.t('accounts.following', count: account.following_count),
 | 
				
			||||||
 | 
					      ].join(' '),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unless hide_followers_count?(account)
 | 
				
			||||||
 | 
					      prepend_stats << [
 | 
				
			||||||
 | 
					        number_to_human(account.followers_count, strip_insignificant_zeros: true),
 | 
				
			||||||
 | 
					        I18n.t('accounts.followers', count: account.followers_count),
 | 
				
			||||||
 | 
					      ].join(' ')
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [prepend_stats.join(', '), account.note].join(' · ')
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def svg_logo
 | 
				
			||||||
 | 
					    content_tag(:svg, tag(:use, 'xlink:href' => '#mastodon-svg-logo'), 'viewBox' => '0 0 216.4144 232.00976')
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def svg_logo_full
 | 
				
			||||||
 | 
					    content_tag(:svg, tag(:use, 'xlink:href' => '#mastodon-svg-logo-full'), 'viewBox' => '0 0 713.35878 175.8678')
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -4,80 +4,6 @@ module StatusesHelper
 | 
				
			||||||
  EMBEDDED_CONTROLLER = 'statuses'
 | 
					  EMBEDDED_CONTROLLER = 'statuses'
 | 
				
			||||||
  EMBEDDED_ACTION = 'embed'
 | 
					  EMBEDDED_ACTION = 'embed'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def display_name(account, **options)
 | 
					 | 
				
			||||||
    if options[:custom_emojify]
 | 
					 | 
				
			||||||
      Formatter.instance.format_display_name(account, options)
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      account.display_name.presence || account.username
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def account_action_button(account)
 | 
					 | 
				
			||||||
    if user_signed_in?
 | 
					 | 
				
			||||||
      if account.id == current_user.account_id
 | 
					 | 
				
			||||||
        link_to settings_profile_url, class: 'button logo-button' do
 | 
					 | 
				
			||||||
          safe_join([svg_logo, t('settings.edit_profile')])
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
      elsif current_account.following?(account) || current_account.requested?(account)
 | 
					 | 
				
			||||||
        link_to account_unfollow_path(account), class: 'button logo-button button--destructive', data: { method: :post } do
 | 
					 | 
				
			||||||
          safe_join([svg_logo, t('accounts.unfollow')])
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
      elsif !(account.memorial? || account.moved?)
 | 
					 | 
				
			||||||
        link_to account_follow_path(account), class: "button logo-button#{account.blocking?(current_account) ? ' disabled' : ''}", data: { method: :post } do
 | 
					 | 
				
			||||||
          safe_join([svg_logo, t('accounts.follow')])
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    elsif !(account.memorial? || account.moved?)
 | 
					 | 
				
			||||||
      link_to account_remote_follow_path(account), class: 'button logo-button modal-button', target: '_new' do
 | 
					 | 
				
			||||||
        safe_join([svg_logo, t('accounts.follow')])
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def minimal_account_action_button(account)
 | 
					 | 
				
			||||||
    if user_signed_in?
 | 
					 | 
				
			||||||
      return if account.id == current_user.account_id
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if current_account.following?(account) || current_account.requested?(account)
 | 
					 | 
				
			||||||
        link_to account_unfollow_path(account), class: 'icon-button active', data: { method: :post }, title: t('accounts.unfollow') do
 | 
					 | 
				
			||||||
          fa_icon('user-times fw')
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
      elsif !(account.memorial? || account.moved?)
 | 
					 | 
				
			||||||
        link_to account_follow_path(account), class: "icon-button#{account.blocking?(current_account) ? ' disabled' : ''}", data: { method: :post }, title: t('accounts.follow') do
 | 
					 | 
				
			||||||
          fa_icon('user-plus fw')
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    elsif !(account.memorial? || account.moved?)
 | 
					 | 
				
			||||||
      link_to account_remote_follow_path(account), class: 'icon-button modal-button', target: '_new', title: t('accounts.follow') do
 | 
					 | 
				
			||||||
        fa_icon('user-plus fw')
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def svg_logo
 | 
					 | 
				
			||||||
    content_tag(:svg, tag(:use, 'xlink:href' => '#mastodon-svg-logo'), 'viewBox' => '0 0 216.4144 232.00976')
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def svg_logo_full
 | 
					 | 
				
			||||||
    content_tag(:svg, tag(:use, 'xlink:href' => '#mastodon-svg-logo-full'), 'viewBox' => '0 0 713.35878 175.8678')
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def account_badge(account, all: false)
 | 
					 | 
				
			||||||
    if account.bot?
 | 
					 | 
				
			||||||
      content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles')
 | 
					 | 
				
			||||||
    elsif (Setting.show_staff_badge && account.user_staff?) || all
 | 
					 | 
				
			||||||
      content_tag(:div, class: 'roles') do
 | 
					 | 
				
			||||||
        if all && !account.user_staff?
 | 
					 | 
				
			||||||
          content_tag(:div, t('admin.accounts.roles.user'), class: 'account-role')
 | 
					 | 
				
			||||||
        elsif account.user_admin?
 | 
					 | 
				
			||||||
          content_tag(:div, t('accounts.roles.admin'), class: 'account-role admin')
 | 
					 | 
				
			||||||
        elsif account.user_moderator?
 | 
					 | 
				
			||||||
          content_tag(:div, t('accounts.roles.moderator'), class: 'account-role moderator')
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def link_to_more(url)
 | 
					  def link_to_more(url)
 | 
				
			||||||
    link_to t('statuses.show_more'), url, class: 'load-more load-gap'
 | 
					    link_to t('statuses.show_more'), url, class: 'load-more load-gap'
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					@ -88,33 +14,6 @@ module StatusesHelper
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def hide_followers_count?(account)
 | 
					 | 
				
			||||||
    Setting.hide_followers_count || account.user&.setting_hide_followers_count
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def account_description(account)
 | 
					 | 
				
			||||||
    prepend_stats = [
 | 
					 | 
				
			||||||
      [
 | 
					 | 
				
			||||||
        number_to_human(account.statuses_count, strip_insignificant_zeros: true),
 | 
					 | 
				
			||||||
        I18n.t('accounts.posts', count: account.statuses_count),
 | 
					 | 
				
			||||||
      ].join(' '),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      [
 | 
					 | 
				
			||||||
        number_to_human(account.following_count, strip_insignificant_zeros: true),
 | 
					 | 
				
			||||||
        I18n.t('accounts.following', count: account.following_count),
 | 
					 | 
				
			||||||
      ].join(' '),
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    unless hide_followers_count?(account)
 | 
					 | 
				
			||||||
      prepend_stats << [
 | 
					 | 
				
			||||||
        number_to_human(account.followers_count, strip_insignificant_zeros: true),
 | 
					 | 
				
			||||||
        I18n.t('accounts.followers', count: account.followers_count),
 | 
					 | 
				
			||||||
      ].join(' ')
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    [prepend_stats.join(', '), account.note].join(' · ')
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def media_summary(status)
 | 
					  def media_summary(status)
 | 
				
			||||||
    attachments = { image: 0, video: 0 }
 | 
					    attachments = { image: 0, video: 0 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -160,14 +59,6 @@ module StatusesHelper
 | 
				
			||||||
    embedded_view? ? '_blank' : nil
 | 
					    embedded_view? ? '_blank' : nil
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def acct(account)
 | 
					 | 
				
			||||||
    if account.local?
 | 
					 | 
				
			||||||
      "@#{account.acct}@#{Rails.configuration.x.local_domain}"
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      "@#{account.acct}"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def style_classes(status, is_predecessor, is_successor, include_threads)
 | 
					  def style_classes(status, is_predecessor, is_successor, include_threads)
 | 
				
			||||||
    classes = ['entry']
 | 
					    classes = ['entry']
 | 
				
			||||||
    classes << 'entry-predecessor' if is_predecessor
 | 
					    classes << 'entry-predecessor' if is_predecessor
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,7 @@ export default class AttachmentList extends ImmutablePureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              return (
 | 
					              return (
 | 
				
			||||||
                <li key={attachment.get('id')}>
 | 
					                <li key={attachment.get('id')}>
 | 
				
			||||||
                  <a href={displayUrl} target='_blank' rel='noopener'><Icon id='link' /> {filename(displayUrl)}</a>
 | 
					                  <a href={displayUrl} target='_blank' rel='noopener noreferrer'><Icon id='link' /> {filename(displayUrl)}</a>
 | 
				
			||||||
                </li>
 | 
					                </li>
 | 
				
			||||||
              );
 | 
					              );
 | 
				
			||||||
            })}
 | 
					            })}
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ export default class AttachmentList extends ImmutablePureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return (
 | 
					            return (
 | 
				
			||||||
              <li key={attachment.get('id')}>
 | 
					              <li key={attachment.get('id')}>
 | 
				
			||||||
                <a href={displayUrl} target='_blank' rel='noopener'>{filename(displayUrl)}</a>
 | 
					                <a href={displayUrl} target='_blank' rel='noopener noreferrer'>{filename(displayUrl)}</a>
 | 
				
			||||||
              </li>
 | 
					              </li>
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
          })}
 | 
					          })}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -143,7 +143,7 @@ class DropdownMenu extends React.PureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <li className='dropdown-menu__item' key={`${text}-${i}`}>
 | 
					      <li className='dropdown-menu__item' key={`${text}-${i}`}>
 | 
				
			||||||
        <a href={href} target={target} data-method={method} rel='noopener' role='button' tabIndex='0' ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}>
 | 
					        <a href={href} target={target} data-method={method} rel='noopener noreferrer' role='button' tabIndex='0' ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}>
 | 
				
			||||||
          {text}
 | 
					          {text}
 | 
				
			||||||
        </a>
 | 
					        </a>
 | 
				
			||||||
      </li>
 | 
					      </li>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,7 @@ export default class ErrorBoundary extends React.PureComponent {
 | 
				
			||||||
        <div>
 | 
					        <div>
 | 
				
			||||||
          <p className='error-boundary__error'><FormattedMessage id='error.unexpected_crash.explanation' defaultMessage='Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.' /></p>
 | 
					          <p className='error-boundary__error'><FormattedMessage id='error.unexpected_crash.explanation' defaultMessage='Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.' /></p>
 | 
				
			||||||
          <p><FormattedMessage id='error.unexpected_crash.next_steps' defaultMessage='Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.' /></p>
 | 
					          <p><FormattedMessage id='error.unexpected_crash.next_steps' defaultMessage='Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.' /></p>
 | 
				
			||||||
          <p className='error-boundary__footer'>Mastodon v{version} · <a href={source_url} rel='noopener' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> · <button onClick={this.handleCopyStackTrace} className={copied && 'copied'}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p>
 | 
					          <p className='error-boundary__footer'>Mastodon v{version} · <a href={source_url} rel='noopener noreferrer' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> · <button onClick={this.handleCopyStackTrace} className={copied && 'copied'}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,4 @@
 | 
				
			||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
import Motion from '../features/ui/util/optional_motion';
 | 
					 | 
				
			||||||
import spring from 'react-motion/lib/spring';
 | 
					 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
import classNames from 'classnames';
 | 
					import classNames from 'classnames';
 | 
				
			||||||
import Icon from 'mastodon/components/icon';
 | 
					import Icon from 'mastodon/components/icon';
 | 
				
			||||||
| 
						 | 
					@ -37,6 +35,21 @@ export default class IconButton extends React.PureComponent {
 | 
				
			||||||
    tabIndex: '0',
 | 
					    tabIndex: '0',
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  state = {
 | 
				
			||||||
 | 
					    activate: false,
 | 
				
			||||||
 | 
					    deactivate: false,
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  componentWillReceiveProps (nextProps) {
 | 
				
			||||||
 | 
					    if (!nextProps.animate) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (this.props.active && !nextProps.active) {
 | 
				
			||||||
 | 
					      this.setState({ activate: false, deactivate: true });
 | 
				
			||||||
 | 
					    } else if (!this.props.active && nextProps.active) {
 | 
				
			||||||
 | 
					      this.setState({ activate: true, deactivate: false });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleClick = (e) =>  {
 | 
					  handleClick = (e) =>  {
 | 
				
			||||||
    e.preventDefault();
 | 
					    e.preventDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,7 +88,6 @@ export default class IconButton extends React.PureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const {
 | 
					    const {
 | 
				
			||||||
      active,
 | 
					      active,
 | 
				
			||||||
      animate,
 | 
					 | 
				
			||||||
      className,
 | 
					      className,
 | 
				
			||||||
      disabled,
 | 
					      disabled,
 | 
				
			||||||
      expanded,
 | 
					      expanded,
 | 
				
			||||||
| 
						 | 
					@ -87,57 +99,37 @@ export default class IconButton extends React.PureComponent {
 | 
				
			||||||
      title,
 | 
					      title,
 | 
				
			||||||
    } = this.props;
 | 
					    } = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const {
 | 
				
			||||||
 | 
					      activate,
 | 
				
			||||||
 | 
					      deactivate,
 | 
				
			||||||
 | 
					    } = this.state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const classes = classNames(className, 'icon-button', {
 | 
					    const classes = classNames(className, 'icon-button', {
 | 
				
			||||||
      active,
 | 
					      active,
 | 
				
			||||||
      disabled,
 | 
					      disabled,
 | 
				
			||||||
      inverted,
 | 
					      inverted,
 | 
				
			||||||
 | 
					      activate,
 | 
				
			||||||
 | 
					      deactivate,
 | 
				
			||||||
      overlayed: overlay,
 | 
					      overlayed: overlay,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!animate) {
 | 
					 | 
				
			||||||
      // Perf optimization: avoid unnecessary <Motion> components unless
 | 
					 | 
				
			||||||
      // we actually need to animate.
 | 
					 | 
				
			||||||
      return (
 | 
					 | 
				
			||||||
        <button
 | 
					 | 
				
			||||||
          aria-label={title}
 | 
					 | 
				
			||||||
          aria-pressed={pressed}
 | 
					 | 
				
			||||||
          aria-expanded={expanded}
 | 
					 | 
				
			||||||
          title={title}
 | 
					 | 
				
			||||||
          className={classes}
 | 
					 | 
				
			||||||
          onClick={this.handleClick}
 | 
					 | 
				
			||||||
          onMouseDown={this.handleMouseDown}
 | 
					 | 
				
			||||||
          onKeyDown={this.handleKeyDown}
 | 
					 | 
				
			||||||
          onKeyPress={this.handleKeyPress}
 | 
					 | 
				
			||||||
          style={style}
 | 
					 | 
				
			||||||
          tabIndex={tabIndex}
 | 
					 | 
				
			||||||
          disabled={disabled}
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
          <Icon id={icon} fixedWidth aria-hidden='true' />
 | 
					 | 
				
			||||||
        </button>
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <Motion defaultStyle={{ rotate: active ? -360 : 0 }} style={{ rotate: animate ? spring(active ? -360 : 0, { stiffness: 120, damping: 7 }) : 0 }}>
 | 
					      <button
 | 
				
			||||||
        {({ rotate }) => (
 | 
					        aria-label={title}
 | 
				
			||||||
          <button
 | 
					        aria-pressed={pressed}
 | 
				
			||||||
            aria-label={title}
 | 
					        aria-expanded={expanded}
 | 
				
			||||||
            aria-pressed={pressed}
 | 
					        title={title}
 | 
				
			||||||
            aria-expanded={expanded}
 | 
					        className={classes}
 | 
				
			||||||
            title={title}
 | 
					        onClick={this.handleClick}
 | 
				
			||||||
            className={classes}
 | 
					        onMouseDown={this.handleMouseDown}
 | 
				
			||||||
            onClick={this.handleClick}
 | 
					        onKeyDown={this.handleKeyDown}
 | 
				
			||||||
            onMouseDown={this.handleMouseDown}
 | 
					        onKeyPress={this.handleKeyPress}
 | 
				
			||||||
            onKeyDown={this.handleKeyDown}
 | 
					        style={style}
 | 
				
			||||||
            onKeyPress={this.handleKeyPress}
 | 
					        tabIndex={tabIndex}
 | 
				
			||||||
            style={style}
 | 
					        disabled={disabled}
 | 
				
			||||||
            tabIndex={tabIndex}
 | 
					      >
 | 
				
			||||||
            disabled={disabled}
 | 
					        <Icon id={icon} fixedWidth aria-hidden='true' />
 | 
				
			||||||
          >
 | 
					      </button>
 | 
				
			||||||
            <Icon id={icon} style={{ transform: `rotate(${rotate}deg)` }} fixedWidth aria-hidden='true' />
 | 
					 | 
				
			||||||
          </button>
 | 
					 | 
				
			||||||
        )}
 | 
					 | 
				
			||||||
      </Motion>
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@ import IconButton from './icon_button';
 | 
				
			||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
					import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
				
			||||||
import { isIOS } from '../is_mobile';
 | 
					import { isIOS } from '../is_mobile';
 | 
				
			||||||
import classNames from 'classnames';
 | 
					import classNames from 'classnames';
 | 
				
			||||||
import { autoPlayGif, displayMedia, useBlurhash } from '../initial_state';
 | 
					import { autoPlayGif, cropImages, displayMedia, useBlurhash } from '../initial_state';
 | 
				
			||||||
import { decode } from 'blurhash';
 | 
					import { decode } from 'blurhash';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messages = defineMessages({
 | 
					const messages = defineMessages({
 | 
				
			||||||
| 
						 | 
					@ -159,7 +159,7 @@ class Item extends React.PureComponent {
 | 
				
			||||||
    if (attachment.get('type') === 'unknown') {
 | 
					    if (attachment.get('type') === 'unknown') {
 | 
				
			||||||
      return (
 | 
					      return (
 | 
				
			||||||
        <div className={classNames('media-gallery__item', { standalone })} key={attachment.get('id')} style={{ left: left, top: top, right: right, bottom: bottom, width: `${width}%`, height: `${height}%` }}>
 | 
					        <div className={classNames('media-gallery__item', { standalone })} key={attachment.get('id')} style={{ left: left, top: top, right: right, bottom: bottom, width: `${width}%`, height: `${height}%` }}>
 | 
				
			||||||
          <a className='media-gallery__item-thumbnail' href={attachment.get('remote_url') || attachment.get('url')} target='_blank' style={{ cursor: 'pointer' }} title={attachment.get('description')}>
 | 
					          <a className='media-gallery__item-thumbnail' href={attachment.get('remote_url') || attachment.get('url')} style={{ cursor: 'pointer' }} title={attachment.get('description')} target='_blank' rel='noopener noreferrer'>
 | 
				
			||||||
            <canvas width={32} height={32} ref={this.setCanvasRef} className='media-gallery__preview' />
 | 
					            <canvas width={32} height={32} ref={this.setCanvasRef} className='media-gallery__preview' />
 | 
				
			||||||
          </a>
 | 
					          </a>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
| 
						 | 
					@ -187,6 +187,7 @@ class Item extends React.PureComponent {
 | 
				
			||||||
          href={attachment.get('remote_url') || originalUrl}
 | 
					          href={attachment.get('remote_url') || originalUrl}
 | 
				
			||||||
          onClick={this.handleClick}
 | 
					          onClick={this.handleClick}
 | 
				
			||||||
          target='_blank'
 | 
					          target='_blank'
 | 
				
			||||||
 | 
					          rel='noopener noreferrer'
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
          <img
 | 
					          <img
 | 
				
			||||||
            src={previewUrl}
 | 
					            src={previewUrl}
 | 
				
			||||||
| 
						 | 
					@ -280,7 +281,7 @@ class MediaGallery extends React.PureComponent {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleRef = (node) => {
 | 
					  handleRef = (node) => {
 | 
				
			||||||
    if (node /*&& this.isStandaloneEligible()*/) {
 | 
					    if (node) {
 | 
				
			||||||
      // offsetWidth triggers a layout, so only calculate when we need to
 | 
					      // offsetWidth triggers a layout, so only calculate when we need to
 | 
				
			||||||
      if (this.props.cacheWidth) this.props.cacheWidth(node.offsetWidth);
 | 
					      if (this.props.cacheWidth) this.props.cacheWidth(node.offsetWidth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -290,13 +291,13 @@ class MediaGallery extends React.PureComponent {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  isStandaloneEligible() {
 | 
					  isFullSizeEligible() {
 | 
				
			||||||
    const { media, standalone } = this.props;
 | 
					    const { media } = this.props;
 | 
				
			||||||
    return standalone && media.size === 1 && media.getIn([0, 'meta', 'small', 'aspect']);
 | 
					    return media.size === 1 && media.getIn([0, 'meta', 'small', 'aspect']);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  render () {
 | 
					  render () {
 | 
				
			||||||
    const { media, intl, sensitive, height, defaultWidth } = this.props;
 | 
					    const { media, intl, sensitive, height, defaultWidth, standalone } = this.props;
 | 
				
			||||||
    const { visible } = this.state;
 | 
					    const { visible } = this.state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const width = this.state.width || defaultWidth;
 | 
					    const width = this.state.width || defaultWidth;
 | 
				
			||||||
| 
						 | 
					@ -305,7 +306,7 @@ class MediaGallery extends React.PureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const style = {};
 | 
					    const style = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (this.isStandaloneEligible()) {
 | 
					    if (this.isFullSizeEligible() && (standalone || !cropImages)) {
 | 
				
			||||||
      if (width) {
 | 
					      if (width) {
 | 
				
			||||||
        style.height = width / this.props.media.getIn([0, 'meta', 'small', 'aspect']);
 | 
					        style.height = width / this.props.media.getIn([0, 'meta', 'small', 'aspect']);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -318,7 +319,7 @@ class MediaGallery extends React.PureComponent {
 | 
				
			||||||
    const size     = media.take(4).size;
 | 
					    const size     = media.take(4).size;
 | 
				
			||||||
    const uncached = media.every(attachment => attachment.get('type') === 'unknown');
 | 
					    const uncached = media.every(attachment => attachment.get('type') === 'unknown');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (this.isStandaloneEligible()) {
 | 
					    if (standalone && this.isFullSizeEligible()) {
 | 
				
			||||||
      children = <Item standalone onClick={this.handleClick} attachment={media.get(0)} displayWidth={width} visible={visible} />;
 | 
					      children = <Item standalone onClick={this.handleClick} attachment={media.get(0)} displayWidth={width} visible={visible} />;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} onClick={this.handleClick} attachment={attachment} index={i} size={size} displayWidth={width} visible={visible || uncached} />);
 | 
					      children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} onClick={this.handleClick} attachment={attachment} index={i} size={size} displayWidth={width} visible={visible || uncached} />);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -437,9 +437,9 @@ class Status extends ImmutablePureComponent {
 | 
				
			||||||
          <div className={classNames('status', `status-${status.get('visibility')}`, { 'status-reply': !!status.get('in_reply_to_id'), muted: this.props.muted, read: unread === false })} data-id={status.get('id')}>
 | 
					          <div className={classNames('status', `status-${status.get('visibility')}`, { 'status-reply': !!status.get('in_reply_to_id'), muted: this.props.muted, read: unread === false })} data-id={status.get('id')}>
 | 
				
			||||||
            <div className='status__expand' onClick={this.handleExpandClick} role='presentation' />
 | 
					            <div className='status__expand' onClick={this.handleExpandClick} role='presentation' />
 | 
				
			||||||
            <div className='status__info'>
 | 
					            <div className='status__info'>
 | 
				
			||||||
              <a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener'><RelativeTimestamp timestamp={status.get('created_at')} /></a>
 | 
					              <a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener noreferrer'><RelativeTimestamp timestamp={status.get('created_at')} /></a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <a onClick={this.handleAccountClick} target='_blank' data-id={status.getIn(['account', 'id'])} href={status.getIn(['account', 'url'])} title={status.getIn(['account', 'acct'])} className='status__display-name'>
 | 
					              <a onClick={this.handleAccountClick} data-id={status.getIn(['account', 'id'])} href={status.getIn(['account', 'url'])} title={status.getIn(['account', 'acct'])} className='status__display-name' target='_blank' rel='noopener noreferrer'>
 | 
				
			||||||
                <div className='status__avatar'>
 | 
					                <div className='status__avatar'>
 | 
				
			||||||
                  {statusAvatar}
 | 
					                  {statusAvatar}
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,7 +59,7 @@ export default class StatusContent extends React.PureComponent {
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      link.setAttribute('target', '_blank');
 | 
					      link.setAttribute('target', '_blank');
 | 
				
			||||||
      link.setAttribute('rel', 'noopener');
 | 
					      link.setAttribute('rel', 'noopener noreferrer');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (
 | 
					    if (
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -253,7 +253,7 @@ class Header extends ImmutablePureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div className='account__header__bar'>
 | 
					        <div className='account__header__bar'>
 | 
				
			||||||
          <div className='account__header__tabs'>
 | 
					          <div className='account__header__tabs'>
 | 
				
			||||||
            <a className='avatar' href={account.get('url')} rel='noopener' target='_blank'>
 | 
					            <a className='avatar' href={account.get('url')} rel='noopener noreferrer' target='_blank'>
 | 
				
			||||||
              <Avatar account={account} size={90} />
 | 
					              <Avatar account={account} size={90} />
 | 
				
			||||||
            </a>
 | 
					            </a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -282,10 +282,10 @@ class Header extends ImmutablePureComponent {
 | 
				
			||||||
                      <dt dangerouslySetInnerHTML={{ __html: proof.get('provider') }} />
 | 
					                      <dt dangerouslySetInnerHTML={{ __html: proof.get('provider') }} />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                      <dd className='verified'>
 | 
					                      <dd className='verified'>
 | 
				
			||||||
                        <a href={proof.get('proof_url')} target='_blank' rel='noopener'><span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(proof.get('updated_at'), dateFormatOptions) })}>
 | 
					                        <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' />
 | 
					                          <Icon id='check' className='verified__mark' />
 | 
				
			||||||
                        </span></a>
 | 
					                        </span></a>
 | 
				
			||||||
                        <a href={proof.get('profile_url')} target='_blank' rel='noopener'><span dangerouslySetInnerHTML={{ __html: ' '+proof.get('provider_username') }} /></a>
 | 
					                        <a href={proof.get('profile_url')} target='_blank' rel='noopener noreferrer'><span dangerouslySetInnerHTML={{ __html: ' '+proof.get('provider_username') }} /></a>
 | 
				
			||||||
                      </dd>
 | 
					                      </dd>
 | 
				
			||||||
                    </dl>
 | 
					                    </dl>
 | 
				
			||||||
                  ))}
 | 
					                  ))}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,12 @@
 | 
				
			||||||
import React from 'react';
 | 
					import { decode } from 'blurhash';
 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					import classNames from 'classnames';
 | 
				
			||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
					 | 
				
			||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
					 | 
				
			||||||
import Icon from 'mastodon/components/icon';
 | 
					import Icon from 'mastodon/components/icon';
 | 
				
			||||||
import { autoPlayGif, displayMedia } from 'mastodon/initial_state';
 | 
					import { autoPlayGif, displayMedia } from 'mastodon/initial_state';
 | 
				
			||||||
import classNames from 'classnames';
 | 
					 | 
				
			||||||
import { decode } from 'blurhash';
 | 
					 | 
				
			||||||
import { isIOS } from 'mastodon/is_mobile';
 | 
					import { isIOS } from 'mastodon/is_mobile';
 | 
				
			||||||
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
				
			||||||
 | 
					import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class MediaItem extends ImmutablePureComponent {
 | 
					export default class MediaItem extends ImmutablePureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -151,7 +151,7 @@ export default class MediaItem extends ImmutablePureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div className='account-gallery__item' style={{ width, height }}>
 | 
					      <div className='account-gallery__item' style={{ width, height }}>
 | 
				
			||||||
        <a className='media-gallery__item-thumbnail' href={status.get('url')} target='_blank' onClick={this.handleClick} title={title}>
 | 
					        <a className='media-gallery__item-thumbnail' href={status.get('url')} onClick={this.handleClick} title={title} target='_blank' rel='noopener noreferrer'>
 | 
				
			||||||
          <canvas width={32} height={32} ref={this.setCanvasRef} className={classNames('media-gallery__preview', { 'media-gallery__preview--hidden': visible && loaded })} />
 | 
					          <canvas width={32} height={32} ref={this.setCanvasRef} className={classNames('media-gallery__preview', { 'media-gallery__preview--hidden': visible && loaded })} />
 | 
				
			||||||
          {visible && thumbnail}
 | 
					          {visible && thumbnail}
 | 
				
			||||||
          {!visible && icon}
 | 
					          {!visible && icon}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@ const messages = defineMessages({
 | 
				
			||||||
  pause: { id: 'video.pause', defaultMessage: 'Pause' },
 | 
					  pause: { id: 'video.pause', defaultMessage: 'Pause' },
 | 
				
			||||||
  mute: { id: 'video.mute', defaultMessage: 'Mute sound' },
 | 
					  mute: { id: 'video.mute', defaultMessage: 'Mute sound' },
 | 
				
			||||||
  unmute: { id: 'video.unmute', defaultMessage: 'Unmute sound' },
 | 
					  unmute: { id: 'video.unmute', defaultMessage: 'Unmute sound' },
 | 
				
			||||||
 | 
					  download: { id: 'video.download', defaultMessage: 'Download file' },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default @injectIntl
 | 
					export default @injectIntl
 | 
				
			||||||
| 
						 | 
					@ -202,6 +203,7 @@ class Audio extends React.PureComponent {
 | 
				
			||||||
              <button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><Icon id={muted ? 'volume-off' : 'volume-up'} fixedWidth /></button>
 | 
					              <button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><Icon id={muted ? 'volume-off' : 'volume-up'} fixedWidth /></button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <div className='video-player__volume' onMouseDown={this.handleVolumeMouseDown} ref={this.setVolumeRef}>
 | 
					              <div className='video-player__volume' onMouseDown={this.handleVolumeMouseDown} ref={this.setVolumeRef}>
 | 
				
			||||||
 | 
					                 
 | 
				
			||||||
                <div className='video-player__volume__current' style={{ width: `${volumeWidth}px` }} />
 | 
					                <div className='video-player__volume__current' style={{ width: `${volumeWidth}px` }} />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <span
 | 
					                <span
 | 
				
			||||||
| 
						 | 
					@ -217,6 +219,14 @@ class Audio extends React.PureComponent {
 | 
				
			||||||
                <span className='video-player__time-total'>{formatTime(this.state.duration || Math.floor(this.props.duration))}</span>
 | 
					                <span className='video-player__time-total'>{formatTime(this.state.duration || Math.floor(this.props.duration))}</span>
 | 
				
			||||||
              </span>
 | 
					              </span>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div className='video-player__buttons right'>
 | 
				
			||||||
 | 
					              <button type='button' aria-label={intl.formatMessage(messages.download)}>
 | 
				
			||||||
 | 
					                <a className='video-player__download__icon' href={this.props.src} download>
 | 
				
			||||||
 | 
					                  <Icon id={'download'} fixedWidth />
 | 
				
			||||||
 | 
					                </a>
 | 
				
			||||||
 | 
					              </button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
 | 
				
			||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
					import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
				
			||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
					import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
				
			||||||
import Toggle from 'react-toggle';
 | 
					import Toggle from 'react-toggle';
 | 
				
			||||||
import AsyncSelect from 'react-select/lib/Async';
 | 
					import AsyncSelect from 'react-select/async';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messages = defineMessages({
 | 
					const messages = defineMessages({
 | 
				
			||||||
  placeholder: { id: 'hashtag.column_settings.select.placeholder', defaultMessage: 'Enter hashtags…' },
 | 
					  placeholder: { id: 'hashtag.column_settings.select.placeholder', defaultMessage: 'Enter hashtags…' },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,7 +148,7 @@ export default class Card extends React.PureComponent {
 | 
				
			||||||
    const horizontal  = (!compact && card.get('width') > card.get('height') && (card.get('width') + 100 >= width)) || card.get('type') !== 'link' || embedded;
 | 
					    const horizontal  = (!compact && card.get('width') > card.get('height') && (card.get('width') + 100 >= width)) || card.get('type') !== 'link' || embedded;
 | 
				
			||||||
    const interactive = card.get('type') !== 'link';
 | 
					    const interactive = card.get('type') !== 'link';
 | 
				
			||||||
    const className   = classnames('status-card', { horizontal, compact, interactive });
 | 
					    const className   = classnames('status-card', { horizontal, compact, interactive });
 | 
				
			||||||
    const title       = interactive ? <a className='status-card__title' href={card.get('url')} title={card.get('title')} rel='noopener' target='_blank'><strong>{card.get('title')}</strong></a> : <strong className='status-card__title' title={card.get('title')}>{card.get('title')}</strong>;
 | 
					    const title       = interactive ? <a className='status-card__title' href={card.get('url')} title={card.get('title')} rel='noopener noreferrer' target='_blank'><strong>{card.get('title')}</strong></a> : <strong className='status-card__title' title={card.get('title')}>{card.get('title')}</strong>;
 | 
				
			||||||
    const ratio       = card.get('width') / card.get('height');
 | 
					    const ratio       = card.get('width') / card.get('height');
 | 
				
			||||||
    const height      = (compact && !embedded) ? (width / (16 / 9)) : (width / ratio);
 | 
					    const height      = (compact && !embedded) ? (width / (16 / 9)) : (width / ratio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -180,7 +180,7 @@ export default class Card extends React.PureComponent {
 | 
				
			||||||
            <div className='status-card__actions'>
 | 
					            <div className='status-card__actions'>
 | 
				
			||||||
              <div>
 | 
					              <div>
 | 
				
			||||||
                <button onClick={this.handleEmbedClick}><Icon id={iconVariant} /></button>
 | 
					                <button onClick={this.handleEmbedClick}><Icon id={iconVariant} /></button>
 | 
				
			||||||
                {horizontal && <a href={card.get('url')} target='_blank' rel='noopener'><Icon id='external-link' /></a>}
 | 
					                {horizontal && <a href={card.get('url')} target='_blank' rel='noopener noreferrer'><Icon id='external-link' /></a>}
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
| 
						 | 
					@ -208,7 +208,7 @@ export default class Card extends React.PureComponent {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <a href={card.get('url')} className={className} target='_blank' rel='noopener' ref={this.setRef}>
 | 
					      <a href={card.get('url')} className={className} target='_blank' rel='noopener noreferrer' ref={this.setRef}>
 | 
				
			||||||
        {embed}
 | 
					        {embed}
 | 
				
			||||||
        {description}
 | 
					        {description}
 | 
				
			||||||
      </a>
 | 
					      </a>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -156,7 +156,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (status.get('application')) {
 | 
					    if (status.get('application')) {
 | 
				
			||||||
      applicationLink = <span> · <a className='detailed-status__application' href={status.getIn(['application', 'website'])} target='_blank' rel='noopener'>{status.getIn(['application', 'name'])}</a></span>;
 | 
					      applicationLink = <span> · <a className='detailed-status__application' href={status.getIn(['application', 'website'])} target='_blank' rel='noopener noreferrer'>{status.getIn(['application', 'name'])}</a></span>;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (status.get('visibility') === 'direct') {
 | 
					    if (status.get('visibility') === 'direct') {
 | 
				
			||||||
| 
						 | 
					@ -220,7 +220,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
 | 
				
			||||||
          {media}
 | 
					          {media}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <div className='detailed-status__meta'>
 | 
					          <div className='detailed-status__meta'>
 | 
				
			||||||
            <a className='detailed-status__datetime' href={status.get('url')} target='_blank' rel='noopener'>
 | 
					            <a className='detailed-status__datetime' href={status.get('url')} target='_blank' rel='noopener noreferrer'>
 | 
				
			||||||
              <FormattedDate value={new Date(status.get('created_at'))} hour12={false} year='numeric' month='short' day='2-digit' hour='2-digit' minute='2-digit' />
 | 
					              <FormattedDate value={new Date(status.get('created_at'))} hour12={false} year='numeric' month='short' day='2-digit' hour='2-digit' minute='2-digit' />
 | 
				
			||||||
            </a>{applicationLink} · {reblogLink} · {favouriteLink}
 | 
					            </a>{applicationLink} · {reblogLink} · {favouriteLink}
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,7 @@ export default class ActionsModal extends ImmutablePureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <li key={`${text}-${i}`}>
 | 
					      <li key={`${text}-${i}`}>
 | 
				
			||||||
        <a href={href} target='_blank' rel='noopener' onClick={this.props.onClick} data-index={i} className={classNames({ active })}>
 | 
					        <a href={href} target='_blank' rel='noopener noreferrer' onClick={this.props.onClick} data-index={i} className={classNames({ active })}>
 | 
				
			||||||
          {icon && <IconButton title={text} icon={icon} role='presentation' tabIndex='-1' inverted />}
 | 
					          {icon && <IconButton title={text} icon={icon} role='presentation' tabIndex='-1' inverted />}
 | 
				
			||||||
          <div>
 | 
					          <div>
 | 
				
			||||||
            <div className={classNames({ 'actions-modal__item-label': !!meta })}>{text}</div>
 | 
					            <div className={classNames({ 'actions-modal__item-label': !!meta })}>{text}</div>
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ export default class ActionsModal extends ImmutablePureComponent {
 | 
				
			||||||
      <div className='status light'>
 | 
					      <div className='status light'>
 | 
				
			||||||
        <div className='boost-modal__status-header'>
 | 
					        <div className='boost-modal__status-header'>
 | 
				
			||||||
          <div className='boost-modal__status-time'>
 | 
					          <div className='boost-modal__status-time'>
 | 
				
			||||||
            <a href={this.props.status.get('url')} className='status__relative-time' target='_blank' rel='noopener'>
 | 
					            <a href={this.props.status.get('url')} className='status__relative-time' target='_blank' rel='noopener noreferrer'>
 | 
				
			||||||
              <RelativeTimestamp timestamp={this.props.status.get('created_at')} />
 | 
					              <RelativeTimestamp timestamp={this.props.status.get('created_at')} />
 | 
				
			||||||
            </a>
 | 
					            </a>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,7 +61,7 @@ class BoostModal extends ImmutablePureComponent {
 | 
				
			||||||
          <div className='status light'>
 | 
					          <div className='status light'>
 | 
				
			||||||
            <div className='boost-modal__status-header'>
 | 
					            <div className='boost-modal__status-header'>
 | 
				
			||||||
              <div className='boost-modal__status-time'>
 | 
					              <div className='boost-modal__status-time'>
 | 
				
			||||||
                <a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener'><RelativeTimestamp timestamp={status.get('created_at')} /></a>
 | 
					                <a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener noreferrer'><RelativeTimestamp timestamp={status.get('created_at')} /></a>
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <a onClick={this.handleAccountClick} href={status.getIn(['account', 'url'])} className='status__display-name'>
 | 
					              <a onClick={this.handleAccountClick} href={status.getIn(['account', 'url'])} className='status__display-name'>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -182,7 +182,7 @@ class ColumnsArea extends ImmutablePureComponent {
 | 
				
			||||||
      const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : <Link key='floating-action-button' to='/statuses/new' className='floating-action-button' aria-label={intl.formatMessage(messages.publish)}><Icon id='pencil' /></Link>;
 | 
					      const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : <Link key='floating-action-button' to='/statuses/new' className='floating-action-button' aria-label={intl.formatMessage(messages.publish)}><Icon id='pencil' /></Link>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const content = columnIndex !== -1 ? (
 | 
					      const content = columnIndex !== -1 ? (
 | 
				
			||||||
        <ReactSwipeableViews key='content' index={columnIndex} onChangeIndex={this.handleSwipe} onTransitionEnd={this.handleAnimationEnd} animateTransitions={shouldAnimate} springConfig={{ duration: '400ms', delay: '0s', easeFunction: 'ease' }} style={{ height: '100%' }}>
 | 
					        <ReactSwipeableViews key='content' hysteresis={0.2} threshold={15} index={columnIndex} onChangeIndex={this.handleSwipe} onTransitionEnd={this.handleAnimationEnd} animateTransitions={shouldAnimate} springConfig={{ duration: '400ms', delay: '0s', easeFunction: 'ease' }} style={{ height: '100%' }}>
 | 
				
			||||||
          {links.map(this.renderView)}
 | 
					          {links.map(this.renderView)}
 | 
				
			||||||
        </ReactSwipeableViews>
 | 
					        </ReactSwipeableViews>
 | 
				
			||||||
      ) : (
 | 
					      ) : (
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,7 @@ class LinkFooter extends React.PureComponent {
 | 
				
			||||||
          <FormattedMessage
 | 
					          <FormattedMessage
 | 
				
			||||||
            id='getting_started.open_source_notice'
 | 
					            id='getting_started.open_source_notice'
 | 
				
			||||||
            defaultMessage='Mastodon is open source software. You can contribute or report issues on GitHub at {github}.'
 | 
					            defaultMessage='Mastodon is open source software. You can contribute or report issues on GitHub at {github}.'
 | 
				
			||||||
            values={{ github: <span><a href={source_url} rel='noopener' target='_blank'>{repository}</a> (v{version})</span> }}
 | 
					            values={{ github: <span><a href={source_url} rel='noopener noreferrer' target='_blank'>{repository}</a> (v{version})</span> }}
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
        </p>
 | 
					        </p>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ const messages = defineMessages({
 | 
				
			||||||
  close: { id: 'video.close', defaultMessage: 'Close video' },
 | 
					  close: { id: 'video.close', defaultMessage: 'Close video' },
 | 
				
			||||||
  fullscreen: { id: 'video.fullscreen', defaultMessage: 'Full screen' },
 | 
					  fullscreen: { id: 'video.fullscreen', defaultMessage: 'Full screen' },
 | 
				
			||||||
  exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' },
 | 
					  exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' },
 | 
				
			||||||
 | 
					  download: { id: 'video.download', defaultMessage: 'Download file' },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const formatTime = secondsNum => {
 | 
					export const formatTime = secondsNum => {
 | 
				
			||||||
| 
						 | 
					@ -470,6 +471,7 @@ class Video extends React.PureComponent {
 | 
				
			||||||
              <button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><Icon id={muted ? 'volume-off' : 'volume-up'} fixedWidth /></button>
 | 
					              <button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><Icon id={muted ? 'volume-off' : 'volume-up'} fixedWidth /></button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <div className='video-player__volume' onMouseDown={this.handleVolumeMouseDown} ref={this.setVolumeRef}>
 | 
					              <div className='video-player__volume' onMouseDown={this.handleVolumeMouseDown} ref={this.setVolumeRef}>
 | 
				
			||||||
 | 
					                 
 | 
				
			||||||
                <div className='video-player__volume__current' style={{ width: `${volumeWidth}px` }} />
 | 
					                <div className='video-player__volume__current' style={{ width: `${volumeWidth}px` }} />
 | 
				
			||||||
                <span
 | 
					                <span
 | 
				
			||||||
                  className={classNames('video-player__volume__handle')}
 | 
					                  className={classNames('video-player__volume__handle')}
 | 
				
			||||||
| 
						 | 
					@ -493,7 +495,13 @@ class Video extends React.PureComponent {
 | 
				
			||||||
              {(!onCloseVideo && !editable) && <button type='button' aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}><Icon id='eye-slash' fixedWidth /></button>}
 | 
					              {(!onCloseVideo && !editable) && <button type='button' aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}><Icon id='eye-slash' fixedWidth /></button>}
 | 
				
			||||||
              {(!fullscreen && onOpenVideo) && <button type='button' aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}><Icon id='expand' fixedWidth /></button>}
 | 
					              {(!fullscreen && onOpenVideo) && <button type='button' aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}><Icon id='expand' fixedWidth /></button>}
 | 
				
			||||||
              {onCloseVideo && <button type='button' aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}><Icon id='compress' fixedWidth /></button>}
 | 
					              {onCloseVideo && <button type='button' aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}><Icon id='compress' fixedWidth /></button>}
 | 
				
			||||||
 | 
					              <button type='button' aria-label={intl.formatMessage(messages.download)}>
 | 
				
			||||||
 | 
					                <a className='video-player__download__icon' href={this.props.src} download>
 | 
				
			||||||
 | 
					                  <Icon id={'download'} fixedWidth />
 | 
				
			||||||
 | 
					                </a>
 | 
				
			||||||
 | 
					              </button>
 | 
				
			||||||
              <button type='button' aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}><Icon id={fullscreen ? 'compress' : 'arrows-alt'} fixedWidth /></button>
 | 
					              <button type='button' aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}><Icon id={fullscreen ? 'compress' : 'arrows-alt'} fixedWidth /></button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,5 +25,6 @@ export const useBlurhash = getMeta('use_blurhash');
 | 
				
			||||||
export const usePendingItems = getMeta('use_pending_items');
 | 
					export const usePendingItems = getMeta('use_pending_items');
 | 
				
			||||||
export const showTrends = getMeta('trends');
 | 
					export const showTrends = getMeta('trends');
 | 
				
			||||||
export const title = getMeta('title');
 | 
					export const title = getMeta('title');
 | 
				
			||||||
 | 
					export const cropImages = getMeta('crop_images');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default initialState;
 | 
					export default initialState;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -776,6 +776,10 @@
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        "defaultMessage": "Unmute sound",
 | 
					        "defaultMessage": "Unmute sound",
 | 
				
			||||||
        "id": "video.unmute"
 | 
					        "id": "video.unmute"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "defaultMessage": "Download file",
 | 
				
			||||||
 | 
					        "id": "video.download"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "path": "app/javascript/mastodon/features/audio/index.json"
 | 
					    "path": "app/javascript/mastodon/features/audio/index.json"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ import {
 | 
				
			||||||
  REBLOG_FAIL,
 | 
					  REBLOG_FAIL,
 | 
				
			||||||
  FAVOURITE_REQUEST,
 | 
					  FAVOURITE_REQUEST,
 | 
				
			||||||
  FAVOURITE_FAIL,
 | 
					  FAVOURITE_FAIL,
 | 
				
			||||||
 | 
					  UNFAVOURITE_SUCCESS,
 | 
				
			||||||
} from '../actions/interactions';
 | 
					} from '../actions/interactions';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  STATUS_MUTE_SUCCESS,
 | 
					  STATUS_MUTE_SUCCESS,
 | 
				
			||||||
| 
						 | 
					@ -37,6 +38,9 @@ export default function statuses(state = initialState, action) {
 | 
				
			||||||
    return importStatuses(state, action.statuses);
 | 
					    return importStatuses(state, action.statuses);
 | 
				
			||||||
  case FAVOURITE_REQUEST:
 | 
					  case FAVOURITE_REQUEST:
 | 
				
			||||||
    return state.setIn([action.status.get('id'), 'favourited'], true);
 | 
					    return state.setIn([action.status.get('id'), 'favourited'], true);
 | 
				
			||||||
 | 
					  case UNFAVOURITE_SUCCESS:
 | 
				
			||||||
 | 
					    const favouritesCount = action.status.get('favourites_count');
 | 
				
			||||||
 | 
					    return state.setIn([action.status.get('id'), 'favourites_count'], favouritesCount - 1);
 | 
				
			||||||
  case FAVOURITE_FAIL:
 | 
					  case FAVOURITE_FAIL:
 | 
				
			||||||
    return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'favourited'], false);
 | 
					    return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'favourited'], false);
 | 
				
			||||||
  case REBLOG_REQUEST:
 | 
					  case REBLOG_REQUEST:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1591,6 +1591,20 @@ a.account__display-name {
 | 
				
			||||||
  color: $gold-star;
 | 
					  color: $gold-star;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.no-reduce-motion .icon-button.star-icon {
 | 
				
			||||||
 | 
					  &.activate {
 | 
				
			||||||
 | 
					    & > .fa-star {
 | 
				
			||||||
 | 
					      animation: spring-rotate-in 1s linear;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &.deactivate {
 | 
				
			||||||
 | 
					    & > .fa-star {
 | 
				
			||||||
 | 
					      animation: spring-rotate-out 1s linear;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.notification__display-name {
 | 
					.notification__display-name {
 | 
				
			||||||
  color: inherit;
 | 
					  color: inherit;
 | 
				
			||||||
  font-weight: 500;
 | 
					  font-weight: 500;
 | 
				
			||||||
| 
						 | 
					@ -3373,6 +3387,50 @@ a.status-card.compact:hover {
 | 
				
			||||||
  animation: loader-figure 1.15s infinite cubic-bezier(0.215, 0.61, 0.355, 1);
 | 
					  animation: loader-figure 1.15s infinite cubic-bezier(0.215, 0.61, 0.355, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@keyframes spring-rotate-in {
 | 
				
			||||||
 | 
					  0% {
 | 
				
			||||||
 | 
					    transform: rotate(0deg);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  30% {
 | 
				
			||||||
 | 
					    transform: rotate(-484.8deg);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  60% {
 | 
				
			||||||
 | 
					    transform: rotate(-316.7deg);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  90% {
 | 
				
			||||||
 | 
					    transform: rotate(-375deg);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  100% {
 | 
				
			||||||
 | 
					    transform: rotate(-360deg);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@keyframes spring-rotate-out {
 | 
				
			||||||
 | 
					  0% {
 | 
				
			||||||
 | 
					    transform: rotate(-360deg);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  30% {
 | 
				
			||||||
 | 
					    transform: rotate(124.8deg);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  60% {
 | 
				
			||||||
 | 
					    transform: rotate(-43.27deg);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  90% {
 | 
				
			||||||
 | 
					    transform: rotate(15deg);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  100% {
 | 
				
			||||||
 | 
					    transform: rotate(0deg);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@keyframes loader-figure {
 | 
					@keyframes loader-figure {
 | 
				
			||||||
  0% {
 | 
					  0% {
 | 
				
			||||||
    width: 0;
 | 
					    width: 0;
 | 
				
			||||||
| 
						 | 
					@ -5194,6 +5252,7 @@ a.status-card.compact:hover {
 | 
				
			||||||
      max-height: 100% !important;
 | 
					      max-height: 100% !important;
 | 
				
			||||||
      width: 100% !important;
 | 
					      width: 100% !important;
 | 
				
			||||||
      height: 100% !important;
 | 
					      height: 100% !important;
 | 
				
			||||||
 | 
					      outline: 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5271,6 +5330,10 @@ a.status-card.compact:hover {
 | 
				
			||||||
    display: flex;
 | 
					    display: flex;
 | 
				
			||||||
    justify-content: space-between;
 | 
					    justify-content: space-between;
 | 
				
			||||||
    padding-bottom: 10px;
 | 
					    padding-bottom: 10px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .video-player__download__icon {
 | 
				
			||||||
 | 
					      color: inherit;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  &__buttons {
 | 
					  &__buttons {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,10 +149,6 @@ a.table-action-link {
 | 
				
			||||||
          margin-top: 0;
 | 
					          margin-top: 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					 | 
				
			||||||
      @media screen and (max-width: $no-gap-breakpoint) {
 | 
					 | 
				
			||||||
        display: none;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    &__actions,
 | 
					    &__actions,
 | 
				
			||||||
| 
						 | 
					@ -174,10 +170,6 @@ a.table-action-link {
 | 
				
			||||||
      text-align: right;
 | 
					      text-align: right;
 | 
				
			||||||
      padding-right: 16px - 5px;
 | 
					      padding-right: 16px - 5px;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    @media screen and (max-width: $no-gap-breakpoint) {
 | 
					 | 
				
			||||||
      display: none;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  &__form {
 | 
					  &__form {
 | 
				
			||||||
| 
						 | 
					@ -198,7 +190,7 @@ a.table-action-link {
 | 
				
			||||||
    background: darken($ui-base-color, 4%);
 | 
					    background: darken($ui-base-color, 4%);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @media screen and (max-width: $no-gap-breakpoint) {
 | 
					    @media screen and (max-width: $no-gap-breakpoint) {
 | 
				
			||||||
      &:first-child {
 | 
					      .optional &:first-child {
 | 
				
			||||||
        border-top: 1px solid darken($ui-base-color, 8%);
 | 
					        border-top: 1px solid darken($ui-base-color, 8%);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -264,6 +256,13 @@ a.table-action-link {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &.optional .batch-table__toolbar,
 | 
				
			||||||
 | 
					  &.optional .batch-table__row__select {
 | 
				
			||||||
 | 
					    @media screen and (max-width: $no-gap-breakpoint) {
 | 
				
			||||||
 | 
					      display: none;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .status__content {
 | 
					  .status__content {
 | 
				
			||||||
    padding-top: 0;
 | 
					    padding-top: 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -153,6 +153,14 @@ class ActivityPub::Activity
 | 
				
			||||||
    fetch_remote_original_status
 | 
					    fetch_remote_original_status
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def follow_request_from_object
 | 
				
			||||||
 | 
					    @follow_request ||= FollowRequest.find_by(target_account: @account, uri: object_uri) unless object_uri.nil?
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def follow_from_object
 | 
				
			||||||
 | 
					    @follow ||= Follow.find_by(target_account: @account, uri: object_uri) unless object_uri.nil?
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def fetch_remote_original_status
 | 
					  def fetch_remote_original_status
 | 
				
			||||||
    if object_uri.start_with?('http')
 | 
					    if object_uri.start_with?('http')
 | 
				
			||||||
      return if ActivityPub::TagManager.instance.local_uri?(object_uri)
 | 
					      return if ActivityPub::TagManager.instance.local_uri?(object_uri)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,17 +2,18 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ActivityPub::Activity::Accept < ActivityPub::Activity
 | 
					class ActivityPub::Activity::Accept < ActivityPub::Activity
 | 
				
			||||||
  def perform
 | 
					  def perform
 | 
				
			||||||
 | 
					    return accept_follow_for_relay if relay_follow?
 | 
				
			||||||
 | 
					    return follow_request_from_object.authorize! unless follow_request_from_object.nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case @object['type']
 | 
					    case @object['type']
 | 
				
			||||||
    when 'Follow'
 | 
					    when 'Follow'
 | 
				
			||||||
      accept_follow
 | 
					      accept_embedded_follow
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def accept_follow
 | 
					  def accept_embedded_follow
 | 
				
			||||||
    return accept_follow_for_relay if relay_follow?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    target_account = account_from_uri(target_uri)
 | 
					    target_account = account_from_uri(target_uri)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return if target_account.nil? || !target_account.local?
 | 
					    return if target_account.nil? || !target_account.local?
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,17 +2,19 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ActivityPub::Activity::Reject < ActivityPub::Activity
 | 
					class ActivityPub::Activity::Reject < ActivityPub::Activity
 | 
				
			||||||
  def perform
 | 
					  def perform
 | 
				
			||||||
 | 
					    return reject_follow_for_relay if relay_follow?
 | 
				
			||||||
 | 
					    return follow_request_from_object.reject! unless follow_request_from_object.nil?
 | 
				
			||||||
 | 
					    return UnfollowService.new.call(follow_from_object.target_account, @account) unless follow_from_object.nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case @object['type']
 | 
					    case @object['type']
 | 
				
			||||||
    when 'Follow'
 | 
					    when 'Follow'
 | 
				
			||||||
      reject_follow
 | 
					      reject_embedded_follow
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def reject_follow
 | 
					  def reject_embedded_follow
 | 
				
			||||||
    return reject_follow_for_relay if relay_follow?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    target_account = account_from_uri(target_uri)
 | 
					    target_account = account_from_uri(target_uri)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return if target_account.nil? || !target_account.local?
 | 
					    return if target_account.nil? || !target_account.local?
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -337,7 +337,7 @@ class Formatter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def link_to_url(entity, options = {})
 | 
					  def link_to_url(entity, options = {})
 | 
				
			||||||
    url        = Addressable::URI.parse(entity[:url])
 | 
					    url        = Addressable::URI.parse(entity[:url])
 | 
				
			||||||
    html_attrs = { target: '_blank', rel: 'nofollow noopener' }
 | 
					    html_attrs = { target: '_blank', rel: 'nofollow noopener noreferrer' }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    html_attrs[:rel] = "me #{html_attrs[:rel]}" if options[:me]
 | 
					    html_attrs[:rel] = "me #{html_attrs[:rel]}" if options[:me]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,7 @@ class Sanitize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      add_attributes: {
 | 
					      add_attributes: {
 | 
				
			||||||
        'a' => {
 | 
					        'a' => {
 | 
				
			||||||
          'rel' => 'nofollow noopener tag',
 | 
					          'rel' => 'nofollow noopener tag noreferrer',
 | 
				
			||||||
          'target' => '_blank',
 | 
					          'target' => '_blank',
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,6 +42,7 @@ class UserSettingsDecorator
 | 
				
			||||||
    user.settings['use_blurhash']        = use_blurhash_preference if change?('setting_use_blurhash')
 | 
					    user.settings['use_blurhash']        = use_blurhash_preference if change?('setting_use_blurhash')
 | 
				
			||||||
    user.settings['use_pending_items']   = use_pending_items_preference if change?('setting_use_pending_items')
 | 
					    user.settings['use_pending_items']   = use_pending_items_preference if change?('setting_use_pending_items')
 | 
				
			||||||
    user.settings['trends']              = trends_preference if change?('setting_trends')
 | 
					    user.settings['trends']              = trends_preference if change?('setting_trends')
 | 
				
			||||||
 | 
					    user.settings['crop_images']         = crop_images_preference if change?('setting_crop_images')
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def merged_notification_emails
 | 
					  def merged_notification_emails
 | 
				
			||||||
| 
						 | 
					@ -152,6 +153,10 @@ class UserSettingsDecorator
 | 
				
			||||||
    boolean_cast_setting 'setting_trends'
 | 
					    boolean_cast_setting 'setting_trends'
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def crop_images_preference
 | 
				
			||||||
 | 
					    boolean_cast_setting 'setting_crop_images'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def boolean_cast_setting(key)
 | 
					  def boolean_cast_setting(key)
 | 
				
			||||||
    ActiveModel::Type::Boolean.new.cast(settings[key])
 | 
					    ActiveModel::Type::Boolean.new.cast(settings[key])
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
class AdminMailer < ApplicationMailer
 | 
					class AdminMailer < ApplicationMailer
 | 
				
			||||||
  layout 'plain_mailer'
 | 
					  layout 'plain_mailer'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  helper :statuses
 | 
					  helper :accounts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def new_report(recipient, report)
 | 
					  def new_report(recipient, report)
 | 
				
			||||||
    @report   = report
 | 
					    @report   = report
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NotificationMailer < ApplicationMailer
 | 
					class NotificationMailer < ApplicationMailer
 | 
				
			||||||
 | 
					  helper :accounts
 | 
				
			||||||
  helper :statuses
 | 
					  helper :statuses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  add_template_helper RoutingHelper
 | 
					  add_template_helper RoutingHelper
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,9 +3,9 @@
 | 
				
			||||||
class UserMailer < Devise::Mailer
 | 
					class UserMailer < Devise::Mailer
 | 
				
			||||||
  layout 'mailer'
 | 
					  layout 'mailer'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  helper :accounts
 | 
				
			||||||
  helper :application
 | 
					  helper :application
 | 
				
			||||||
  helper :instance
 | 
					  helper :instance
 | 
				
			||||||
  helper :statuses
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  add_template_helper RoutingHelper
 | 
					  add_template_helper RoutingHelper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,6 +87,7 @@ class MediaAttachment < ApplicationRecord
 | 
				
			||||||
      convert_options: {
 | 
					      convert_options: {
 | 
				
			||||||
        output: {
 | 
					        output: {
 | 
				
			||||||
          'loglevel' => 'fatal',
 | 
					          'loglevel' => 'fatal',
 | 
				
			||||||
 | 
					          'map_metadata' => '-1',
 | 
				
			||||||
          'q:a' => 2,
 | 
					          'q:a' => 2,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,7 +108,7 @@ class User < ApplicationRecord
 | 
				
			||||||
  delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :favourite_modal, :delete_modal,
 | 
					  delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :favourite_modal, :delete_modal,
 | 
				
			||||||
           :reduce_motion, :system_font_ui, :noindex, :flavour, :skin, :display_media, :hide_network, :hide_followers_count,
 | 
					           :reduce_motion, :system_font_ui, :noindex, :flavour, :skin, :display_media, :hide_network, :hide_followers_count,
 | 
				
			||||||
           :expand_spoilers, :default_language, :aggregate_reblogs, :show_application,
 | 
					           :expand_spoilers, :default_language, :aggregate_reblogs, :show_application,
 | 
				
			||||||
           :advanced_layout, :use_blurhash, :use_pending_items, :trends,
 | 
					           :advanced_layout, :use_blurhash, :use_pending_items, :trends, :crop_images,
 | 
				
			||||||
           :default_content_type, :system_emoji_font,
 | 
					           :default_content_type, :system_emoji_font,
 | 
				
			||||||
           to: :settings, prefix: :setting, allow_nil: false
 | 
					           to: :settings, prefix: :setting, allow_nil: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,11 +55,13 @@ class InitialStateSerializer < ActiveModel::Serializer
 | 
				
			||||||
      store[:trends]            = Setting.trends && object.current_account.user.setting_trends
 | 
					      store[:trends]            = Setting.trends && object.current_account.user.setting_trends
 | 
				
			||||||
      store[:default_content_type] = object.current_account.user.setting_default_content_type
 | 
					      store[:default_content_type] = object.current_account.user.setting_default_content_type
 | 
				
			||||||
      store[:system_emoji_font] = object.current_account.user.setting_system_emoji_font
 | 
					      store[:system_emoji_font] = object.current_account.user.setting_system_emoji_font
 | 
				
			||||||
 | 
					      store[:crop_images]       = object.current_account.user.setting_crop_images
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      store[:auto_play_gif] = Setting.auto_play_gif
 | 
					      store[:auto_play_gif] = Setting.auto_play_gif
 | 
				
			||||||
      store[:display_media] = Setting.display_media
 | 
					      store[:display_media] = Setting.display_media
 | 
				
			||||||
      store[:reduce_motion] = Setting.reduce_motion
 | 
					      store[:reduce_motion] = Setting.reduce_motion
 | 
				
			||||||
      store[:use_blurhash]  = Setting.use_blurhash
 | 
					      store[:use_blurhash]  = Setting.use_blurhash
 | 
				
			||||||
 | 
					      store[:crop_images]   = Setting.crop_images
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    store
 | 
					    store
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RSS::AccountSerializer
 | 
					class RSS::AccountSerializer
 | 
				
			||||||
  include ActionView::Helpers::NumberHelper
 | 
					  include ActionView::Helpers::NumberHelper
 | 
				
			||||||
  include StatusesHelper
 | 
					  include AccountsHelper
 | 
				
			||||||
  include RoutingHelper
 | 
					  include RoutingHelper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def render(account, statuses, tag)
 | 
					  def render(account, statuses, tag)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,6 @@
 | 
				
			||||||
class RSS::TagSerializer
 | 
					class RSS::TagSerializer
 | 
				
			||||||
  include ActionView::Helpers::NumberHelper
 | 
					  include ActionView::Helpers::NumberHelper
 | 
				
			||||||
  include ActionView::Helpers::SanitizeHelper
 | 
					  include ActionView::Helpers::SanitizeHelper
 | 
				
			||||||
  include StatusesHelper
 | 
					 | 
				
			||||||
  include RoutingHelper
 | 
					  include RoutingHelper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def render(tag, statuses)
 | 
					  def render(tag, statuses)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,7 +84,7 @@ class FetchLinkCardService < BaseService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def skip_link?(a)
 | 
					  def skip_link?(a)
 | 
				
			||||||
    # Avoid links for hashtags and mentions (microformats)
 | 
					    # Avoid links for hashtags and mentions (microformats)
 | 
				
			||||||
    a['rel']&.include?('tag') || a['class']&.include?('u-url') || mention_link?(a)
 | 
					    a['rel']&.include?('tag') || a['class']&.match?(/u-url|h-card/) || mention_link?(a)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def attempt_oembed
 | 
					  def attempt_oembed
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,7 @@
 | 
				
			||||||
                %small= t('about.browse_public_posts')
 | 
					                %small= t('about.browse_public_posts')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .directory__tag
 | 
					        .directory__tag
 | 
				
			||||||
          = link_to 'https://joinmastodon.org/apps', target: '_blank', rel: 'noopener' do
 | 
					          = link_to 'https://joinmastodon.org/apps', target: '_blank', rel: 'noopener noreferrer' do
 | 
				
			||||||
            %h4
 | 
					            %h4
 | 
				
			||||||
              = fa_icon 'tablet fw'
 | 
					              = fa_icon 'tablet fw'
 | 
				
			||||||
              = t('about.get_apps')
 | 
					              = t('about.get_apps')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@
 | 
				
			||||||
    = t('accounts.moved_html', name: content_tag(:bdi, content_tag(:strong, display_name(account, custom_emojify: true), class: :emojify)), new_profile_link: link_to(content_tag(:strong, safe_join(['@', content_tag(:span, moved_to_account.acct)])), ActivityPub::TagManager.instance.url_for(moved_to_account), class: 'mention'))
 | 
					    = t('accounts.moved_html', name: content_tag(:bdi, content_tag(:strong, display_name(account, custom_emojify: true), class: :emojify)), new_profile_link: link_to(content_tag(:strong, safe_join(['@', content_tag(:span, moved_to_account.acct)])), ActivityPub::TagManager.instance.url_for(moved_to_account), class: 'mention'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .moved-account-widget__card
 | 
					  .moved-account-widget__card
 | 
				
			||||||
    = link_to ActivityPub::TagManager.instance.url_for(moved_to_account), class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'me noopener' do
 | 
					    = link_to ActivityPub::TagManager.instance.url_for(moved_to_account), class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'me noopener noreferrer' do
 | 
				
			||||||
      .detailed-status__display-avatar
 | 
					      .detailed-status__display-avatar
 | 
				
			||||||
        .account__avatar-overlay
 | 
					        .account__avatar-overlay
 | 
				
			||||||
          .account__avatar-overlay-base{ style: "background-image: url('#{moved_to_account.avatar.url(:original)}')" }
 | 
					          .account__avatar-overlay-base{ style: "background-image: url('#{moved_to_account.avatar.url(:original)}')" }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -143,12 +143,15 @@
 | 
				
			||||||
            %th= t('admin.accounts.most_recent_ip')
 | 
					            %th= t('admin.accounts.most_recent_ip')
 | 
				
			||||||
            %td= @account.user_current_sign_in_ip
 | 
					            %td= @account.user_current_sign_in_ip
 | 
				
			||||||
            %td
 | 
					            %td
 | 
				
			||||||
 | 
					              - if @account.user_current_sign_in_ip
 | 
				
			||||||
 | 
					                = table_link_to 'search', t('admin.accounts.search_same_ip'), admin_accounts_path(ip: @account.user_current_sign_in_ip)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          %tr
 | 
					          %tr
 | 
				
			||||||
            %th= t('admin.accounts.most_recent_activity')
 | 
					            %th= t('admin.accounts.most_recent_activity')
 | 
				
			||||||
            %td
 | 
					            %td
 | 
				
			||||||
              - if @account.user_current_sign_in_at
 | 
					              - if @account.user_current_sign_in_at
 | 
				
			||||||
                %time.formatted{ datetime: @account.user_current_sign_in_at.iso8601, title: l(@account.user_current_sign_in_at) }= l @account.user_current_sign_in_at
 | 
					                %time.formatted{ datetime: @account.user_current_sign_in_at.iso8601, title: l(@account.user_current_sign_in_at) }= l @account.user_current_sign_in_at
 | 
				
			||||||
 | 
					            %td
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          - if @account.user&.invited?
 | 
					          - if @account.user&.invited?
 | 
				
			||||||
            %tr
 | 
					            %tr
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@
 | 
				
			||||||
        = react_component :media_gallery, height: 343, sensitive: !current_account&.user&.show_all_media? && status.proper.sensitive? || current_account&.user&.hide_all_media?, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.proper.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }
 | 
					        = react_component :media_gallery, height: 343, sensitive: !current_account&.user&.show_all_media? && status.proper.sensitive? || current_account&.user&.hide_all_media?, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.proper.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .detailed-status__meta
 | 
					    .detailed-status__meta
 | 
				
			||||||
      = link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', target: stream_link_target, rel: 'noopener' do
 | 
					      = link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', target: stream_link_target, rel: 'noopener noreferrer' do
 | 
				
			||||||
        %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
 | 
					        %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
 | 
				
			||||||
      - if status.discarded?
 | 
					      - if status.discarded?
 | 
				
			||||||
        ·
 | 
					        ·
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@
 | 
				
			||||||
  - Admin::FilterHelper::TAGS_FILTERS.each do |key|
 | 
					  - Admin::FilterHelper::TAGS_FILTERS.each do |key|
 | 
				
			||||||
    = hidden_field_tag key, params[key] if params[key].present?
 | 
					    = hidden_field_tag key, params[key] if params[key].present?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .batch-table
 | 
					  .batch-table.optional
 | 
				
			||||||
    .batch-table__toolbar
 | 
					    .batch-table__toolbar
 | 
				
			||||||
      %label.batch-table__toolbar__select.batch-checkbox-all
 | 
					      %label.batch-table__toolbar__select.batch-checkbox-all
 | 
				
			||||||
        = check_box_tag :batch_checkbox_all, nil, false
 | 
					        = check_box_tag :batch_checkbox_all, nil, false
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.dashboard__counters
 | 
					.dashboard__counters
 | 
				
			||||||
  %div
 | 
					  %div
 | 
				
			||||||
    = link_to tag_url(@tag), target: '_blank', rel: 'noopener' do
 | 
					    = link_to tag_url(@tag), target: '_blank', rel: 'noopener noreferrer' do
 | 
				
			||||||
      .dashboard__counters__num= number_with_delimiter @accounts_today
 | 
					      .dashboard__counters__num= number_with_delimiter @accounts_today
 | 
				
			||||||
      .dashboard__counters__label= t 'admin.tags.accounts_today'
 | 
					      .dashboard__counters__label= t 'admin.tags.accounts_today'
 | 
				
			||||||
  %div
 | 
					  %div
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
- account_url = local_assigns[:admin] ? admin_account_path(account.id) : ActivityPub::TagManager.instance.url_for(account)
 | 
					- account_url = local_assigns[:admin] ? admin_account_path(account.id) : ActivityPub::TagManager.instance.url_for(account)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.card.h-card
 | 
					.card.h-card
 | 
				
			||||||
  = link_to account_url, target: '_blank', rel: 'noopener' do
 | 
					  = link_to account_url, target: '_blank', rel: 'noopener noreferrer' do
 | 
				
			||||||
    .card__img
 | 
					    .card__img
 | 
				
			||||||
      = image_tag account.header.url, alt: ''
 | 
					      = image_tag account.header.url, alt: ''
 | 
				
			||||||
    .card__bar
 | 
					    .card__bar
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@
 | 
				
			||||||
            - if application.website.blank?
 | 
					            - if application.website.blank?
 | 
				
			||||||
              = application.name
 | 
					              = application.name
 | 
				
			||||||
            - else
 | 
					            - else
 | 
				
			||||||
              = link_to application.name, application.website, target: '_blank', rel: 'noopener'
 | 
					              = link_to application.name, application.website, target: '_blank', rel: 'noopener noreferrer'
 | 
				
			||||||
          %th!= application.scopes.map { |scope| t(scope, scope: [:doorkeeper, :scopes]) }.join(', ')
 | 
					          %th!= application.scopes.map { |scope| t(scope, scope: [:doorkeeper, :scopes]) }.join(', ')
 | 
				
			||||||
          %td= l application.created_at
 | 
					          %td= l application.created_at
 | 
				
			||||||
          %td
 | 
					          %td
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,11 @@
 | 
				
			||||||
    = f.input :setting_system_font_ui, as: :boolean, wrapper: :with_label
 | 
					    = f.input :setting_system_font_ui, as: :boolean, wrapper: :with_label
 | 
				
			||||||
    = f.input :setting_system_emoji_font, as: :boolean, wrapper: :with_label
 | 
					    = f.input :setting_system_emoji_font, as: :boolean, wrapper: :with_label
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  %h4= t 'appearance.toot_layout'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .fields-group
 | 
				
			||||||
 | 
					    = f.input :setting_crop_images, as: :boolean, wrapper: :with_label
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  %h4= t 'appearance.discovery'
 | 
					  %h4= t 'appearance.discovery'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .fields-group
 | 
					  .fields-group
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,14 +44,14 @@
 | 
				
			||||||
  .detailed-status__meta
 | 
					  .detailed-status__meta
 | 
				
			||||||
    %data.dt-published{ value: status.created_at.to_time.iso8601 }
 | 
					    %data.dt-published{ value: status.created_at.to_time.iso8601 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    = link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime u-url u-uid', target: stream_link_target, rel: 'noopener' do
 | 
					    = link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime u-url u-uid', target: stream_link_target, rel: 'noopener noreferrer' do
 | 
				
			||||||
      %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
 | 
					      %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
 | 
				
			||||||
    ·
 | 
					    ·
 | 
				
			||||||
    - if status.application && @account.user&.setting_show_application
 | 
					    - if status.application && @account.user&.setting_show_application
 | 
				
			||||||
      - if status.application.website.blank?
 | 
					      - if status.application.website.blank?
 | 
				
			||||||
        %strong.detailed-status__application= status.application.name
 | 
					        %strong.detailed-status__application= status.application.name
 | 
				
			||||||
      - else
 | 
					      - else
 | 
				
			||||||
        = link_to status.application.name, status.application.website, class: 'detailed-status__application', target: '_blank', rel: 'noopener'
 | 
					        = link_to status.application.name, status.application.website, class: 'detailed-status__application', target: '_blank', rel: 'noopener noreferrer'
 | 
				
			||||||
      ·
 | 
					      ·
 | 
				
			||||||
    = link_to remote_interaction_path(status, type: :reply), class: 'modal-button detailed-status__link' do
 | 
					    = link_to remote_interaction_path(status, type: :reply), class: 'modal-button detailed-status__link' do
 | 
				
			||||||
      - if status.in_reply_to_id.nil?
 | 
					      - if status.in_reply_to_id.nil?
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,11 @@
 | 
				
			||||||
.status
 | 
					.status
 | 
				
			||||||
  .status__info
 | 
					  .status__info
 | 
				
			||||||
    = link_to ActivityPub::TagManager.instance.url_for(status), class: 'status__relative-time u-url u-uid', target: stream_link_target, rel: 'noopener' do
 | 
					    = link_to ActivityPub::TagManager.instance.url_for(status), class: 'status__relative-time u-url u-uid', target: stream_link_target, rel: 'noopener noreferrer' do
 | 
				
			||||||
      %time.time-ago{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
 | 
					      %time.time-ago{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
 | 
				
			||||||
    %data.dt-published{ value: status.created_at.to_time.iso8601 }
 | 
					    %data.dt-published{ value: status.created_at.to_time.iso8601 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .p-author.h-card
 | 
					    .p-author.h-card
 | 
				
			||||||
      = link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'status__display-name u-url', target: stream_link_target, rel: 'noopener' do
 | 
					      = link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'status__display-name u-url', target: stream_link_target, rel: 'noopener noreferrer' do
 | 
				
			||||||
        .status__avatar
 | 
					        .status__avatar
 | 
				
			||||||
          %div
 | 
					          %div
 | 
				
			||||||
            - if current_account&.user&.setting_auto_play_gif || autoplay
 | 
					            - if current_account&.user&.setting_auto_play_gif || autoplay
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -175,6 +175,7 @@ en:
 | 
				
			||||||
        user: User
 | 
					        user: User
 | 
				
			||||||
      salmon_url: Salmon URL
 | 
					      salmon_url: Salmon URL
 | 
				
			||||||
      search: Search
 | 
					      search: Search
 | 
				
			||||||
 | 
					      search_same_ip: Other users with the same IP
 | 
				
			||||||
      shared_inbox_url: Shared inbox URL
 | 
					      shared_inbox_url: Shared inbox URL
 | 
				
			||||||
      show:
 | 
					      show:
 | 
				
			||||||
        created_reports: Made reports
 | 
					        created_reports: Made reports
 | 
				
			||||||
| 
						 | 
					@ -588,6 +589,7 @@ en:
 | 
				
			||||||
    confirmation_dialogs: Confirmation dialogs
 | 
					    confirmation_dialogs: Confirmation dialogs
 | 
				
			||||||
    discovery: Discovery
 | 
					    discovery: Discovery
 | 
				
			||||||
    sensitive_content: Sensitive content
 | 
					    sensitive_content: Sensitive content
 | 
				
			||||||
 | 
					    toot_layout: Toot layout
 | 
				
			||||||
  application_mailer:
 | 
					  application_mailer:
 | 
				
			||||||
    notification_preferences: Change e-mail preferences
 | 
					    notification_preferences: Change e-mail preferences
 | 
				
			||||||
    salutation: "%{name},"
 | 
					    salutation: "%{name},"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,7 +83,7 @@ en:
 | 
				
			||||||
        text: Custom warning
 | 
					        text: Custom warning
 | 
				
			||||||
        type: Action
 | 
					        type: Action
 | 
				
			||||||
        types:
 | 
					        types:
 | 
				
			||||||
          disable: Disable
 | 
					          disable: Disable login
 | 
				
			||||||
          none: Do nothing
 | 
					          none: Do nothing
 | 
				
			||||||
          silence: Silence
 | 
					          silence: Silence
 | 
				
			||||||
          suspend: Suspend and irreversibly delete account data
 | 
					          suspend: Suspend and irreversibly delete account data
 | 
				
			||||||
| 
						 | 
					@ -118,6 +118,7 @@ en:
 | 
				
			||||||
        setting_aggregate_reblogs: Group boosts in timelines
 | 
					        setting_aggregate_reblogs: Group boosts in timelines
 | 
				
			||||||
        setting_auto_play_gif: Auto-play animated GIFs
 | 
					        setting_auto_play_gif: Auto-play animated GIFs
 | 
				
			||||||
        setting_boost_modal: Show confirmation dialog before boosting
 | 
					        setting_boost_modal: Show confirmation dialog before boosting
 | 
				
			||||||
 | 
					        setting_crop_images: Crop images in non-expanded toots to 16x9
 | 
				
			||||||
        setting_default_content_type: Default format for toots
 | 
					        setting_default_content_type: Default format for toots
 | 
				
			||||||
        setting_default_content_type_html: HTML
 | 
					        setting_default_content_type_html: HTML
 | 
				
			||||||
        setting_default_content_type_markdown: Markdown
 | 
					        setting_default_content_type_markdown: Markdown
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,6 +41,7 @@ defaults: &defaults
 | 
				
			||||||
  use_pending_items: false
 | 
					  use_pending_items: false
 | 
				
			||||||
  trends: true
 | 
					  trends: true
 | 
				
			||||||
  trendable_by_default: false
 | 
					  trendable_by_default: false
 | 
				
			||||||
 | 
					  crop_images: true
 | 
				
			||||||
  notification_emails:
 | 
					  notification_emails:
 | 
				
			||||||
    follow: false
 | 
					    follow: false
 | 
				
			||||||
    reblog: false
 | 
					    reblog: false
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										16
									
								
								package.json
								
								
								
								
							
							
						
						
									
										16
									
								
								package.json
								
								
								
								
							| 
						 | 
					@ -72,7 +72,7 @@
 | 
				
			||||||
    "@babel/preset-env": "^7.6.0",
 | 
					    "@babel/preset-env": "^7.6.0",
 | 
				
			||||||
    "@babel/preset-react": "^7.0.0",
 | 
					    "@babel/preset-react": "^7.0.0",
 | 
				
			||||||
    "@babel/runtime": "^7.5.4",
 | 
					    "@babel/runtime": "^7.5.4",
 | 
				
			||||||
    "@clusterws/cws": "^0.15.0",
 | 
					    "@clusterws/cws": "^0.15.2",
 | 
				
			||||||
    "array-includes": "^3.0.3",
 | 
					    "array-includes": "^3.0.3",
 | 
				
			||||||
    "atrament": "^0.2.3",
 | 
					    "atrament": "^0.2.3",
 | 
				
			||||||
    "autoprefixer": "^9.6.1",
 | 
					    "autoprefixer": "^9.6.1",
 | 
				
			||||||
| 
						 | 
					@ -87,7 +87,7 @@
 | 
				
			||||||
    "classnames": "^2.2.5",
 | 
					    "classnames": "^2.2.5",
 | 
				
			||||||
    "compression-webpack-plugin": "^3.0.0",
 | 
					    "compression-webpack-plugin": "^3.0.0",
 | 
				
			||||||
    "copy-webpack-plugin": "^5.0.4",
 | 
					    "copy-webpack-plugin": "^5.0.4",
 | 
				
			||||||
    "cross-env": "^5.1.4",
 | 
					    "cross-env": "^6.0.3",
 | 
				
			||||||
    "css-loader": "^3.2.0",
 | 
					    "css-loader": "^3.2.0",
 | 
				
			||||||
    "cssnano": "^4.1.10",
 | 
					    "cssnano": "^4.1.10",
 | 
				
			||||||
    "detect-passive-events": "^1.0.2",
 | 
					    "detect-passive-events": "^1.0.2",
 | 
				
			||||||
| 
						 | 
					@ -128,8 +128,8 @@
 | 
				
			||||||
    "prop-types": "^15.5.10",
 | 
					    "prop-types": "^15.5.10",
 | 
				
			||||||
    "punycode": "^2.1.0",
 | 
					    "punycode": "^2.1.0",
 | 
				
			||||||
    "rails-ujs": "^5.2.3",
 | 
					    "rails-ujs": "^5.2.3",
 | 
				
			||||||
    "react": "^16.8.6",
 | 
					    "react": "^16.10.2",
 | 
				
			||||||
    "react-dom": "^16.8.6",
 | 
					    "react-dom": "^16.10.2",
 | 
				
			||||||
    "react-hotkeys": "^1.1.4",
 | 
					    "react-hotkeys": "^1.1.4",
 | 
				
			||||||
    "react-immutable-proptypes": "^2.1.0",
 | 
					    "react-immutable-proptypes": "^2.1.0",
 | 
				
			||||||
    "react-immutable-pure-component": "^1.1.1",
 | 
					    "react-immutable-pure-component": "^1.1.1",
 | 
				
			||||||
| 
						 | 
					@ -142,7 +142,7 @@
 | 
				
			||||||
    "react-redux-loading-bar": "^4.0.8",
 | 
					    "react-redux-loading-bar": "^4.0.8",
 | 
				
			||||||
    "react-router-dom": "^4.1.1",
 | 
					    "react-router-dom": "^4.1.1",
 | 
				
			||||||
    "react-router-scroll-4": "^1.0.0-beta.1",
 | 
					    "react-router-scroll-4": "^1.0.0-beta.1",
 | 
				
			||||||
    "react-select": "^2.4.4",
 | 
					    "react-select": "^3.0.5",
 | 
				
			||||||
    "react-sparklines": "^1.7.0",
 | 
					    "react-sparklines": "^1.7.0",
 | 
				
			||||||
    "react-swipeable-views": "^0.13.3",
 | 
					    "react-swipeable-views": "^0.13.3",
 | 
				
			||||||
    "react-textarea-autosize": "^7.1.0",
 | 
					    "react-textarea-autosize": "^7.1.0",
 | 
				
			||||||
| 
						 | 
					@ -155,7 +155,7 @@
 | 
				
			||||||
    "requestidlecallback": "^0.3.0",
 | 
					    "requestidlecallback": "^0.3.0",
 | 
				
			||||||
    "reselect": "^4.0.0",
 | 
					    "reselect": "^4.0.0",
 | 
				
			||||||
    "rimraf": "^3.0.0",
 | 
					    "rimraf": "^3.0.0",
 | 
				
			||||||
    "sass": "^1.22.12",
 | 
					    "sass": "^1.23.0",
 | 
				
			||||||
    "sass-loader": "^7.0.3",
 | 
					    "sass-loader": "^7.0.3",
 | 
				
			||||||
    "stringz": "^2.0.0",
 | 
					    "stringz": "^2.0.0",
 | 
				
			||||||
    "substring-trie": "^1.0.2",
 | 
					    "substring-trie": "^1.0.2",
 | 
				
			||||||
| 
						 | 
					@ -177,7 +177,7 @@
 | 
				
			||||||
    "babel-jest": "^24.9.0",
 | 
					    "babel-jest": "^24.9.0",
 | 
				
			||||||
    "enzyme": "^3.10.0",
 | 
					    "enzyme": "^3.10.0",
 | 
				
			||||||
    "enzyme-adapter-react-16": "^1.14.0",
 | 
					    "enzyme-adapter-react-16": "^1.14.0",
 | 
				
			||||||
    "eslint": "^6.5.0",
 | 
					    "eslint": "^6.5.1",
 | 
				
			||||||
    "eslint-plugin-import": "~2.18.2",
 | 
					    "eslint-plugin-import": "~2.18.2",
 | 
				
			||||||
    "eslint-plugin-jsx-a11y": "~6.2.3",
 | 
					    "eslint-plugin-jsx-a11y": "~6.2.3",
 | 
				
			||||||
    "eslint-plugin-promise": "~4.2.1",
 | 
					    "eslint-plugin-promise": "~4.2.1",
 | 
				
			||||||
| 
						 | 
					@ -185,7 +185,7 @@
 | 
				
			||||||
    "jest": "^24.9.0",
 | 
					    "jest": "^24.9.0",
 | 
				
			||||||
    "raf": "^3.4.1",
 | 
					    "raf": "^3.4.1",
 | 
				
			||||||
    "react-intl-translations-manager": "^5.0.3",
 | 
					    "react-intl-translations-manager": "^5.0.3",
 | 
				
			||||||
    "react-test-renderer": "^16.8.6",
 | 
					    "react-test-renderer": "^16.10.2",
 | 
				
			||||||
    "sass-lint": "^1.13.1",
 | 
					    "sass-lint": "^1.13.1",
 | 
				
			||||||
    "webpack-dev-server": "^3.8.0",
 | 
					    "webpack-dev-server": "^3.8.0",
 | 
				
			||||||
    "yargs": "^13.3.0"
 | 
					    "yargs": "^13.3.0"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -123,7 +123,7 @@
 | 
				
			||||||
    <published>2016-10-10T00:41:31Z</published>
 | 
					    <published>2016-10-10T00:41:31Z</published>
 | 
				
			||||||
    <updated>2016-10-10T00:41:31Z</updated>
 | 
					    <updated>2016-10-10T00:41:31Z</updated>
 | 
				
			||||||
    <title>Social media needs MOAR cats! http://kickass.zone/media/3</title>
 | 
					    <title>Social media needs MOAR cats! http://kickass.zone/media/3</title>
 | 
				
			||||||
    <content type="html"><p>Social media needs MOAR cats! <a rel="nofollow noopener" href="http://kickass.zone/media/3">http://kickass.zone/media/3</a></p></content>
 | 
					    <content type="html"><p>Social media needs MOAR cats! <a rel="nofollow noopener noreferrer" href="http://kickass.zone/media/3">http://kickass.zone/media/3</a></p></content>
 | 
				
			||||||
    <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
 | 
					    <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
 | 
				
			||||||
    <link rel="self" type="application/atom+xml" href="http://kickass.zone/users/localhost/updates/9.atom"/>
 | 
					    <link rel="self" type="application/atom+xml" href="http://kickass.zone/users/localhost/updates/9.atom"/>
 | 
				
			||||||
    <link rel="alternate" type="text/html" href="http://kickass.zone/users/localhost/updates/9"/>
 | 
					    <link rel="alternate" type="text/html" href="http://kickass.zone/users/localhost/updates/9"/>
 | 
				
			||||||
| 
						 | 
					@ -135,7 +135,7 @@
 | 
				
			||||||
    <published>2016-10-10T00:38:39Z</published>
 | 
					    <published>2016-10-10T00:38:39Z</published>
 | 
				
			||||||
    <updated>2016-10-10T00:38:39Z</updated>
 | 
					    <updated>2016-10-10T00:38:39Z</updated>
 | 
				
			||||||
    <title>http://kickass.zone/media/2</title>
 | 
					    <title>http://kickass.zone/media/2</title>
 | 
				
			||||||
    <content type="html"><p><a rel="nofollow noopener" href="http://kickass.zone/media/2">http://kickass.zone/media/2</a></p></content>
 | 
					    <content type="html"><p><a rel="nofollow noopener noreferrer" href="http://kickass.zone/media/2">http://kickass.zone/media/2</a></p></content>
 | 
				
			||||||
    <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
 | 
					    <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
 | 
				
			||||||
    <link rel="self" type="application/atom+xml" href="http://kickass.zone/users/localhost/updates/8.atom"/>
 | 
					    <link rel="self" type="application/atom+xml" href="http://kickass.zone/users/localhost/updates/8.atom"/>
 | 
				
			||||||
    <link rel="alternate" type="text/html" href="http://kickass.zone/users/localhost/updates/8"/>
 | 
					    <link rel="alternate" type="text/html" href="http://kickass.zone/users/localhost/updates/8"/>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,67 @@
 | 
				
			||||||
 | 
					require 'rails_helper'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RSpec.describe AccountsHelper, type: :helper do
 | 
				
			||||||
 | 
					  def set_not_embedded_view
 | 
				
			||||||
 | 
					    params[:controller] = "not_#{StatusesHelper::EMBEDDED_CONTROLLER}"
 | 
				
			||||||
 | 
					    params[:action] = "not_#{StatusesHelper::EMBEDDED_ACTION}"
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_embedded_view
 | 
				
			||||||
 | 
					    params[:controller] = StatusesHelper::EMBEDDED_CONTROLLER
 | 
				
			||||||
 | 
					    params[:action] = StatusesHelper::EMBEDDED_ACTION
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe '#display_name' do
 | 
				
			||||||
 | 
					    it 'uses the display name when it exists' do
 | 
				
			||||||
 | 
					      account = Account.new(display_name: "Display", username: "Username")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      expect(helper.display_name(account)).to eq "Display"
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'uses the username when display name is nil' do
 | 
				
			||||||
 | 
					      account = Account.new(display_name: nil, username: "Username")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      expect(helper.display_name(account)).to eq "Username"
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe '#acct' do
 | 
				
			||||||
 | 
					    it 'is fully qualified for embedded local accounts' do
 | 
				
			||||||
 | 
					      allow(Rails.configuration.x).to receive(:local_domain).and_return('local_domain')
 | 
				
			||||||
 | 
					      set_embedded_view
 | 
				
			||||||
 | 
					      account = Account.new(domain: nil, username: 'user')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      acct = helper.acct(account)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      expect(acct).to eq '@user@local_domain'
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'is fully qualified for embedded foreign accounts' do
 | 
				
			||||||
 | 
					      set_embedded_view
 | 
				
			||||||
 | 
					      account = Account.new(domain: 'foreign_server.com', username: 'user')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      acct = helper.acct(account)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      expect(acct).to eq '@user@foreign_server.com'
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'is fully qualified for non embedded foreign accounts' do
 | 
				
			||||||
 | 
					      set_not_embedded_view
 | 
				
			||||||
 | 
					      account = Account.new(domain: 'foreign_server.com', username: 'user')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      acct = helper.acct(account)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      expect(acct).to eq '@user@foreign_server.com'
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'is fully qualified for non embedded local accounts' do
 | 
				
			||||||
 | 
					      allow(Rails.configuration.x).to receive(:local_domain).and_return('local_domain')
 | 
				
			||||||
 | 
					      set_not_embedded_view
 | 
				
			||||||
 | 
					      account = Account.new(domain: nil, username: 'user')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      acct = helper.acct(account)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      expect(acct).to eq '@user@local_domain'
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
require 'rails_helper'
 | 
					require 'rails_helper'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RSpec.describe Admin::AccountModerationNotesHelper, type: :helper do
 | 
					RSpec.describe Admin::AccountModerationNotesHelper, type: :helper do
 | 
				
			||||||
  include StatusesHelper
 | 
					  include AccountsHelper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe '#admin_account_link_to' do
 | 
					  describe '#admin_account_link_to' do
 | 
				
			||||||
    context 'account is nil' do
 | 
					    context 'account is nil' do
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,20 +1,6 @@
 | 
				
			||||||
require 'rails_helper'
 | 
					require 'rails_helper'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RSpec.describe StatusesHelper, type: :helper do
 | 
					RSpec.describe StatusesHelper, type: :helper do
 | 
				
			||||||
  describe '#display_name' do
 | 
					 | 
				
			||||||
    it 'uses the display name when it exists' do
 | 
					 | 
				
			||||||
      account = Account.new(display_name: "Display", username: "Username")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      expect(helper.display_name(account)).to eq "Display"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    it 'uses the username when display name is nil' do
 | 
					 | 
				
			||||||
      account = Account.new(display_name: nil, username: "Username")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      expect(helper.display_name(account)).to eq "Username"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  describe '#stream_link_target' do
 | 
					  describe '#stream_link_target' do
 | 
				
			||||||
    it 'returns nil if it is not an embedded view' do
 | 
					    it 'returns nil if it is not an embedded view' do
 | 
				
			||||||
      set_not_embedded_view
 | 
					      set_not_embedded_view
 | 
				
			||||||
| 
						 | 
					@ -29,46 +15,6 @@ RSpec.describe StatusesHelper, type: :helper do
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe '#acct' do
 | 
					 | 
				
			||||||
    it 'is fully qualified for embedded local accounts' do
 | 
					 | 
				
			||||||
      allow(Rails.configuration.x).to receive(:local_domain).and_return('local_domain')
 | 
					 | 
				
			||||||
      set_embedded_view
 | 
					 | 
				
			||||||
      account = Account.new(domain: nil, username: 'user')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      acct = helper.acct(account)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      expect(acct).to eq '@user@local_domain'
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    it 'is fully qualified for embedded foreign accounts' do
 | 
					 | 
				
			||||||
      set_embedded_view
 | 
					 | 
				
			||||||
      account = Account.new(domain: 'foreign_server.com', username: 'user')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      acct = helper.acct(account)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      expect(acct).to eq '@user@foreign_server.com'
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    it 'is fully qualified for non embedded foreign accounts' do
 | 
					 | 
				
			||||||
      set_not_embedded_view
 | 
					 | 
				
			||||||
      account = Account.new(domain: 'foreign_server.com', username: 'user')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      acct = helper.acct(account)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      expect(acct).to eq '@user@foreign_server.com'
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    it 'is fully qualified for non embedded local accounts' do
 | 
					 | 
				
			||||||
      allow(Rails.configuration.x).to receive(:local_domain).and_return('local_domain')
 | 
					 | 
				
			||||||
      set_not_embedded_view
 | 
					 | 
				
			||||||
      account = Account.new(domain: nil, username: 'user')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      acct = helper.acct(account)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      expect(acct).to eq '@user@local_domain'
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def set_not_embedded_view
 | 
					  def set_not_embedded_view
 | 
				
			||||||
    params[:controller] = "not_#{StatusesHelper::EMBEDDED_CONTROLLER}"
 | 
					    params[:controller] = "not_#{StatusesHelper::EMBEDDED_CONTROLLER}"
 | 
				
			||||||
    params[:action] = "not_#{StatusesHelper::EMBEDDED_ACTION}"
 | 
					    params[:action] = "not_#{StatusesHelper::EMBEDDED_ACTION}"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,7 +80,7 @@ RSpec.describe FetchLinkCardService, type: :service do
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  context 'in a remote status' do
 | 
					  context 'in a remote status' do
 | 
				
			||||||
    let(:status) { Fabricate(:status, account: Fabricate(:account, domain: 'example.com'), text: 'Habt ihr ein paar gute Links zu #<span class="tag"><a href="https://quitter.se/tag/wannacry" target="_blank" rel="tag noopener" title="https://quitter.se/tag/wannacry">Wannacry</a></span> herumfliegen?   Ich will mal unter <br> <a href="https://github.com/qbi/WannaCry" target="_blank" rel="noopener" title="https://github.com/qbi/WannaCry">https://github.com/qbi/WannaCry</a> was sammeln. !<a href="http://sn.jonkman.ca/group/416/id" target="_blank" rel="noopener" title="http://sn.jonkman.ca/group/416/id">security</a> ') }
 | 
					    let(:status) { Fabricate(:status, account: Fabricate(:account, domain: 'example.com'), text: 'Habt ihr ein paar gute Links zu #<span class="tag"><a href="https://quitter.se/tag/wannacry" target="_blank" rel="tag noopener noreferrer" title="https://quitter.se/tag/wannacry">Wannacry</a></span> herumfliegen?   Ich will mal unter <br> <a href="https://github.com/qbi/WannaCry" target="_blank" rel="noopener noreferrer" title="https://github.com/qbi/WannaCry">https://github.com/qbi/WannaCry</a> was sammeln. !<a href="http://sn.jonkman.ca/group/416/id" target="_blank" rel="noopener noreferrer" title="http://sn.jonkman.ca/group/416/id">security</a> ') }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it 'parses out URLs' do
 | 
					    it 'parses out URLs' do
 | 
				
			||||||
      expect(a_request(:get, 'https://github.com/qbi/WannaCry')).to have_been_made.at_least_once
 | 
					      expect(a_request(:get, 'https://github.com/qbi/WannaCry')).to have_been_made.at_least_once
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,12 +28,12 @@ RSpec.describe VerifyLinkService, type: :service do
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    context 'when a link contains an <a rel="noopener"> back' do
 | 
					    context 'when a link contains an <a rel="noopener noreferrer"> back' do
 | 
				
			||||||
      let(:html) do
 | 
					      let(:html) do
 | 
				
			||||||
        <<-HTML
 | 
					        <<-HTML
 | 
				
			||||||
          <!doctype html>
 | 
					          <!doctype html>
 | 
				
			||||||
          <body>
 | 
					          <body>
 | 
				
			||||||
            <a href="#{ActivityPub::TagManager.instance.url_for(account)}" rel="noopener me" target="_blank">Follow me on Mastodon</a>
 | 
					            <a href="#{ActivityPub::TagManager.instance.url_for(account)}" rel="me noopener noreferrer" target="_blank">Follow me on Mastodon</a>
 | 
				
			||||||
          </body>
 | 
					          </body>
 | 
				
			||||||
        HTML
 | 
					        HTML
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										325
									
								
								yarn.lock
								
								
								
								
							
							
						
						
									
										325
									
								
								yarn.lock
								
								
								
								
							| 
						 | 
					@ -782,10 +782,10 @@
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    regenerator-runtime "^0.12.0"
 | 
					    regenerator-runtime "^0.12.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@babel/runtime@^7.1.2", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5":
 | 
					"@babel/runtime@^7.1.2", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5":
 | 
				
			||||||
  version "7.5.5"
 | 
					  version "7.6.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
 | 
					  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.0.tgz#4fc1d642a9fd0299754e8b5de62c631cf5568205"
 | 
				
			||||||
  integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
 | 
					  integrity sha512-89eSBLJsxNxOERC0Op4vd+0Bqm6wRMqMbFtV3i0/fbaWw/mJ8Q3eBvgX0G4SyrOOLCtbu98HspF8o09MRT+KzQ==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    regenerator-runtime "^0.13.2"
 | 
					    regenerator-runtime "^0.13.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -831,10 +831,10 @@
 | 
				
			||||||
    lodash "^4.17.13"
 | 
					    lodash "^4.17.13"
 | 
				
			||||||
    to-fast-properties "^2.0.0"
 | 
					    to-fast-properties "^2.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@clusterws/cws@^0.15.0":
 | 
					"@clusterws/cws@^0.15.2":
 | 
				
			||||||
  version "0.15.0"
 | 
					  version "0.15.2"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@clusterws/cws/-/cws-0.15.0.tgz#1d585927252d1cd92e676c952fa6d69df14a0d07"
 | 
					  resolved "https://registry.yarnpkg.com/@clusterws/cws/-/cws-0.15.2.tgz#b4cc9d224992d939cf996fca24c655e34a1f5c94"
 | 
				
			||||||
  integrity sha512-41QpCngw86n41hIdU5Nx2QJmmxZuA9FPtDkjONrYpk27L7HjL1kj6J5oWEjbr14yXLfigZit3VY+oACDCGbiHw==
 | 
					  integrity sha512-nTXrmbv8IK38VBvfhdhigrxC7GvN4fsDrImCGx/b8jb3AP34e5B23cfXQCxZ2H3M3rywWbkeNdX9bGc01nX2rw==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@cnakazawa/watch@^1.0.3":
 | 
					"@cnakazawa/watch@^1.0.3":
 | 
				
			||||||
  version "1.0.3"
 | 
					  version "1.0.3"
 | 
				
			||||||
| 
						 | 
					@ -844,52 +844,82 @@
 | 
				
			||||||
    exec-sh "^0.3.2"
 | 
					    exec-sh "^0.3.2"
 | 
				
			||||||
    minimist "^1.2.0"
 | 
					    minimist "^1.2.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@emotion/babel-utils@^0.6.4":
 | 
					"@emotion/cache@^10.0.17", "@emotion/cache@^10.0.9":
 | 
				
			||||||
  version "0.6.10"
 | 
					  version "10.0.19"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@emotion/babel-utils/-/babel-utils-0.6.10.tgz#83dbf3dfa933fae9fc566e54fbb45f14674c6ccc"
 | 
					  resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.19.tgz#d258d94d9c707dcadaf1558def968b86bb87ad71"
 | 
				
			||||||
  integrity sha512-/fnkM/LTEp3jKe++T0KyTszVGWNKPNOUJfjNKLO17BzQ6QPxgbg3whayom1Qr2oLFH3V92tDymU+dT5q676uow==
 | 
					  integrity sha512-BoiLlk4vEsGBg2dAqGSJu0vJl/PgVtCYLBFJaEO8RmQzPugXewQCXZJNXTDFaRlfCs0W+quesayav4fvaif5WQ==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    "@emotion/hash" "^0.6.6"
 | 
					    "@emotion/sheet" "0.9.3"
 | 
				
			||||||
    "@emotion/memoize" "^0.6.6"
 | 
					    "@emotion/stylis" "0.8.4"
 | 
				
			||||||
    "@emotion/serialize" "^0.9.1"
 | 
					    "@emotion/utils" "0.11.2"
 | 
				
			||||||
    convert-source-map "^1.5.1"
 | 
					    "@emotion/weak-memoize" "0.2.4"
 | 
				
			||||||
    find-root "^1.1.0"
 | 
					 | 
				
			||||||
    source-map "^0.7.2"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@emotion/hash@^0.6.2", "@emotion/hash@^0.6.6":
 | 
					"@emotion/core@^10.0.9":
 | 
				
			||||||
  version "0.6.6"
 | 
					  version "10.0.17"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.6.6.tgz#62266c5f0eac6941fece302abad69f2ee7e25e44"
 | 
					  resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.17.tgz#3367376709721f4ee2068cff54ba581d362789d8"
 | 
				
			||||||
  integrity sha512-ojhgxzUHZ7am3D2jHkMzPpsBAiB005GF5YU4ea+8DNPybMk01JJUM9V9YRlF/GE95tcOm8DxQvWA2jq19bGalQ==
 | 
					  integrity sha512-gykyjjr0sxzVuZBVTVK4dUmYsorc2qLhdYgSiOVK+m7WXgcYTKZevGWZ7TLAgTZvMelCTvhNq8xnf8FR1IdTbg==
 | 
				
			||||||
 | 
					 | 
				
			||||||
"@emotion/memoize@^0.6.1", "@emotion/memoize@^0.6.6":
 | 
					 | 
				
			||||||
  version "0.6.6"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.6.6.tgz#004b98298d04c7ca3b4f50ca2035d4f60d2eed1b"
 | 
					 | 
				
			||||||
  integrity sha512-h4t4jFjtm1YV7UirAFuSuFGyLa+NNxjdkq6DpFLANNQY5rHueFZHVY+8Cu1HYVP6DrheB0kv4m5xPjo7eKT7yQ==
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
"@emotion/serialize@^0.9.1":
 | 
					 | 
				
			||||||
  version "0.9.1"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.9.1.tgz#a494982a6920730dba6303eb018220a2b629c145"
 | 
					 | 
				
			||||||
  integrity sha512-zTuAFtyPvCctHBEL8KZ5lJuwBanGSutFEncqLn/m9T1a6a93smBStK+bZzcNPgj4QS8Rkw9VTwJGhRIUVO8zsQ==
 | 
					 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    "@emotion/hash" "^0.6.6"
 | 
					    "@babel/runtime" "^7.5.5"
 | 
				
			||||||
    "@emotion/memoize" "^0.6.6"
 | 
					    "@emotion/cache" "^10.0.17"
 | 
				
			||||||
    "@emotion/unitless" "^0.6.7"
 | 
					    "@emotion/css" "^10.0.14"
 | 
				
			||||||
    "@emotion/utils" "^0.8.2"
 | 
					    "@emotion/serialize" "^0.11.10"
 | 
				
			||||||
 | 
					    "@emotion/sheet" "0.9.3"
 | 
				
			||||||
 | 
					    "@emotion/utils" "0.11.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@emotion/stylis@^0.7.0":
 | 
					"@emotion/css@^10.0.14", "@emotion/css@^10.0.9":
 | 
				
			||||||
  version "0.7.1"
 | 
					  version "10.0.14"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.7.1.tgz#50f63225e712d99e2b2b39c19c70fff023793ca5"
 | 
					  resolved "https://registry.yarnpkg.com/@emotion/css/-/css-10.0.14.tgz#95dacabdd0e22845d1a1b0b5968d9afa34011139"
 | 
				
			||||||
  integrity sha512-/SLmSIkN13M//53TtNxgxo57mcJk/UJIDFRKwOiLIBEyBHEcipgR6hNMQ/59Sl4VjCJ0Z/3zeAZyvnSLPG/1HQ==
 | 
					  integrity sha512-MozgPkBEWvorcdpqHZE5x1D/PLEHUitALQCQYt2wayf4UNhpgQs2tN0UwHYS4FMy5ROBH+0ALyCFVYJ/ywmwlg==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    "@emotion/serialize" "^0.11.8"
 | 
				
			||||||
 | 
					    "@emotion/utils" "0.11.2"
 | 
				
			||||||
 | 
					    babel-plugin-emotion "^10.0.14"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@emotion/unitless@^0.6.2", "@emotion/unitless@^0.6.7":
 | 
					"@emotion/hash@0.7.3":
 | 
				
			||||||
  version "0.6.7"
 | 
					  version "0.7.3"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.6.7.tgz#53e9f1892f725b194d5e6a1684a7b394df592397"
 | 
					  resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.3.tgz#a166882c81c0c6040975dd30df24fae8549bd96f"
 | 
				
			||||||
  integrity sha512-Arj1hncvEVqQ2p7Ega08uHLr1JuRYBuO5cIvcA+WWEQ5+VmkOE3ZXzl04NbQxeQpWX78G7u6MqxKuNX3wvYZxg==
 | 
					  integrity sha512-14ZVlsB9akwvydAdaEnVnvqu6J2P6ySv39hYyl/aoB6w/V+bXX0tay8cF6paqbgZsN2n5Xh15uF4pE+GvE+itw==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@emotion/utils@^0.8.2":
 | 
					"@emotion/memoize@0.7.3":
 | 
				
			||||||
  version "0.8.2"
 | 
					  version "0.7.3"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.8.2.tgz#576ff7fb1230185b619a75d258cbc98f0867a8dc"
 | 
					  resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.3.tgz#5b6b1c11d6a6dddf1f2fc996f74cf3b219644d78"
 | 
				
			||||||
  integrity sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw==
 | 
					  integrity sha512-2Md9mH6mvo+ygq1trTeVp2uzAKwE2P7In0cRpD/M9Q70aH8L+rxMLbb3JCN2JoSWsV2O+DdFjfbbXoMoLBczow==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@emotion/serialize@^0.11.10", "@emotion/serialize@^0.11.11", "@emotion/serialize@^0.11.8":
 | 
				
			||||||
 | 
					  version "0.11.11"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.11.tgz#c92a5e5b358070a7242d10508143306524e842a4"
 | 
				
			||||||
 | 
					  integrity sha512-YG8wdCqoWtuoMxhHZCTA+egL0RSGdHEc+YCsmiSBPBEDNuVeMWtjEWtGrhUterSChxzwnWBXvzSxIFQI/3sHLw==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    "@emotion/hash" "0.7.3"
 | 
				
			||||||
 | 
					    "@emotion/memoize" "0.7.3"
 | 
				
			||||||
 | 
					    "@emotion/unitless" "0.7.4"
 | 
				
			||||||
 | 
					    "@emotion/utils" "0.11.2"
 | 
				
			||||||
 | 
					    csstype "^2.5.7"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@emotion/sheet@0.9.3":
 | 
				
			||||||
 | 
					  version "0.9.3"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.3.tgz#689f135ecf87d3c650ed0c4f5ddcbe579883564a"
 | 
				
			||||||
 | 
					  integrity sha512-c3Q6V7Df7jfwSq5AzQWbXHa5soeE4F5cbqi40xn0CzXxWW9/6Mxq48WJEtqfWzbZtW9odZdnRAkwCQwN12ob4A==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@emotion/stylis@0.8.4":
 | 
				
			||||||
 | 
					  version "0.8.4"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.4.tgz#6c51afdf1dd0d73666ba09d2eb6c25c220d6fe4c"
 | 
				
			||||||
 | 
					  integrity sha512-TLmkCVm8f8gH0oLv+HWKiu7e8xmBIaokhxcEKPh1m8pXiV/akCiq50FvYgOwY42rjejck8nsdQxZlXZ7pmyBUQ==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@emotion/unitless@0.7.4":
 | 
				
			||||||
 | 
					  version "0.7.4"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.4.tgz#a87b4b04e5ae14a88d48ebef15015f6b7d1f5677"
 | 
				
			||||||
 | 
					  integrity sha512-kBa+cDHOR9jpRJ+kcGMsysrls0leukrm68DmFQoMIWQcXdr2cZvyvypWuGYT7U+9kAExUE7+T7r6G3C3A6L8MQ==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@emotion/utils@0.11.2":
 | 
				
			||||||
 | 
					  version "0.11.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.2.tgz#713056bfdffb396b0a14f1c8f18e7b4d0d200183"
 | 
				
			||||||
 | 
					  integrity sha512-UHX2XklLl3sIaP6oiMmlVzT0J+2ATTVpf0dHQVyPJHTkOITvXfaSqnRk6mdDhV9pR8T/tHc3cex78IKXssmzrA==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@emotion/weak-memoize@0.2.4":
 | 
				
			||||||
 | 
					  version "0.2.4"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc"
 | 
				
			||||||
 | 
					  integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@jest/console@^24.7.1":
 | 
					"@jest/console@^24.7.1":
 | 
				
			||||||
  version "24.7.1"
 | 
					  version "24.7.1"
 | 
				
			||||||
| 
						 | 
					@ -1795,23 +1825,21 @@ babel-plugin-dynamic-import-node@^2.3.0:
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    object.assign "^4.1.0"
 | 
					    object.assign "^4.1.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
babel-plugin-emotion@^9.2.11:
 | 
					babel-plugin-emotion@^10.0.14:
 | 
				
			||||||
  version "9.2.11"
 | 
					  version "10.0.19"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-9.2.11.tgz#319c005a9ee1d15bb447f59fe504c35fd5807728"
 | 
					  resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.19.tgz#67b9b213f7505c015f163a387a005c12c502b1de"
 | 
				
			||||||
  integrity sha512-dgCImifnOPPSeXod2znAmgc64NhaaOjGEHROR/M+lmStb3841yK1sgaDYAYMnlvWNz8GnpwIPN0VmNpbWYZ+VQ==
 | 
					  integrity sha512-1pJb5uKN/gx6bi3gGr588Krj49sxARI9KmxhtMUa+NRJb6lR3OfC51mh3NlWRsOqdjWlT4cSjnZpnFq5K3T5ZA==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    "@babel/helper-module-imports" "^7.0.0"
 | 
					    "@babel/helper-module-imports" "^7.0.0"
 | 
				
			||||||
    "@emotion/babel-utils" "^0.6.4"
 | 
					    "@emotion/hash" "0.7.3"
 | 
				
			||||||
    "@emotion/hash" "^0.6.2"
 | 
					    "@emotion/memoize" "0.7.3"
 | 
				
			||||||
    "@emotion/memoize" "^0.6.1"
 | 
					    "@emotion/serialize" "^0.11.11"
 | 
				
			||||||
    "@emotion/stylis" "^0.7.0"
 | 
					 | 
				
			||||||
    babel-plugin-macros "^2.0.0"
 | 
					    babel-plugin-macros "^2.0.0"
 | 
				
			||||||
    babel-plugin-syntax-jsx "^6.18.0"
 | 
					    babel-plugin-syntax-jsx "^6.18.0"
 | 
				
			||||||
    convert-source-map "^1.5.0"
 | 
					    convert-source-map "^1.5.0"
 | 
				
			||||||
 | 
					    escape-string-regexp "^1.0.5"
 | 
				
			||||||
    find-root "^1.1.0"
 | 
					    find-root "^1.1.0"
 | 
				
			||||||
    mkdirp "^0.5.1"
 | 
					 | 
				
			||||||
    source-map "^0.5.7"
 | 
					    source-map "^0.5.7"
 | 
				
			||||||
    touch "^2.0.1"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
babel-plugin-istanbul@^5.1.0:
 | 
					babel-plugin-istanbul@^5.1.0:
 | 
				
			||||||
  version "5.1.1"
 | 
					  version "5.1.1"
 | 
				
			||||||
| 
						 | 
					@ -2703,7 +2731,7 @@ content-type@~1.0.4:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
 | 
					  resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
 | 
				
			||||||
  integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
 | 
					  integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1:
 | 
					convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0:
 | 
				
			||||||
  version "1.6.0"
 | 
					  version "1.6.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20"
 | 
					  resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20"
 | 
				
			||||||
  integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==
 | 
					  integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==
 | 
				
			||||||
| 
						 | 
					@ -2822,19 +2850,6 @@ create-ecdh@^4.0.0:
 | 
				
			||||||
    bn.js "^4.1.0"
 | 
					    bn.js "^4.1.0"
 | 
				
			||||||
    elliptic "^6.0.0"
 | 
					    elliptic "^6.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
create-emotion@^9.2.12:
 | 
					 | 
				
			||||||
  version "9.2.12"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-9.2.12.tgz#0fc8e7f92c4f8bb924b0fef6781f66b1d07cb26f"
 | 
					 | 
				
			||||||
  integrity sha512-P57uOF9NL2y98Xrbl2OuiDQUZ30GVmASsv5fbsjF4Hlraip2kyAvMm+2PoYUvFFw03Fhgtxk3RqZSm2/qHL9hA==
 | 
					 | 
				
			||||||
  dependencies:
 | 
					 | 
				
			||||||
    "@emotion/hash" "^0.6.2"
 | 
					 | 
				
			||||||
    "@emotion/memoize" "^0.6.1"
 | 
					 | 
				
			||||||
    "@emotion/stylis" "^0.7.0"
 | 
					 | 
				
			||||||
    "@emotion/unitless" "^0.6.2"
 | 
					 | 
				
			||||||
    csstype "^2.5.2"
 | 
					 | 
				
			||||||
    stylis "^3.5.0"
 | 
					 | 
				
			||||||
    stylis-rule-sheet "^0.0.10"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
create-hash@^1.1.0, create-hash@^1.1.2:
 | 
					create-hash@^1.1.0, create-hash@^1.1.2:
 | 
				
			||||||
  version "1.2.0"
 | 
					  version "1.2.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
 | 
					  resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
 | 
				
			||||||
| 
						 | 
					@ -2858,13 +2873,12 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
 | 
				
			||||||
    safe-buffer "^5.0.1"
 | 
					    safe-buffer "^5.0.1"
 | 
				
			||||||
    sha.js "^2.4.8"
 | 
					    sha.js "^2.4.8"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cross-env@^5.1.4:
 | 
					cross-env@^6.0.3:
 | 
				
			||||||
  version "5.2.0"
 | 
					  version "6.0.3"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.2.0.tgz#6ecd4c015d5773e614039ee529076669b9d126f2"
 | 
					  resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-6.0.3.tgz#4256b71e49b3a40637a0ce70768a6ef5c72ae941"
 | 
				
			||||||
  integrity sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg==
 | 
					  integrity sha512-+KqxF6LCvfhWvADcDPqo64yVIB31gv/jQulX2NGzKS/g3GEVz6/pt4wjHFtFWsHMddebWD/sDthJemzM4MaAag==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    cross-spawn "^6.0.5"
 | 
					    cross-spawn "^7.0.0"
 | 
				
			||||||
    is-windows "^1.0.0"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
 | 
					cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
 | 
				
			||||||
  version "6.0.5"
 | 
					  version "6.0.5"
 | 
				
			||||||
| 
						 | 
					@ -2877,6 +2891,15 @@ cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
 | 
				
			||||||
    shebang-command "^1.2.0"
 | 
					    shebang-command "^1.2.0"
 | 
				
			||||||
    which "^1.2.9"
 | 
					    which "^1.2.9"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cross-spawn@^7.0.0:
 | 
				
			||||||
 | 
					  version "7.0.1"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14"
 | 
				
			||||||
 | 
					  integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    path-key "^3.1.0"
 | 
				
			||||||
 | 
					    shebang-command "^2.0.0"
 | 
				
			||||||
 | 
					    which "^2.0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
crypto-browserify@^3.11.0:
 | 
					crypto-browserify@^3.11.0:
 | 
				
			||||||
  version "3.12.0"
 | 
					  version "3.12.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
 | 
					  resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
 | 
				
			||||||
| 
						 | 
					@ -3120,10 +3143,10 @@ csstype@^2.2.0:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.0.tgz#6cf7b2fa7fc32aab3d746802c244d4eda71371a2"
 | 
					  resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.0.tgz#6cf7b2fa7fc32aab3d746802c244d4eda71371a2"
 | 
				
			||||||
  integrity sha512-by8hi8BlLbowQq0qtkx54d9aN73R9oUW20HISpka5kmgsR9F7nnxgfsemuR2sdCKZh+CDNf5egW9UZMm4mgJRg==
 | 
					  integrity sha512-by8hi8BlLbowQq0qtkx54d9aN73R9oUW20HISpka5kmgsR9F7nnxgfsemuR2sdCKZh+CDNf5egW9UZMm4mgJRg==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
csstype@^2.5.2:
 | 
					csstype@^2.5.7:
 | 
				
			||||||
  version "2.6.5"
 | 
					  version "2.6.6"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.5.tgz#1cd1dff742ebf4d7c991470ae71e12bb6751e034"
 | 
					  resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.6.tgz#c34f8226a94bbb10c32cc0d714afdf942291fc41"
 | 
				
			||||||
  integrity sha512-JsTaiksRsel5n7XwqPAfB0l3TFKdpjW/kgAELf9vrb5adGA7UCPLajKK5s3nFrcFm3Rkyp/Qkgl73ENc1UY3cA==
 | 
					  integrity sha512-RpFbQGUE74iyPgvr46U9t1xoQBM8T4BL8SxrN66Le2xYAPSaDJJKeztV3awugusb3g3G9iL8StmkBBXhcbbXhg==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cyclist@^1.0.1:
 | 
					cyclist@^1.0.1:
 | 
				
			||||||
  version "1.0.1"
 | 
					  version "1.0.1"
 | 
				
			||||||
| 
						 | 
					@ -3547,14 +3570,6 @@ emojis-list@^2.0.0:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
 | 
					  resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
 | 
				
			||||||
  integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
 | 
					  integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
emotion@^9.1.2:
 | 
					 | 
				
			||||||
  version "9.2.12"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/emotion/-/emotion-9.2.12.tgz#53925aaa005614e65c6e43db8243c843574d1ea9"
 | 
					 | 
				
			||||||
  integrity sha512-hcx7jppaI8VoXxIWEhxpDW7I+B4kq9RNzQLmsrF6LY8BGKqe2N+gFAQr0EfuFucFlPs2A9HM4+xNj4NeqEWIOQ==
 | 
					 | 
				
			||||||
  dependencies:
 | 
					 | 
				
			||||||
    babel-plugin-emotion "^9.2.11"
 | 
					 | 
				
			||||||
    create-emotion "^9.2.12"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
encodeurl@~1.0.2:
 | 
					encodeurl@~1.0.2:
 | 
				
			||||||
  version "1.0.2"
 | 
					  version "1.0.2"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
 | 
					  resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
 | 
				
			||||||
| 
						 | 
					@ -3921,10 +3936,10 @@ eslint@^2.7.0:
 | 
				
			||||||
    text-table "~0.2.0"
 | 
					    text-table "~0.2.0"
 | 
				
			||||||
    user-home "^2.0.0"
 | 
					    user-home "^2.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
eslint@^6.5.0:
 | 
					eslint@^6.5.1:
 | 
				
			||||||
  version "6.5.0"
 | 
					  version "6.5.1"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.5.0.tgz#304623eec903969dd5c9f2d61c6ce3d6ecec8750"
 | 
					  resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.5.1.tgz#828e4c469697d43bb586144be152198b91e96ed6"
 | 
				
			||||||
  integrity sha512-IIbSW+vKOqMatPmS9ayyku4tvWxHY2iricSRtOz6+ZA5IPRlgXzEL0u/j6dr4eha0ugmhMwDTqxtmNu3kj9O4w==
 | 
					  integrity sha512-32h99BoLYStT1iq1v2P9uwpyznQ4M2jRiFB6acitKz52Gqn+vPaMDUTB1bYi1WN4Nquj2w+t+bimYUG83DC55A==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    "@babel/code-frame" "^7.0.0"
 | 
					    "@babel/code-frame" "^7.0.0"
 | 
				
			||||||
    ajv "^6.10.0"
 | 
					    ajv "^6.10.0"
 | 
				
			||||||
| 
						 | 
					@ -5691,7 +5706,7 @@ is-url@^1.2.4:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52"
 | 
					  resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52"
 | 
				
			||||||
  integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==
 | 
					  integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
is-windows@^1.0.0, is-windows@^1.0.1, is-windows@^1.0.2:
 | 
					is-windows@^1.0.1, is-windows@^1.0.2:
 | 
				
			||||||
  version "1.0.2"
 | 
					  version "1.0.2"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
 | 
					  resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
 | 
				
			||||||
  integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
 | 
					  integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
 | 
				
			||||||
| 
						 | 
					@ -7090,13 +7105,6 @@ nopt@^4.0.1:
 | 
				
			||||||
    abbrev "1"
 | 
					    abbrev "1"
 | 
				
			||||||
    osenv "^0.1.4"
 | 
					    osenv "^0.1.4"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nopt@~1.0.10:
 | 
					 | 
				
			||||||
  version "1.0.10"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
 | 
					 | 
				
			||||||
  integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=
 | 
					 | 
				
			||||||
  dependencies:
 | 
					 | 
				
			||||||
    abbrev "1"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
normalize-package-data@^2.3.2:
 | 
					normalize-package-data@^2.3.2:
 | 
				
			||||||
  version "2.4.0"
 | 
					  version "2.4.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
 | 
					  resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
 | 
				
			||||||
| 
						 | 
					@ -7651,6 +7659,11 @@ path-key@^2.0.0, path-key@^2.0.1:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
 | 
					  resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
 | 
				
			||||||
  integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
 | 
					  integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					path-key@^3.1.0:
 | 
				
			||||||
 | 
					  version "3.1.0"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.0.tgz#99a10d870a803bdd5ee6f0470e58dfcd2f9a54d3"
 | 
				
			||||||
 | 
					  integrity sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
path-parse@^1.0.6:
 | 
					path-parse@^1.0.6:
 | 
				
			||||||
  version "1.0.6"
 | 
					  version "1.0.6"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
 | 
					  resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
 | 
				
			||||||
| 
						 | 
					@ -8497,15 +8510,15 @@ rc@^1.2.7:
 | 
				
			||||||
    minimist "^1.2.0"
 | 
					    minimist "^1.2.0"
 | 
				
			||||||
    strip-json-comments "~2.0.1"
 | 
					    strip-json-comments "~2.0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
react-dom@^16.8.6:
 | 
					react-dom@^16.10.2:
 | 
				
			||||||
  version "16.8.6"
 | 
					  version "16.10.2"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f"
 | 
					  resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.10.2.tgz#4840bce5409176bc3a1f2bd8cb10b92db452fda6"
 | 
				
			||||||
  integrity sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA==
 | 
					  integrity sha512-kWGDcH3ItJK4+6Pl9DZB16BXYAZyrYQItU4OMy0jAkv5aNqc+mAKb4TpFtAteI6TJZu+9ZlNhaeNQSVQDHJzkw==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    loose-envify "^1.1.0"
 | 
					    loose-envify "^1.1.0"
 | 
				
			||||||
    object-assign "^4.1.1"
 | 
					    object-assign "^4.1.1"
 | 
				
			||||||
    prop-types "^15.6.2"
 | 
					    prop-types "^15.6.2"
 | 
				
			||||||
    scheduler "^0.13.6"
 | 
					    scheduler "^0.16.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
react-event-listener@^0.6.0:
 | 
					react-event-listener@^0.6.0:
 | 
				
			||||||
  version "0.6.5"
 | 
					  version "0.6.5"
 | 
				
			||||||
| 
						 | 
					@ -8574,11 +8587,16 @@ react-intl@^2.9.0:
 | 
				
			||||||
    intl-relativeformat "^2.1.0"
 | 
					    intl-relativeformat "^2.1.0"
 | 
				
			||||||
    invariant "^2.1.1"
 | 
					    invariant "^2.1.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
react-is@^16.3.2, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0:
 | 
					react-is@^16.3.2, react-is@^16.7.0, react-is@^16.8.4, react-is@^16.9.0:
 | 
				
			||||||
  version "16.9.0"
 | 
					  version "16.9.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb"
 | 
					  resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb"
 | 
				
			||||||
  integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==
 | 
					  integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					react-is@^16.8.1, react-is@^16.8.6:
 | 
				
			||||||
 | 
					  version "16.10.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.10.2.tgz#984120fd4d16800e9a738208ab1fba422d23b5ab"
 | 
				
			||||||
 | 
					  integrity sha512-INBT1QEgtcCCgvccr5/86CfD71fw9EPmDxgiJX4I2Ddr6ZsV6iFXsuby+qWJPtmNuMY0zByTsG4468P7nHuNWA==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4:
 | 
					react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4:
 | 
				
			||||||
  version "3.0.4"
 | 
					  version "3.0.4"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
 | 
					  resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
 | 
				
			||||||
| 
						 | 
					@ -8674,13 +8692,16 @@ react-router@^4.3.1:
 | 
				
			||||||
    prop-types "^15.6.1"
 | 
					    prop-types "^15.6.1"
 | 
				
			||||||
    warning "^4.0.1"
 | 
					    warning "^4.0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
react-select@^2.4.4:
 | 
					react-select@^3.0.5:
 | 
				
			||||||
  version "2.4.4"
 | 
					  version "3.0.5"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/react-select/-/react-select-2.4.4.tgz#ba72468ef1060c7d46fbb862b0748f96491f1f73"
 | 
					  resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.0.5.tgz#f2810e63fa8a6be375b3fa6f390284e9e33c9573"
 | 
				
			||||||
  integrity sha512-C4QPLgy9h42J/KkdrpVxNmkY6p4lb49fsrbDk/hRcZpX7JvZPNb6mGj+c5SzyEtBv1DmQ9oPH4NmhAFvCrg8Jw==
 | 
					  integrity sha512-2tBXZ1XSqbk2boMUzSmKXwGl/6W46VkSMSLMy+ShccOVyD1kDTLPwLX7lugISkRMmL0v5BcLtriXOLfYwO0otw==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    "@babel/runtime" "^7.4.4"
 | 
				
			||||||
 | 
					    "@emotion/cache" "^10.0.9"
 | 
				
			||||||
 | 
					    "@emotion/core" "^10.0.9"
 | 
				
			||||||
 | 
					    "@emotion/css" "^10.0.9"
 | 
				
			||||||
    classnames "^2.2.5"
 | 
					    classnames "^2.2.5"
 | 
				
			||||||
    emotion "^9.1.2"
 | 
					 | 
				
			||||||
    memoize-one "^5.0.0"
 | 
					    memoize-one "^5.0.0"
 | 
				
			||||||
    prop-types "^15.6.0"
 | 
					    prop-types "^15.6.0"
 | 
				
			||||||
    raf "^3.4.0"
 | 
					    raf "^3.4.0"
 | 
				
			||||||
| 
						 | 
					@ -8726,7 +8747,7 @@ react-swipeable-views@^0.13.3:
 | 
				
			||||||
    react-swipeable-views-utils "^0.13.3"
 | 
					    react-swipeable-views-utils "^0.13.3"
 | 
				
			||||||
    warning "^4.0.1"
 | 
					    warning "^4.0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
react-test-renderer@^16.0.0-0, react-test-renderer@^16.8.6:
 | 
					react-test-renderer@^16.0.0-0:
 | 
				
			||||||
  version "16.8.6"
 | 
					  version "16.8.6"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.6.tgz#188d8029b8c39c786f998aa3efd3ffe7642d5ba1"
 | 
					  resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.6.tgz#188d8029b8c39c786f998aa3efd3ffe7642d5ba1"
 | 
				
			||||||
  integrity sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw==
 | 
					  integrity sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw==
 | 
				
			||||||
| 
						 | 
					@ -8736,6 +8757,16 @@ react-test-renderer@^16.0.0-0, react-test-renderer@^16.8.6:
 | 
				
			||||||
    react-is "^16.8.6"
 | 
					    react-is "^16.8.6"
 | 
				
			||||||
    scheduler "^0.13.6"
 | 
					    scheduler "^0.13.6"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					react-test-renderer@^16.10.2:
 | 
				
			||||||
 | 
					  version "16.10.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.10.2.tgz#4d8492f8678c9b43b721a7d79ed0840fdae7c518"
 | 
				
			||||||
 | 
					  integrity sha512-k9Qzyev6cTIcIfrhgrFlYQAFxh5EEDO6ALNqYqmKsWVA7Q/rUMTay5nD3nthi6COmYsd4ghVYyi8U86aoeMqYQ==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    object-assign "^4.1.1"
 | 
				
			||||||
 | 
					    prop-types "^15.6.2"
 | 
				
			||||||
 | 
					    react-is "^16.8.6"
 | 
				
			||||||
 | 
					    scheduler "^0.16.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
react-textarea-autosize@^7.1.0:
 | 
					react-textarea-autosize@^7.1.0:
 | 
				
			||||||
  version "7.1.0"
 | 
					  version "7.1.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-7.1.0.tgz#3132cb77e65d94417558d37c0bfe415a5afd3445"
 | 
					  resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-7.1.0.tgz#3132cb77e65d94417558d37c0bfe415a5afd3445"
 | 
				
			||||||
| 
						 | 
					@ -8761,15 +8792,14 @@ react-transition-group@^2.2.0, react-transition-group@^2.2.1:
 | 
				
			||||||
    prop-types "^15.6.2"
 | 
					    prop-types "^15.6.2"
 | 
				
			||||||
    react-lifecycles-compat "^3.0.4"
 | 
					    react-lifecycles-compat "^3.0.4"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
react@^16.8.6:
 | 
					react@^16.10.2:
 | 
				
			||||||
  version "16.8.6"
 | 
					  version "16.10.2"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"
 | 
					  resolved "https://registry.yarnpkg.com/react/-/react-16.10.2.tgz#a5ede5cdd5c536f745173c8da47bda64797a4cf0"
 | 
				
			||||||
  integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==
 | 
					  integrity sha512-MFVIq0DpIhrHFyqLU0S3+4dIcBhhOvBE8bJ/5kHPVOVaGdo0KuiQzpcjCPsf585WvhypqtrMILyoE2th6dT+Lw==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    loose-envify "^1.1.0"
 | 
					    loose-envify "^1.1.0"
 | 
				
			||||||
    object-assign "^4.1.1"
 | 
					    object-assign "^4.1.1"
 | 
				
			||||||
    prop-types "^15.6.2"
 | 
					    prop-types "^15.6.2"
 | 
				
			||||||
    scheduler "^0.13.6"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
read-pkg-up@^2.0.0:
 | 
					read-pkg-up@^2.0.0:
 | 
				
			||||||
  version "2.0.0"
 | 
					  version "2.0.0"
 | 
				
			||||||
| 
						 | 
					@ -9331,10 +9361,10 @@ sass-loader@^7.0.3:
 | 
				
			||||||
    pify "^3.0.0"
 | 
					    pify "^3.0.0"
 | 
				
			||||||
    semver "^5.5.0"
 | 
					    semver "^5.5.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sass@^1.22.12:
 | 
					sass@^1.23.0:
 | 
				
			||||||
  version "1.22.12"
 | 
					  version "1.23.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/sass/-/sass-1.22.12.tgz#5cbdd38720ffd1857da695331faee9f634bcb5d7"
 | 
					  resolved "https://registry.yarnpkg.com/sass/-/sass-1.23.0.tgz#bd526ff40dbc5d09a4ed69e2cffa849749977710"
 | 
				
			||||||
  integrity sha512-u5Rxn+dKTPCW5/11kMNxtmqKsxCjcpnqj9CaJoru1NqeJ0DOa9rOM00e0HqmseTAatGkKoLY+jaNecMYevu1gg==
 | 
					  integrity sha512-W4HT8+WE31Rzk3EPQC++CXjD5O+lOxgYBIB8Ohvt7/zeE2UzYW+TOczDrRU3KcEy3+xwXXbmDsOZFkoqgD4TKw==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    chokidar ">=2.0.0 <4.0.0"
 | 
					    chokidar ">=2.0.0 <4.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9351,6 +9381,14 @@ scheduler@^0.13.6:
 | 
				
			||||||
    loose-envify "^1.1.0"
 | 
					    loose-envify "^1.1.0"
 | 
				
			||||||
    object-assign "^4.1.1"
 | 
					    object-assign "^4.1.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					scheduler@^0.16.2:
 | 
				
			||||||
 | 
					  version "0.16.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.16.2.tgz#f74cd9d33eff6fc554edfb79864868e4819132c1"
 | 
				
			||||||
 | 
					  integrity sha512-BqYVWqwz6s1wZMhjFvLfVR5WXP7ZY32M/wYPo04CcuPM7XZEbV2TBNW7Z0UkguPTl0dWMA59VbNXxK6q+pHItg==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    loose-envify "^1.1.0"
 | 
				
			||||||
 | 
					    object-assign "^4.1.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
schema-utils@^1.0.0:
 | 
					schema-utils@^1.0.0:
 | 
				
			||||||
  version "1.0.0"
 | 
					  version "1.0.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
 | 
					  resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
 | 
				
			||||||
| 
						 | 
					@ -9509,11 +9547,23 @@ shebang-command@^1.2.0:
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    shebang-regex "^1.0.0"
 | 
					    shebang-regex "^1.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shebang-command@^2.0.0:
 | 
				
			||||||
 | 
					  version "2.0.0"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
 | 
				
			||||||
 | 
					  integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    shebang-regex "^3.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
shebang-regex@^1.0.0:
 | 
					shebang-regex@^1.0.0:
 | 
				
			||||||
  version "1.0.0"
 | 
					  version "1.0.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
 | 
					  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
 | 
				
			||||||
  integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
 | 
					  integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shebang-regex@^3.0.0:
 | 
				
			||||||
 | 
					  version "3.0.0"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
 | 
				
			||||||
 | 
					  integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
shelljs@^0.6.0:
 | 
					shelljs@^0.6.0:
 | 
				
			||||||
  version "0.6.1"
 | 
					  version "0.6.1"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8"
 | 
					  resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8"
 | 
				
			||||||
| 
						 | 
					@ -9669,11 +9719,6 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
 | 
					  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
 | 
				
			||||||
  integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
 | 
					  integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
source-map@^0.7.2:
 | 
					 | 
				
			||||||
  version "0.7.3"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
 | 
					 | 
				
			||||||
  integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
spdx-correct@^3.0.0:
 | 
					spdx-correct@^3.0.0:
 | 
				
			||||||
  version "3.1.0"
 | 
					  version "3.1.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4"
 | 
					  resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4"
 | 
				
			||||||
| 
						 | 
					@ -9948,16 +9993,6 @@ stylehacks@^4.0.0:
 | 
				
			||||||
    postcss "^7.0.0"
 | 
					    postcss "^7.0.0"
 | 
				
			||||||
    postcss-selector-parser "^3.0.0"
 | 
					    postcss-selector-parser "^3.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
stylis-rule-sheet@^0.0.10:
 | 
					 | 
				
			||||||
  version "0.0.10"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430"
 | 
					 | 
				
			||||||
  integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
stylis@^3.5.0:
 | 
					 | 
				
			||||||
  version "3.5.4"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe"
 | 
					 | 
				
			||||||
  integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
substring-trie@^1.0.2:
 | 
					substring-trie@^1.0.2:
 | 
				
			||||||
  version "1.0.2"
 | 
					  version "1.0.2"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/substring-trie/-/substring-trie-1.0.2.tgz#7b42592391628b4f2cb17365c6cce4257c7b7af5"
 | 
					  resolved "https://registry.yarnpkg.com/substring-trie/-/substring-trie-1.0.2.tgz#7b42592391628b4f2cb17365c6cce4257c7b7af5"
 | 
				
			||||||
| 
						 | 
					@ -10249,13 +10284,6 @@ toidentifier@1.0.0:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
 | 
					  resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
 | 
				
			||||||
  integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
 | 
					  integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
touch@^2.0.1:
 | 
					 | 
				
			||||||
  version "2.0.2"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/touch/-/touch-2.0.2.tgz#ca0b2a3ae3211246a61b16ba9e6cbf1596287164"
 | 
					 | 
				
			||||||
  integrity sha512-qjNtvsFXTRq7IuMLweVgFxmEuQ6gLbRs2jQxL80TtZ31dEKWYIxRXquij6w6VimyDek5hD3PytljHmEtAs2u0A==
 | 
					 | 
				
			||||||
  dependencies:
 | 
					 | 
				
			||||||
    nopt "~1.0.10"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
tough-cookie@>=2.3.3, tough-cookie@^2.3.4:
 | 
					tough-cookie@>=2.3.3, tough-cookie@^2.3.4:
 | 
				
			||||||
  version "2.5.0"
 | 
					  version "2.5.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
 | 
					  resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
 | 
				
			||||||
| 
						 | 
					@ -10848,6 +10876,13 @@ which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    isexe "^2.0.0"
 | 
					    isexe "^2.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					which@^2.0.1:
 | 
				
			||||||
 | 
					  version "2.0.1"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/which/-/which-2.0.1.tgz#f1cf94d07a8e571b6ff006aeb91d0300c47ef0a4"
 | 
				
			||||||
 | 
					  integrity sha512-N7GBZOTswtB9lkQBZA4+zAXrjEIWAUOB93AvzUiudRzRxhUdLURQ7D/gAIMY1gatT/LTbmbcv8SiYazy3eYB7w==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    isexe "^2.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
wide-align@^1.1.0:
 | 
					wide-align@^1.1.0:
 | 
				
			||||||
  version "1.1.3"
 | 
					  version "1.1.3"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
 | 
					  resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue