From 66acf8203b87bc88402edd7eec9ec00f48bbc42c Mon Sep 17 00:00:00 2001 From: Daigo 3 Dango Date: Thu, 16 Jul 2020 10:01:34 -1000 Subject: [PATCH 01/19] Stop using heroku-buildpack-nodejs (#14341) heroku-buildpack-ruby started to install Node 12 by default. This makes it possible to run Mastodon without heroku-buildpack-nodejs. --- app.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/app.json b/app.json index 211f17d812e22..e4f7cf403ec4a 100644 --- a/app.json +++ b/app.json @@ -88,9 +88,6 @@ { "url": "https://github.com/heroku/heroku-buildpack-apt" }, - { - "url": "heroku/nodejs" - }, { "url": "heroku/ruby" } From d668fd8b83fdbb38291927762722d47306788ab1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Jul 2020 07:06:45 +0200 Subject: [PATCH 02/19] Bump lodash from 4.17.15 to 4.17.19 (#14321) Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19) 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 178c18d0ed248..37c6d97d3c753 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "intl-relativeformat": "^6.4.3", "is-nan": "^1.3.0", "js-yaml": "^3.13.1", - "lodash": "^4.17.14", + "lodash": "^4.17.19", "mark-loader": "^0.1.6", "marky": "^1.2.1", "mini-css-extract-plugin": "^0.9.0", diff --git a/yarn.lock b/yarn.lock index 5b71b6b79b423..5449ae10ff52a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6969,10 +6969,10 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.3.0, lodash@~4.17.12: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.3.0, lodash@~4.17.12: + version "4.17.19" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" + integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== loglevel@^1.6.8: version "1.6.8" From 85bc0f9639c9c1ecccfa6963929b6c405fb8452c Mon Sep 17 00:00:00 2001 From: ThibG Date: Fri, 17 Jul 2020 07:07:18 +0200 Subject: [PATCH 03/19] Fix audio player controls color in mastodon-light theme (#14338) Fixes #14337 The new audio player sets the background and foreground colors automatically based on the thumbnail of the audio file, but the mastodon-light theme overrides the controls' colors with a hardcoded color, which sometimes make them unreadable. --- app/javascript/styles/mastodon-light/diff.scss | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index 7a846bcc678ff..8c8d69fc47e28 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -767,10 +767,3 @@ html { .compose-form .compose-form__warning { box-shadow: none; } - -.audio-player .video-player__controls button, -.audio-player .video-player__time-sep, -.audio-player .video-player__time-current, -.audio-player .video-player__time-total { - color: $primary-text-color; -} From 322d74fc2aa9db2d05e5bad944661c6edf1660e1 Mon Sep 17 00:00:00 2001 From: ThibG Date: Fri, 17 Jul 2020 07:07:54 +0200 Subject: [PATCH 04/19] Fix boosted toots from blocked account not being retroactively removed from TL (#14339) * Fix boosted toots from blocked account not being retroactively removed from TL Fixes #14301 * Add test for clear_from_timeline --- app/lib/feed_manager.rb | 8 +++++++- spec/lib/feed_manager_spec.rb | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 53ff31f5ecb19..96fa6cfc06ea5 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -124,9 +124,15 @@ class FeedManager end def clear_from_timeline(account, target_account) + # Clear from timeline all statuses from or mentionning target_account timeline_key = key(:home, account.id) timeline_status_ids = redis.zrange(timeline_key, 0, -1) - target_statuses = Status.where(id: timeline_status_ids, account: target_account) + statuses = Status.where(id: timeline_status_ids).select(:id, :reblog_of_id, :account_id).to_a + reblogged_ids = Status.where(id: statuses.map(&:reblog_of_id).compact, account: target_account).pluck(:id) + with_mentions_ids = Mention.active.where(status_id: statuses.flat_map { |s| [s.id, s.reblog_of_id] }.compact, account: target_account).pluck(:status_id) + target_statuses = statuses.filter do |status| + status.account_id == target_account.id || reblogged_ids.include?(status.reblog_of_id) || with_mentions_ids.include?(status.id) || with_mentions_ids.include?(status.reblog_of_id) + end target_statuses.each do |status| unpush_from_home(account, status) diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb index b996997b1367e..22eddd2ab6e31 100644 --- a/spec/lib/feed_manager_spec.rb +++ b/spec/lib/feed_manager_spec.rb @@ -429,4 +429,29 @@ RSpec.describe FeedManager do expect(Redis.current).to have_received(:publish).with("timeline:#{receiver.id}", deletion) end end + + describe '#clear_from_timeline' do + let(:account) { Fabricate(:account) } + let(:followed_account) { Fabricate(:account) } + let(:target_account) { Fabricate(:account) } + let(:status_1) { Fabricate(:status, account: followed_account) } + let(:status_2) { Fabricate(:status, account: target_account) } + let(:status_3) { Fabricate(:status, account: followed_account, mentions: [Fabricate(:mention, account: target_account)]) } + let(:status_4) { Fabricate(:status, mentions: [Fabricate(:mention, account: target_account)]) } + let(:status_5) { Fabricate(:status, account: followed_account, reblog: status_4) } + let(:status_6) { Fabricate(:status, account: followed_account, reblog: status_2) } + let(:status_7) { Fabricate(:status, account: followed_account) } + + before do + [status_1, status_3, status_5, status_6, status_7].each do |status| + Redis.current.zadd("feed:home:#{account.id}", status.id, status.id) + end + end + + it 'correctly cleans the timeline' do + FeedManager.instance.clear_from_timeline(account, target_account) + + expect(Redis.current.zrange("feed:home:#{account.id}", 0, -1)).to eq [status_1.id.to_s, status_7.id.to_s] + end + end end From 17b1d71536609c6deabcf3b13ec9be0ec9fd793f Mon Sep 17 00:00:00 2001 From: Sasha Sorokin Date: Fri, 17 Jul 2020 12:08:23 +0700 Subject: [PATCH 05/19] Fix following_counter plural to include "one" (#14342) That should've worked just fine, but unfortunately, Crowdin wasn't able to pick up on our non-existent "one" category, thus appending empty translation block to people's translations. Empty block WILL BE used by any ICU FormatMessage library, thus resulting in an empty translation for "one" category, and that requires immediate fix. This commit duplicates contents of the "other" plural category. --- app/javascript/mastodon/components/common_counter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/mastodon/components/common_counter.js b/app/javascript/mastodon/components/common_counter.js index 4fdf3babfdad1..e10cd9b765206 100644 --- a/app/javascript/mastodon/components/common_counter.js +++ b/app/javascript/mastodon/components/common_counter.js @@ -37,7 +37,7 @@ export function counterRenderer(counterType, isBold = true) { return (displayNumber, pluralReady) => ( Date: Sat, 18 Jul 2020 18:55:36 +0200 Subject: [PATCH 06/19] Fix keyboard navigation in scrollable lists (#14348) Fixes #14347 --- app/javascript/mastodon/components/scrollable_list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/mastodon/components/scrollable_list.js b/app/javascript/mastodon/components/scrollable_list.js index 35740f226a462..2689b18ef3dba 100644 --- a/app/javascript/mastodon/components/scrollable_list.js +++ b/app/javascript/mastodon/components/scrollable_list.js @@ -20,7 +20,7 @@ const mapStateToProps = (state, { scrollKey }) => { }; }; -export default @connect(mapStateToProps) +export default @connect(mapStateToProps, null, null, { forwardRef: true }) class ScrollableList extends PureComponent { static contextTypes = { From f2d977914efe0707ac6258c23ebfc68d5bba24e6 Mon Sep 17 00:00:00 2001 From: David Cook Date: Sat, 18 Jul 2020 12:00:59 -0500 Subject: [PATCH 07/19] Set bundle config in local file, and set path (#14351) --- .circleci/config.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9f43a057356bb..862fa126b7f08 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -72,11 +72,12 @@ aliases: - run: name: Set bundler settings command: | - bundle config clean 'true' - bundle config deployment 'true' - bundle config with 'pam_authentication' - bundle config without 'development production' - bundle config frozen 'true' + bundle config --local clean 'true' + bundle config --local deployment 'true' + bundle config --local with 'pam_authentication' + bundle config --local without 'development production' + bundle config --local frozen 'true' + bundle config --local path $BUNDLE_PATH - run: name: Install bundler dependencies command: bundle check || (bundle install && bundle clean) From d87958e1775e6aa99b52d21bd8976cd3c76067d6 Mon Sep 17 00:00:00 2001 From: mayaeh Date: Sun, 19 Jul 2020 02:01:16 +0900 Subject: [PATCH 08/19] ran `yarn manage:translations` (#14344) --- app/javascript/mastodon/locales/ar.json | 2 +- app/javascript/mastodon/locales/ast.json | 2 +- app/javascript/mastodon/locales/bg.json | 2 +- app/javascript/mastodon/locales/bn.json | 2 +- app/javascript/mastodon/locales/cs.json | 2 +- app/javascript/mastodon/locales/cy.json | 2 +- app/javascript/mastodon/locales/da.json | 2 +- .../mastodon/locales/defaultMessages.json | 18 +++++++++++++++++- app/javascript/mastodon/locales/en.json | 2 +- app/javascript/mastodon/locales/et.json | 2 +- app/javascript/mastodon/locales/eu.json | 2 +- app/javascript/mastodon/locales/fi.json | 2 +- app/javascript/mastodon/locales/ga.json | 2 +- app/javascript/mastodon/locales/he.json | 2 +- app/javascript/mastodon/locales/hi.json | 2 +- app/javascript/mastodon/locales/hr.json | 2 +- app/javascript/mastodon/locales/id.json | 2 +- app/javascript/mastodon/locales/io.json | 2 +- app/javascript/mastodon/locales/is.json | 2 +- app/javascript/mastodon/locales/ka.json | 2 +- app/javascript/mastodon/locales/kab.json | 2 +- app/javascript/mastodon/locales/kk.json | 2 +- app/javascript/mastodon/locales/kn.json | 2 +- app/javascript/mastodon/locales/ku.json | 2 +- app/javascript/mastodon/locales/lt.json | 2 +- app/javascript/mastodon/locales/lv.json | 2 +- app/javascript/mastodon/locales/mk.json | 2 +- app/javascript/mastodon/locales/ml.json | 2 +- app/javascript/mastodon/locales/mr.json | 2 +- app/javascript/mastodon/locales/ms.json | 2 +- app/javascript/mastodon/locales/nl.json | 2 +- app/javascript/mastodon/locales/nn.json | 2 +- app/javascript/mastodon/locales/no.json | 2 +- app/javascript/mastodon/locales/oc.json | 2 +- app/javascript/mastodon/locales/pl.json | 2 +- app/javascript/mastodon/locales/ro.json | 2 +- app/javascript/mastodon/locales/sc.json | 2 +- app/javascript/mastodon/locales/sk.json | 2 +- app/javascript/mastodon/locales/sl.json | 2 +- app/javascript/mastodon/locales/sr-Latn.json | 2 +- app/javascript/mastodon/locales/sr.json | 2 +- app/javascript/mastodon/locales/sv.json | 2 +- app/javascript/mastodon/locales/szl.json | 2 +- app/javascript/mastodon/locales/ta.json | 2 +- app/javascript/mastodon/locales/tai.json | 2 +- app/javascript/mastodon/locales/te.json | 2 +- app/javascript/mastodon/locales/th.json | 2 +- app/javascript/mastodon/locales/tr.json | 2 +- app/javascript/mastodon/locales/ug.json | 2 +- app/javascript/mastodon/locales/uk.json | 2 +- app/javascript/mastodon/locales/ur.json | 2 +- app/javascript/mastodon/locales/zh-HK.json | 2 +- app/javascript/mastodon/locales/zh-TW.json | 2 +- 53 files changed, 69 insertions(+), 53 deletions(-) diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index a0b540432e819..548471edfd88b 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -16,7 +16,7 @@ "account.followers": "مُتابِعون", "account.followers.empty": "لا أحد يتبع هذا الحساب بعد.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "هذا الحساب لا يتبع أحدًا بعد.", "account.follows_you": "يتابعك", "account.hide_reblogs": "إخفاء ترقيات @{name}", diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json index 491faa0570dd2..6c6232262effd 100644 --- a/app/javascript/mastodon/locales/ast.json +++ b/app/javascript/mastodon/locales/ast.json @@ -16,7 +16,7 @@ "account.followers": "Siguidores", "account.followers.empty": "Naide sigue a esti usuariu entá.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Esti usuariu entá nun sigue a naide.", "account.follows_you": "Síguete", "account.hide_reblogs": "Anubrir les comparticiones de @{name}", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 472c88afc74cf..16520dbad5281 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -16,7 +16,7 @@ "account.followers": "Последователи", "account.followers.empty": "Все още никой не следва този потребител.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Този потребител все още не следва никого.", "account.follows_you": "Твой последовател", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/bn.json b/app/javascript/mastodon/locales/bn.json index b41cdf16d17d4..7de1a10221b24 100644 --- a/app/javascript/mastodon/locales/bn.json +++ b/app/javascript/mastodon/locales/bn.json @@ -16,7 +16,7 @@ "account.followers": "অনুসরণকারী", "account.followers.empty": "এই সদস্যকে এখনো কেউ অনুসরণ করে না।.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "এই সদস্য কাওকে এখনো অনুসরণ করেন না.", "account.follows_you": "আপনাকে অনুসরণ করে", "account.hide_reblogs": "@{name}'র সমর্থনগুলি লুকিয়ে ফেলুন", diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index f991b7a25c550..0ddd18de898a7 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -16,7 +16,7 @@ "account.followers": "Sledující", "account.followers.empty": "Tohoto uživatele ještě nikdo nesleduje.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Tento uživatel ještě nikoho nesleduje.", "account.follows_you": "Sleduje vás", "account.hide_reblogs": "Skrýt boosty od uživatele @{name}", diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json index 984237a3291d4..312a0f97a2706 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -16,7 +16,7 @@ "account.followers": "Dilynwyr", "account.followers.empty": "Nid oes neb yn dilyn y defnyddiwr hwn eto.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Nid yw'r defnyddiwr hwn yn dilyn unrhyw un eto.", "account.follows_you": "Yn eich dilyn chi", "account.hide_reblogs": "Cuddio bwstiau o @{name}", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index e59f5283c20bd..a0fb354e6692f 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -16,7 +16,7 @@ "account.followers": "Følgere", "account.followers.empty": "Der er endnu ingen der følger denne bruger.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Denne bruger følger endnu ikke nogen.", "account.follows_you": "Følger dig", "account.hide_reblogs": "Skjul fremhævelserne fra @{name}", diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index 179cfd6bc7d88..bd9ebbc0de960 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -146,7 +146,7 @@ "id": "account.statuses_counter" }, { - "defaultMessage": "{count, plural, other {{counter} Following}}", + "defaultMessage": "{count, plural, one {{counter} Following} other {{counter} Following}}", "id": "account.following_counter" }, { @@ -2659,6 +2659,22 @@ "defaultMessage": "Boost", "id": "status.reblog" }, + { + "defaultMessage": "Public", + "id": "privacy.public.short" + }, + { + "defaultMessage": "Unlisted", + "id": "privacy.unlisted.short" + }, + { + "defaultMessage": "Followers-only", + "id": "privacy.private.short" + }, + { + "defaultMessage": "Direct", + "id": "privacy.direct.short" + }, { "defaultMessage": "You can press {combo} to skip this next time", "id": "boost_modal.combo" diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 529c233971889..381ff028bbaab 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json index fc00a6270656e..558fe38de2590 100644 --- a/app/javascript/mastodon/locales/et.json +++ b/app/javascript/mastodon/locales/et.json @@ -16,7 +16,7 @@ "account.followers": "Jälgijad", "account.followers.empty": "Keegi ei jälgi seda kasutajat veel.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "See kasutaja ei jälgi veel kedagi.", "account.follows_you": "Jälgib Teid", "account.hide_reblogs": "Peida upitused kasutajalt @{name}", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index 0a8043d4d399c..09471ff2ab429 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -16,7 +16,7 @@ "account.followers": "Jarraitzaileak", "account.followers.empty": "Ez du inork erabiltzaile hau jarraitzen oraindik.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Erabiltzaile honek ez du inor jarraitzen oraindik.", "account.follows_you": "Jarraitzen dizu", "account.hide_reblogs": "Ezkutatu @{name}(r)en bultzadak", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 364427e6537f4..44589aa4afb3e 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -16,7 +16,7 @@ "account.followers": "Seuraajaa", "account.followers.empty": "Tällä käyttäjällä ei ole vielä seuraajia.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Tämä käyttäjä ei vielä seuraa ketään.", "account.follows_you": "Seuraa sinua", "account.hide_reblogs": "Piilota buustaukset käyttäjältä @{name}", diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json index 5a27ed96c4faf..5de7b27a50b6c 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index 81e713dc3cd2e..91fce039f5bb0 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -16,7 +16,7 @@ "account.followers": "עוקבים", "account.followers.empty": "אף אחד לא עוקב אחר המשתמש הזה עדיין.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "משתמש זה לא עוקב אחר אף אחד עדיין.", "account.follows_you": "במעקב אחריך", "account.hide_reblogs": "להסתיר הידהודים מאת @{name}", diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json index 4cc12830fd34d..ff207d6406f64 100644 --- a/app/javascript/mastodon/locales/hi.json +++ b/app/javascript/mastodon/locales/hi.json @@ -16,7 +16,7 @@ "account.followers": "फॉलोवर", "account.followers.empty": "कोई भी इस यूज़र् को फ़ॉलो नहीं करता है", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "यह यूज़र् अभी तक किसी को फॉलो नहीं करता है।", "account.follows_you": "आपको फॉलो करता है", "account.hide_reblogs": "@{name} के बूस्ट छुपाएं", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json index a7e13b2eb100f..7179bc5364092 100644 --- a/app/javascript/mastodon/locales/hr.json +++ b/app/javascript/mastodon/locales/hr.json @@ -16,7 +16,7 @@ "account.followers": "Sljedbenici", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "te slijedi", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index 5b0f345af9d76..91ad76e039476 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -16,7 +16,7 @@ "account.followers": "Pengikut", "account.followers.empty": "Tidak ada satupun yang mengkuti pengguna ini saat ini.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Pengguna ini belum mengikuti siapapun.", "account.follows_you": "Mengikuti anda", "account.hide_reblogs": "Sembunyikan boosts dari @{name}", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index 45e74b6751723..e79bee21da7e5 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -16,7 +16,7 @@ "account.followers": "Sequanti", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Sequas tu", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json index 4a281cf805b8d..72d8fefaf6119 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -16,7 +16,7 @@ "account.followers": "Fylgjendur", "account.followers.empty": "Ennþá fylgist enginn með þessum notanda.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Þessi notandi fylgist ennþá ekki með neinum.", "account.follows_you": "Fylgir þér", "account.hide_reblogs": "Fela endurbirtingar fyrir @{name}", diff --git a/app/javascript/mastodon/locales/ka.json b/app/javascript/mastodon/locales/ka.json index 36f27e69d91d7..0051fee1fed6a 100644 --- a/app/javascript/mastodon/locales/ka.json +++ b/app/javascript/mastodon/locales/ka.json @@ -16,7 +16,7 @@ "account.followers": "მიმდევრები", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "მოგყვებათ", "account.hide_reblogs": "დაიმალოს ბუსტები @{name}-სგან", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index dceb434d3fe96..05f72596b5375 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -16,7 +16,7 @@ "account.followers": "Imeḍfaren", "account.followers.empty": "Ar tura, ulac yiwen i yeṭṭafaṛen amseqdac-agi.", "account.followers_counter": "{count, plural, one {{count} n umeḍfar} other {{count} n imeḍfaren}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Ar tura, amseqdac-agi ur yeṭṭafaṛ yiwen.", "account.follows_you": "Yeṭṭafaṛ-ik", "account.hide_reblogs": "Ffer ayen i ibeṭṭu @{name}", diff --git a/app/javascript/mastodon/locales/kk.json b/app/javascript/mastodon/locales/kk.json index d7adf58362a17..322c15fff69dc 100644 --- a/app/javascript/mastodon/locales/kk.json +++ b/app/javascript/mastodon/locales/kk.json @@ -16,7 +16,7 @@ "account.followers": "Оқырмандар", "account.followers.empty": "Әлі ешкім жазылмаған.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Ешкімге жазылмапты.", "account.follows_you": "Сізге жазылыпты", "account.hide_reblogs": "@{name} атты қолданушының әрекеттерін жасыру", diff --git a/app/javascript/mastodon/locales/kn.json b/app/javascript/mastodon/locales/kn.json index 43738ba70e902..e9618e0f2e91c 100644 --- a/app/javascript/mastodon/locales/kn.json +++ b/app/javascript/mastodon/locales/kn.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/ku.json b/app/javascript/mastodon/locales/ku.json index 36f55e80025c8..e5d833fe87465 100644 --- a/app/javascript/mastodon/locales/ku.json +++ b/app/javascript/mastodon/locales/ku.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index 43738ba70e902..e9618e0f2e91c 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index 01fe7a07c3ce0..2812760a658a2 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -16,7 +16,7 @@ "account.followers": "Sekotāji", "account.followers.empty": "Šim lietotājam nav sekotāju.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Šis lietotājs pagaidām nevienam neseko.", "account.follows_you": "Seko tev", "account.hide_reblogs": "Paslēpt paceltos ierakstus no lietotāja @{name}", diff --git a/app/javascript/mastodon/locales/mk.json b/app/javascript/mastodon/locales/mk.json index 7e9c0dc426941..2bb9a2e2ac778 100644 --- a/app/javascript/mastodon/locales/mk.json +++ b/app/javascript/mastodon/locales/mk.json @@ -16,7 +16,7 @@ "account.followers": "Следбеници", "account.followers.empty": "Никој не го следи овој корисник сеуште.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Корисникот не следи никој сеуште.", "account.follows_you": "Те следи тебе", "account.hide_reblogs": "Сокриј буст од @{name}", diff --git a/app/javascript/mastodon/locales/ml.json b/app/javascript/mastodon/locales/ml.json index 78dced5320e4f..4a390ad70fb57 100644 --- a/app/javascript/mastodon/locales/ml.json +++ b/app/javascript/mastodon/locales/ml.json @@ -16,7 +16,7 @@ "account.followers": "പിന്തുടരുന്നവർ", "account.followers.empty": "ഈ ഉപയോക്താവിനെ ആരും ഇതുവരെ പിന്തുടരുന്നില്ല.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "ഈ ഉപയോക്താവ് ആരേയും ഇതുവരെ പിന്തുടരുന്നില്ല.", "account.follows_you": "നിങ്ങളെ പിന്തുടരുന്നു", "account.hide_reblogs": "@{name} ബൂസ്റ്റ് ചെയ്തവ മറയ്കുക", diff --git a/app/javascript/mastodon/locales/mr.json b/app/javascript/mastodon/locales/mr.json index a56d2544a7b0d..5a93ae851bec0 100644 --- a/app/javascript/mastodon/locales/mr.json +++ b/app/javascript/mastodon/locales/mr.json @@ -16,7 +16,7 @@ "account.followers": "अनुयायी", "account.followers.empty": "ह्या वापरकर्त्याचा आतापर्यंत कोणी अनुयायी नाही.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "हा वापरकर्ता अजूनपर्यंत कोणाचा अनुयायी नाही.", "account.follows_you": "तुमचा अनुयायी आहे", "account.hide_reblogs": "@{name} पासून सर्व बूस्ट लपवा", diff --git a/app/javascript/mastodon/locales/ms.json b/app/javascript/mastodon/locales/ms.json index a1948301418d7..5fc7778879347 100644 --- a/app/javascript/mastodon/locales/ms.json +++ b/app/javascript/mastodon/locales/ms.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index ad10bb63ce2ec..73e2b9a1369e2 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -16,7 +16,7 @@ "account.followers": "Volgers", "account.followers.empty": "Niemand volgt nog deze gebruiker.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Deze gebruiker volgt nog niemand.", "account.follows_you": "Volgt jou", "account.hide_reblogs": "Verberg boosts van @{name}", diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json index ed151565d99a3..b567a35330d89 100644 --- a/app/javascript/mastodon/locales/nn.json +++ b/app/javascript/mastodon/locales/nn.json @@ -16,7 +16,7 @@ "account.followers": "Fylgjarar", "account.followers.empty": "Ingen fylgjer denne brukaren enno.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Denne brukaren fylgjer ikkje nokon enno.", "account.follows_you": "Fylgjer deg", "account.hide_reblogs": "Gøym fremhevingar frå @{name}", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index 7ddfea5bc0a02..a15e96fdc2d19 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -16,7 +16,7 @@ "account.followers": "Følgere", "account.followers.empty": "Ingen følger denne brukeren ennå.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Denne brukeren følger ikke noen enda.", "account.follows_you": "Følger deg", "account.hide_reblogs": "Skjul fremhevinger fra @{name}", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index dfee6f157716b..1aa0193a527b0 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -16,7 +16,7 @@ "account.followers": "Seguidors", "account.followers.empty": "Degun sèc pas aqueste utilizaire pel moment.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Aqueste utilizaire sèc pas degun pel moment.", "account.follows_you": "Vos sèc", "account.hide_reblogs": "Rescondre los partatges de @{name}", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index 3755b762c5be7..4e0230b75815b 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -16,7 +16,7 @@ "account.followers": "Śledzący", "account.followers.empty": "Nikt jeszcze nie śledzi tego użytkownika.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Ten użytkownik nie śledzi jeszcze nikogo.", "account.follows_you": "Śledzi Cię", "account.hide_reblogs": "Ukryj podbicia od @{name}", diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json index c00eca2974e25..544d6810215dd 100644 --- a/app/javascript/mastodon/locales/ro.json +++ b/app/javascript/mastodon/locales/ro.json @@ -16,7 +16,7 @@ "account.followers": "Urmăritori", "account.followers.empty": "Acest utilizator nu are încă urmăritori.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Acest utilizator nu urmărește pe nimeni încă.", "account.follows_you": "Te urmărește", "account.hide_reblogs": "Ascunde impulsurile de la @{name}", diff --git a/app/javascript/mastodon/locales/sc.json b/app/javascript/mastodon/locales/sc.json index 916576656b278..30a3e33745b1f 100644 --- a/app/javascript/mastodon/locales/sc.json +++ b/app/javascript/mastodon/locales/sc.json @@ -16,7 +16,7 @@ "account.followers": "Sighiduras", "account.followers.empty": "Nemos sighit ancora custa persone.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Custa persone non sighit ancora a nemos.", "account.follows_you": "Ti sighit", "account.hide_reblogs": "Cua is cumpartziduras de @{name}", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index 569a8cd125cd9..4e48d53c84fe2 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -16,7 +16,7 @@ "account.followers": "Sledujúci", "account.followers.empty": "Tohto používateľa ešte nikto nenásleduje.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Tento používateľ ešte nikoho nenasleduje.", "account.follows_you": "Nasleduje ťa", "account.hide_reblogs": "Skry vyzdvihnutia od @{name}", diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json index d13bf5e36daa6..71ba0d1b62297 100644 --- a/app/javascript/mastodon/locales/sl.json +++ b/app/javascript/mastodon/locales/sl.json @@ -16,7 +16,7 @@ "account.followers": "Sledilci", "account.followers.empty": "Nihče ne sledi temu uporabniku.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Ta uporabnik še ne sledi nikomur.", "account.follows_you": "Sledi tebi", "account.hide_reblogs": "Skrij spodbude od @{name}", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index 7a17e9134a57e..d7be7380f5da7 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -16,7 +16,7 @@ "account.followers": "Pratioca", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Prati Vas", "account.hide_reblogs": "Sakrij podrške koje daje korisnika @{name}", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index bcaa45ed08403..7c42f0e8a015e 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -16,7 +16,7 @@ "account.followers": "Пратиоци", "account.followers.empty": "Тренутно нико не прати овог корисника.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Корисник тренутно не прати никога.", "account.follows_you": "Прати Вас", "account.hide_reblogs": "Сакриј подршке које даје корисника @{name}", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index a0d0807abb732..c9251d73c53c5 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -16,7 +16,7 @@ "account.followers": "Följare", "account.followers.empty": "Ingen följer denna användare än.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Denna användare följer inte någon än.", "account.follows_you": "Följer dig", "account.hide_reblogs": "Dölj knuffar från @{name}", diff --git a/app/javascript/mastodon/locales/szl.json b/app/javascript/mastodon/locales/szl.json index 36f55e80025c8..e5d833fe87465 100644 --- a/app/javascript/mastodon/locales/szl.json +++ b/app/javascript/mastodon/locales/szl.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/ta.json b/app/javascript/mastodon/locales/ta.json index 9caef05825dc4..28f03f7811300 100644 --- a/app/javascript/mastodon/locales/ta.json +++ b/app/javascript/mastodon/locales/ta.json @@ -16,7 +16,7 @@ "account.followers": "பின்தொடர்பவர்கள்", "account.followers.empty": "இதுவரை யாரும் இந்த பயனரைப் பின்தொடரவில்லை.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "இந்த பயனர் இதுவரை யாரையும் பின்தொடரவில்லை.", "account.follows_you": "உங்களைப் பின்தொடர்கிறார்", "account.hide_reblogs": "இருந்து ஊக்கியாக மறை @{name}", diff --git a/app/javascript/mastodon/locales/tai.json b/app/javascript/mastodon/locales/tai.json index 36f55e80025c8..e5d833fe87465 100644 --- a/app/javascript/mastodon/locales/tai.json +++ b/app/javascript/mastodon/locales/tai.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json index a57efd7c614cc..4763dcbd30915 100644 --- a/app/javascript/mastodon/locales/te.json +++ b/app/javascript/mastodon/locales/te.json @@ -16,7 +16,7 @@ "account.followers": "అనుచరులు", "account.followers.empty": "ఈ వినియోగదారుడిని ఇంకా ఎవరూ అనుసరించడంలేదు.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "ఈ వినియోగదారి ఇంకా ఎవరినీ అనుసరించడంలేదు.", "account.follows_you": "మిమ్మల్ని అనుసరిస్తున్నారు", "account.hide_reblogs": "@{name} నుంచి బూస్ట్ లను దాచిపెట్టు", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 5852ec5caa217..a5c6b07cde640 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -16,7 +16,7 @@ "account.followers": "ผู้ติดตาม", "account.followers.empty": "ยังไม่มีใครติดตามผู้ใช้นี้", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "ผู้ใช้นี้ยังไม่ได้ติดตามใคร", "account.follows_you": "ติดตามคุณ", "account.hide_reblogs": "ซ่อนการดันจาก @{name}", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index a5bbbfcd9332f..351e80f8119d6 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -16,7 +16,7 @@ "account.followers": "Takipçi", "account.followers.empty": "Henüz kimse bu kullanıcıyı takip etmiyor.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Bu kullanıcı henüz kimseyi takip etmiyor.", "account.follows_you": "Seni takip ediyor", "account.hide_reblogs": "@{name} kişisinin yinelemelerini gizle", diff --git a/app/javascript/mastodon/locales/ug.json b/app/javascript/mastodon/locales/ug.json index 36f55e80025c8..e5d833fe87465 100644 --- a/app/javascript/mastodon/locales/ug.json +++ b/app/javascript/mastodon/locales/ug.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 18e1512632547..244f04a9e87f8 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -16,7 +16,7 @@ "account.followers": "Підписники", "account.followers.empty": "Ніхто ще не підписався на цього користувача.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Цей користувач ще ні на кого не підписався.", "account.follows_you": "Підписаний(-а) на вас", "account.hide_reblogs": "Сховати передмухи від @{name}", diff --git a/app/javascript/mastodon/locales/ur.json b/app/javascript/mastodon/locales/ur.json index 5924d148705e3..b94b7c1620066 100644 --- a/app/javascript/mastodon/locales/ur.json +++ b/app/javascript/mastodon/locales/ur.json @@ -16,7 +16,7 @@ "account.followers": "پیروکار", "account.followers.empty": "\"ہنوز اس صارف کی کوئی پیروی نہیں کرتا\".", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "\"یہ صارف ہنوز کسی کی پیروی نہیں کرتا ہے\".", "account.follows_you": "آپ کا پیروکار ہے", "account.hide_reblogs": "@{name} سے فروغ چھپائیں", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index b537ca4f3d9f7..24a63ab6b3872 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -16,7 +16,7 @@ "account.followers": "關注的人", "account.followers.empty": "尚沒有人關注這位使用者。", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "這位使用者尚未關注任何使用者。", "account.follows_you": "關注你", "account.hide_reblogs": "隱藏 @{name} 的轉推", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index d674734c1180f..e964ccd4961fd 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -16,7 +16,7 @@ "account.followers": "關注者", "account.followers.empty": "尚沒有人關注這位使用者。", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "這位使用者尚未關注任何使用者。", "account.follows_you": "關注了你", "account.hide_reblogs": "隱藏來自 @{name} 的轉推", From a29080256ecb39c7c719a7717fa15d3bc6d9776b Mon Sep 17 00:00:00 2001 From: Alex Dunn Date: Sat, 18 Jul 2020 10:30:46 -0700 Subject: [PATCH 09/19] helm: add examples of annotation for NGINX upload limits (#14350) --- chart/values.yaml.template | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/chart/values.yaml.template b/chart/values.yaml.template index 4a8286d0014fe..694bc4d4224bf 100644 --- a/chart/values.yaml.template +++ b/chart/values.yaml.template @@ -16,6 +16,12 @@ ingress: kubernetes.io/ingress.class: nginx kubernetes.io/tls-acme: "true" # cert-manager.io/cluster-issuer: "letsencrypt" + # + # ensure that NGINX's upload size matches Mastodon's + # for the K8s ingress controller: + # nginx.ingress.kubernetes.io/proxy-body-size: 40m + # for the NGINX ingress controller: + # nginx.org/client-max-body-size: 40m # this value is used for LOCAL_DOMAIN hostname: mastodon.local tls: From 101485a41fb2ea326496142d9ccb368522cbe0f0 Mon Sep 17 00:00:00 2001 From: Takeshi Umeda Date: Sun, 19 Jul 2020 20:09:47 +0900 Subject: [PATCH 10/19] Fix mimetype returning nil (#14356) --- lib/paperclip/media_type_spoof_detector_extensions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/paperclip/media_type_spoof_detector_extensions.rb b/lib/paperclip/media_type_spoof_detector_extensions.rb index 363934d8d1395..43337cc688422 100644 --- a/lib/paperclip/media_type_spoof_detector_extensions.rb +++ b/lib/paperclip/media_type_spoof_detector_extensions.rb @@ -18,7 +18,7 @@ module Paperclip @type_from_mime_magic ||= begin begin File.open(@file.path) do |file| - MimeMagic.by_magic(file)&.type + MimeMagic.by_magic(file)&.type || '' end rescue Errno::ENOENT '' From 2ada2ae18af3429f9666fd35c70675dc62a0b99f Mon Sep 17 00:00:00 2001 From: Ariel Date: Sun, 19 Jul 2020 12:04:02 -0300 Subject: [PATCH 11/19] Fix/14021 behaviour on add or remove toots (#14212) * Add toot send by current user at local state after send a new toot Related to #14021 * Decrement toot counter at profile when remove a toot Related to #14021 * Remove semicolon at end of line --- app/controllers/api/v1/statuses_controller.rb | 1 + app/javascript/mastodon/actions/compose.js | 2 +- app/javascript/mastodon/actions/statuses.js | 3 ++- app/javascript/mastodon/actions/streaming.js | 13 +++++++------ .../mastodon/features/account_timeline/index.js | 15 +++++++++++++++ 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index 8d6cb84b6675f..106fc8224e287 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -57,6 +57,7 @@ class Api::V1::StatusesController < Api::BaseController @status.discard RemovalWorker.perform_async(@status.id, redraft: true) + @status.account.statuses_count = @status.account.statuses_count - 1 render json: @status, serializer: REST::StatusSerializer, source_requested: true end diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index 20341f9ec0e24..030922520264f 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -163,7 +163,6 @@ export function submitCompose(routerHistory) { // To make the app more responsive, immediately push the status // into the columns - const insertIfOnline = timelineId => { const timeline = getState().getIn(['timelines', timelineId]); @@ -179,6 +178,7 @@ export function submitCompose(routerHistory) { if (response.data.in_reply_to_id === null && response.data.visibility === 'public') { insertIfOnline('community'); insertIfOnline('public'); + insertIfOnline(`account:${response.data.account.id}`); } }).catch(function (error) { dispatch(submitComposeFail(error)); diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js index 5640201c621f0..e565e0b0ab59d 100644 --- a/app/javascript/mastodon/actions/statuses.js +++ b/app/javascript/mastodon/actions/statuses.js @@ -3,7 +3,7 @@ import openDB from '../storage/db'; import { evictStatus } from '../storage/modifier'; import { deleteFromTimelines } from './timelines'; -import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus } from './importer'; +import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus, importFetchedAccount } from './importer'; import { ensureComposeIsVisible } from './compose'; export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST'; @@ -155,6 +155,7 @@ export function deleteStatus(id, routerHistory, withRedraft = false) { evictStatus(id); dispatch(deleteStatusSuccess(id)); dispatch(deleteFromTimelines(id)); + dispatch(importFetchedAccount(response.data.account)); if (withRedraft) { dispatch(redraft(status, response.data.text)); diff --git a/app/javascript/mastodon/actions/streaming.js b/app/javascript/mastodon/actions/streaming.js index d998fcac48023..7cecff66e1bf1 100644 --- a/app/javascript/mastodon/actions/streaming.js +++ b/app/javascript/mastodon/actions/streaming.js @@ -71,9 +71,10 @@ const refreshHomeTimelineAndNotification = (dispatch, done) => { dispatch(fetchAnnouncements(done)))))); }; -export const connectUserStream = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification); -export const connectCommunityStream = ({ onlyMedia } = {}) => connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`); -export const connectPublicStream = ({ onlyMedia, onlyRemote } = {}) => connectTimelineStream(`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`); -export const connectHashtagStream = (id, tag, local, accept) => connectTimelineStream(`hashtag:${id}${local ? ':local' : ''}`, `hashtag${local ? ':local' : ''}&tag=${tag}`, null, accept); -export const connectDirectStream = () => connectTimelineStream('direct', 'direct'); -export const connectListStream = id => connectTimelineStream(`list:${id}`, `list&list=${id}`); +export const connectUserStream = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification); +export const connectUserTimelineStream = (accountId) => connectTimelineStream(`account:${accountId}`, 'user'); +export const connectCommunityStream = ({ onlyMedia } = {}) => connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`); +export const connectPublicStream = ({ onlyMedia, onlyRemote } = {}) => connectTimelineStream(`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`); +export const connectHashtagStream = (id, tag, local, accept) => connectTimelineStream(`hashtag:${id}${local ? ':local' : ''}`, `hashtag${local ? ':local' : ''}&tag=${tag}`, null, accept); +export const connectDirectStream = () => connectTimelineStream('direct', 'direct'); +export const connectListStream = id => connectTimelineStream(`list:${id}`, `list&list=${id}`); diff --git a/app/javascript/mastodon/features/account_timeline/index.js b/app/javascript/mastodon/features/account_timeline/index.js index 5ea907a1f11fd..3846cc6377f30 100644 --- a/app/javascript/mastodon/features/account_timeline/index.js +++ b/app/javascript/mastodon/features/account_timeline/index.js @@ -15,6 +15,8 @@ import { FormattedMessage } from 'react-intl'; import { fetchAccountIdentityProofs } from '../../actions/identity_proofs'; import MissingIndicator from 'mastodon/components/missing_indicator'; import TimelineHint from 'mastodon/components/timeline_hint'; +import { me } from 'mastodon/initial_state'; +import { connectUserTimelineStream } from '../../actions/streaming'; const emptyList = ImmutableList(); @@ -73,6 +75,12 @@ class AccountTimeline extends ImmutablePureComponent { this.props.dispatch(expandAccountTimeline(accountId, { withReplies })); } + componentDidMount () { + if (this.props.params.accountId === me) { + this.disconnect = this.props.dispatch(connectUserTimelineStream(me)); + } + } + componentWillReceiveProps (nextProps) { if ((nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) || nextProps.withReplies !== this.props.withReplies) { this.props.dispatch(fetchAccount(nextProps.params.accountId)); @@ -86,6 +94,13 @@ class AccountTimeline extends ImmutablePureComponent { } } + componentWillUnmount () { + if (this.disconnect) { + this.disconnect(); + this.disconnect = null; + } + } + handleLoadMore = maxId => { this.props.dispatch(expandAccountTimeline(this.props.params.accountId, { maxId, withReplies: this.props.withReplies })); } From 47931db1f50db3b6773fbb3cc4645fdb4a4692eb Mon Sep 17 00:00:00 2001 From: Takeshi Umeda Date: Mon, 20 Jul 2020 02:53:31 +0900 Subject: [PATCH 12/19] Add thumbnail_remote_url in MediaAttachment REST response (#14358) * Add thumbnail_remote_url in MediaAttachment REST response * Change thumbnail_remote_url to preview_remote_url --- app/serializers/rest/media_attachment_serializer.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/serializers/rest/media_attachment_serializer.rb b/app/serializers/rest/media_attachment_serializer.rb index e65f7acf1a9e6..a24f953152f4a 100644 --- a/app/serializers/rest/media_attachment_serializer.rb +++ b/app/serializers/rest/media_attachment_serializer.rb @@ -4,7 +4,7 @@ class REST::MediaAttachmentSerializer < ActiveModel::Serializer include RoutingHelper attributes :id, :type, :url, :preview_url, - :remote_url, :text_url, :meta, + :remote_url, :preview_remote_url, :text_url, :meta, :description, :blurhash def id @@ -35,6 +35,10 @@ class REST::MediaAttachmentSerializer < ActiveModel::Serializer end end + def preview_remote_url + object.thumbnail_remote_url.presence + end + def text_url object.local? ? medium_url(object) : nil end From 7540e235a2b387ca08cf57f8942d1b190d242808 Mon Sep 17 00:00:00 2001 From: Takeshi Umeda Date: Mon, 20 Jul 2020 05:28:27 +0900 Subject: [PATCH 13/19] Fix movie width and frame_rate returning nil (#14357) * Fix movie width and frame_rate returning nil * Add StreamValidationError and raise * Fix code style --- app/lib/exceptions.rb | 1 + app/models/concerns/remotable.rb | 2 +- app/models/media_attachment.rb | 1 + app/services/update_account_service.rb | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/lib/exceptions.rb b/app/lib/exceptions.rb index 3362576b0bc6a..7c8e778713a2b 100644 --- a/app/lib/exceptions.rb +++ b/app/lib/exceptions.rb @@ -7,6 +7,7 @@ module Mastodon class HostValidationError < ValidationError; end class LengthValidationError < ValidationError; end class DimensionsValidationError < ValidationError; end + class StreamValidationError < ValidationError; end class RaceConditionError < Error; end class RateLimitExceededError < Error; end diff --git a/app/models/concerns/remotable.rb b/app/models/concerns/remotable.rb index c6d0c7f1f440a..56b9c0164221f 100644 --- a/app/models/concerns/remotable.rb +++ b/app/models/concerns/remotable.rb @@ -29,7 +29,7 @@ module Remotable rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError => e Rails.logger.debug "Error fetching remote #{attachment_name}: #{e}" raise e unless suppress_errors - rescue Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Paperclip::Error, Mastodon::DimensionsValidationError => e + rescue Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Paperclip::Error, Mastodon::DimensionsValidationError, Mastodon::StreamValidationError => e Rails.logger.debug "Error fetching remote #{attachment_name}: #{e}" end diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 3f2e0ceb1b85a..3d93ec75ba899 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -336,6 +336,7 @@ class MediaAttachment < ApplicationRecord return unless movie.valid? + raise Mastodon::StreamValidationError, 'Video has no video stream' if movie.width.nil? || movie.frame_rate.nil? raise Mastodon::DimensionsValidationError, "#{movie.width}x#{movie.height} videos are not supported" if movie.width * movie.height > MAX_VIDEO_MATRIX_LIMIT raise Mastodon::DimensionsValidationError, "#{movie.frame_rate.to_i}fps videos are not supported" if movie.frame_rate > MAX_VIDEO_FRAME_RATE end diff --git a/app/services/update_account_service.rb b/app/services/update_account_service.rb index 4172d577408f4..666db5c7113be 100644 --- a/app/services/update_account_service.rb +++ b/app/services/update_account_service.rb @@ -12,7 +12,7 @@ class UpdateAccountService < BaseService check_links(account) process_hashtags(account) end - rescue Mastodon::DimensionsValidationError => de + rescue Mastodon::DimensionsValidationError, Mastodon::StreamValidationError => de account.errors.add(:avatar, de.message) false end From 0ab97107c76732d3af2ff415d8d9d9d89da25d93 Mon Sep 17 00:00:00 2001 From: Jeong Arm Date: Mon, 20 Jul 2020 16:48:10 +0900 Subject: [PATCH 14/19] Remove nodejs buildpack from buildpacks (#14364) --- .buildpacks | 1 - 1 file changed, 1 deletion(-) diff --git a/.buildpacks b/.buildpacks index 3450683ce84ce..5e73304a5d7c5 100644 --- a/.buildpacks +++ b/.buildpacks @@ -1,4 +1,3 @@ https://github.com/heroku/heroku-buildpack-apt https://github.com/Scalingo/ffmpeg-buildpack -https://github.com/Scalingo/nodejs-buildpack https://github.com/Scalingo/ruby-buildpack From fcb3f259e5a36dc4ac5300aa715d583f3a577c2b Mon Sep 17 00:00:00 2001 From: Takeshi Umeda Date: Mon, 20 Jul 2020 18:25:26 +0900 Subject: [PATCH 15/19] Fix to add RedisLock to handle Announce activity (#14365) --- app/lib/activitypub/activity/announce.rb | 39 +++++++++++++++--------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb index 34c646668b15a..9e108985a3e46 100644 --- a/app/lib/activitypub/activity/announce.rb +++ b/app/lib/activitypub/activity/announce.rb @@ -4,25 +4,32 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity def perform return reject_payload! if delete_arrived_first?(@json['id']) || !related_to_local_activity? - original_status = status_from_object + RedisLock.acquire(lock_options) do |lock| + if lock.acquired? + original_status = status_from_object - return reject_payload! if original_status.nil? || !announceable?(original_status) + return reject_payload! if original_status.nil? || !announceable?(original_status) - status = Status.find_by(account: @account, reblog: original_status) + @status = Status.find_by(account: @account, reblog: original_status) - return status unless status.nil? + return @status unless @status.nil? - status = Status.create!( - account: @account, - reblog: original_status, - uri: @json['id'], - created_at: @json['published'], - override_timestamps: @options[:override_timestamps], - visibility: visibility_from_audience - ) + @status = Status.create!( + account: @account, + reblog: original_status, + uri: @json['id'], + created_at: @json['published'], + override_timestamps: @options[:override_timestamps], + visibility: visibility_from_audience + ) - distribute(status) - status + distribute(@status) + else + raise Mastodon::RaceConditionError + end + end + + @status end private @@ -54,4 +61,8 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity def reblog_of_local_status? status_from_uri(object_uri)&.account&.local? end + + def lock_options + { redis: Redis.current, key: "announce:#{@object['id']}" } + end end From a8b6524b43235a3ce477b7594c918eaa957f27a2 Mon Sep 17 00:00:00 2001 From: Takeshi Umeda Date: Mon, 20 Jul 2020 18:26:12 +0900 Subject: [PATCH 16/19] Changed retries and rescued in ActivityPub::ProcessingWorker (#14355) * Changed the number of retries and rescued exceptions in ActivityPub::ProcessingWorker * Remove RecordNotUnique from rescue --- app/workers/activitypub/processing_worker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/activitypub/processing_worker.rb b/app/workers/activitypub/processing_worker.rb index 05139f616db96..cef5953194993 100644 --- a/app/workers/activitypub/processing_worker.rb +++ b/app/workers/activitypub/processing_worker.rb @@ -3,7 +3,7 @@ class ActivityPub::ProcessingWorker include Sidekiq::Worker - sidekiq_options backtrace: true + sidekiq_options backtrace: true, retry: 8 def perform(account_id, body, delivered_to_account_id = nil) ActivityPub::ProcessCollectionService.new.call(body, Account.find(account_id), override_timestamps: true, delivered_to_account_id: delivered_to_account_id, delivery: true) From bcf85b5208c936486550da0ce978098840218073 Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 22 Jul 2020 11:43:17 +0200 Subject: [PATCH 17/19] Dereference object URIs in Create and Update messages (#14359) * Dereference object URIs in Create and Update messages Fixes #14353 Signed-off-by: Thibaut Girka * Refactor, and perform origin check *before* attempting to fetch object Co-authored-by: Fire Demon --- app/lib/activitypub/activity.rb | 28 ++++++++++++++++++++++++++ app/lib/activitypub/activity/create.rb | 2 ++ app/lib/activitypub/activity/update.rb | 2 ++ 3 files changed, 32 insertions(+) diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 0ce279d287321..ab946470b9f5c 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -157,6 +157,34 @@ class ActivityPub::Activity fetch_remote_original_status end + def dereference_object! + return unless @object.is_a?(String) + return if invalid_origin?(@object) + + object = fetch_resource(@object, true, signed_fetch_account) + return unless object.present? && object.is_a?(Hash) && supported_context?(object) + + @object = object + end + + def signed_fetch_account + first_mentioned_local_account || first_local_follower + end + + def first_mentioned_local_account + audience = (as_array(@json['to']) + as_array(@json['cc'])).uniq + local_usernames = audience.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) } + .map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) } + + return if local_usernames.empty? + + Account.local.where(username: local_usernames).first + end + + def first_local_follower + @account.followers.local.first + end + def follow_request_from_object @follow_request ||= FollowRequest.find_by(target_account: @account, uri: object_uri) unless object_uri.nil? end diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index e81452e3cae83..08dd98e942d9a 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -2,6 +2,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def perform + dereference_object! + case @object['type'] when 'EncryptedMessage' create_encrypted_message diff --git a/app/lib/activitypub/activity/update.rb b/app/lib/activitypub/activity/update.rb index 70035325b65b4..018e2df549299 100644 --- a/app/lib/activitypub/activity/update.rb +++ b/app/lib/activitypub/activity/update.rb @@ -4,6 +4,8 @@ class ActivityPub::Activity::Update < ActivityPub::Activity SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze def perform + dereference_object! + if equals_or_includes_any?(@object['type'], SUPPORTED_TYPES) update_account elsif equals_or_includes_any?(@object['type'], %w(Question)) From f55dd193f9a62623054dba1537d01bd7f5cd32f3 Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 22 Jul 2020 11:44:02 +0200 Subject: [PATCH 18/19] Fix RSS feeds not being cachable (#14368) * Add tests for some cachable responses This only covers responses that we should have managed to make cachable so far. It's not the case of all responses that should be cachable in the end. * Fix RSS feeds not being cachable --- app/controllers/application_controller.rb | 2 +- spec/controllers/accounts_controller_spec.rb | 31 ++++++++++++------- .../collections_controller_spec.rb | 23 ++++++++++---- .../activitypub/outboxes_controller_spec.rb | 23 ++++++++++---- .../activitypub/replies_controller_spec.rb | 23 ++++++++++---- spec/controllers/statuses_controller_spec.rb | 23 ++++++++++---- 6 files changed, 88 insertions(+), 37 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 973db6aca9765..2201e463e68d0 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -55,7 +55,7 @@ class ApplicationController < ActionController::Base end def store_current_location - store_location_for(:user, request.url) unless request.format == :json + store_location_for(:user, request.url) unless [:json, :rss].include?(request.format&.to_sym) end def require_admin! diff --git a/spec/controllers/accounts_controller_spec.rb b/spec/controllers/accounts_controller_spec.rb index bd36f5494074c..93bf2c83f4076 100644 --- a/spec/controllers/accounts_controller_spec.rb +++ b/spec/controllers/accounts_controller_spec.rb @@ -5,6 +5,21 @@ RSpec.describe AccountsController, type: :controller do let(:account) { Fabricate(:user).account } + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + describe 'GET #show' do let(:format) { 'html' } @@ -323,9 +338,7 @@ RSpec.describe AccountsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'renders account' do json = body_as_json @@ -343,9 +356,7 @@ RSpec.describe AccountsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns Vary header with Signature' do expect(response.headers['Vary']).to include 'Signature' @@ -401,9 +412,7 @@ RSpec.describe AccountsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'renders account' do json = body_as_json @@ -447,9 +456,7 @@ RSpec.describe AccountsController, type: :controller do expect(response).to have_http_status(200) end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' end context do diff --git a/spec/controllers/activitypub/collections_controller_spec.rb b/spec/controllers/activitypub/collections_controller_spec.rb index 56be49be3d7c7..89939d1d25835 100644 --- a/spec/controllers/activitypub/collections_controller_spec.rb +++ b/spec/controllers/activitypub/collections_controller_spec.rb @@ -6,6 +6,21 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do let!(:account) { Fabricate(:account) } let(:remote_account) { nil } + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + before do allow(controller).to receive(:signed_request_account).and_return(remote_account) @@ -31,9 +46,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns orderedItems with pinned statuses' do json = body_as_json @@ -58,9 +71,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns orderedItems with pinned statuses' do json = body_as_json diff --git a/spec/controllers/activitypub/outboxes_controller_spec.rb b/spec/controllers/activitypub/outboxes_controller_spec.rb index 03490533dd592..1baf5a62300b3 100644 --- a/spec/controllers/activitypub/outboxes_controller_spec.rb +++ b/spec/controllers/activitypub/outboxes_controller_spec.rb @@ -3,6 +3,21 @@ require 'rails_helper' RSpec.describe ActivityPub::OutboxesController, type: :controller do let!(:account) { Fabricate(:account) } + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + before do Fabricate(:status, account: account, visibility: :public) Fabricate(:status, account: account, visibility: :unlisted) @@ -39,9 +54,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do expect(json[:totalItems]).to eq 4 end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' end context 'with page requested' do @@ -62,9 +75,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do expect(json[:orderedItems].all? { |item| item[:to].include?(ActivityPub::TagManager::COLLECTIONS[:public]) || item[:cc].include?(ActivityPub::TagManager::COLLECTIONS[:public]) }).to be true end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' end end diff --git a/spec/controllers/activitypub/replies_controller_spec.rb b/spec/controllers/activitypub/replies_controller_spec.rb index d956e1b35f0e0..ed383864dd1fe 100644 --- a/spec/controllers/activitypub/replies_controller_spec.rb +++ b/spec/controllers/activitypub/replies_controller_spec.rb @@ -7,6 +7,21 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do let(:remote_reply_id) { nil } let(:remote_account) { nil } + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + before do allow(controller).to receive(:signed_request_account).and_return(remote_account) @@ -36,9 +51,7 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns items with account\'s own replies' do json = body_as_json @@ -87,9 +100,7 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' context 'without only_other_accounts' do it 'returns items with account\'s own replies' do diff --git a/spec/controllers/statuses_controller_spec.rb b/spec/controllers/statuses_controller_spec.rb index ba1f1370a631e..cd6e1e6074b3d 100644 --- a/spec/controllers/statuses_controller_spec.rb +++ b/spec/controllers/statuses_controller_spec.rb @@ -5,6 +5,21 @@ require 'rails_helper' describe StatusesController do render_views + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + describe 'GET #show' do let(:account) { Fabricate(:account) } let(:status) { Fabricate(:status, account: account) } @@ -80,9 +95,7 @@ describe StatusesController do expect(response.headers['Vary']).to eq 'Accept' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns Content-Type header' do expect(response.headers['Content-Type']).to include 'application/activity+json' @@ -470,9 +483,7 @@ describe StatusesController do expect(response.headers['Vary']).to eq 'Accept' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns Content-Type header' do expect(response.headers['Content-Type']).to include 'application/activity+json' From 5d9acc0ce41aa0274fef2dd321a8fad1fb0665ea Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 22 Jul 2020 11:45:35 +0200 Subject: [PATCH 19/19] Fix not handling Undo on some activity types when they aren't inlined (#14346) * Fix not handling Undo on some activity types when they aren't inlined When receiving an Undo for a non-inlined activity, try looking it up in database using the URI. The queries are ad-hoc because we don't have a global index of object URIs, and not all activity types are stored in database with an index on their URI. Announces are just statuses, and have an index on URIs, so this check can be done efficiently. Accepts cannot be handled at all because we don't record their URI at any point. Follows don't have an index on URI, but they have an index on the issuing account, which should make such queries largely manageable. Likes don't have an index on URI, they have an index on the issuing account, but the number of favs per account may be very high, so I decided not to handle that. Blocks don't have an index on URI, but they have an index on the issuing account, which should make such queries largely manageable. In all cases, if an Undo could not be handled properly, we call `delete_later!` because that does not require us to know more than the URI of the undone property. * Add tests * Make newer blocks overwrite older ones Allows re-synchronizing block info by re-blocking and un-blocking again when the original Undo Block has been lost. --- app/lib/activitypub/activity/block.rb | 7 ++- app/lib/activitypub/activity/undo.rb | 51 +++++++++++++++++++++ spec/lib/activitypub/activity/block_spec.rb | 22 +++++++++ spec/lib/activitypub/activity/undo_spec.rb | 35 +++++++++++++- 4 files changed, 112 insertions(+), 3 deletions(-) diff --git a/app/lib/activitypub/activity/block.rb b/app/lib/activitypub/activity/block.rb index a17a2d50a6af0..90477bf3369dc 100644 --- a/app/lib/activitypub/activity/block.rb +++ b/app/lib/activitypub/activity/block.rb @@ -4,7 +4,12 @@ class ActivityPub::Activity::Block < ActivityPub::Activity def perform target_account = account_from_uri(object_uri) - return if target_account.nil? || !target_account.local? || @account.blocking?(target_account) + return if target_account.nil? || !target_account.local? + + if @account.blocking?(target_account) + @account.block_relationships.find_by(target_account: target_account).update(uri: @json['id']) if @json['id'].present? + return + end UnfollowService.new.call(target_account, @account) if target_account.following?(@account) diff --git a/app/lib/activitypub/activity/undo.rb b/app/lib/activitypub/activity/undo.rb index 599823c6e25db..9eff1b71c9db3 100644 --- a/app/lib/activitypub/activity/undo.rb +++ b/app/lib/activitypub/activity/undo.rb @@ -13,11 +13,62 @@ class ActivityPub::Activity::Undo < ActivityPub::Activity undo_like when 'Block' undo_block + when nil + handle_reference end end private + def handle_reference + # Some implementations do not inline the object, and as we don't have a + # global index, we have to guess what object it is. + return if object_uri.nil? + + try_undo_announce || try_undo_accept || try_undo_follow || try_undo_like || try_undo_block || delete_later!(object_uri) + end + + def try_undo_announce + status = Status.where.not(reblog_of_id: nil).find_by(uri: object_uri, account: @account) + if status.present? + RemoveStatusService.new.call(status) + true + else + false + end + end + + def try_undo_accept + # We can't currently handle `Undo Accept` as we don't record `Accept`'s uri + false + end + + def try_undo_follow + follow = @account.follow_requests.find_by(uri: object_uri) || @account.active_relationships.find_by(uri: object_uri) + + if follow.present? + follow.destroy + true + else + false + end + end + + def try_undo_like + # There is an index on accounts, but an account may have *many* favs, so this may be too costly + false + end + + def try_undo_block + block = @account.block_relationships.find_by(uri: object_uri) + if block.present? + UnblockService.new.call(@account, block.target_account) + true + else + false + end + end + def undo_announce return if object_uri.nil? diff --git a/spec/lib/activitypub/activity/block_spec.rb b/spec/lib/activitypub/activity/block_spec.rb index 94d37356dd14c..42bdfdc810ef6 100644 --- a/spec/lib/activitypub/activity/block_spec.rb +++ b/spec/lib/activitypub/activity/block_spec.rb @@ -28,6 +28,28 @@ RSpec.describe ActivityPub::Activity::Block do end end + context 'when the recipient is already blocked' do + before do + sender.block!(recipient, uri: 'old') + end + + describe '#perform' do + subject { described_class.new(json, sender) } + + before do + subject.perform + end + + it 'creates a block from sender to recipient' do + expect(sender.blocking?(recipient)).to be true + end + + it 'sets the uri to that of last received block activity' do + expect(sender.block_relationships.find_by(target_account: recipient).uri).to eq 'foo' + end + end + end + context 'when the recipient follows the sender' do before do recipient.follow!(sender) diff --git a/spec/lib/activitypub/activity/undo_spec.rb b/spec/lib/activitypub/activity/undo_spec.rb index 9545e1f46af6b..c0309e49dafce 100644 --- a/spec/lib/activitypub/activity/undo_spec.rb +++ b/spec/lib/activitypub/activity/undo_spec.rb @@ -50,6 +50,19 @@ RSpec.describe ActivityPub::Activity::Undo do expect(sender.reblogged?(status)).to be false end end + + context 'with only object uri' do + let(:object_json) { 'bar' } + + before do + Fabricate(:status, reblog: status, account: sender, uri: 'bar') + end + + it 'deletes the reblog by uri' do + subject.perform + expect(sender.reblogged?(status)).to be false + end + end end context 'with Accept' do @@ -91,13 +104,22 @@ RSpec.describe ActivityPub::Activity::Undo do end before do - sender.block!(recipient) + sender.block!(recipient, uri: 'bar') end it 'deletes block from sender to recipient' do subject.perform expect(sender.blocking?(recipient)).to be false end + + context 'with only object uri' do + let(:object_json) { 'bar' } + + it 'deletes block from sender to recipient' do + subject.perform + expect(sender.blocking?(recipient)).to be false + end + end end context 'with Follow' do @@ -113,13 +135,22 @@ RSpec.describe ActivityPub::Activity::Undo do end before do - sender.follow!(recipient) + sender.follow!(recipient, uri: 'bar') end it 'deletes follow from sender to recipient' do subject.perform expect(sender.following?(recipient)).to be false end + + context 'with only object uri' do + let(:object_json) { 'bar' } + + it 'deletes follow from sender to recipient' do + subject.perform + expect(sender.following?(recipient)).to be false + end + end end context 'with Like' do