Merge pull request #1310 from ThibG/glitch-soc/merge-upstream
Merge upstream changes
This commit is contained in:
		
						commit
						7061b36c17
					
				
					 75 changed files with 605 additions and 556 deletions
				
			
		
							
								
								
									
										14
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Gemfile
									
									
									
									
									
								
							|  | @ -69,7 +69,7 @@ gem 'nilsimsa', git: 'https://github.com/witgo/nilsimsa', ref: 'fd184883048b922b | ||||||
| gem 'nokogiri', '~> 1.10' | gem 'nokogiri', '~> 1.10' | ||||||
| gem 'nsa', '~> 0.2' | gem 'nsa', '~> 0.2' | ||||||
| gem 'oj', '~> 3.10' | gem 'oj', '~> 3.10' | ||||||
| gem 'ox', '~> 2.12' | gem 'ox', '~> 2.13' | ||||||
| gem 'parslet' | gem 'parslet' | ||||||
| gem 'parallel', '~> 1.19' | gem 'parallel', '~> 1.19' | ||||||
| gem 'posix-spawn', git: 'https://github.com/rtomayko/posix-spawn', ref: '58465d2e213991f8afb13b984854a49fcdcc980c' | gem 'posix-spawn', git: 'https://github.com/rtomayko/posix-spawn', ref: '58465d2e213991f8afb13b984854a49fcdcc980c' | ||||||
|  | @ -94,7 +94,7 @@ gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie' | ||||||
| gem 'stoplight', '~> 2.2.0' | gem 'stoplight', '~> 2.2.0' | ||||||
| gem 'strong_migrations', '~> 0.6' | gem 'strong_migrations', '~> 0.6' | ||||||
| gem 'tty-command', '~> 0.9', require: false | gem 'tty-command', '~> 0.9', require: false | ||||||
| gem 'tty-prompt', '~> 0.20', require: false | gem 'tty-prompt', '~> 0.21', require: false | ||||||
| gem 'twitter-text', '~> 1.14' | gem 'twitter-text', '~> 1.14' | ||||||
| gem 'tzinfo-data', '~> 1.2019' | gem 'tzinfo-data', '~> 1.2019' | ||||||
| gem 'webpacker', '~> 4.2' | gem 'webpacker', '~> 4.2' | ||||||
|  | @ -112,7 +112,7 @@ group :development, :test do | ||||||
|   gem 'i18n-tasks', '~> 0.9', require: false |   gem 'i18n-tasks', '~> 0.9', require: false | ||||||
|   gem 'pry-byebug', '~> 3.8' |   gem 'pry-byebug', '~> 3.8' | ||||||
|   gem 'pry-rails', '~> 0.3' |   gem 'pry-rails', '~> 0.3' | ||||||
|   gem 'rspec-rails', '~> 3.9' |   gem 'rspec-rails', '~> 4.0' | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| group :production, :test do | group :production, :test do | ||||||
|  | @ -122,19 +122,19 @@ end | ||||||
| group :test do | group :test do | ||||||
|   gem 'capybara', '~> 3.31' |   gem 'capybara', '~> 3.31' | ||||||
|   gem 'climate_control', '~> 0.2' |   gem 'climate_control', '~> 0.2' | ||||||
|   gem 'faker', '~> 2.10' |   gem 'faker', '~> 2.11' | ||||||
|   gem 'microformats', '~> 4.2' |   gem 'microformats', '~> 4.2' | ||||||
|   gem 'rails-controller-testing', '~> 1.0' |   gem 'rails-controller-testing', '~> 1.0' | ||||||
|   gem 'rspec-sidekiq', '~> 3.0' |   gem 'rspec-sidekiq', '~> 3.0' | ||||||
|   gem 'simplecov', '~> 0.18', require: false |   gem 'simplecov', '~> 0.18', require: false | ||||||
|   gem 'webmock', '~> 3.8' |   gem 'webmock', '~> 3.8' | ||||||
|   gem 'parallel_tests', '~> 2.30' |   gem 'parallel_tests', '~> 2.32' | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| group :development do | group :development do | ||||||
|   gem 'active_record_query_trace', '~> 1.7' |   gem 'active_record_query_trace', '~> 1.7' | ||||||
|   gem 'annotate', '~> 3.0' |   gem 'annotate', '~> 3.0' | ||||||
|   gem 'better_errors', '~> 2.5' |   gem 'better_errors', '~> 2.6' | ||||||
|   gem 'binding_of_caller', '~> 0.7' |   gem 'binding_of_caller', '~> 0.7' | ||||||
|   gem 'bullet', '~> 6.1' |   gem 'bullet', '~> 6.1' | ||||||
|   gem 'letter_opener', '~> 1.7' |   gem 'letter_opener', '~> 1.7' | ||||||
|  | @ -142,7 +142,7 @@ group :development do | ||||||
|   gem 'memory_profiler' |   gem 'memory_profiler' | ||||||
|   gem 'rubocop', '~> 0.79', require: false |   gem 'rubocop', '~> 0.79', require: false | ||||||
|   gem 'rubocop-rails', '~> 2.4', require: false |   gem 'rubocop-rails', '~> 2.4', require: false | ||||||
|   gem 'brakeman', '~> 4.7', require: false |   gem 'brakeman', '~> 4.8', require: false | ||||||
|   gem 'bundler-audit', '~> 0.6', require: false |   gem 'bundler-audit', '~> 0.6', require: false | ||||||
| 
 | 
 | ||||||
|   gem 'capistrano', '~> 3.12' |   gem 'capistrano', '~> 3.12' | ||||||
|  |  | ||||||
							
								
								
									
										66
									
								
								Gemfile.lock
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								Gemfile.lock
									
									
									
									
									
								
							|  | @ -108,7 +108,7 @@ GEM | ||||||
|     aws-sigv4 (1.1.1) |     aws-sigv4 (1.1.1) | ||||||
|       aws-eventstream (~> 1.0, >= 1.0.2) |       aws-eventstream (~> 1.0, >= 1.0.2) | ||||||
|     bcrypt (3.1.12) |     bcrypt (3.1.12) | ||||||
|     better_errors (2.5.1) |     better_errors (2.6.0) | ||||||
|       coderay (>= 1.0.0) |       coderay (>= 1.0.0) | ||||||
|       erubi (>= 1.0.0) |       erubi (>= 1.0.0) | ||||||
|       rack (>= 0.9.0) |       rack (>= 0.9.0) | ||||||
|  | @ -116,9 +116,9 @@ GEM | ||||||
|       debug_inspector (>= 0.0.1) |       debug_inspector (>= 0.0.1) | ||||||
|     blurhash (0.1.4) |     blurhash (0.1.4) | ||||||
|       ffi (~> 1.10.0) |       ffi (~> 1.10.0) | ||||||
|     bootsnap (1.4.5) |     bootsnap (1.4.6) | ||||||
|       msgpack (~> 1.0) |       msgpack (~> 1.0) | ||||||
|     brakeman (4.7.2) |     brakeman (4.8.0) | ||||||
|     browser (4.0.0) |     browser (4.0.0) | ||||||
|     builder (3.2.4) |     builder (3.2.4) | ||||||
|     bullet (6.1.0) |     bullet (6.1.0) | ||||||
|  | @ -166,7 +166,7 @@ GEM | ||||||
|     cocaine (0.5.8) |     cocaine (0.5.8) | ||||||
|       climate_control (>= 0.0.3, < 1.0) |       climate_control (>= 0.0.3, < 1.0) | ||||||
|     coderay (1.1.2) |     coderay (1.1.2) | ||||||
|     concurrent-ruby (1.1.5) |     concurrent-ruby (1.1.6) | ||||||
|     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) | ||||||
|  | @ -218,7 +218,7 @@ GEM | ||||||
|       tzinfo |       tzinfo | ||||||
|     excon (0.71.0) |     excon (0.71.0) | ||||||
|     fabrication (2.21.0) |     fabrication (2.21.0) | ||||||
|     faker (2.10.1) |     faker (2.11.0) | ||||||
|       i18n (>= 1.6, < 2) |       i18n (>= 1.6, < 2) | ||||||
|     faraday (0.17.3) |     faraday (0.17.3) | ||||||
|       multipart-post (>= 1.2, < 3) |       multipart-post (>= 1.2, < 3) | ||||||
|  | @ -299,19 +299,19 @@ GEM | ||||||
|       terminal-table (>= 1.5.1) |       terminal-table (>= 1.5.1) | ||||||
|     idn-ruby (0.1.0) |     idn-ruby (0.1.0) | ||||||
|     ipaddress (0.8.3) |     ipaddress (0.8.3) | ||||||
|     iso-639 (0.2.8) |     iso-639 (0.3.5) | ||||||
|     jaro_winkler (1.5.4) |     jaro_winkler (1.5.4) | ||||||
|     jmespath (1.4.0) |     jmespath (1.4.0) | ||||||
|     json (2.3.0) |     json (2.3.0) | ||||||
|     json-canonicalization (0.2.0) |     json-canonicalization (0.2.0) | ||||||
|     json-ld (3.1.1) |     json-ld (3.1.2) | ||||||
|       htmlentities (~> 4.3) |       htmlentities (~> 4.3) | ||||||
|       json-canonicalization (~> 0.2) |       json-canonicalization (~> 0.2) | ||||||
|       link_header (~> 0.0, >= 0.0.8) |       link_header (~> 0.0, >= 0.0.8) | ||||||
|       multi_json (~> 1.14) |       multi_json (~> 1.14) | ||||||
|       rack (~> 2.0) |       rack (~> 2.0) | ||||||
|       rdf (~> 3.1) |       rdf (~> 3.1) | ||||||
|     json-ld-preloaded (3.1.1) |     json-ld-preloaded (3.1.2) | ||||||
|       json-ld (~> 3.1) |       json-ld (~> 3.1) | ||||||
|       rdf (~> 3.1) |       rdf (~> 3.1) | ||||||
|     jsonapi-renderer (0.2.2) |     jsonapi-renderer (0.2.2) | ||||||
|  | @ -365,7 +365,7 @@ GEM | ||||||
|     mini_mime (1.0.2) |     mini_mime (1.0.2) | ||||||
|     mini_portile2 (2.4.0) |     mini_portile2 (2.4.0) | ||||||
|     minitest (5.14.0) |     minitest (5.14.0) | ||||||
|     msgpack (1.3.1) |     msgpack (1.3.3) | ||||||
|     multi_json (1.14.1) |     multi_json (1.14.1) | ||||||
|     multipart-post (2.1.1) |     multipart-post (2.1.1) | ||||||
|     necromancer (0.5.1) |     necromancer (0.5.1) | ||||||
|  | @ -383,7 +383,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.10.3) |     oj (3.10.5) | ||||||
|     omniauth (1.9.1) |     omniauth (1.9.1) | ||||||
|       hashie (>= 3.4.6) |       hashie (>= 3.4.6) | ||||||
|       rack (>= 1.6.2, < 3) |       rack (>= 1.6.2, < 3) | ||||||
|  | @ -395,7 +395,7 @@ GEM | ||||||
|       omniauth (~> 1.3, >= 1.3.2) |       omniauth (~> 1.3, >= 1.3.2) | ||||||
|       ruby-saml (~> 1.7) |       ruby-saml (~> 1.7) | ||||||
|     orm_adapter (0.5.0) |     orm_adapter (0.5.0) | ||||||
|     ox (2.12.1) |     ox (2.13.2) | ||||||
|     paperclip (6.0.0) |     paperclip (6.0.0) | ||||||
|       activemodel (>= 4.2.0) |       activemodel (>= 4.2.0) | ||||||
|       activesupport (>= 4.2.0) |       activesupport (>= 4.2.0) | ||||||
|  | @ -406,7 +406,7 @@ GEM | ||||||
|       av (~> 0.9.0) |       av (~> 0.9.0) | ||||||
|       paperclip (>= 2.5.2) |       paperclip (>= 2.5.2) | ||||||
|     parallel (1.19.1) |     parallel (1.19.1) | ||||||
|     parallel_tests (2.30.1) |     parallel_tests (2.32.0) | ||||||
|       parallel |       parallel | ||||||
|     parser (2.7.0.5) |     parser (2.7.0.5) | ||||||
|       ast (~> 2.4.0) |       ast (~> 2.4.0) | ||||||
|  | @ -414,7 +414,7 @@ GEM | ||||||
|     pastel (0.7.3) |     pastel (0.7.3) | ||||||
|       equatable (~> 0.6) |       equatable (~> 0.6) | ||||||
|       tty-color (~> 0.5) |       tty-color (~> 0.5) | ||||||
|     pg (1.2.2) |     pg (1.2.3) | ||||||
|     pghero (2.4.1) |     pghero (2.4.1) | ||||||
|       activerecord (>= 5) |       activerecord (>= 5) | ||||||
|     pkg-config (1.4.1) |     pkg-config (1.4.1) | ||||||
|  | @ -531,14 +531,14 @@ GEM | ||||||
|     rspec-mocks (3.9.1) |     rspec-mocks (3.9.1) | ||||||
|       diff-lcs (>= 1.2.0, < 2.0) |       diff-lcs (>= 1.2.0, < 2.0) | ||||||
|       rspec-support (~> 3.9.0) |       rspec-support (~> 3.9.0) | ||||||
|     rspec-rails (3.9.1) |     rspec-rails (4.0.0) | ||||||
|       actionpack (>= 3.0) |       actionpack (>= 4.2) | ||||||
|       activesupport (>= 3.0) |       activesupport (>= 4.2) | ||||||
|       railties (>= 3.0) |       railties (>= 4.2) | ||||||
|       rspec-core (~> 3.9.0) |       rspec-core (~> 3.9) | ||||||
|       rspec-expectations (~> 3.9.0) |       rspec-expectations (~> 3.9) | ||||||
|       rspec-mocks (~> 3.9.0) |       rspec-mocks (~> 3.9) | ||||||
|       rspec-support (~> 3.9.0) |       rspec-support (~> 3.9) | ||||||
|     rspec-sidekiq (3.0.3) |     rspec-sidekiq (3.0.3) | ||||||
|       rspec-core (~> 3.0, >= 3.0.0) |       rspec-core (~> 3.0, >= 3.0.0) | ||||||
|       sidekiq (>= 2.4.0) |       sidekiq (>= 2.4.0) | ||||||
|  | @ -577,7 +577,7 @@ GEM | ||||||
|       sidekiq (>= 3) |       sidekiq (>= 3) | ||||||
|       thwait |       thwait | ||||||
|       tilt (>= 1.4.0) |       tilt (>= 1.4.0) | ||||||
|     sidekiq-unique-jobs (6.0.20) |     sidekiq-unique-jobs (6.0.21) | ||||||
|       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) | ||||||
|  | @ -616,11 +616,11 @@ GEM | ||||||
|     thread_safe (0.3.6) |     thread_safe (0.3.6) | ||||||
|     thwait (0.1.0) |     thwait (0.1.0) | ||||||
|     tilt (2.0.10) |     tilt (2.0.10) | ||||||
|     tty-color (0.5.0) |     tty-color (0.5.1) | ||||||
|     tty-command (0.9.0) |     tty-command (0.9.0) | ||||||
|       pastel (~> 0.7.0) |       pastel (~> 0.7.0) | ||||||
|     tty-cursor (0.7.0) |     tty-cursor (0.7.1) | ||||||
|     tty-prompt (0.20.0) |     tty-prompt (0.21.0) | ||||||
|       necromancer (~> 0.5.0) |       necromancer (~> 0.5.0) | ||||||
|       pastel (~> 0.7.0) |       pastel (~> 0.7.0) | ||||||
|       tty-reader (~> 0.7.0) |       tty-reader (~> 0.7.0) | ||||||
|  | @ -628,7 +628,7 @@ GEM | ||||||
|       tty-cursor (~> 0.7) |       tty-cursor (~> 0.7) | ||||||
|       tty-screen (~> 0.7) |       tty-screen (~> 0.7) | ||||||
|       wisper (~> 2.0.0) |       wisper (~> 2.0.0) | ||||||
|     tty-screen (0.7.0) |     tty-screen (0.7.1) | ||||||
|     twitter-text (1.14.7) |     twitter-text (1.14.7) | ||||||
|       unf (~> 0.1.0) |       unf (~> 0.1.0) | ||||||
|     tzinfo (1.2.6) |     tzinfo (1.2.6) | ||||||
|  | @ -669,11 +669,11 @@ DEPENDENCIES | ||||||
|   addressable (~> 2.7) |   addressable (~> 2.7) | ||||||
|   annotate (~> 3.0) |   annotate (~> 3.0) | ||||||
|   aws-sdk-s3 (~> 1.61) |   aws-sdk-s3 (~> 1.61) | ||||||
|   better_errors (~> 2.5) |   better_errors (~> 2.6) | ||||||
|   binding_of_caller (~> 0.7) |   binding_of_caller (~> 0.7) | ||||||
|   blurhash (~> 0.1) |   blurhash (~> 0.1) | ||||||
|   bootsnap (~> 1.4) |   bootsnap (~> 1.4) | ||||||
|   brakeman (~> 4.7) |   brakeman (~> 4.8) | ||||||
|   browser |   browser | ||||||
|   bullet (~> 6.1) |   bullet (~> 6.1) | ||||||
|   bundler-audit (~> 0.6) |   bundler-audit (~> 0.6) | ||||||
|  | @ -696,7 +696,7 @@ DEPENDENCIES | ||||||
|   dotenv-rails (~> 2.7) |   dotenv-rails (~> 2.7) | ||||||
|   e2mmap (~> 0.1.0) |   e2mmap (~> 0.1.0) | ||||||
|   fabrication (~> 2.21) |   fabrication (~> 2.21) | ||||||
|   faker (~> 2.10) |   faker (~> 2.11) | ||||||
|   fast_blank (~> 1.0) |   fast_blank (~> 1.0) | ||||||
|   fastimage |   fastimage | ||||||
|   fog-core (<= 2.1.0) |   fog-core (<= 2.1.0) | ||||||
|  | @ -734,11 +734,11 @@ DEPENDENCIES | ||||||
|   omniauth (~> 1.9) |   omniauth (~> 1.9) | ||||||
|   omniauth-cas (~> 1.1) |   omniauth-cas (~> 1.1) | ||||||
|   omniauth-saml (~> 1.10) |   omniauth-saml (~> 1.10) | ||||||
|   ox (~> 2.12) |   ox (~> 2.13) | ||||||
|   paperclip (~> 6.0) |   paperclip (~> 6.0) | ||||||
|   paperclip-av-transcoder (~> 0.6) |   paperclip-av-transcoder (~> 0.6) | ||||||
|   parallel (~> 1.19) |   parallel (~> 1.19) | ||||||
|   parallel_tests (~> 2.30) |   parallel_tests (~> 2.32) | ||||||
|   parslet |   parslet | ||||||
|   pg (~> 1.2) |   pg (~> 1.2) | ||||||
|   pghero (~> 2.4) |   pghero (~> 2.4) | ||||||
|  | @ -763,7 +763,7 @@ DEPENDENCIES | ||||||
|   redis-namespace (~> 1.7) |   redis-namespace (~> 1.7) | ||||||
|   redis-rails (~> 5.0) |   redis-rails (~> 5.0) | ||||||
|   rqrcode (~> 1.1) |   rqrcode (~> 1.1) | ||||||
|   rspec-rails (~> 3.9) |   rspec-rails (~> 4.0) | ||||||
|   rspec-sidekiq (~> 3.0) |   rspec-sidekiq (~> 3.0) | ||||||
|   rubocop (~> 0.79) |   rubocop (~> 0.79) | ||||||
|   rubocop-rails (~> 2.4) |   rubocop-rails (~> 2.4) | ||||||
|  | @ -785,7 +785,7 @@ DEPENDENCIES | ||||||
|   thor (~> 0.20) |   thor (~> 0.20) | ||||||
|   thwait (~> 0.1.0) |   thwait (~> 0.1.0) | ||||||
|   tty-command (~> 0.9) |   tty-command (~> 0.9) | ||||||
|   tty-prompt (~> 0.20) |   tty-prompt (~> 0.21) | ||||||
|   twitter-text (~> 1.14) |   twitter-text (~> 1.14) | ||||||
|   tzinfo-data (~> 1.2019) |   tzinfo-data (~> 1.2019) | ||||||
|   webmock (~> 3.8) |   webmock (~> 3.8) | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ class Api::V1::StatusesController < Api::BaseController | ||||||
|   before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only:   [:create, :destroy] |   before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only:   [:create, :destroy] | ||||||
|   before_action :require_user!, except:  [:show, :context] |   before_action :require_user!, except:  [:show, :context] | ||||||
|   before_action :set_status, only:       [:show, :context] |   before_action :set_status, only:       [:show, :context] | ||||||
|  |   before_action :set_thread, only:       [:create] | ||||||
| 
 | 
 | ||||||
|   override_rate_limit_headers :create, family: :statuses |   override_rate_limit_headers :create, family: :statuses | ||||||
| 
 | 
 | ||||||
|  | @ -36,7 +37,7 @@ class Api::V1::StatusesController < Api::BaseController | ||||||
|   def create |   def create | ||||||
|     @status = PostStatusService.new.call(current_user.account, |     @status = PostStatusService.new.call(current_user.account, | ||||||
|                                          text: status_params[:status], |                                          text: status_params[:status], | ||||||
|                                          thread: status_params[:in_reply_to_id].blank? ? nil : Status.find(status_params[:in_reply_to_id]), |                                          thread: @thread, | ||||||
|                                          media_ids: status_params[:media_ids], |                                          media_ids: status_params[:media_ids], | ||||||
|                                          sensitive: status_params[:sensitive], |                                          sensitive: status_params[:sensitive], | ||||||
|                                          spoiler_text: status_params[:spoiler_text], |                                          spoiler_text: status_params[:spoiler_text], | ||||||
|  | @ -70,6 +71,12 @@ class Api::V1::StatusesController < Api::BaseController | ||||||
|     raise ActiveRecord::RecordNotFound |     raise ActiveRecord::RecordNotFound | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   def set_thread | ||||||
|  |     @thread = status_params[:in_reply_to_id].blank? ? nil : Status.find(status_params[:in_reply_to_id]) | ||||||
|  |   rescue ActiveRecord::RecordNotFound | ||||||
|  |     render json: { error: I18n.t('statuses.errors.in_reply_not_found') }, status: 404 | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   def status_params |   def status_params | ||||||
|     params.permit( |     params.permit( | ||||||
|       :status, |       :status, | ||||||
|  |  | ||||||
|  | @ -29,6 +29,6 @@ class Settings::ImportsController < Settings::BaseController | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def import_params |   def import_params | ||||||
|     params.require(:import).permit(:data, :type) |     params.require(:import).permit(:data, :type, :mode) | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -370,6 +370,7 @@ export function fetchFollowersFail(id, error) { | ||||||
|     type: FOLLOWERS_FETCH_FAIL, |     type: FOLLOWERS_FETCH_FAIL, | ||||||
|     id, |     id, | ||||||
|     error, |     error, | ||||||
|  |     skipNotFound: true, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -456,6 +457,7 @@ export function fetchFollowingFail(id, error) { | ||||||
|     type: FOLLOWING_FETCH_FAIL, |     type: FOLLOWING_FETCH_FAIL, | ||||||
|     id, |     id, | ||||||
|     error, |     error, | ||||||
|  |     skipNotFound: true, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -545,6 +547,7 @@ export function fetchRelationshipsFail(error) { | ||||||
|     type: RELATIONSHIPS_FETCH_FAIL, |     type: RELATIONSHIPS_FETCH_FAIL, | ||||||
|     error, |     error, | ||||||
|     skipLoading: true, |     skipLoading: true, | ||||||
|  |     skipNotFound: true, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,11 +34,11 @@ export function showAlert(title = messages.unexpectedTitle, message = messages.u | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export function showAlertForError(error) { | export function showAlertForError(error, skipNotFound = false) { | ||||||
|   if (error.response) { |   if (error.response) { | ||||||
|     const { data, status, statusText, headers } = error.response; |     const { data, status, statusText, headers } = error.response; | ||||||
| 
 | 
 | ||||||
|     if (status === 404 || status === 410) { |     if (skipNotFound && (status === 404 || status === 410)) { | ||||||
|       // Skip these errors as they are reflected in the UI
 |       // Skip these errors as they are reflected in the UI
 | ||||||
|       return { type: ALERT_NOOP }; |       return { type: ALERT_NOOP }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -27,4 +27,5 @@ export const fetchAccountIdentityProofsFail = (accountId, err) => ({ | ||||||
|   type: IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL, |   type: IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL, | ||||||
|   accountId, |   accountId, | ||||||
|   err, |   err, | ||||||
|  |   skipNotFound: true, | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | @ -165,6 +165,7 @@ export function expandTimelineFail(timeline, error, isLoadingMore) { | ||||||
|     timeline, |     timeline, | ||||||
|     error, |     error, | ||||||
|     skipLoading: !isLoadingMore, |     skipLoading: !isLoadingMore, | ||||||
|  |     skipNotFound: timeline.startsWith('account:'), | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -127,15 +127,7 @@ class Poll extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|       <li key={option.get('title')}> |       <li key={option.get('title')}> | ||||||
|         {showResults && ( |         <label className={classNames('poll__option', { selectable: !showResults })}> | ||||||
|           <Motion defaultStyle={{ width: 0 }} style={{ width: spring(percent, { stiffness: 180, damping: 12 }) }}> |  | ||||||
|             {({ width }) => |  | ||||||
|               <span className={classNames('poll__chart', { leading })} style={{ width: `${width}%` }} /> |  | ||||||
|             } |  | ||||||
|           </Motion> |  | ||||||
|         )} |  | ||||||
| 
 |  | ||||||
|         <label className={classNames('poll__text', { selectable: !showResults })}> |  | ||||||
|           <input |           <input | ||||||
|             name='vote-options' |             name='vote-options' | ||||||
|             type={poll.get('multiple') ? 'checkbox' : 'radio'} |             type={poll.get('multiple') ? 'checkbox' : 'radio'} | ||||||
|  | @ -157,12 +149,26 @@ class Poll extends ImmutablePureComponent { | ||||||
|             /> |             /> | ||||||
|           )} |           )} | ||||||
|           {showResults && <span className='poll__number'> |           {showResults && <span className='poll__number'> | ||||||
|             {!!voted && <Icon id='check' className='poll__vote__mark' title={intl.formatMessage(messages.voted)} />} |  | ||||||
|             {Math.round(percent)}% |             {Math.round(percent)}% | ||||||
|           </span>} |           </span>} | ||||||
| 
 | 
 | ||||||
|           <span dangerouslySetInnerHTML={{ __html: titleEmojified }} /> |           <span | ||||||
|  |             className='poll__option__text' | ||||||
|  |             dangerouslySetInnerHTML={{ __html: titleEmojified }} | ||||||
|  |           /> | ||||||
|  | 
 | ||||||
|  |           {!!voted && <span className='poll__voted'> | ||||||
|  |             <Icon id='check' className='poll__voted__mark' title={intl.formatMessage(messages.voted)} /> | ||||||
|  |           </span>} | ||||||
|         </label> |         </label> | ||||||
|  | 
 | ||||||
|  |         {showResults && ( | ||||||
|  |           <Motion defaultStyle={{ width: 0 }} style={{ width: spring(percent, { stiffness: 180, damping: 12 }) }}> | ||||||
|  |             {({ width }) => | ||||||
|  |               <span className={classNames('poll__chart', { leading })} style={{ width: `${width}%` }} /> | ||||||
|  |             } | ||||||
|  |           </Motion> | ||||||
|  |         )} | ||||||
|       </li> |       </li> | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -62,7 +62,7 @@ class Option extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|       <li> |       <li> | ||||||
|         <label className='poll__text editable'> |         <label className='poll__option editable'> | ||||||
|           <span className={classNames('poll__input', { checkbox: isPollMultiple })} /> |           <span className={classNames('poll__input', { checkbox: isPollMultiple })} /> | ||||||
| 
 | 
 | ||||||
|           <AutosuggestInput |           <AutosuggestInput | ||||||
|  |  | ||||||
|  | @ -195,7 +195,7 @@ class Conversation extends ImmutablePureComponent { | ||||||
|     return ( |     return ( | ||||||
|       <HotKeys handlers={handlers}> |       <HotKeys handlers={handlers}> | ||||||
|         <div className={classNames('conversation focusable muted', { 'conversation--unread': unread })} tabIndex='0'> |         <div className={classNames('conversation focusable muted', { 'conversation--unread': unread })} tabIndex='0'> | ||||||
|           <div className='conversation__avatar'> |           <div className='conversation__avatar' onClick={this.handleClick} role='presentation'> | ||||||
|             <AvatarComposite accounts={accounts} size={48} /> |             <AvatarComposite accounts={accounts} size={48} /> | ||||||
|           </div> |           </div> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ export default function errorsMiddleware() { | ||||||
|       const isFail = new RegExp(`${defaultFailSuffix}$`, 'g'); |       const isFail = new RegExp(`${defaultFailSuffix}$`, 'g'); | ||||||
| 
 | 
 | ||||||
|       if (action.type.match(isFail)) { |       if (action.type.match(isFail)) { | ||||||
|         dispatch(showAlertForError(action.error)); |         dispatch(showAlertForError(action.error, action.skipNotFound)); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -344,7 +344,6 @@ export default function compose(state = initialState, action) { | ||||||
|     }); |     }); | ||||||
|   case COMPOSE_SPOILERNESS_CHANGE: |   case COMPOSE_SPOILERNESS_CHANGE: | ||||||
|     return state.withMutations(map => { |     return state.withMutations(map => { | ||||||
|       map.set('spoiler_text', ''); |  | ||||||
|       map.set('spoiler', !state.get('spoiler')); |       map.set('spoiler', !state.get('spoiler')); | ||||||
|       map.set('idempotencyKey', uuid()); |       map.set('idempotencyKey', uuid()); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -51,7 +51,6 @@ | ||||||
|     @include avatar-radius; |     @include avatar-radius; | ||||||
|     overflow: hidden; |     overflow: hidden; | ||||||
|     position: relative; |     position: relative; | ||||||
|     cursor: default; |  | ||||||
| 
 | 
 | ||||||
|     & div { |     & div { | ||||||
|       @include avatar-radius; |       @include avatar-radius; | ||||||
|  |  | ||||||
|  | @ -1515,6 +1515,7 @@ | ||||||
|     padding: 10px; |     padding: 10px; | ||||||
|     padding-top: 12px; |     padding-top: 12px; | ||||||
|     position: relative; |     position: relative; | ||||||
|  |     cursor: pointer; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   &__unread { |   &__unread { | ||||||
|  |  | ||||||
|  | @ -331,13 +331,11 @@ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .display-name { |     .display-name { | ||||||
|  |       color: $light-text-color; | ||||||
|  | 
 | ||||||
|       strong { |       strong { | ||||||
|         color: $inverted-text-color; |         color: $inverted-text-color; | ||||||
|       } |       } | ||||||
| 
 |  | ||||||
|       span { |  | ||||||
|         color: $lighter-text-color; |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .status__content { |     .status__content { | ||||||
|  |  | ||||||
|  | @ -14,20 +14,18 @@ | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   &__chart { |   &__chart { | ||||||
|     position: absolute; |  | ||||||
|     top: 0; |  | ||||||
|     left: 0; |  | ||||||
|     height: 100%; |  | ||||||
|     display: inline-block; |  | ||||||
|     border-radius: 4px; |     border-radius: 4px; | ||||||
|     background: darken($ui-primary-color, 14%); |     display: block; | ||||||
|  |     background: darken($ui-primary-color, 5%); | ||||||
|  |     height: 5px; | ||||||
|  |     min-width: 1%; | ||||||
| 
 | 
 | ||||||
|     &.leading { |     &.leading { | ||||||
|       background: $ui-highlight-color; |       background: $ui-highlight-color; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   &__text { |   &__option { | ||||||
|     position: relative; |     position: relative; | ||||||
|     display: flex; |     display: flex; | ||||||
|     padding: 6px 0; |     padding: 6px 0; | ||||||
|  | @ -35,6 +33,13 @@ | ||||||
|     cursor: default; |     cursor: default; | ||||||
|     overflow: hidden; |     overflow: hidden; | ||||||
| 
 | 
 | ||||||
|  |     &__text { | ||||||
|  |       display: inline-block; | ||||||
|  |       word-wrap: break-word; | ||||||
|  |       overflow-wrap: break-word; | ||||||
|  |       max-width: calc(100% - 45px - 25px); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     input[type=radio], |     input[type=radio], | ||||||
|     input[type=checkbox] { |     input[type=checkbox] { | ||||||
|       display: none; |       display: none; | ||||||
|  | @ -119,19 +124,18 @@ | ||||||
| 
 | 
 | ||||||
|   &__number { |   &__number { | ||||||
|     display: inline-block; |     display: inline-block; | ||||||
|     width: 52px; |     width: 45px; | ||||||
|     font-weight: 700; |     font-weight: 700; | ||||||
|     padding: 0 10px; |     flex: 0 0 45px; | ||||||
|     padding-left: 8px; |  | ||||||
|     text-align: right; |  | ||||||
|     margin-top: auto; |  | ||||||
|     margin-bottom: auto; |  | ||||||
|     flex: 0 0 52px; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   &__vote__mark { |   &__voted { | ||||||
|     float: left; |     padding: 0 5px; | ||||||
|     line-height: 18px; |     display: inline-block; | ||||||
|  | 
 | ||||||
|  |     &__mark { | ||||||
|  |       font-size: 18px; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   &__footer { |   &__footer { | ||||||
|  | @ -208,7 +212,7 @@ | ||||||
|     display: flex; |     display: flex; | ||||||
|     align-items: center; |     align-items: center; | ||||||
| 
 | 
 | ||||||
|     .poll__text { |     .poll__option { | ||||||
|       flex: 0 0 auto; |       flex: 0 0 auto; | ||||||
|       width: calc(100% - (23px + 6px)); |       width: calc(100% - (23px + 6px)); | ||||||
|       margin-right: 6px; |       margin-right: 6px; | ||||||
|  |  | ||||||
|  | @ -396,6 +396,7 @@ export function fetchFollowersFail(id, error) { | ||||||
|     type: FOLLOWERS_FETCH_FAIL, |     type: FOLLOWERS_FETCH_FAIL, | ||||||
|     id, |     id, | ||||||
|     error, |     error, | ||||||
|  |     skipNotFound: true, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -482,6 +483,7 @@ export function fetchFollowingFail(id, error) { | ||||||
|     type: FOLLOWING_FETCH_FAIL, |     type: FOLLOWING_FETCH_FAIL, | ||||||
|     id, |     id, | ||||||
|     error, |     error, | ||||||
|  |     skipNotFound: true, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -571,6 +573,7 @@ export function fetchRelationshipsFail(error) { | ||||||
|     type: RELATIONSHIPS_FETCH_FAIL, |     type: RELATIONSHIPS_FETCH_FAIL, | ||||||
|     error, |     error, | ||||||
|     skipLoading: true, |     skipLoading: true, | ||||||
|  |     skipNotFound: true, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,11 +34,11 @@ export function showAlert(title = messages.unexpectedTitle, message = messages.u | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export function showAlertForError(error) { | export function showAlertForError(error, skipNotFound = false) { | ||||||
|   if (error.response) { |   if (error.response) { | ||||||
|     const { data, status, statusText, headers } = error.response; |     const { data, status, statusText, headers } = error.response; | ||||||
| 
 | 
 | ||||||
|     if (status === 404 || status === 410) { |     if (skipNotFound && (status === 404 || status === 410)) { | ||||||
|       // Skip these errors as they are reflected in the UI
 |       // Skip these errors as they are reflected in the UI
 | ||||||
|       return { type: ALERT_NOOP }; |       return { type: ALERT_NOOP }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -27,4 +27,5 @@ export const fetchAccountIdentityProofsFail = (accountId, err) => ({ | ||||||
|   type: IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL, |   type: IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL, | ||||||
|   accountId, |   accountId, | ||||||
|   err, |   err, | ||||||
|  |   skipNotFound: true, | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | @ -149,6 +149,7 @@ export function expandTimelineFail(timeline, error, isLoadingMore) { | ||||||
|     timeline, |     timeline, | ||||||
|     error, |     error, | ||||||
|     skipLoading: !isLoadingMore, |     skipLoading: !isLoadingMore, | ||||||
|  |     skipNotFound: timeline.startsWith('account:'), | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -76,8 +76,9 @@ class ColumnHeader extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handlePin = () => { |   handlePin = () => { | ||||||
|     if (!this.props.pinned) { |     if (!this.props.pinned) { | ||||||
|       this.historyBack(); |       this.context.router.history.replace('/'); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     this.props.onPin(); |     this.props.onPin(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -127,15 +127,7 @@ class Poll extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|       <li key={option.get('title')}> |       <li key={option.get('title')}> | ||||||
|         {showResults && ( |         <label className={classNames('poll__option', { selectable: !showResults })}> | ||||||
|           <Motion defaultStyle={{ width: 0 }} style={{ width: spring(percent, { stiffness: 180, damping: 12 }) }}> |  | ||||||
|             {({ width }) => |  | ||||||
|               <span className={classNames('poll__chart', { leading })} style={{ width: `${width}%` }} /> |  | ||||||
|             } |  | ||||||
|           </Motion> |  | ||||||
|         )} |  | ||||||
| 
 |  | ||||||
|         <label className={classNames('poll__text', { selectable: !showResults })}> |  | ||||||
|           <input |           <input | ||||||
|             name='vote-options' |             name='vote-options' | ||||||
|             type={poll.get('multiple') ? 'checkbox' : 'radio'} |             type={poll.get('multiple') ? 'checkbox' : 'radio'} | ||||||
|  | @ -157,12 +149,26 @@ class Poll extends ImmutablePureComponent { | ||||||
|             /> |             /> | ||||||
|           )} |           )} | ||||||
|           {showResults && <span className='poll__number'> |           {showResults && <span className='poll__number'> | ||||||
|             {!!voted && <Icon id='check' className='poll__vote__mark' title={intl.formatMessage(messages.voted)} />} |  | ||||||
|             {Math.round(percent)}% |             {Math.round(percent)}% | ||||||
|           </span>} |           </span>} | ||||||
| 
 | 
 | ||||||
|           <span dangerouslySetInnerHTML={{ __html: titleEmojified }} /> |           <span | ||||||
|  |             className='poll__option__text' | ||||||
|  |             dangerouslySetInnerHTML={{ __html: titleEmojified }} | ||||||
|  |           /> | ||||||
|  | 
 | ||||||
|  |           {!!voted && <span className='poll__voted'> | ||||||
|  |             <Icon id='check' className='poll__voted__mark' title={intl.formatMessage(messages.voted)} /> | ||||||
|  |           </span>} | ||||||
|         </label> |         </label> | ||||||
|  | 
 | ||||||
|  |         {showResults && ( | ||||||
|  |           <Motion defaultStyle={{ width: 0 }} style={{ width: spring(percent, { stiffness: 180, damping: 12 }) }}> | ||||||
|  |             {({ width }) => | ||||||
|  |               <span className={classNames('poll__chart', { leading })} style={{ width: `${width}%` }} /> | ||||||
|  |             } | ||||||
|  |           </Motion> | ||||||
|  |         )} | ||||||
|       </li> |       </li> | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -432,16 +432,10 @@ class Status extends ImmutablePureComponent { | ||||||
|               </a> |               </a> | ||||||
|             </div> |             </div> | ||||||
| 
 | 
 | ||||||
|             <StatusContent status={status} onClick={this.handleClick} expanded={!status.get('hidden')} onExpandedToggle={this.handleExpandedToggle} collapsable onCollapsedToggle={this.handleCollapsedToggle} /> |             <StatusContent status={status} onClick={this.handleClick} expanded={!status.get('hidden')} showThread={showThread} onExpandedToggle={this.handleExpandedToggle} collapsable onCollapsedToggle={this.handleCollapsedToggle} /> | ||||||
| 
 | 
 | ||||||
|             {media} |             {media} | ||||||
| 
 | 
 | ||||||
|             {showThread && status.get('in_reply_to_id') && status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) && ( |  | ||||||
|               <button className='status__content__read-more-button' onClick={this.handleClick}> |  | ||||||
|                 <FormattedMessage id='status.show_thread' defaultMessage='Show thread' /> |  | ||||||
|               </button> |  | ||||||
|             )} |  | ||||||
| 
 |  | ||||||
|             <StatusActionBar status={status} account={account} {...other} /> |             <StatusActionBar status={status} account={account} {...other} /> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ export default class StatusContent extends React.PureComponent { | ||||||
|   static propTypes = { |   static propTypes = { | ||||||
|     status: ImmutablePropTypes.map.isRequired, |     status: ImmutablePropTypes.map.isRequired, | ||||||
|     expanded: PropTypes.bool, |     expanded: PropTypes.bool, | ||||||
|  |     showThread: PropTypes.bool, | ||||||
|     onExpandedToggle: PropTypes.func, |     onExpandedToggle: PropTypes.func, | ||||||
|     onClick: PropTypes.func, |     onClick: PropTypes.func, | ||||||
|     collapsable: PropTypes.bool, |     collapsable: PropTypes.bool, | ||||||
|  | @ -181,6 +182,7 @@ export default class StatusContent extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|     const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden; |     const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden; | ||||||
|     const renderReadMore = this.props.onClick && status.get('collapsed'); |     const renderReadMore = this.props.onClick && status.get('collapsed'); | ||||||
|  |     const renderViewThread = this.props.showThread && status.get('in_reply_to_id') && status.get('in_reply_to_account_id') === status.getIn(['account', 'id']); | ||||||
| 
 | 
 | ||||||
|     const content = { __html: status.get('contentHtml') }; |     const content = { __html: status.get('contentHtml') }; | ||||||
|     const spoilerContent = { __html: status.get('spoilerHtml') }; |     const spoilerContent = { __html: status.get('spoilerHtml') }; | ||||||
|  | @ -195,6 +197,12 @@ export default class StatusContent extends React.PureComponent { | ||||||
|       directionStyle.direction = 'rtl'; |       directionStyle.direction = 'rtl'; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     const showThreadButton = ( | ||||||
|  |       <button className='status__content__read-more-button' onClick={this.props.onClick}> | ||||||
|  |         <FormattedMessage id='status.show_thread' defaultMessage='Show thread' /> | ||||||
|  |       </button> | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|     const readMoreButton = ( |     const readMoreButton = ( | ||||||
|       <button className='status__content__read-more-button' onClick={this.props.onClick} key='read-more'> |       <button className='status__content__read-more-button' onClick={this.props.onClick} key='read-more'> | ||||||
|         <FormattedMessage id='status.read_more' defaultMessage='Read more' /><Icon id='angle-right' fixedWidth /> |         <FormattedMessage id='status.read_more' defaultMessage='Read more' /><Icon id='angle-right' fixedWidth /> | ||||||
|  | @ -229,6 +237,8 @@ export default class StatusContent extends React.PureComponent { | ||||||
|           <div tabIndex={!hidden ? 0 : null} className={`status__content__text ${!hidden ? 'status__content__text--visible' : ''}`} style={directionStyle} dangerouslySetInnerHTML={content} /> |           <div tabIndex={!hidden ? 0 : null} className={`status__content__text ${!hidden ? 'status__content__text--visible' : ''}`} style={directionStyle} dangerouslySetInnerHTML={content} /> | ||||||
| 
 | 
 | ||||||
|           {!hidden && !!status.get('poll') && <PollContainer pollId={status.get('poll')} />} |           {!hidden && !!status.get('poll') && <PollContainer pollId={status.get('poll')} />} | ||||||
|  | 
 | ||||||
|  |           {renderViewThread && showThreadButton} | ||||||
|         </div> |         </div> | ||||||
|       ); |       ); | ||||||
|     } else if (this.props.onClick) { |     } else if (this.props.onClick) { | ||||||
|  | @ -237,6 +247,8 @@ export default class StatusContent extends React.PureComponent { | ||||||
|           <div className='status__content__text status__content__text--visible' style={directionStyle} dangerouslySetInnerHTML={content} /> |           <div className='status__content__text status__content__text--visible' style={directionStyle} dangerouslySetInnerHTML={content} /> | ||||||
| 
 | 
 | ||||||
|           {!!status.get('poll') && <PollContainer pollId={status.get('poll')} />} |           {!!status.get('poll') && <PollContainer pollId={status.get('poll')} />} | ||||||
|  | 
 | ||||||
|  |           {renderViewThread && showThreadButton} | ||||||
|         </div>, |         </div>, | ||||||
|       ]; |       ]; | ||||||
| 
 | 
 | ||||||
|  | @ -251,6 +263,8 @@ export default class StatusContent extends React.PureComponent { | ||||||
|           <div className='status__content__text status__content__text--visible' style={directionStyle} dangerouslySetInnerHTML={content} /> |           <div className='status__content__text status__content__text--visible' style={directionStyle} dangerouslySetInnerHTML={content} /> | ||||||
| 
 | 
 | ||||||
|           {!!status.get('poll') && <PollContainer pollId={status.get('poll')} />} |           {!!status.get('poll') && <PollContainer pollId={status.get('poll')} />} | ||||||
|  | 
 | ||||||
|  |           {renderViewThread && showThreadButton} | ||||||
|         </div> |         </div> | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -75,7 +75,7 @@ class Option extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|       <li> |       <li> | ||||||
|         <label className='poll__text editable'> |         <label className='poll__option editable'> | ||||||
|           <span |           <span | ||||||
|             className={classNames('poll__input', { checkbox: isPollMultiple })} |             className={classNames('poll__input', { checkbox: isPollMultiple })} | ||||||
|             onClick={this.handleToggleMultiple} |             onClick={this.handleToggleMultiple} | ||||||
|  |  | ||||||
|  | @ -160,7 +160,7 @@ class Conversation extends ImmutablePureComponent { | ||||||
|     return ( |     return ( | ||||||
|       <HotKeys handlers={handlers}> |       <HotKeys handlers={handlers}> | ||||||
|         <div className={classNames('conversation focusable muted', { 'conversation--unread': unread })} tabIndex='0'> |         <div className={classNames('conversation focusable muted', { 'conversation--unread': unread })} tabIndex='0'> | ||||||
|           <div className='conversation__avatar'> |           <div className='conversation__avatar' onClick={this.handleClick} role='presentation'> | ||||||
|             <AvatarComposite accounts={accounts} size={48} /> |             <AvatarComposite accounts={accounts} size={48} /> | ||||||
|           </div> |           </div> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ export default function errorsMiddleware() { | ||||||
|       const isFail = new RegExp(`${defaultFailSuffix}$`, 'g'); |       const isFail = new RegExp(`${defaultFailSuffix}$`, 'g'); | ||||||
| 
 | 
 | ||||||
|       if (action.type.match(isFail)) { |       if (action.type.match(isFail)) { | ||||||
|         dispatch(showAlertForError(action.error)); |         dispatch(showAlertForError(action.error, action.skipNotFound)); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -261,7 +261,6 @@ export default function compose(state = initialState, action) { | ||||||
|     }); |     }); | ||||||
|   case COMPOSE_SPOILERNESS_CHANGE: |   case COMPOSE_SPOILERNESS_CHANGE: | ||||||
|     return state.withMutations(map => { |     return state.withMutations(map => { | ||||||
|       map.set('spoiler_text', ''); |  | ||||||
|       map.set('spoiler', !state.get('spoiler')); |       map.set('spoiler', !state.get('spoiler')); | ||||||
|       map.set('idempotencyKey', uuid()); |       map.set('idempotencyKey', uuid()); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -142,7 +142,7 @@ html { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .compose-form__autosuggest-wrapper, | .compose-form__autosuggest-wrapper, | ||||||
| .poll__text input[type="text"], | .poll__option input[type="text"], | ||||||
| .compose-form .spoiler-input__input, | .compose-form .spoiler-input__input, | ||||||
| .compose-form__poll-wrapper select, | .compose-form__poll-wrapper select, | ||||||
| .search__input, | .search__input, | ||||||
|  |  | ||||||
|  | @ -1028,13 +1028,11 @@ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .display-name { |     .display-name { | ||||||
|  |       color: $light-text-color; | ||||||
|  | 
 | ||||||
|       strong { |       strong { | ||||||
|         color: $inverted-text-color; |         color: $inverted-text-color; | ||||||
|       } |       } | ||||||
| 
 |  | ||||||
|       span { |  | ||||||
|         color: $light-text-color; |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .status__content { |     .status__content { | ||||||
|  | @ -1333,7 +1331,6 @@ | ||||||
|     border-radius: 50%; |     border-radius: 50%; | ||||||
|     overflow: hidden; |     overflow: hidden; | ||||||
|     position: relative; |     position: relative; | ||||||
|     cursor: default; |  | ||||||
| 
 | 
 | ||||||
|     & > div { |     & > div { | ||||||
|       float: left; |       float: left; | ||||||
|  | @ -6570,6 +6567,7 @@ noscript { | ||||||
|     padding: 10px; |     padding: 10px; | ||||||
|     padding-top: 12px; |     padding-top: 12px; | ||||||
|     position: relative; |     position: relative; | ||||||
|  |     cursor: pointer; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   &__unread { |   &__unread { | ||||||
|  |  | ||||||
|  | @ -8,20 +8,18 @@ | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   &__chart { |   &__chart { | ||||||
|     position: absolute; |  | ||||||
|     top: 0; |  | ||||||
|     left: 0; |  | ||||||
|     height: 100%; |  | ||||||
|     display: inline-block; |  | ||||||
|     border-radius: 4px; |     border-radius: 4px; | ||||||
|     background: darken($ui-primary-color, 14%); |     display: block; | ||||||
|  |     background: darken($ui-primary-color, 5%); | ||||||
|  |     height: 5px; | ||||||
|  |     min-width: 1%; | ||||||
| 
 | 
 | ||||||
|     &.leading { |     &.leading { | ||||||
|       background: $ui-highlight-color; |       background: $ui-highlight-color; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   &__text { |   &__option { | ||||||
|     position: relative; |     position: relative; | ||||||
|     display: flex; |     display: flex; | ||||||
|     padding: 6px 0; |     padding: 6px 0; | ||||||
|  | @ -29,6 +27,13 @@ | ||||||
|     cursor: default; |     cursor: default; | ||||||
|     overflow: hidden; |     overflow: hidden; | ||||||
| 
 | 
 | ||||||
|  |     &__text { | ||||||
|  |       display: inline-block; | ||||||
|  |       word-wrap: break-word; | ||||||
|  |       overflow-wrap: break-word; | ||||||
|  |       max-width: calc(100% - 45px - 25px); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     input[type=radio], |     input[type=radio], | ||||||
|     input[type=checkbox] { |     input[type=checkbox] { | ||||||
|       display: none; |       display: none; | ||||||
|  | @ -112,19 +117,18 @@ | ||||||
| 
 | 
 | ||||||
|   &__number { |   &__number { | ||||||
|     display: inline-block; |     display: inline-block; | ||||||
|     width: 52px; |     width: 45px; | ||||||
|     font-weight: 700; |     font-weight: 700; | ||||||
|     padding: 0 10px; |     flex: 0 0 45px; | ||||||
|     padding-left: 8px; |  | ||||||
|     text-align: right; |  | ||||||
|     margin-top: auto; |  | ||||||
|     margin-bottom: auto; |  | ||||||
|     flex: 0 0 52px; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   &__vote__mark { |   &__voted { | ||||||
|     float: left; |     padding: 0 5px; | ||||||
|     line-height: 18px; |     display: inline-block; | ||||||
|  | 
 | ||||||
|  |     &__mark { | ||||||
|  |       font-size: 18px; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   &__footer { |   &__footer { | ||||||
|  | @ -199,7 +203,7 @@ | ||||||
|     display: flex; |     display: flex; | ||||||
|     align-items: center; |     align-items: center; | ||||||
| 
 | 
 | ||||||
|     .poll__text { |     .poll__option { | ||||||
|       flex: 0 0 auto; |       flex: 0 0 auto; | ||||||
|       width: calc(100% - (23px + 6px)); |       width: calc(100% - (23px + 6px)); | ||||||
|       margin-right: 6px; |       margin-right: 6px; | ||||||
|  |  | ||||||
|  | @ -64,7 +64,8 @@ class ImportService < BaseService | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def import_relationships!(action, undo_action, overwrite_scope, limit, extra_fields = {}) |   def import_relationships!(action, undo_action, overwrite_scope, limit, extra_fields = {}) | ||||||
|     items = @data.take(limit).map { |row| [row['Account address']&.strip, Hash[extra_fields.map { |key, header| [key, row[header]&.strip] }]] }.reject { |(id, _)| id.blank? } |     local_domain_suffix = "@#{Rails.configuration.x.local_domain}" | ||||||
|  |     items = @data.take(limit).map { |row| [row['Account address']&.strip&.delete_suffix(local_domain_suffix), Hash[extra_fields.map { |key, header| [key, row[header]&.strip] }]] }.reject { |(id, _)| id.blank? } | ||||||
| 
 | 
 | ||||||
|     if @import.overwrite? |     if @import.overwrite? | ||||||
|       presence_hash = items.each_with_object({}) { |(id, extra), mapping| mapping[id] = [true, extra] } |       presence_hash = items.each_with_object({}) { |(id, extra), mapping| mapping[id] = [true, extra] } | ||||||
|  |  | ||||||
|  | @ -10,10 +10,10 @@ class SearchService < BaseService | ||||||
|     @resolve = options[:resolve] || false |     @resolve = options[:resolve] || false | ||||||
| 
 | 
 | ||||||
|     default_results.tap do |results| |     default_results.tap do |results| | ||||||
|       next if @query.blank? |       next if @query.blank? || @limit.zero? | ||||||
| 
 | 
 | ||||||
|       if url_query? |       if url_query? | ||||||
|         results.merge!(url_resource_results) unless url_resource.nil? || (@options[:type].present? && url_resource_symbol != @options[:type].to_sym) |         results.merge!(url_resource_results) unless url_resource.nil? || @offset.positive? || (@options[:type].present? && url_resource_symbol != @options[:type].to_sym) | ||||||
|       elsif @query.present? |       elsif @query.present? | ||||||
|         results[:accounts] = perform_accounts_search! if account_searchable? |         results[:accounts] = perform_accounts_search! if account_searchable? | ||||||
|         results[:statuses] = perform_statuses_search! if full_text_searchable? |         results[:statuses] = perform_statuses_search! if full_text_searchable? | ||||||
|  |  | ||||||
|  | @ -8,16 +8,16 @@ | ||||||
|       %li |       %li | ||||||
|         - if show_results |         - if show_results | ||||||
|           - percent = total_votes_count > 0 ? 100 * option.votes_count / total_votes_count : 0 |           - percent = total_votes_count > 0 ? 100 * option.votes_count / total_votes_count : 0 | ||||||
|           %span.poll__chart{ style: "width: #{percent}%" } |           %label.poll__option>< | ||||||
| 
 |  | ||||||
|           %label.poll__text>< |  | ||||||
|             %span.poll__number>< |             %span.poll__number>< | ||||||
|               - if own_votes.include?(index) |               - if own_votes.include?(index) | ||||||
|                 %i.poll__vote__mark.fa.fa-check |                 %i.poll__voted__mark.fa.fa-check | ||||||
|               = percent.round |               = percent.round | ||||||
|             = Formatter.instance.format_poll_option(status, option, autoplay: autoplay) |             = Formatter.instance.format_poll_option(status, option, autoplay: autoplay) | ||||||
|  | 
 | ||||||
|  |             %span.poll__chart{ style: "width: #{percent}%" } | ||||||
|         - else |         - else | ||||||
|           %label.poll__text>< |           %label.poll__option>< | ||||||
|             %span.poll__input{ class: poll.multiple? ? 'checkbox' : nil}>< |             %span.poll__input{ class: poll.multiple? ? 'checkbox' : nil}>< | ||||||
|             = Formatter.instance.format_poll_option(status, option, autoplay: autoplay) |             = Formatter.instance.format_poll_option(status, option, autoplay: autoplay) | ||||||
|   .poll__footer |   .poll__footer | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ class ActivityPub::DistributePollUpdateWorker | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
|   include Payloadable |   include Payloadable | ||||||
| 
 | 
 | ||||||
|   sidekiq_options queue: 'push', unique: :until_executed, retry: 0 |   sidekiq_options queue: 'push', lock: :until_executed, retry: 0 | ||||||
| 
 | 
 | ||||||
|   def perform(status_id) |   def perform(status_id) | ||||||
|     @status  = Status.find(status_id) |     @status  = Status.find(status_id) | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class ActivityPub::SynchronizeFeaturedCollectionWorker | class ActivityPub::SynchronizeFeaturedCollectionWorker | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options queue: 'pull', unique: :until_executed |   sidekiq_options queue: 'pull', lock: :until_executed | ||||||
| 
 | 
 | ||||||
|   def perform(account_id) |   def perform(account_id) | ||||||
|     ActivityPub::FetchFeaturedCollectionService.new.call(Account.find(account_id)) |     ActivityPub::FetchFeaturedCollectionService.new.call(Account.find(account_id)) | ||||||
|  |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class AfterRemoteFollowRequestWorker |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options queue: 'pull', retry: 5 |  | ||||||
| 
 |  | ||||||
|   def perform(follow_request_id); end |  | ||||||
| end |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class AfterRemoteFollowWorker |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options queue: 'pull', retry: 5 |  | ||||||
| 
 |  | ||||||
|   def perform(follow_id); end |  | ||||||
| end |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class NotificationWorker |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options queue: 'push', retry: 5 |  | ||||||
| 
 |  | ||||||
|   def perform(xml, source_account_id, target_account_id); end |  | ||||||
| end |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class PollExpirationNotifyWorker | class PollExpirationNotifyWorker | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options unique: :until_executed |   sidekiq_options lock: :until_executed | ||||||
| 
 | 
 | ||||||
|   def perform(poll_id) |   def perform(poll_id) | ||||||
|     poll = Poll.find(poll_id) |     poll = Poll.find(poll_id) | ||||||
|  |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class ProcessingWorker |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options backtrace: true |  | ||||||
| 
 |  | ||||||
|   def perform(account_id, body); end |  | ||||||
| end |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class PublishScheduledStatusWorker | class PublishScheduledStatusWorker | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options unique: :until_executed |   sidekiq_options lock: :until_executed | ||||||
| 
 | 
 | ||||||
|   def perform(scheduled_status_id) |   def perform(scheduled_status_id) | ||||||
|     scheduled_status = ScheduledStatus.find(scheduled_status_id) |     scheduled_status = ScheduledStatus.find(scheduled_status_id) | ||||||
|  |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class Pubsubhubbub::ConfirmationWorker |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options queue: 'push', retry: false |  | ||||||
| 
 |  | ||||||
|   def perform(subscription_id, mode, secret = nil, lease_seconds = nil); end |  | ||||||
| end |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class Pubsubhubbub::DeliveryWorker |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options queue: 'push', retry: 3, dead: false |  | ||||||
| 
 |  | ||||||
|   def perform(subscription_id, payload); end |  | ||||||
| end |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class Pubsubhubbub::DistributionWorker |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options queue: 'push' |  | ||||||
| 
 |  | ||||||
|   def perform(stream_entry_ids); end |  | ||||||
| end |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class Pubsubhubbub::RawDistributionWorker |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options queue: 'push' |  | ||||||
| 
 |  | ||||||
|   def perform(xml, source_account_id); end |  | ||||||
| end |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class Pubsubhubbub::SubscribeWorker |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options queue: 'push', retry: 10, unique: :until_executed, dead: false |  | ||||||
| 
 |  | ||||||
|   def perform(account_id); end |  | ||||||
| end |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class Pubsubhubbub::UnsubscribeWorker |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options queue: 'push', retry: false, unique: :until_executed, dead: false |  | ||||||
| 
 |  | ||||||
|   def perform(account_id); end |  | ||||||
| end |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class RegenerationWorker | class RegenerationWorker | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options unique: :until_executed |   sidekiq_options lock: :until_executed | ||||||
| 
 | 
 | ||||||
|   def perform(account_id, _ = :home) |   def perform(account_id, _ = :home) | ||||||
|     account = Account.find(account_id) |     account = Account.find(account_id) | ||||||
|  |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class RemoteProfileUpdateWorker |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options queue: 'pull' |  | ||||||
| 
 |  | ||||||
|   def perform(account_id, body, resubscribe); end |  | ||||||
| end |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class ResolveAccountWorker | class ResolveAccountWorker | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options queue: 'pull', unique: :until_executed |   sidekiq_options queue: 'pull', lock: :until_executed | ||||||
| 
 | 
 | ||||||
|   def perform(uri) |   def perform(uri) | ||||||
|     ResolveAccountService.new.call(uri) |     ResolveAccountService.new.call(uri) | ||||||
|  |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class SalmonWorker |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options backtrace: true |  | ||||||
| 
 |  | ||||||
|   def perform(account_id, body); end |  | ||||||
| end |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class Scheduler::BackupCleanupScheduler | class Scheduler::BackupCleanupScheduler | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options unique: :until_executed, retry: 0 |   sidekiq_options lock: :until_executed, retry: 0 | ||||||
| 
 | 
 | ||||||
|   def perform |   def perform | ||||||
|     old_backups.reorder(nil).find_each(&:destroy!) |     old_backups.reorder(nil).find_each(&:destroy!) | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class Scheduler::DoorkeeperCleanupScheduler | class Scheduler::DoorkeeperCleanupScheduler | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options unique: :until_executed, retry: 0 |   sidekiq_options lock: :until_executed, retry: 0 | ||||||
| 
 | 
 | ||||||
|   def perform |   def perform | ||||||
|     Doorkeeper::AccessToken.where('revoked_at IS NOT NULL').where('revoked_at < NOW()').delete_all |     Doorkeeper::AccessToken.where('revoked_at IS NOT NULL').where('revoked_at < NOW()').delete_all | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class Scheduler::EmailScheduler | class Scheduler::EmailScheduler | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options unique: :until_executed, retry: 0 |   sidekiq_options lock: :until_executed, retry: 0 | ||||||
| 
 | 
 | ||||||
|   FREQUENCY      = 7.days.freeze |   FREQUENCY      = 7.days.freeze | ||||||
|   SIGN_IN_OFFSET = 1.day.freeze |   SIGN_IN_OFFSET = 1.day.freeze | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ class Scheduler::FeedCleanupScheduler | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
|   include Redisable |   include Redisable | ||||||
| 
 | 
 | ||||||
|   sidekiq_options unique: :until_executed, retry: 0 |   sidekiq_options lock: :until_executed, retry: 0 | ||||||
| 
 | 
 | ||||||
|   def perform |   def perform | ||||||
|     clean_home_feeds! |     clean_home_feeds! | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ class Scheduler::IpCleanupScheduler | ||||||
| 
 | 
 | ||||||
|   RETENTION_PERIOD = 1.year |   RETENTION_PERIOD = 1.year | ||||||
| 
 | 
 | ||||||
|   sidekiq_options unique: :until_executed, retry: 0 |   sidekiq_options lock: :until_executed, retry: 0 | ||||||
| 
 | 
 | ||||||
|   def perform |   def perform | ||||||
|     time_ago = RETENTION_PERIOD.ago |     time_ago = RETENTION_PERIOD.ago | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class Scheduler::MediaCleanupScheduler | class Scheduler::MediaCleanupScheduler | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options unique: :until_executed, retry: 0 |   sidekiq_options lock: :until_executed, retry: 0 | ||||||
| 
 | 
 | ||||||
|   def perform |   def perform | ||||||
|     unattached_media.find_each(&:destroy) |     unattached_media.find_each(&:destroy) | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class Scheduler::PgheroScheduler | class Scheduler::PgheroScheduler | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options unique: :until_executed, retry: 0 |   sidekiq_options lock: :until_executed, retry: 0 | ||||||
| 
 | 
 | ||||||
|   def perform |   def perform | ||||||
|     PgHero.capture_space_stats |     PgHero.capture_space_stats | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class Scheduler::ScheduledStatusesScheduler | class Scheduler::ScheduledStatusesScheduler | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options unique: :until_executed, retry: 0 |   sidekiq_options lock: :until_executed, retry: 0 | ||||||
| 
 | 
 | ||||||
|   def perform |   def perform | ||||||
|     publish_scheduled_statuses! |     publish_scheduled_statuses! | ||||||
|  |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class Scheduler::SubscriptionsCleanupScheduler |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options unique: :until_executed, retry: 0 |  | ||||||
| 
 |  | ||||||
|   def perform; end |  | ||||||
| end |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| class Scheduler::SubscriptionsScheduler |  | ||||||
|   include Sidekiq::Worker |  | ||||||
| 
 |  | ||||||
|   sidekiq_options unique: :until_executed, retry: 0 |  | ||||||
| 
 |  | ||||||
|   def perform; end |  | ||||||
| end |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class Scheduler::TrendingTagsScheduler | class Scheduler::TrendingTagsScheduler | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options unique: :until_executed, retry: 0 |   sidekiq_options lock: :until_executed, retry: 0 | ||||||
| 
 | 
 | ||||||
|   def perform |   def perform | ||||||
|     TrendingTags.update! if Setting.trends |     TrendingTags.update! if Setting.trends | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class Scheduler::UserCleanupScheduler | class Scheduler::UserCleanupScheduler | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options unique: :until_executed, retry: 0 |   sidekiq_options lock: :until_executed, retry: 0 | ||||||
| 
 | 
 | ||||||
|   def perform |   def perform | ||||||
|     User.where('confirmed_at is NULL AND confirmation_sent_at <= ?', 2.days.ago).reorder(nil).find_in_batches do |batch| |     User.where('confirmed_at is NULL AND confirmation_sent_at <= ?', 2.days.ago).reorder(nil).find_in_batches do |batch| | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| class VerifyAccountLinksWorker | class VerifyAccountLinksWorker | ||||||
|   include Sidekiq::Worker |   include Sidekiq::Worker | ||||||
| 
 | 
 | ||||||
|   sidekiq_options queue: 'pull', retry: false, unique: :until_executed |   sidekiq_options queue: 'pull', retry: false, lock: :until_executed | ||||||
| 
 | 
 | ||||||
|   def perform(account_id) |   def perform(account_id) | ||||||
|     account = Account.find(account_id) |     account = Account.find(account_id) | ||||||
|  |  | ||||||
|  | @ -37,6 +37,7 @@ if Rails.env.production? | ||||||
|     p.style_src       :self, :unsafe_inline, assets_host |     p.style_src       :self, :unsafe_inline, assets_host | ||||||
|     p.media_src       :self, :data, *data_hosts |     p.media_src       :self, :data, *data_hosts | ||||||
|     p.frame_src       :self, :https |     p.frame_src       :self, :https | ||||||
|  |     p.child_src       :self, :blob, assets_host | ||||||
|     p.worker_src      :self, :blob, assets_host |     p.worker_src      :self, :blob, assets_host | ||||||
|     p.connect_src     :self, :blob, :data, Rails.configuration.x.streaming_api_base_url, *data_hosts |     p.connect_src     :self, :blob, :data, Rails.configuration.x.streaming_api_base_url, *data_hosts | ||||||
|     p.manifest_src    :self, assets_host |     p.manifest_src    :self, assets_host | ||||||
|  |  | ||||||
|  | @ -42,6 +42,7 @@ class Rack::Attack | ||||||
|     /auth/sign_in |     /auth/sign_in | ||||||
|     /auth |     /auth | ||||||
|     /auth/password |     /auth/password | ||||||
|  |     /auth/confirmation | ||||||
|   ).freeze |   ).freeze | ||||||
| 
 | 
 | ||||||
|   PROTECTED_PATHS_REGEX = Regexp.union(PROTECTED_PATHS.map { |path| /\A#{Regexp.escape(path)}/ }) |   PROTECTED_PATHS_REGEX = Regexp.union(PROTECTED_PATHS.map { |path| /\A#{Regexp.escape(path)}/ }) | ||||||
|  |  | ||||||
|  | @ -13,6 +13,11 @@ Sidekiq.configure_server do |config| | ||||||
|   config.server_middleware do |chain| |   config.server_middleware do |chain| | ||||||
|     chain.add SidekiqErrorHandler |     chain.add SidekiqErrorHandler | ||||||
|   end |   end | ||||||
|  | 
 | ||||||
|  |   config.death_handlers << lambda do |job, _ex| | ||||||
|  |     digest = job['lock_digest'] | ||||||
|  |     SidekiqUniqueJobs::Digests.delete_by_digest(digest) if digest | ||||||
|  |   end | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| Sidekiq.configure_client do |config| | Sidekiq.configure_client do |config| | ||||||
|  |  | ||||||
|  | @ -1093,6 +1093,8 @@ en: | ||||||
|     disallowed_hashtags: |     disallowed_hashtags: | ||||||
|       one: 'contained a disallowed hashtag: %{tags}' |       one: 'contained a disallowed hashtag: %{tags}' | ||||||
|       other: 'contained the disallowed hashtags: %{tags}' |       other: 'contained the disallowed hashtags: %{tags}' | ||||||
|  |     errors: | ||||||
|  |       in_reply_not_found: The status you are trying to reply to does not appear to exist. | ||||||
|     language_detection: Automatically detect language |     language_detection: Automatically detect language | ||||||
|     open_in_web: Open in web |     open_in_web: Open in web | ||||||
|     over_character_limit: character limit of %{max} exceeded |     over_character_limit: character limit of %{max} exceeded | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| # frozen_string_literal: true | # frozen_string_literal: true | ||||||
| 
 | 
 | ||||||
| require 'sidekiq/web' | require 'sidekiq_unique_jobs/web' | ||||||
| require 'sidekiq-scheduler/web' | require 'sidekiq-scheduler/web' | ||||||
| 
 | 
 | ||||||
| Sidekiq::Web.set :session_secret, Rails.application.secrets[:secret_key_base] | Sidekiq::Web.set :session_secret, Rails.application.secrets[:secret_key_base] | ||||||
|  |  | ||||||
|  | @ -115,7 +115,7 @@ module Mastodon | ||||||
|       when :filesystem |       when :filesystem | ||||||
|         require 'find' |         require 'find' | ||||||
| 
 | 
 | ||||||
|         root_path = ENV.fetch('RAILS_ROOT_PATH', File.join(':rails_root', 'public', 'system')).gsub(':rails_root', Rails.root.to_s) |         root_path = ENV.fetch('PAPERCLIP_ROOT_PATH', File.join(':rails_root', 'public', 'system')).gsub(':rails_root', Rails.root.to_s) | ||||||
| 
 | 
 | ||||||
|         Find.find(File.join(*[root_path, prefix].compact)) do |path| |         Find.find(File.join(*[root_path, prefix].compact)) do |path| | ||||||
|           next if File.directory?(path) |           next if File.directory?(path) | ||||||
|  |  | ||||||
							
								
								
									
										18
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								package.json
									
									
									
									
									
								
							|  | @ -65,17 +65,17 @@ | ||||||
|     "@babel/plugin-proposal-decorators": "^7.8.3", |     "@babel/plugin-proposal-decorators": "^7.8.3", | ||||||
|     "@babel/plugin-transform-react-inline-elements": "^7.9.0", |     "@babel/plugin-transform-react-inline-elements": "^7.9.0", | ||||||
|     "@babel/plugin-transform-runtime": "^7.9.0", |     "@babel/plugin-transform-runtime": "^7.9.0", | ||||||
|     "@babel/preset-env": "^7.8.3", |     "@babel/preset-env": "^7.9.0", | ||||||
|     "@babel/preset-react": "^7.8.3", |     "@babel/preset-react": "^7.9.4", | ||||||
|     "@babel/runtime": "^7.8.4", |     "@babel/runtime": "^7.8.4", | ||||||
|     "@clusterws/cws": "^0.17.3", |     "@clusterws/cws": "^0.17.3", | ||||||
|     "@gamestdio/websocket": "^0.3.2", |     "@gamestdio/websocket": "^0.3.2", | ||||||
|     "array-includes": "^3.1.1", |     "array-includes": "^3.1.1", | ||||||
|     "arrow-key-navigation": "^1.1.0", |     "arrow-key-navigation": "^1.1.0", | ||||||
|     "atrament": "0.2.4", |     "atrament": "0.2.4", | ||||||
|     "autoprefixer": "^9.7.4", |     "autoprefixer": "^9.7.5", | ||||||
|     "axios": "^0.19.2", |     "axios": "^0.19.2", | ||||||
|     "babel-loader": "^8.0.6", |     "babel-loader": "^8.1.0", | ||||||
|     "babel-plugin-lodash": "^3.3.4", |     "babel-plugin-lodash": "^3.3.4", | ||||||
|     "babel-plugin-preval": "^5.0.0", |     "babel-plugin-preval": "^5.0.0", | ||||||
|     "babel-plugin-react-intl": "^3.4.1", |     "babel-plugin-react-intl": "^3.4.1", | ||||||
|  | @ -127,7 +127,7 @@ | ||||||
|     "prop-types": "^15.5.10", |     "prop-types": "^15.5.10", | ||||||
|     "punycode": "^2.1.0", |     "punycode": "^2.1.0", | ||||||
|     "@rails/ujs": "^6.0.2", |     "@rails/ujs": "^6.0.2", | ||||||
|     "react": "^16.12.0", |     "react": "^16.13.1", | ||||||
|     "react-dom": "^16.13.0", |     "react-dom": "^16.13.0", | ||||||
|     "react-hotkeys": "^1.1.4", |     "react-hotkeys": "^1.1.4", | ||||||
|     "react-immutable-proptypes": "^2.2.0", |     "react-immutable-proptypes": "^2.2.0", | ||||||
|  | @ -157,13 +157,13 @@ | ||||||
|     "sass": "^1.26.3", |     "sass": "^1.26.3", | ||||||
|     "sass-loader": "^8.0.2", |     "sass-loader": "^8.0.2", | ||||||
|     "stacktrace-js": "^2.0.2", |     "stacktrace-js": "^2.0.2", | ||||||
|     "stringz": "^2.0.0", |     "stringz": "^2.1.0", | ||||||
|     "substring-trie": "^1.0.2", |     "substring-trie": "^1.0.2", | ||||||
|     "terser-webpack-plugin": "^2.3.5", |     "terser-webpack-plugin": "^2.3.5", | ||||||
|     "tesseract.js": "^2.0.0-alpha.16", |     "tesseract.js": "^2.0.0-alpha.16", | ||||||
|     "throng": "^4.0.0", |     "throng": "^4.0.0", | ||||||
|     "tiny-queue": "^0.2.1", |     "tiny-queue": "^0.2.1", | ||||||
|     "uuid": "^3.4.0", |     "uuid": "^7.0.2", | ||||||
|     "wavesurfer.js": "^3.3.1", |     "wavesurfer.js": "^3.3.1", | ||||||
|     "webpack": "^4.42.1", |     "webpack": "^4.42.1", | ||||||
|     "webpack-assets-manifest": "^3.1.1", |     "webpack-assets-manifest": "^3.1.1", | ||||||
|  | @ -174,7 +174,7 @@ | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "babel-eslint": "^10.0.3", |     "babel-eslint": "^10.0.3", | ||||||
|     "babel-jest": "^25.1.0", |     "babel-jest": "^25.2.4", | ||||||
|     "enzyme": "^3.11.0", |     "enzyme": "^3.11.0", | ||||||
|     "enzyme-adapter-react-16": "^1.15.2", |     "enzyme-adapter-react-16": "^1.15.2", | ||||||
|     "eslint": "^6.8.0", |     "eslint": "^6.8.0", | ||||||
|  | @ -188,6 +188,6 @@ | ||||||
|     "react-test-renderer": "^16.13.0", |     "react-test-renderer": "^16.13.0", | ||||||
|     "sass-lint": "^1.13.1", |     "sass-lint": "^1.13.1", | ||||||
|     "webpack-dev-server": "^3.10.3", |     "webpack-dev-server": "^3.10.3", | ||||||
|     "yargs": "^15.1.0" |     "yargs": "^15.3.1" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -91,10 +91,6 @@ RSpec.describe ImportService, type: :service do | ||||||
| 
 | 
 | ||||||
|     let(:csv) { attachment_fixture('mute-imports.txt') } |     let(:csv) { attachment_fixture('mute-imports.txt') } | ||||||
| 
 | 
 | ||||||
|     before do |  | ||||||
|       allow(NotificationWorker).to receive(:perform_async) |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     describe 'when no accounts are followed' do |     describe 'when no accounts are followed' do | ||||||
|       let(:import) { Import.create(account: account, type: 'following', data: csv) } |       let(:import) { Import.create(account: account, type: 'following', data: csv) } | ||||||
|       it 'follows the listed accounts, including boosts' do |       it 'follows the listed accounts, including boosts' do | ||||||
|  | @ -135,10 +131,6 @@ RSpec.describe ImportService, type: :service do | ||||||
| 
 | 
 | ||||||
|     let(:csv) { attachment_fixture('new-following-imports.txt') } |     let(:csv) { attachment_fixture('new-following-imports.txt') } | ||||||
| 
 | 
 | ||||||
|     before do |  | ||||||
|       allow(NotificationWorker).to receive(:perform_async) |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     describe 'when no accounts are followed' do |     describe 'when no accounts are followed' do | ||||||
|       let(:import) { Import.create(account: account, type: 'following', data: csv) } |       let(:import) { Import.create(account: account, type: 'following', data: csv) } | ||||||
|       it 'follows the listed accounts, respecting boosts' do |       it 'follows the listed accounts, respecting boosts' do | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue