From 2c5abee2b0aef63b6b61bbf761664221f20ccc97 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Jul 2021 22:24:02 +0900 Subject: [PATCH 01/11] Bump eslint from 7.30.0 to 7.31.0 (#16523) Bumps [eslint](https://github.com/eslint/eslint) from 7.30.0 to 7.31.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v7.30.0...v7.31.0) --- updated-dependencies: - dependency-name: eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index da1dfdea2..20fd10369 100644 --- a/package.json +++ b/package.json @@ -175,7 +175,7 @@ "@testing-library/react": "^11.2.7", "babel-eslint": "^10.1.0", "babel-jest": "^27.0.6", - "eslint": "^7.30.0", + "eslint": "^7.31.0", "eslint-plugin-import": "~2.23.4", "eslint-plugin-jsx-a11y": "~6.4.1", "eslint-plugin-promise": "~5.1.0", diff --git a/yarn.lock b/yarn.lock index efc86cad9..f1dde367b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1092,10 +1092,10 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== -"@eslint/eslintrc@^0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.2.tgz#f63d0ef06f5c0c57d76c4ab5f63d3835c51b0179" - integrity sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg== +"@eslint/eslintrc@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" + integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== dependencies: ajv "^6.12.4" debug "^4.1.1" @@ -4450,13 +4450,13 @@ eslint@^2.7.0: text-table "~0.2.0" user-home "^2.0.0" -eslint@^7.30.0: - version "7.30.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.30.0.tgz#6d34ab51aaa56112fd97166226c9a97f505474f8" - integrity sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg== +eslint@^7.31.0: + version "7.31.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.31.0.tgz#f972b539424bf2604907a970860732c5d99d3aca" + integrity sha512-vafgJpSh2ia8tnTkNUkwxGmnumgckLh5aAbLa1xRmIn9+owi8qBNGKL+B881kNKNTy7FFqTEkpNkUvmw0n6PkA== dependencies: "@babel/code-frame" "7.12.11" - "@eslint/eslintrc" "^0.4.2" + "@eslint/eslintrc" "^0.4.3" "@humanwhocodes/config-array" "^0.5.0" ajv "^6.10.0" chalk "^4.0.0" From 6f569c7bbd6982008da65df7524f4746ac67d18c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Jul 2021 22:24:16 +0900 Subject: [PATCH 02/11] Bump json-ld-preloaded from 3.1.5 to 3.1.6 (#16522) Bumps [json-ld-preloaded](https://github.com/ruby-rdf/json-ld-preloaded) from 3.1.5 to 3.1.6. - [Release notes](https://github.com/ruby-rdf/json-ld-preloaded/releases) - [Commits](https://github.com/ruby-rdf/json-ld-preloaded/compare/3.1.5...3.1.6) --- updated-dependencies: - dependency-name: json-ld-preloaded dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3db3ea786..7147328af 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -301,7 +301,7 @@ GEM multi_json (~> 1.14) rack (~> 2.0) rdf (~> 3.1) - json-ld-preloaded (3.1.5) + json-ld-preloaded (3.1.6) json-ld (~> 3.1) rdf (~> 3.1) jsonapi-renderer (0.2.2) @@ -480,7 +480,7 @@ GEM thor (~> 1.0) rainbow (3.0.0) rake (13.0.3) - rdf (3.1.13) + rdf (3.1.15) hamster (~> 3.0) link_header (~> 0.0, >= 0.0.8) rdf-normalize (0.4.0) From b89591453dc21adece64fe828a6f16f266e06403 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Jul 2021 22:24:41 +0900 Subject: [PATCH 03/11] Bump css-loader from 5.2.6 to 5.2.7 (#16500) Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 5.2.6 to 5.2.7. - [Release notes](https://github.com/webpack-contrib/css-loader/releases) - [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md) - [Commits](https://github.com/webpack-contrib/css-loader/compare/v5.2.6...v5.2.7) --- updated-dependencies: - dependency-name: css-loader dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 20fd10369..77b145aed 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "color-blend": "^3.0.1", "compression-webpack-plugin": "^6.1.1", "cross-env": "^7.0.3", - "css-loader": "^5.2.6", + "css-loader": "^5.2.7", "cssnano": "^4.1.11", "detect-passive-events": "^2.0.3", "dotenv": "^9.0.2", diff --git a/yarn.lock b/yarn.lock index f1dde367b..c77b672d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3460,10 +3460,10 @@ css-list-helpers@^1.0.1: dependencies: tcomb "^2.5.0" -css-loader@^5.2.6: - version "5.2.6" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.2.6.tgz#c3c82ab77fea1f360e587d871a6811f4450cc8d1" - integrity sha512-0wyN5vXMQZu6BvjbrPdUJvkCzGEO24HC7IS7nW4llc6BBFC+zwR9CKtYGv63Puzsg10L/o12inMY5/2ByzfD6w== +css-loader@^5.2.7: + version "5.2.7" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.2.7.tgz#9b9f111edf6fb2be5dc62525644cbc9c232064ae" + integrity sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg== dependencies: icss-utils "^5.1.0" loader-utils "^2.0.0" From 6994c57fed2e7d7668a3bb8e25ee03f810637dd6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Jul 2021 22:24:57 +0900 Subject: [PATCH 04/11] Bump rubocop-rails from 2.11.2 to 2.11.3 (#16494) Bumps [rubocop-rails](https://github.com/rubocop/rubocop-rails) from 2.11.2 to 2.11.3. - [Release notes](https://github.com/rubocop/rubocop-rails/releases) - [Changelog](https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md) - [Commits](https://github.com/rubocop/rubocop-rails/compare/v2.11.2...v2.11.3) --- updated-dependencies: - dependency-name: rubocop-rails dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 7147328af..b6e5a12a0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -401,7 +401,7 @@ GEM parallel (1.20.1) parallel_tests (3.7.0) parallel - parser (3.0.1.1) + parser (3.0.2.0) ast (~> 2.4.1) parslet (2.0.0) pastel (0.8.0) @@ -534,7 +534,7 @@ GEM unicode-display_width (>= 1.4.0, < 3.0) rubocop-ast (1.7.0) parser (>= 3.0.1.1) - rubocop-rails (2.11.2) + rubocop-rails (2.11.3) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.7.0, < 2.0) From b16d220ec99ddac487bb93a7d9ad7c86a82432ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Jul 2021 22:25:09 +0900 Subject: [PATCH 05/11] Bump oj from 3.11.8 to 3.12.1 (#16493) Bumps [oj](https://github.com/ohler55/oj) from 3.11.8 to 3.12.1. - [Release notes](https://github.com/ohler55/oj/releases) - [Changelog](https://github.com/ohler55/oj/blob/develop/CHANGELOG.md) - [Commits](https://github.com/ohler55/oj/compare/v3.11.8...v3.12.1) --- updated-dependencies: - dependency-name: oj dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index e80312047..5f76abbb7 100644 --- a/Gemfile +++ b/Gemfile @@ -62,7 +62,7 @@ gem 'link_header', '~> 0.0' gem 'mime-types', '~> 3.3.1', require: 'mime/types/columnar' gem 'nokogiri', '~> 1.11' gem 'nsa', '~> 0.2' -gem 'oj', '~> 3.11' +gem 'oj', '~> 3.12' gem 'ox', '~> 2.14' gem 'parslet' gem 'parallel', '~> 1.20' diff --git a/Gemfile.lock b/Gemfile.lock index b6e5a12a0..eaea9ea63 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -374,7 +374,7 @@ GEM concurrent-ruby (~> 1.0, >= 1.0.2) sidekiq (>= 3.5) statsd-ruby (~> 1.4, >= 1.4.0) - oj (3.11.8) + oj (3.12.1) omniauth (1.9.1) hashie (>= 3.4.6) rack (>= 1.6.2, < 3) @@ -733,7 +733,7 @@ DEPENDENCIES net-ldap (~> 0.17) nokogiri (~> 1.11) nsa (~> 0.2) - oj (~> 3.11) + oj (~> 3.12) omniauth (~> 1.9) omniauth-cas (~> 2.0) omniauth-rails_csrf_protection (~> 0.1) From c1d62c4c01900daaac58ccd53dc133d66d2a2e06 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Jul 2021 22:25:19 +0900 Subject: [PATCH 06/11] Bump ws from 7.5.2 to 7.5.3 (#16486) Bumps [ws](https://github.com/websockets/ws) from 7.5.2 to 7.5.3. - [Release notes](https://github.com/websockets/ws/releases) - [Commits](https://github.com/websockets/ws/compare/7.5.2...7.5.3) --- updated-dependencies: - dependency-name: ws dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 77b145aed..b1d2fa3c1 100644 --- a/package.json +++ b/package.json @@ -168,7 +168,7 @@ "webpack-cli": "^3.3.12", "webpack-merge": "^5.8.0", "wicg-inert": "^3.1.1", - "ws": "^7.5.2" + "ws": "^7.5.3" }, "devDependencies": { "@testing-library/jest-dom": "^5.14.1", diff --git a/yarn.lock b/yarn.lock index c77b672d8..9383a2ae2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11720,10 +11720,10 @@ ws@^6.2.1: dependencies: async-limiter "~1.0.0" -ws@^7.2.3, ws@^7.3.1, ws@^7.5.2: - version "7.5.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.2.tgz#09cc8fea3bec1bc5ed44ef51b42f945be36900f6" - integrity sha512-lkF7AWRicoB9mAgjeKbGqVUekLnSNO4VjKVnuPHpQeOxZOErX6BPXwJk70nFslRCEEA8EVW7ZjKwXaP9N+1sKQ== +ws@^7.2.3, ws@^7.3.1, ws@^7.5.3: + version "7.5.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" + integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== xml-name-validator@^3.0.0: version "3.0.0" From d8629e7b86b6fcaedc8b31de57dd95e85fe4fb04 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 21 Jul 2021 18:34:39 +0200 Subject: [PATCH 07/11] Add logging of S3-related errors (#16381) --- app/controllers/api/base_controller.rb | 7 ++++++- app/controllers/application_controller.rb | 7 ++++++- app/lib/activitypub/activity/create.rb | 8 ++++---- app/services/backup_service.rb | 4 ++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 85f4cc768..b863d8643 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -40,7 +40,12 @@ class Api::BaseController < ApplicationController render json: { error: 'This action is not allowed' }, status: 403 end - rescue_from Mastodon::RaceConditionError, Seahorse::Client::NetworkingError, Stoplight::Error::RedLight do + rescue_from Seahorse::Client::NetworkingError do |e| + Rails.logger.warn "Storage server error: #{e}" + render json: { error: 'There was a temporary problem serving your request, please try again' }, status: 503 + end + + rescue_from Mastodon::RaceConditionError, Stoplight::Error::RedLight do render json: { error: 'There was a temporary problem serving your request, please try again' }, status: 503 end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b4fb83661..3d2f8280b 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -26,7 +26,12 @@ class ApplicationController < ActionController::Base rescue_from Mastodon::RateLimitExceededError, with: :too_many_requests rescue_from HTTP::Error, OpenSSL::SSL::SSLError, with: :internal_server_error - rescue_from Mastodon::RaceConditionError, Seahorse::Client::NetworkingError, Stoplight::Error::RedLight, ActiveRecord::SerializationFailure, with: :service_unavailable + rescue_from Mastodon::RaceConditionError, Stoplight::Error::RedLight, ActiveRecord::SerializationFailure, with: :service_unavailable + + rescue_from Seahorse::Client::NetworkingError do |e| + Rails.logger.warn "Storage server error: #{e}" + service_unavailable + end before_action :store_current_location, except: :raise_not_found, unless: :devise_controller? before_action :require_functional!, if: :user_signed_in? diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 9a2960507..504f10a67 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -223,8 +223,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity emoji ||= CustomEmoji.new(domain: @account.domain, shortcode: shortcode, uri: uri) emoji.image_remote_url = image_url emoji.save - rescue Seahorse::Client::NetworkingError - nil + rescue Seahorse::Client::NetworkingError => e + Rails.logger.warn "Error storing emoji: #{e}" end def process_attachments @@ -247,8 +247,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity media_attachment.save rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError RedownloadMediaWorker.perform_in(rand(30..600).seconds, media_attachment.id) - rescue Seahorse::Client::NetworkingError - nil + rescue Seahorse::Client::NetworkingError => e + Rails.logger.warn "Error storing media attachment: #{e}" end end diff --git a/app/services/backup_service.rb b/app/services/backup_service.rb index 6a1575616..037f519d3 100644 --- a/app/services/backup_service.rb +++ b/app/services/backup_service.rb @@ -167,7 +167,7 @@ class BackupService < BaseService io.write(buffer) end end - rescue Errno::ENOENT, Seahorse::Client::NetworkingError - Rails.logger.warn "Could not backup file #{filename}: file not found" + rescue Errno::ENOENT, Seahorse::Client::NetworkingError => e + Rails.logger.warn "Could not backup file #{filename}: #{e}" end end From e9659ae0312d0bf0acf2b55eed5dc688929cae04 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 23 Jul 2021 02:53:17 +0200 Subject: [PATCH 08/11] Fix crashes with Microsoft Translate on Microsoft Edge (#16525) Fixes #16509 Microsoft Edge with translation enabled rewrites the DOM in ways that confuse react and prevent it from working properly. Wrapping the offending parts in a span avoids this issue. --- app/javascript/mastodon/components/status.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index 295e83f58..ccc9067d1 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -309,8 +309,8 @@ class Status extends ImmutablePureComponent { return (
- {status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])} - {status.get('content')} + {status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])} + {status.get('content')}
); From 1d67acb72fa418a456c5e4762425702bfe7702b1 Mon Sep 17 00:00:00 2001 From: Claire Date: Sat, 24 Jul 2021 14:41:46 +0200 Subject: [PATCH 09/11] Fix scoped order warning in RemoveStatusService (#16531) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes “Scoped order is ignored, it's forced to be batch order.” --- app/services/remove_status_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb index b680c8e96..f9c3dcf78 100644 --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@ -102,7 +102,7 @@ class RemoveStatusService < BaseService # because once original status is gone, reblogs will disappear # without us being able to do all the fancy stuff - @status.reblogs.includes(:account).find_each do |reblog| + @status.reblogs.includes(:account).reorder(nil).find_each do |reblog| RemoveStatusService.new.call(reblog, original_removed: true) end end From af08229ff43cf61b6b3eb386ca9d6205d05dc295 Mon Sep 17 00:00:00 2001 From: Claire Date: Sun, 25 Jul 2021 01:13:46 +0200 Subject: [PATCH 10/11] =?UTF-8?q?Fix=20=E2=80=9Copen=E2=80=9D=20link=20of?= =?UTF-8?q?=20media=20modal=20not=20closing=20modal=20(#16524)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/picture_in_picture/components/footer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/picture_in_picture/components/footer.js b/app/javascript/mastodon/features/picture_in_picture/components/footer.js index 1ecb18bf8..f5ce50ac8 100644 --- a/app/javascript/mastodon/features/picture_in_picture/components/footer.js +++ b/app/javascript/mastodon/features/picture_in_picture/components/footer.js @@ -114,7 +114,11 @@ class Footer extends ImmutablePureComponent { return; } - const { status } = this.props; + const { status, onClose } = this.props; + + if (onClose) { + onClose(); + } router.history.push(`/statuses/${status.get('id')}`); } From a8a7066e977cb0aa1988d340ef8b7c542f179b14 Mon Sep 17 00:00:00 2001 From: Claire Date: Sun, 25 Jul 2021 01:14:43 +0200 Subject: [PATCH 11/11] Add confirmation modal when closing media edit modal with unsaved changes (#16518) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add confirmation modal when closing media edit modal with unsaved changes * Move focal point media state to redux so it does not get erased by confirmation dialog * Change upload modal behavior to keep it open while saving changes Instead of closing it immediately and losing changes if they fail to save… * Make it work with react-intl 2.9 --- app/javascript/mastodon/actions/compose.js | 32 ++++++ .../compose/containers/upload_container.js | 5 +- .../ui/components/focal_point_modal.js | 108 ++++++++---------- .../features/ui/components/modal_root.js | 23 +++- .../features/ui/containers/modal_container.js | 16 ++- app/javascript/mastodon/reducers/compose.js | 24 ++++ app/javascript/mastodon/reducers/modal.js | 3 + 7 files changed, 142 insertions(+), 69 deletions(-) diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index 891403969..39d31a88f 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -9,6 +9,7 @@ import { importFetchedAccounts } from './importer'; import { updateTimeline } from './timelines'; import { showAlertForError } from './alerts'; import { showAlert } from './alerts'; +import { openModal } from './modal'; import { defineMessages } from 'react-intl'; let cancelFetchComposeSuggestionsAccounts, cancelFetchComposeSuggestionsTags; @@ -63,6 +64,11 @@ export const COMPOSE_POLL_OPTION_CHANGE = 'COMPOSE_POLL_OPTION_CHANGE'; export const COMPOSE_POLL_OPTION_REMOVE = 'COMPOSE_POLL_OPTION_REMOVE'; export const COMPOSE_POLL_SETTINGS_CHANGE = 'COMPOSE_POLL_SETTINGS_CHANGE'; +export const INIT_MEDIA_EDIT_MODAL = 'INIT_MEDIA_EDIT_MODAL'; + +export const COMPOSE_CHANGE_MEDIA_DESCRIPTION = 'COMPOSE_CHANGE_MEDIA_DESCRIPTION'; +export const COMPOSE_CHANGE_MEDIA_FOCUS = 'COMPOSE_CHANGE_MEDIA_FOCUS'; + const messages = defineMessages({ uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' }, uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' }, @@ -306,6 +312,32 @@ export const uploadThumbnailFail = error => ({ skipLoading: true, }); +export function initMediaEditModal(id) { + return dispatch => { + dispatch({ + type: INIT_MEDIA_EDIT_MODAL, + id, + }); + + dispatch(openModal('FOCAL_POINT', { id })); + }; +}; + +export function onChangeMediaDescription(description) { + return { + type: COMPOSE_CHANGE_MEDIA_DESCRIPTION, + description, + }; +}; + +export function onChangeMediaFocus(focusX, focusY) { + return { + type: COMPOSE_CHANGE_MEDIA_FOCUS, + focusX, + focusY, + }; +}; + export function changeUploadCompose(id, params) { return (dispatch, getState) => { dispatch(changeUploadComposeRequest()); diff --git a/app/javascript/mastodon/features/compose/containers/upload_container.js b/app/javascript/mastodon/features/compose/containers/upload_container.js index 342b0c2a9..05cd2ecc1 100644 --- a/app/javascript/mastodon/features/compose/containers/upload_container.js +++ b/app/javascript/mastodon/features/compose/containers/upload_container.js @@ -1,7 +1,6 @@ import { connect } from 'react-redux'; import Upload from '../components/upload'; -import { undoUploadCompose } from '../../../actions/compose'; -import { openModal } from '../../../actions/modal'; +import { undoUploadCompose, initMediaEditModal } from '../../../actions/compose'; import { submitCompose } from '../../../actions/compose'; const mapStateToProps = (state, { id }) => ({ @@ -15,7 +14,7 @@ const mapDispatchToProps = dispatch => ({ }, onOpenFocalPoint: id => { - dispatch(openModal('FOCAL_POINT', { id })); + dispatch(initMediaEditModal(id)); }, onSubmit (router) { diff --git a/app/javascript/mastodon/features/ui/components/focal_point_modal.js b/app/javascript/mastodon/features/ui/components/focal_point_modal.js index edeb281e9..a2e6b3d16 100644 --- a/app/javascript/mastodon/features/ui/components/focal_point_modal.js +++ b/app/javascript/mastodon/features/ui/components/focal_point_modal.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; import classNames from 'classnames'; -import { changeUploadCompose, uploadThumbnail } from '../../../actions/compose'; +import { changeUploadCompose, uploadThumbnail, onChangeMediaDescription, onChangeMediaFocus } from '../../../actions/compose'; import { getPointerPosition } from '../../video'; import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import IconButton from 'mastodon/components/icon_button'; @@ -27,14 +27,22 @@ import { assetHost } from 'mastodon/utils/config'; const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, apply: { id: 'upload_modal.apply', defaultMessage: 'Apply' }, + applying: { id: 'upload_modal.applying', defaultMessage: 'Applying…' }, placeholder: { id: 'upload_modal.description_placeholder', defaultMessage: 'A quick brown fox jumps over the lazy dog' }, chooseImage: { id: 'upload_modal.choose_image', defaultMessage: 'Choose image' }, + discardMessage: { id: 'confirmations.discard_edit_media.message', defaultMessage: 'You have unsaved changes to the media description or preview, discard them anyway?' }, + discardConfirm: { id: 'confirmations.discard_edit_media.confirm', defaultMessage: 'Discard' }, }); const mapStateToProps = (state, { id }) => ({ media: state.getIn(['compose', 'media_attachments']).find(item => item.get('id') === id), account: state.getIn(['accounts', me]), isUploadingThumbnail: state.getIn(['compose', 'isUploadingThumbnail']), + description: state.getIn(['compose', 'media_modal', 'description']), + focusX: state.getIn(['compose', 'media_modal', 'focusX']), + focusY: state.getIn(['compose', 'media_modal', 'focusY']), + dirty: state.getIn(['compose', 'media_modal', 'dirty']), + is_changing_upload: state.getIn(['compose', 'is_changing_upload']), }); const mapDispatchToProps = (dispatch, { id }) => ({ @@ -43,6 +51,14 @@ const mapDispatchToProps = (dispatch, { id }) => ({ dispatch(changeUploadCompose(id, { description, focus: `${x.toFixed(2)},${y.toFixed(2)}` })); }, + onChangeDescription: (description) => { + dispatch(onChangeMediaDescription(description)); + }, + + onChangeFocus: (focusX, focusY) => { + dispatch(onChangeMediaFocus(focusX, focusY)); + }, + onSelectThumbnail: files => { dispatch(uploadThumbnail(id, files[0])); }, @@ -83,8 +99,8 @@ class ImageLoader extends React.PureComponent { } -export default @connect(mapStateToProps, mapDispatchToProps) -@injectIntl +export default @connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true }) +@(component => injectIntl(component, { withRef: true })) class FocalPointModal extends ImmutablePureComponent { static propTypes = { @@ -92,34 +108,21 @@ class FocalPointModal extends ImmutablePureComponent { account: ImmutablePropTypes.map.isRequired, isUploadingThumbnail: PropTypes.bool, onSave: PropTypes.func.isRequired, + onChangeDescription: PropTypes.func.isRequired, + onChangeFocus: PropTypes.func.isRequired, onSelectThumbnail: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, }; state = { - x: 0, - y: 0, - focusX: 0, - focusY: 0, dragging: false, - description: '', dirty: false, progress: 0, loading: true, ocrStatus: '', }; - componentWillMount () { - this.updatePositionFromMedia(this.props.media); - } - - componentWillReceiveProps (nextProps) { - if (this.props.media.get('id') !== nextProps.media.get('id')) { - this.updatePositionFromMedia(nextProps.media); - } - } - componentWillUnmount () { document.removeEventListener('mousemove', this.handleMouseMove); document.removeEventListener('mouseup', this.handleMouseUp); @@ -164,54 +167,37 @@ class FocalPointModal extends ImmutablePureComponent { const focusX = (x - .5) * 2; const focusY = (y - .5) * -2; - this.setState({ x, y, focusX, focusY, dirty: true }); - } - - updatePositionFromMedia = media => { - const focusX = media.getIn(['meta', 'focus', 'x']); - const focusY = media.getIn(['meta', 'focus', 'y']); - const description = media.get('description') || ''; - - if (focusX && focusY) { - const x = (focusX / 2) + .5; - const y = (focusY / -2) + .5; - - this.setState({ - x, - y, - focusX, - focusY, - description, - dirty: false, - }); - } else { - this.setState({ - x: 0.5, - y: 0.5, - focusX: 0, - focusY: 0, - description, - dirty: false, - }); - } + this.props.onChangeFocus(focusX, focusY); } handleChange = e => { - this.setState({ description: e.target.value, dirty: true }); + this.props.onChangeDescription(e.target.value); } handleKeyDown = (e) => { if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) { e.preventDefault(); e.stopPropagation(); - this.setState({ description: e.target.value, dirty: true }); + this.props.onChangeDescription(e.target.value); this.handleSubmit(); } } handleSubmit = () => { - this.props.onSave(this.state.description, this.state.focusX, this.state.focusY); - this.props.onClose(); + this.props.onSave(this.props.description, this.props.focusX, this.props.focusY); + } + + getCloseConfirmationMessage = () => { + const { intl, dirty } = this.props; + + if (dirty) { + return { + message: intl.formatMessage(messages.discardMessage), + confirm: intl.formatMessage(messages.discardConfirm), + }; + } else { + return null; + } } setRef = c => { @@ -257,7 +243,8 @@ class FocalPointModal extends ImmutablePureComponent { await worker.loadLanguage('eng'); await worker.initialize('eng'); const { data: { text } } = await worker.recognize(media_url); - this.setState({ description: removeExtraLineBreaks(text), dirty: true, detecting: false }); + this.setState({ detecting: false }); + this.props.onChangeDescription(removeExtraLineBreaks(text)); await worker.terminate(); })().catch((e) => { if (refreshCache) { @@ -274,7 +261,6 @@ class FocalPointModal extends ImmutablePureComponent { handleThumbnailChange = e => { if (e.target.files.length > 0) { - this.setState({ dirty: true }); this.props.onSelectThumbnail(e.target.files); } } @@ -288,8 +274,10 @@ class FocalPointModal extends ImmutablePureComponent { } render () { - const { media, intl, account, onClose, isUploadingThumbnail } = this.props; - const { x, y, dragging, description, dirty, detecting, progress, ocrStatus } = this.state; + const { media, intl, account, onClose, isUploadingThumbnail, description, focusX, focusY, dirty, is_changing_upload } = this.props; + const { dragging, detecting, progress, ocrStatus } = this.state; + const x = (focusX / 2) + .5; + const y = (focusY / -2) + .5; const width = media.getIn(['meta', 'original', 'width']) || null; const height = media.getIn(['meta', 'original', 'height']) || null; @@ -344,7 +332,7 @@ class FocalPointModal extends ImmutablePureComponent { accept='image/png,image/jpeg' onChange={this.handleThumbnailChange} style={{ display: 'none' }} - disabled={isUploadingThumbnail} + disabled={isUploadingThumbnail || is_changing_upload} /> @@ -363,7 +351,7 @@ class FocalPointModal extends ImmutablePureComponent { value={detecting ? '…' : description} onChange={this.handleChange} onKeyDown={this.handleKeyDown} - disabled={detecting} + disabled={detecting || is_changing_upload} autoFocus /> @@ -373,11 +361,11 @@ class FocalPointModal extends ImmutablePureComponent {
- +
-