diff --git a/Gemfile b/Gemfile index 0ebf5f2a6a..f110812a6b 100644 --- a/Gemfile +++ b/Gemfile @@ -69,7 +69,7 @@ gem 'nilsimsa', git: 'https://github.com/witgo/nilsimsa', ref: 'fd184883048b922b gem 'nokogiri', '~> 1.10' gem 'nsa', '~> 0.2' gem 'oj', '~> 3.10' -gem 'ox', '~> 2.12' +gem 'ox', '~> 2.13' gem 'parslet' gem 'parallel', '~> 1.19' 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 'strong_migrations', '~> 0.6' 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 'tzinfo-data', '~> 1.2019' gem 'webpacker', '~> 4.2' @@ -112,7 +112,7 @@ group :development, :test do gem 'i18n-tasks', '~> 0.9', require: false gem 'pry-byebug', '~> 3.8' gem 'pry-rails', '~> 0.3' - gem 'rspec-rails', '~> 3.9' + gem 'rspec-rails', '~> 4.0' end group :production, :test do @@ -122,19 +122,19 @@ end group :test do gem 'capybara', '~> 3.31' gem 'climate_control', '~> 0.2' - gem 'faker', '~> 2.10' + gem 'faker', '~> 2.11' gem 'microformats', '~> 4.2' gem 'rails-controller-testing', '~> 1.0' gem 'rspec-sidekiq', '~> 3.0' gem 'simplecov', '~> 0.18', require: false gem 'webmock', '~> 3.8' - gem 'parallel_tests', '~> 2.30' + gem 'parallel_tests', '~> 2.32' end group :development do gem 'active_record_query_trace', '~> 1.7' gem 'annotate', '~> 3.0' - gem 'better_errors', '~> 2.5' + gem 'better_errors', '~> 2.6' gem 'binding_of_caller', '~> 0.7' gem 'bullet', '~> 6.1' gem 'letter_opener', '~> 1.7' @@ -142,7 +142,7 @@ group :development do gem 'memory_profiler' gem 'rubocop', '~> 0.79', 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 'capistrano', '~> 3.12' diff --git a/Gemfile.lock b/Gemfile.lock index ee4a98f388..86dccfcc41 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -108,7 +108,7 @@ GEM aws-sigv4 (1.1.1) aws-eventstream (~> 1.0, >= 1.0.2) bcrypt (3.1.12) - better_errors (2.5.1) + better_errors (2.6.0) coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) @@ -116,9 +116,9 @@ GEM debug_inspector (>= 0.0.1) blurhash (0.1.4) ffi (~> 1.10.0) - bootsnap (1.4.5) + bootsnap (1.4.6) msgpack (~> 1.0) - brakeman (4.7.2) + brakeman (4.8.0) browser (4.0.0) builder (3.2.4) bullet (6.1.0) @@ -166,7 +166,7 @@ GEM cocaine (0.5.8) climate_control (>= 0.0.3, < 1.0) coderay (1.1.2) - concurrent-ruby (1.1.5) + concurrent-ruby (1.1.6) connection_pool (2.2.2) crack (0.4.3) safe_yaml (~> 1.0.0) @@ -218,7 +218,7 @@ GEM tzinfo excon (0.71.0) fabrication (2.21.0) - faker (2.10.1) + faker (2.11.0) i18n (>= 1.6, < 2) faraday (0.17.3) multipart-post (>= 1.2, < 3) @@ -299,19 +299,19 @@ GEM terminal-table (>= 1.5.1) idn-ruby (0.1.0) ipaddress (0.8.3) - iso-639 (0.2.8) + iso-639 (0.3.5) jaro_winkler (1.5.4) jmespath (1.4.0) json (2.3.0) json-canonicalization (0.2.0) - json-ld (3.1.1) + json-ld (3.1.2) htmlentities (~> 4.3) json-canonicalization (~> 0.2) link_header (~> 0.0, >= 0.0.8) multi_json (~> 1.14) rack (~> 2.0) rdf (~> 3.1) - json-ld-preloaded (3.1.1) + json-ld-preloaded (3.1.2) json-ld (~> 3.1) rdf (~> 3.1) jsonapi-renderer (0.2.2) @@ -365,7 +365,7 @@ GEM mini_mime (1.0.2) mini_portile2 (2.4.0) minitest (5.14.0) - msgpack (1.3.1) + msgpack (1.3.3) multi_json (1.14.1) multipart-post (2.1.1) necromancer (0.5.1) @@ -383,7 +383,7 @@ GEM concurrent-ruby (~> 1.0, >= 1.0.2) sidekiq (>= 3.5) statsd-ruby (~> 1.4, >= 1.4.0) - oj (3.10.3) + oj (3.10.5) omniauth (1.9.1) hashie (>= 3.4.6) rack (>= 1.6.2, < 3) @@ -395,7 +395,7 @@ GEM omniauth (~> 1.3, >= 1.3.2) ruby-saml (~> 1.7) orm_adapter (0.5.0) - ox (2.12.1) + ox (2.13.2) paperclip (6.0.0) activemodel (>= 4.2.0) activesupport (>= 4.2.0) @@ -406,7 +406,7 @@ GEM av (~> 0.9.0) paperclip (>= 2.5.2) parallel (1.19.1) - parallel_tests (2.30.1) + parallel_tests (2.32.0) parallel parser (2.7.0.5) ast (~> 2.4.0) @@ -414,7 +414,7 @@ GEM pastel (0.7.3) equatable (~> 0.6) tty-color (~> 0.5) - pg (1.2.2) + pg (1.2.3) pghero (2.4.1) activerecord (>= 5) pkg-config (1.4.1) @@ -531,14 +531,14 @@ GEM rspec-mocks (3.9.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.9.0) - rspec-rails (3.9.1) - actionpack (>= 3.0) - activesupport (>= 3.0) - railties (>= 3.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) - rspec-support (~> 3.9.0) + rspec-rails (4.0.0) + actionpack (>= 4.2) + activesupport (>= 4.2) + railties (>= 4.2) + rspec-core (~> 3.9) + rspec-expectations (~> 3.9) + rspec-mocks (~> 3.9) + rspec-support (~> 3.9) rspec-sidekiq (3.0.3) rspec-core (~> 3.0, >= 3.0.0) sidekiq (>= 2.4.0) @@ -577,7 +577,7 @@ GEM sidekiq (>= 3) thwait tilt (>= 1.4.0) - sidekiq-unique-jobs (6.0.20) + sidekiq-unique-jobs (6.0.21) concurrent-ruby (~> 1.0, >= 1.0.5) sidekiq (>= 4.0, < 7.0) thor (~> 0) @@ -616,11 +616,11 @@ GEM thread_safe (0.3.6) thwait (0.1.0) tilt (2.0.10) - tty-color (0.5.0) + tty-color (0.5.1) tty-command (0.9.0) pastel (~> 0.7.0) - tty-cursor (0.7.0) - tty-prompt (0.20.0) + tty-cursor (0.7.1) + tty-prompt (0.21.0) necromancer (~> 0.5.0) pastel (~> 0.7.0) tty-reader (~> 0.7.0) @@ -628,7 +628,7 @@ GEM tty-cursor (~> 0.7) tty-screen (~> 0.7) wisper (~> 2.0.0) - tty-screen (0.7.0) + tty-screen (0.7.1) twitter-text (1.14.7) unf (~> 0.1.0) tzinfo (1.2.6) @@ -669,11 +669,11 @@ DEPENDENCIES addressable (~> 2.7) annotate (~> 3.0) aws-sdk-s3 (~> 1.61) - better_errors (~> 2.5) + better_errors (~> 2.6) binding_of_caller (~> 0.7) blurhash (~> 0.1) bootsnap (~> 1.4) - brakeman (~> 4.7) + brakeman (~> 4.8) browser bullet (~> 6.1) bundler-audit (~> 0.6) @@ -696,7 +696,7 @@ DEPENDENCIES dotenv-rails (~> 2.7) e2mmap (~> 0.1.0) fabrication (~> 2.21) - faker (~> 2.10) + faker (~> 2.11) fast_blank (~> 1.0) fastimage fog-core (<= 2.1.0) @@ -734,11 +734,11 @@ DEPENDENCIES omniauth (~> 1.9) omniauth-cas (~> 1.1) omniauth-saml (~> 1.10) - ox (~> 2.12) + ox (~> 2.13) paperclip (~> 6.0) paperclip-av-transcoder (~> 0.6) parallel (~> 1.19) - parallel_tests (~> 2.30) + parallel_tests (~> 2.32) parslet pg (~> 1.2) pghero (~> 2.4) @@ -763,7 +763,7 @@ DEPENDENCIES redis-namespace (~> 1.7) redis-rails (~> 5.0) rqrcode (~> 1.1) - rspec-rails (~> 3.9) + rspec-rails (~> 4.0) rspec-sidekiq (~> 3.0) rubocop (~> 0.79) rubocop-rails (~> 2.4) @@ -785,7 +785,7 @@ DEPENDENCIES thor (~> 0.20) thwait (~> 0.1.0) tty-command (~> 0.9) - tty-prompt (~> 0.20) + tty-prompt (~> 0.21) twitter-text (~> 1.14) tzinfo-data (~> 1.2019) webmock (~> 3.8) diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index 544e8e3c93..29ae917626 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -7,6 +7,7 @@ class Api::V1::StatusesController < Api::BaseController before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [:create, :destroy] before_action :require_user!, except: [:show, :context] before_action :set_status, only: [:show, :context] + before_action :set_thread, only: [:create] override_rate_limit_headers :create, family: :statuses @@ -36,7 +37,7 @@ class Api::V1::StatusesController < Api::BaseController def create @status = PostStatusService.new.call(current_user.account, 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], sensitive: status_params[:sensitive], spoiler_text: status_params[:spoiler_text], @@ -70,6 +71,12 @@ class Api::V1::StatusesController < Api::BaseController raise ActiveRecord::RecordNotFound 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 params.permit( :status, diff --git a/app/controllers/settings/imports_controller.rb b/app/controllers/settings/imports_controller.rb index 38f2e39c1d..7b8c4ae235 100644 --- a/app/controllers/settings/imports_controller.rb +++ b/app/controllers/settings/imports_controller.rb @@ -29,6 +29,6 @@ class Settings::ImportsController < Settings::BaseController end def import_params - params.require(:import).permit(:data, :type) + params.require(:import).permit(:data, :type, :mode) end end diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js index 4af36e9983..cb2c682a45 100644 --- a/app/javascript/mastodon/actions/accounts.js +++ b/app/javascript/mastodon/actions/accounts.js @@ -396,6 +396,7 @@ export function fetchFollowersFail(id, error) { type: FOLLOWERS_FETCH_FAIL, id, error, + skipNotFound: true, }; }; @@ -482,6 +483,7 @@ export function fetchFollowingFail(id, error) { type: FOLLOWING_FETCH_FAIL, id, error, + skipNotFound: true, }; }; @@ -571,6 +573,7 @@ export function fetchRelationshipsFail(error) { type: RELATIONSHIPS_FETCH_FAIL, error, skipLoading: true, + skipNotFound: true, }; }; diff --git a/app/javascript/mastodon/actions/alerts.js b/app/javascript/mastodon/actions/alerts.js index cd36d8007b..1670f9c10d 100644 --- a/app/javascript/mastodon/actions/alerts.js +++ b/app/javascript/mastodon/actions/alerts.js @@ -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) { 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 return { type: ALERT_NOOP }; } diff --git a/app/javascript/mastodon/actions/identity_proofs.js b/app/javascript/mastodon/actions/identity_proofs.js index 449debf616..1039839566 100644 --- a/app/javascript/mastodon/actions/identity_proofs.js +++ b/app/javascript/mastodon/actions/identity_proofs.js @@ -27,4 +27,5 @@ export const fetchAccountIdentityProofsFail = (accountId, err) => ({ type: IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL, accountId, err, + skipNotFound: true, }); diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js index 0546686559..cdd2111f8e 100644 --- a/app/javascript/mastodon/actions/timelines.js +++ b/app/javascript/mastodon/actions/timelines.js @@ -149,6 +149,7 @@ export function expandTimelineFail(timeline, error, isLoadingMore) { timeline, error, skipLoading: !isLoadingMore, + skipNotFound: timeline.startsWith('account:'), }; }; diff --git a/app/javascript/mastodon/components/column_header.js b/app/javascript/mastodon/components/column_header.js index ea82f9ef9d..1bb583583a 100644 --- a/app/javascript/mastodon/components/column_header.js +++ b/app/javascript/mastodon/components/column_header.js @@ -76,8 +76,9 @@ class ColumnHeader extends React.PureComponent { handlePin = () => { if (!this.props.pinned) { - this.historyBack(); + this.context.router.history.replace('/'); } + this.props.onPin(); } diff --git a/app/javascript/mastodon/components/poll.js b/app/javascript/mastodon/components/poll.js index 3a17e80e72..7525a1030a 100644 --- a/app/javascript/mastodon/components/poll.js +++ b/app/javascript/mastodon/components/poll.js @@ -127,15 +127,7 @@ class Poll extends ImmutablePureComponent { return (
  • - {showResults && ( - - {({ width }) => - - } - - )} - -
  • ); } diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index 0dc00cb98d..075ee1b870 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -432,16 +432,10 @@ class Status extends ImmutablePureComponent { - + {media} - {showThread && status.get('in_reply_to_id') && status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) && ( - - )} - diff --git a/app/javascript/mastodon/components/status_content.js b/app/javascript/mastodon/components/status_content.js index 5d921fd412..3200f2d82f 100644 --- a/app/javascript/mastodon/components/status_content.js +++ b/app/javascript/mastodon/components/status_content.js @@ -20,6 +20,7 @@ export default class StatusContent extends React.PureComponent { static propTypes = { status: ImmutablePropTypes.map.isRequired, expanded: PropTypes.bool, + showThread: PropTypes.bool, onExpandedToggle: PropTypes.func, onClick: PropTypes.func, 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 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 spoilerContent = { __html: status.get('spoilerHtml') }; @@ -195,6 +197,12 @@ export default class StatusContent extends React.PureComponent { directionStyle.direction = 'rtl'; } + const showThreadButton = ( + + ); + const readMoreButton = (