From 12ed74781185cfd74435bf53181a72bd0d6585f2 Mon Sep 17 00:00:00 2001 From: Rintan Date: Sun, 8 Mar 2020 21:03:15 +0900 Subject: [PATCH 1/9] Material theme (dev) initial release --- .../styles/fonts/MaterialIcons-Regular.woff2 | Bin 0 -> 44300 bytes .../styles/mastodon-material-dev.scss | 15 + .../styles/mastodon-material-dev/_mixins.scss | 23 ++ .../styles/mastodon-material-dev/account.scss | 127 +++++++ .../styles/mastodon-material-dev/basics.scss | 20 + .../styles/mastodon-material-dev/button.scss | 59 +++ .../styles/mastodon-material-dev/cards.scss | 1 + .../mastodon-material-dev/color/dark.scss | 30 ++ .../mastodon-material-dev/color/light.scss | 93 +++++ .../styles/mastodon-material-dev/columns.scss | 351 ++++++++++++++++++ .../mastodon-material-dev/components.scss | 329 ++++++++++++++++ .../styles/mastodon-material-dev/config.scss | 21 ++ .../styles/mastodon-material-dev/control.scss | 59 +++ .../mastodon-material-dev/emoji-picker.scss | 88 +++++ .../styles/mastodon-material-dev/icons.scss | 36 ++ .../mastodon-material-dev/material-icons.scss | 88 +++++ .../styles/mastodon-material-dev/media.scss | 17 + .../styles/mastodon-material-dev/mobile.scss | 0 .../profile/material-v1.scss | 52 +++ .../profile/material-v2.scss | 66 ++++ .../mastodon-material-dev/statuses.scss | 135 +++++++ .../initializers/content_security_policy.rb | 2 - config/locales/en.yml | 3 +- config/locales/ja.yml | 2 + config/themes.yml | 3 + 25 files changed, 1617 insertions(+), 3 deletions(-) create mode 100644 app/javascript/styles/fonts/MaterialIcons-Regular.woff2 create mode 100644 app/javascript/styles/mastodon-material-dev.scss create mode 100644 app/javascript/styles/mastodon-material-dev/_mixins.scss create mode 100644 app/javascript/styles/mastodon-material-dev/account.scss create mode 100644 app/javascript/styles/mastodon-material-dev/basics.scss create mode 100644 app/javascript/styles/mastodon-material-dev/button.scss create mode 100644 app/javascript/styles/mastodon-material-dev/cards.scss create mode 100644 app/javascript/styles/mastodon-material-dev/color/dark.scss create mode 100644 app/javascript/styles/mastodon-material-dev/color/light.scss create mode 100644 app/javascript/styles/mastodon-material-dev/columns.scss create mode 100644 app/javascript/styles/mastodon-material-dev/components.scss create mode 100644 app/javascript/styles/mastodon-material-dev/config.scss create mode 100644 app/javascript/styles/mastodon-material-dev/control.scss create mode 100644 app/javascript/styles/mastodon-material-dev/emoji-picker.scss create mode 100644 app/javascript/styles/mastodon-material-dev/icons.scss create mode 100644 app/javascript/styles/mastodon-material-dev/material-icons.scss create mode 100644 app/javascript/styles/mastodon-material-dev/media.scss create mode 100644 app/javascript/styles/mastodon-material-dev/mobile.scss create mode 100644 app/javascript/styles/mastodon-material-dev/profile/material-v1.scss create mode 100644 app/javascript/styles/mastodon-material-dev/profile/material-v2.scss create mode 100644 app/javascript/styles/mastodon-material-dev/statuses.scss diff --git a/app/javascript/styles/fonts/MaterialIcons-Regular.woff2 b/app/javascript/styles/fonts/MaterialIcons-Regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..9fa211252080046a23b2449dbdced6abc2b0bb34 GIT binary patch literal 44300 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 QW8}wPUeo^@jR61v08@RD2LJ#7 literal 0 HcmV?d00001 diff --git a/app/javascript/styles/mastodon-material-dev.scss b/app/javascript/styles/mastodon-material-dev.scss new file mode 100644 index 00000000000000..9cc10708dd3411 --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev.scss @@ -0,0 +1,15 @@ +@charset "UTF-8"; + +@import 'mastodon-material-dev/account'; +@import 'mastodon-material-dev/basics'; +@import 'mastodon-material-dev/button'; +// @import 'mastodon-material-dev/cards'; +@import 'mastodon-material-dev/columns'; +@import 'mastodon-material-dev/components'; +@import 'mastodon-material-dev/config'; +@import 'mastodon-material-dev/control'; +@import 'mastodon-material-dev/emoji-picker'; +@import 'mastodon-material-dev/icons'; +@import 'mastodon-material-dev/material-icons'; +@import 'mastodon-material-dev/media'; +@import 'mastodon-material-dev/statuses'; \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/_mixins.scss b/app/javascript/styles/mastodon-material-dev/_mixins.scss new file mode 100644 index 00000000000000..798e690e7002f8 --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/_mixins.scss @@ -0,0 +1,23 @@ +@charset "UTF-8"; + + +$shadow-color-1: rgba(0,0,0,.2); +$shadow-color-2: rgba(0,0,0,.14); +$shadow-color-3: rgba(0,0,0,.12); + +@mixin shadow-1dp { box-shadow: 0 2px 1px -1px $shadow-color-1, 0 1px 1px 0 $shadow-color-2, 0 1px 3px 0 $shadow-color-3 } +@mixin shadow-2dp { box-shadow: 0 3px 1px -2px $shadow-color-1, 0 2px 2px 0 $shadow-color-2, 0 1px 5px 0 $shadow-color-3 } +@mixin shadow-3dp { box-shadow: 0 3px 3px -2px $shadow-color-1, 0 3px 4px 0 $shadow-color-2, 0 1px 8px 0 $shadow-color-3 } +@mixin shadow-4dp { box-shadow: 0 2px 4px -1px $shadow-color-1, 0 4px 5px 0 $shadow-color-2, 0 1px 10px 0 $shadow-color-3 } +@mixin shadow-5dp { box-shadow: 0 3px 5px -1px $shadow-color-1, 0 5px 8px 0 $shadow-color-2, 0 1px 14px 0 $shadow-color-3 } +@mixin shadow-6dp { box-shadow: 0 3px 5px -1px $shadow-color-1, 0 6px 10px 0 $shadow-color-2, 0 1px 18px 0 $shadow-color-3 } +@mixin shadow-7dp { box-shadow: 0 4px 5px -2px $shadow-color-1, 0 7px 10px 1px $shadow-color-2, 0 2px 16px 1px $shadow-color-3 } +@mixin shadow-8dp { box-shadow: 0 5px 5px -3px $shadow-color-1, 0 8px 10px 1px $shadow-color-2, 0 3px 14px 2px $shadow-color-3 } +@mixin shadow-9dp { box-shadow: 0 5px 6px -3px $shadow-color-1, 0 9px 12px 1px $shadow-color-2, 0 3px 16px 2px $shadow-color-3 } +@mixin shadow-10dp { box-shadow: 0 6px 6px -3px $shadow-color-1, 0 10px 14px 1px $shadow-color-2, 0 4px 18px 3px $shadow-color-3 } +@mixin shadow-11dp { box-shadow: 0 6px 7px -4px $shadow-color-1, 0 11px 15px 1px $shadow-color-2, 0 4px 20px 3px $shadow-color-3 } +@mixin shadow-12dp { box-shadow: 0 7px 8px -4px $shadow-color-1, 0 12px 17px 2px $shadow-color-2, 0 5px 22px 4px $shadow-color-3 } +@mixin shadow-13dp { box-shadow: 0 7px 8px -4px $shadow-color-1, 0 13px 19px 2px $shadow-color-2, 0 5px 24px 4px $shadow-color-3 } +@mixin shadow-14dp { box-shadow: 0 7px 9px -4px $shadow-color-1, 0 14px 21px 2px $shadow-color-2, 0 5px 26px 4px $shadow-color-3 } +@mixin shadow-15dp { box-shadow: 0 8px 9px -5px $shadow-color-1, 0 15px 22px 2px $shadow-color-2, 0 6px 28px 5px $shadow-color-3 } +@mixin shadow-16dp { box-shadow: 0 8px 10px -5px $shadow-color-1, 0 16px 24px 2px $shadow-color-2, 0 6px 30px 5px $shadow-color-3 } diff --git a/app/javascript/styles/mastodon-material-dev/account.scss b/app/javascript/styles/mastodon-material-dev/account.scss new file mode 100644 index 00000000000000..46203b7e4f6af4 --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/account.scss @@ -0,0 +1,127 @@ +@charset "UTF-8"; +@import 'config'; +@import 'mixins'; + +.account { + border-bottom: 1px solid $border-color; + + .account__display-name, + .account__display-name strong { color: $secondary-text-color } + + &__header { + &__bar { + background: $card-background-color; + padding: 8px; + border-bottom: 1px solid $border-color; + + .avatar .account__avatar { border: none } + } + + &__tabs { + padding: 8px; + + &__name { + padding: 8px; + + h1 { + color: $primary-text-color; + + small { color: $secondary-text-color } + } + } + + &__buttons { + .icon-button { + border: none; + border-radius: 50%; + padding: 0; + } + } + } + + &__extra { + margin-top: 0; + + &__links { + color: $secondary-text-color; + padding: 10px 0; + + a { + color: $secondary-text-color; + padding: 4px 12px; + + strong { color: $ui-text-color } + } + } + } + + &__bio { + margin: 0; + + .account__header { + &__content { + color: $primary-text-color; + padding: 8px; + } + + &__fields { + border: 1px solid $border-color; + border-radius: 4px; + + .verified { + border: none; + background: $verified-background-color; + + a, + &__mark { color: $primary-text-color } + } + + dl { + border-bottom: 1px solid $border-color; + + &:first-child .verified { border-radius: 0 } + + &:last-child { border-bottom: 0 } + } + + dt { + color: $primary-text-color; + background: $list-background-inactive-color; + } + + dd { color: $primary-text-color } + } + } + } + } + + &__section-headline { + background: $card-background-color; + border-bottom: 1px solid $border-color; + + a { + padding: 16px 0; + color: $secondary-text-color; + + &.active { + color: $tab-indicator-color; + border-bottom: 4px solid $tab-indicator-color; + + &:before, + &:after { border: none } + + &:focus { background: $tab-indicator-background-focus-color } + } + + &:hover { background: $tab-indicator-background-hover-color } + } + } +} + +.account-role { + padding: 4px 8px; + border-radius: 17px; + color: $ui-text-color; + background-color: $outlined-chip-color; + border: 1px solid $border-color; +} \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/basics.scss b/app/javascript/styles/mastodon-material-dev/basics.scss new file mode 100644 index 00000000000000..fd5abf7a8eb7ad --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/basics.scss @@ -0,0 +1,20 @@ +@charset "UTF-8"; +@import 'config'; + + +body { + background: $background-color; +} + +::-webkit-scrollbar-thumb { + background: $scroll-bar-thumb-color; + + &:hover { background: $scroll-bar-thumb-hover-color } + &:active { background: $scroll-bar-thumb-active-color } +} + +::-webkit-scrollbar-track, +::-webkit-scrollbar-track:hover, +::-webkit-scrollbar-track:active { + background: transparent !important; +} \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/button.scss b/app/javascript/styles/mastodon-material-dev/button.scss new file mode 100644 index 00000000000000..b1a0b99a3ae1e8 --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/button.scss @@ -0,0 +1,59 @@ +@charset "UTF-8"; +@import 'config'; +@import 'mixins'; + +.icon-button { + color: $icon-button-color; + border-radius: 50%; + + &.active { color: $icon-button-active-color } + + &.disabled { color: $disabled-icon-color } + + &.inverted { + &:hover { + color: $icon-button-hover-color; + background-color: $icon-background-hover-color; + } + } + + &:hover { + color: $icon-button-hover-color; + background-color: $icon-background-hover-color; + } + + &:active, + &:focus { background-color: transparent } +} + +.text-icon-button { + color: $icon-button-color; + border-radius: 50%; + font-size: 12px; + + &:hover { + background-color: $icon-background-hover-color; + } +} + +.button, +.button:active, +.button:focus { + background-color: $contained-button-color; + border-radius: $button-radius; +} + +.button:hover { + @include shadow-2dp; + background-color: $contained-button-hover-color; +} + +.button.logo-button { + background: $contained-button-color; + + &:hover { background: $contained-button-hover-color } + + .button--destructive:hover { background: $contained-button-hover-color } +} + +.button.button--block { margin: 8px 0 } \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/cards.scss b/app/javascript/styles/mastodon-material-dev/cards.scss new file mode 100644 index 00000000000000..08778d7a80e7c7 --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/cards.scss @@ -0,0 +1 @@ +{\rtf1} \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/color/dark.scss b/app/javascript/styles/mastodon-material-dev/color/dark.scss new file mode 100644 index 00000000000000..75759126a2cb28 --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/color/dark.scss @@ -0,0 +1,30 @@ +@charset "UTF-8"; + + +// Base color +$primary-color: #db4437; +$secondary-color: #ffffff; +$error-color: #d50000; + +// Text color +$ui-text-color: #ffffff; +$secondary-text-color: #80868b; +$info-text-color: #5e5e5e; +$tips-text-color: #ffffff; +$disabled-text-color: #ffffff; +$inverted-text-color: #ffffff; +$link-text-color: #4285f4; + +// Background-color +$background-color: #121212; + +// Icon color +$icon-color: #757575; + +// Button color +$icon-button-color: #757575; +$contained-button-color: #4285f4; + +// Derived color +$top-bar-color: lighten($background-color, 10%); +$search-bar-color: lighten($background-color, 20%); \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/color/light.scss b/app/javascript/styles/mastodon-material-dev/color/light.scss new file mode 100644 index 00000000000000..c2c47545ae4132 --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/color/light.scss @@ -0,0 +1,93 @@ +@charset "UTF-8"; + + +// Base color +$primary-color: #4285f4; +$secondary-color: #db4437; +$error-color: #B00020; +$verified-color: #4caf50; + +// Text color +$ui-text-color: #202124; +$ui-inverted-text-color: #ffffff; +$primary-text-color: #000000; +$secondary-text-color: #5f6368; +$section-text-color: $primary-color; +$info-text-color: #5e5e5e; +$tips-text-color: #c0c0c0; +$disabled-text-color: rgba(0,0,0,.54); +$link-text-color: #4285f4; + +// Background-color +$background-color: #ffffff; +$menu-background-color: $background-color; +$menu-background-hover-color: darken($background-color, 6%); +$menu-background-active-color: darken($background-color, 10%); +$card-background-color: $background-color; +$card-background-inactive-color: darken($card-background-color, 6%); +$list-background-color: $background-color; +$list-background-inactive-color: darken($list-background-color, 6%); +$verified-background-color: lighten($verified-color, 20%); + +// Chip color +$contained-chip-color: #e0e0e0; +$contained-chip-hover-color: darken($contained-chip-color, 6%); +$contained-chip-selected-color: darken($contained-chip-color, 12%); +$outlined-chip-color: #ffffff; +$outlined-chip-hover-color: darken($outlined-chip-color, 6%); +$outlined-chip-selected-color: darken($outlined-chip-color, 12%); + +// Badge color +$badge-color: $primary-color; +//$badge-color: $secondary-color; + +// Icon color +$icon-color: #757575; +$icon-hover-color: darken($icon-color, 30%); +$icon-background-hover-color: darken($background-color, 4%); +$icon-background-active-color: darken($background-color, 8%); +$disabled-icon-color: lighten($icon-color, 16%); +$top-bar-icon-color: $icon-color; +$media-icon-color: transparentize(#ffffff, 0.4); +$media-icon-hover-color: transparentize(#ffffff, 0.2); +$media-icon-background-color: transparentize(#000000, 0.5); +$control-border-color: $icon-color; + +// Button color +$icon-button-color: $icon-color; +$icon-button-hover-color: $icon-hover-color; +$icon-button-active-color: $primary-color; +$contained-button-color: $primary-color; +$contained-button-hover-color: lighten($contained-button-color, 10%); +$outlined-button-color: $primary-color; +$outlined-button-hover-color: lighten($primary-color, 36%); +$outlined-button-active-color: lighten($primary-color, 30%); +$text-button-color: $primary-color; +$text-button-hover-color: lighten($text-button-color, 36%); +$text-button-focus-color: lighten($text-button-color, 30%); + +// Toggle color +$toggle-thumb-color: #ffffff; +$toggle-track-color: $disabled-icon-color; +$toggle-thumb-active-color: $primary-color; +$toggle-track-active-color: lighten($primary-color, 26%); + +// Border color +$border-color: #dadce0; +$border-active-color: darken($border-color, 30%); + +// Scroll bar color +$scroll-bar-thumb-color: darken($background-color, 20%); +$scroll-bar-thumb-hover-color: darken($background-color, 30%); +$scroll-bar-thumb-active-color: darken($background-color, 38%); + +// App bar color +$top-bar-color: $background-color; +$top-bar-hover-color: $icon-background-hover-color; +$search-bar-color: darken($background-color, 6%); +$search-bar-focus-color: $background-color; + +// Tab color +$tab-indicator-color: $primary-color; +$tab-indicator-background-hover-color: lighten($tab-indicator-color, 36%); +$tab-indicator-background-focus-color: lighten($tab-indicator-color, 30%); \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/columns.scss b/app/javascript/styles/mastodon-material-dev/columns.scss new file mode 100644 index 00000000000000..796382d31bdeea --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/columns.scss @@ -0,0 +1,351 @@ +@charset "UTF-8"; +@import 'config'; +@import 'mixins'; + +.column { + @include shadow-1dp; + padding: 0; + margin: 10px 8px; + border-radius: $card-radius; + + &>.scrollable { background: $list-background-color } + + &:last-child { box-shadow: none } +} + +.column-header { + background: $top-bar-color; + border-radius: $bar-radius; + + > button { + padding: 16px 0 16px 16px; + color: $ui-text-color; + } + + &.active { + .column-header__icon { + color: $primary-color; + text-shadow: none; + } + } + + &__icon { + margin-right: 16px; + color: $top-bar-icon-color; + font-size: 20px; + } + + &__buttons { height: 56px } + + &__button { + background: $top-bar-color; + color: $icon-button-color; + margin: 8px 10px; + padding: 10px 12px; + border-radius: 50%; + + &.active { + color: $icon-button-active-color; + background: $icon-background-active-color; + + &:hover { + color: $icon-button-active-color; + background: $icon-background-hover-color; + } + } + + &:hover { + color: $icon-button-hover-color; + background: $icon-background-hover-color; + } + } + + &__setting-btn { + color: $icon-button-color; + + &:hover { + color: $icon-button-hover-color; + background: $icon-background-hover-color; + } + } + + &__setting-arrows { font-size: 16px } + + &__wrapper { + @include shadow-4dp; + border-radius: $bar-radius; + + .announcements { border-top: 1px solid $border-color } + + &.active { + @include shadow-4dp; + + &:before { background: transparent } + } + } + + &__collapsible { + color: $ui-text-color; + border-top: 1px solid $border-color; + + &-inner { + background: $top-bar-color; + padding: 16px; + } + } + + &__back-button { + background: $top-bar-color; + color: $icon-color; + padding: 8px; + margin: auto 0; + border-radius: 50%; + + span { display: none } + } +} + +.column-subheading { + color: $section-text-color; + background: $menu-background-color; + padding: 12px 16px; + border-top: 1px solid $border-color; +} + +.column-link { + color: $ui-text-color; + background: $menu-background-color; + padding: 16px; + border-radius: $nav-drawer-item-radius; + + &:hover { background: $menu-background-hover-color } + + &:active, + &:focus { background: $menu-background-active-color } + + &__icon { + margin-right: 32px; + font-size: 20px; + } +} + +.column-settings { + &__section { + color: $section-text-color; + margin-bottom: 0; + margin-top: 8px; + } +} + +.column-back-button { + @include shadow-4dp; + background: $top-bar-color; + color: $icon-color; + padding: 16px; +} + +.column-inline-form { + padding: 16px 0 16px 16px; + background: $card-background-color; + + .icon-button { margin: 0 16px } +} + +.setting-text { + color: $primary-text-color; + background: $search-bar-color; + border-radius: $bar-radius; + + &::placeholder { color: $tips-text-color } + + &:focus { + @include shadow-1dp; + background: $search-bar-focus-color; + } +} + +.empty-column-indicator { + color: $secondary-text-color; + background: $card-background-color; + font-size: 16px; +} + +.conversation { + border-bottom: 1px solid $border-color; + padding: 12px; + background: $list-background-inactive-color; + + &--unread { + background: $list-background-color; + + .conversation__content__relative-time { color: $info-text-color } + } + + &__unread { background: $primary-color } + + &__avatar { padding: 0 16px 0 0 } + + &__content { + padding: 0; + + &__relative-time { + font-size: 14px; + color: $info-text-color; + } + + &__names, + &__names a { + color: $primary-text-color; + font-size: 16px; + } + } +} + +.muted { + .status__content { + color: $primary-text-color; + + p { color: $primary-text-color } + + a { color: $secondary-text-color } + } +} + +.load-gap { border-bottom: 1px solid $border-color } + +.load-more { + color: $icon-color; + padding: 16px; + + &:hover { background: $menu-background-hover-color } +} + +.getting-started { + background: $background-color; + color: $ui-text-color; + + &__wrapper { + background: $background-color; + height: auto !important; + border-bottom: 1px solid $border-color; + } + + &__footer { + padding: 16px; + + p { + color: $secondary-text-color; + font-size: 12px; + margin-bottom: 16px; + } + + a { color: $ui-text-color } + + p a { color: $link-text-color } + + } +} + +.setting-toggle { + &__label { + color: $ui-text-color; + margin: 8px 8px 8px 14px; + } +} + +.announcements { + background: $background-color; + padding: 0; + + &__container { color: $primary-text-color } + + &__item { + padding: 16px; + font-size: 16px; + + &__unread { background: $badge-color } + } +} + +.reactions-bar { + .emoji-button { + color: $icon-button-color; + font-size: 20px; + + &:hover { color: $icon-button-hover-color } + + &:active { color: $icon-button-active-color } + } + + &__item { + background: $contained-chip-color; + border-radius: 17px; + margin: 2px 4px; + + &.active { + background-color: $contained-chip-selected-color; + .reactions-bar__item__count { color: $ui-text-color } + } + + &__emoji { + width: 24px; + height: 24px; + margin: 4px 0 4px 2px; + } + + &__count { + font-size: 16px; + margin: 0 8px; + color: $secondary-text-color; + } + + &:hover { background: $contained-chip-hover-color } + } +} + +.notification { + &__filter-bar { + background: $top-bar-color; + border-bottom: 1px solid $border-color; + + button { + background: $top-bar-color; + color: $secondary-text-color; + font-size: 16px; + + span { font-size: 14px } + + &.active { + color: $tab-indicator-color; + border-bottom: 4px solid $tab-indicator-color; + + &:before, + &:after { border: none } + + &:focus { background: $tab-indicator-background-focus-color } + } + + &:hover { background: $tab-indicator-background-hover-color } + } + } + + &__message { + color: $secondary-text-color; + margin: 0 16px 0 70px; + font-size: 16px; + } + + &__display-name:hover { color: inherit } +} + +div.notification.notification-favourite.focusable, +div.notification.notification-follow.focusable { background: $list-background-inactive-color } + +.notification-favourite .status.status-direct { background: transparent } + +.relationship-tag { + color: $ui-inverted-text-color; + background-color: $media-icon-background-color; + font-size: 12px; + border-radius: 17px; +} \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/components.scss b/app/javascript/styles/mastodon-material-dev/components.scss new file mode 100644 index 00000000000000..e2a0d6af8de452 --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/components.scss @@ -0,0 +1,329 @@ +@charset "UTF-8"; +@import 'config'; +@import 'mixins'; + + +.drawer { + &__header { + @include shadow-4dp; + background: $top-bar-color; + border-radius: $bar-radius; + justify-content: space-around; + + a { transition: none } + + a:hover { + background: $top-bar-hover-color; + border-radius: 50%; + } + } + + &__tab { + color: $top-bar-icon-color; + font-size: 20px; + margin: 12px auto 12px; + padding: 8px; + flex: none; + height: 16px; + + &:hover { color: $icon-button-hover-color } + } + + &__pager { + @include shadow-1dp; + border-radius: $card-radius; + } + + &__inner { + background: $background-color; + + &.darker { background: $card-background-color } + + &__mastodon { + background: $background-color + } + } +} + +.search { + &__input { + background: $search-bar-color; + color: $tips-text-color; + border-radius: $bar-radius; + padding: 12px 12px 12px 40px; + + &:focus { + @include shadow-2dp; + background: $search-bar-focus-color; + color: $ui-text-color; + } + + &::placeholder { color: $tips-text-color } + } + + &__icon { + .fa { + color: $icon-color; + font-size: 20px; + top: 12px; + right: unset; + left: 12px; + height: 6px; + transition: none; + + &.active { opacity: 1 } + + &-search { + transform: none; + opacity: 1; + } + &-times-circle.active { + right: 10px; + left: unset; + transform: none; + } + } + } +} + +.search-popout { + @include shadow-2dp; + background: $search-bar-focus-color; + border-radius: 0px $bar-radius; + border-top: 1px solid $border-color; + margin-top: 0; + color: $tips-text-color; + + h4 { + color: $secondary-text-color; + } + + em { + color: $ui-text-color; + } +} + +.search-results { + &__header { + color: $secondary-text-color; + background-color: $card-background-color; + padding: 16px; + + .fa { margin-right: 8px } + } + + &__section { + h5 { + background: $card-background-color; + border-bottom: 1px solid $border-color; + padding: 16px; + color: $section-text-color; + + .fa { margin-right: 8px } + } + } +} + +.account__avatar { + border-radius: $avater-radius; + width: 40px; + height: 40px; +} + +.navigation-bar { + color: $secondary-text-color; + + strong { + color: $ui-text-color; + } +} + +.dropdown-menu { + @include shadow-8dp; + background: $menu-background-color; + padding: 8px 0; + border-radius: $menu-radius; + + &__arrow { visibility: hidden } + + &__item a { + font-size: 14px; + padding: 9px 16px; + background: $menu-background-color; + color: $ui-text-color; + + &:hover, &:active { + background: $menu-background-hover-color; + color: $ui-text-color; + } + } + + &__separator { + margin: 8px 0; + border-bottom: 1px solid $border-color; + } +} + +.compose-form { + .autosuggest-textarea__textarea { + background: $background-color; + color: $ui-text-color; + } + + .compose-form { + &__warning { + @include shadow-1dp; + color: $secondary-text-color; + background: $card-background-color; + padding: 16px; + + a { color: $link-text-color } + } + + &__modifiers { + background: $background-color; + color: $tips-text-color; + } + + &__buttons-wrapper { + background: $background-color; + color: $tips-text-color; + } + + &__poll-wrapper { + border-top: 1px solid $border-color; + + ul { padding: 12px } + + select { + color: $ui-text-color; + background-color: $background-color; + border: 0; + + &:focus { border-color: $border-active-color } + } + + .button.button-secondary { + box-shadow: none; + color: $outlined-button-color; + border-color: $outlined-button-color; + + &:hover { background-color: $outlined-button-hover-color } + + &:active { background-color: $outlined-button-active-color } + + &:focus { background-color: $outlined-button-color } + + + } + } + + &__utilBtns { padding-top: 0 } + + &__publish .compose-form__publish-button-wrapper { box-shadow: none } + } +} + +.poll__input { + border: 2px solid $control-border-color; + width: 20px; + height: 20px; + flex: 0 0 20px; +} + +.poll__text input[type=text] { + color: $ui-text-color; + background: $background-color; + border: 1px solid $border-color; + padding: 8px 12px; + + &:focus { border-color: $border-active-color } +} + +.privacy-dropdown { + &.active .privacy-dropdown__value.active { + background: $icon-background-hover-color; + border-radius: 50%; + box-shadow: none; + + .icon-button { color: $icon-button-active-color } + } + + &__dropdown { + @include shadow-8dp; + background: $menu-background-color; + border-radius: $dialog-radius; + } + + &__option { + color: $icon-color; + padding: 8px 16px; + + &__icon { + font-size: 20px; + margin-right: 12px; + } + + &__content { + color: $secondary-text-color; + + strong { color: $ui-text-color } + } + + &.active { + background: $menu-background-active-color; + color: $icon-hover-color; + + .privacy-dropdown__option__content { + color: $secondary-text-color; + + strong { color: $ui-text-color } + } + + &:hover { + background: $menu-background-active-color; + + .privacy-dropdown__option__content { + color: $secondary-text-color; + + strong { color: $ui-text-color } + } + } + } + + &:hover { + background: $menu-background-hover-color; + color: $icon-hover-color; + + .privacy-dropdown__option__content { + color: $secondary-text-color; + + strong { color: $ui-text-color } + } + } + } +} + +.character-counter { + color: $secondary-text-color; +} + +.reply-indicator { + @include shadow-1dp; + border-radius: $card-radius; + background: $card-background-color; + padding: 16px; + + &__header { margin-bottom: 4px } + + &__display { + &-name { + color: $primary-text-color; + padding-right: 24px; + } + + &-avatar { margin-right: 8px } + } + + &__content { color: $primary-text-color } +} \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/config.scss b/app/javascript/styles/mastodon-material-dev/config.scss new file mode 100644 index 00000000000000..e733bc8af62f56 --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/config.scss @@ -0,0 +1,21 @@ +@charset "UTF-8"; + + +// Color scheme +@import 'color/light'; + + +// Profile +@import 'profile/material-v1'; + + +// Material Design Icon settings +// If you want to use self-hosting font, please place MaterialIcons-Regular.woff2 file in .../fonts folder and configure below. +@font-face { + font-family: "Material Icons"; + src: + local("Material Icons"), + //url("https://raw.githubusercontent.com/google/material-design-icons/master/iconfont/MaterialIcons-Regular.woff2"); // GitHub + //url("https://fonts.gstatic.com/s/materialicons/v50/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2"); // Google Fonts + url("../fonts/MaterialIcons-Regular.woff2"); // Self-hosting +} \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/control.scss b/app/javascript/styles/mastodon-material-dev/control.scss new file mode 100644 index 00000000000000..9048d122809329 --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/control.scss @@ -0,0 +1,59 @@ +@charset "UTF-8"; +@import 'config'; +@import 'mixins'; + + +.react-toggle { + width: 36px; + height: 16px; + border-radius: 15px; + + &-track { + background-color: $disabled-icon-color; + margin: 4px; + width: 36px; + height: 16px; + + &-check { visibility: hidden } + &-x { visibility: hidden } + } + + &-thumb { + @include shadow-1dp; + width: 20px; + height: 20px; + border: 0; + background-color: $toggle-thumb-color; + } + + &--checked { + .react-toggle{ + &-track { background-color: $toggle-track-active-color } + + &-thumb { + background-color: $toggle-thumb-active-color; + left: 24px; + } + } + + &:hover:not(.react-toggle--disabled) .react-toggle-track { background-color: $toggle-track-active-color !important } + + } + + &:hover:not(.react-toggle--disabled) .react-toggle-track { background-color: $toggle-track-color } +} + +.radio-button { + padding: 8px 0; + + &__input { + border: 2px solid $border-color; + + &.checked { + border-color: $icon-button-active-color; + background: $icon-button-active-color; + padding: 3px; + background-clip: content-box; + } + } +} \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/emoji-picker.scss b/app/javascript/styles/mastodon-material-dev/emoji-picker.scss new file mode 100644 index 00000000000000..d5eada5570fa38 --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/emoji-picker.scss @@ -0,0 +1,88 @@ +@charset "UTF-8"; +@import 'config'; +@import 'mixins'; + +.emoji-picker-dropdown { + &__menu { + @include shadow-8dp; + background: $menu-background-color; + border-radius: $menu-radius; + } + + &__modifiers__menu { + @include shadow-8dp; + background: $menu-background-color; + border-radius: $menu-radius; + + button { + padding: 8px; + } + } +} + +.emoji-mart { + width: 388px !important; + font-size: 14px; + color: $ui-text-color; + + &-bar { + border: 0 solid $border-color; + + &:first-child { + background: $menu-background-color; + } + } + + &-anchors { + color: $icon-button-color; + padding: 0; + } + + &-anchor { + padding: 10px 4px; + + &-selected { + color: $icon-button-active-color; + } + + &-bar { + background-color: $tab-indicator-color; + } + + &:hover { + color: $icon-button-hover-color; + } + } + + &-search { + background: $menu-background-color; + + input { + outline: none; + padding: 8px; + background: $search-bar-color; + color: $ui-text-color; + border: 0; + border-radius: $bar-radius; + + &:focus { + @include shadow-2dp; + background: $search-bar-focus-color; + } + } + } + + &-scroll { + padding: 0 8px 8px; + background: $menu-background-color; + } + + &-category-label span { + padding: 4px 6px; + background: $menu-background-color; + } + + &-emoji:hover:before { + background-color: $icon-background-hover-color; + } +} \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/icons.scss b/app/javascript/styles/mastodon-material-dev/icons.scss new file mode 100644 index 00000000000000..d4cc4ebff2651c --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/icons.scss @@ -0,0 +1,36 @@ +@charset "UTF-8"; +@import 'config'; +@import 'mixins'; + +.fa.fa-users.column-link, +.fa.fa-globe.column-link, +.fa.fa-address-book.column-link, +.fa.fa-bullhorn.column-link, +.fa.fa-envelope.column-link, +.fa.fa-bookmark.column-link, +.fa.fa-star.column-link, +.fa.fa-list-ul.column-link { + &__icon.fa-fw { color: $icon-color } +} + + +.fa { vertical-align: sub } //マテリアルアイコンを文字の高さにそろえる + +.fa.fa-times, +.fa.fa-eraser { vertical-align: middle } //↑の例外 + +.fa.fa-lock { text-transform: none } + +.fa-fw { width: 16px } + +.fa.fa-chevron-left.column-back-button__icon.fa-fw { + font-size: 20px; + margin-right: 16px; +} + +.icon-with-badge__badge { + background: $badge-color; + border: none; + padding: 2px 6px; + border-radius: 12px; +} \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/material-icons.scss b/app/javascript/styles/mastodon-material-dev/material-icons.scss new file mode 100644 index 00000000000000..d7c8fcbd71908c --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/material-icons.scss @@ -0,0 +1,88 @@ +@charset "UTF-8"; +@import 'config'; + + +.fa { + &.fa-bars, + &.fa-navicon, + &.fa-reorder, + &.fa-globe, + &.fa-cog, + &.fa-cogs, + &.fa-gears, + &.fa-sign-out, + &.fa-search, + &.fa-times, + &.fa-times-circle, + &.fa-close, + &.fa-remove, + &.fa-chevron-down, + &.fa-ellipsis-v, + &.fa-paperclip, + &.fa-tasks, + &.fa-plus, + &.fa-unlock, + &.fa-lock, + &.fa-envelope, + &.fa-home, + &.fa-bullhorn, + &.fa-sliders, + &.fa-chevron-left, + &.fa-chevron-right, + &.fa-reply, + &.fa-reply-all, + &.fa-star, + &.fa-bookmark, + &.fa-ellipsis-h, + &.fa-bell, + &.fa-eraser, + &.fa-users, + &.fa-file-text, + &.fa-user-plus, + &.fa-address-book, + &.fa-list, + &.fa-list-ul, + &.fa-eye, + &.fa-eye-slash, + &.fa-pencil, + &.fa-trash { + font-family: "Material Icons"; + } +} + +.fa { + &.fa-bars:before, &.fa-navicon:before,&.fa-reorder:before { content: "menu" } + &.fa-globe:before { content: "public" } + &.fa-cog:before, &.fa-cogs:before, &.fa-gears:before { content: "settings" } + &.fa-sign-out:before { content: "exit_to_app" } + &.fa-search:before { content: "search" } + &.fa-times:before, &.fa-times-circle:before, &.fa-close:before, &.fa-remove:before { content: "close" } + &.fa-chevron-down:before, &.fa-ellipsis-v:before { content: "more_vert" } + &.fa-paperclip:before { content: "attach_file" } + &.fa-tasks:before { content: "poll" } + &.fa-plus:before { content: "add" } + &.fa-unlock:before { content: "lock_open" } + &.fa-lock:before { content: "lock" } + &.fa-envelope:before { content: "mail" } + &.fa-home:before { content: "home" } + &.fa-bullhorn:before { content: "announcement" } + &.fa-sliders:before { content: "tune" } + &.fa-chevron-left:before { content: "arrow_back" } + &.fa-chevron-right:before { content: "arrow_forward" } + &.fa-reply:before { content: "reply" } + &.fa-reply-all:before { content: "reply_all" } + &.fa-bookmark:before { content: "bookmark" } + &.fa-ellipsis-h:before { content: "more_horiz" } + &.fa-bell:before { content: "notifications" } + &.fa-eraser:before { content: "clear_all" } + &.fa-users:before { content: "people" } + &.fa-file-text:before { content: "web" } + &.fa-user-plus:before { content: "person_add" } + &.fa-address-book:before { content: "explore" } + &.fa-list:before { content: "list" } + &.fa-list-ul:before { content: "list" } + &.fa-eye:before { content: "visibility" } + &.fa-eye-slash:before { content : "visibility_off" } + &.fa-pencil:before { content: "create" } + &.fa-trash:before { content: "delete" } +} \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/media.scss b/app/javascript/styles/mastodon-material-dev/media.scss new file mode 100644 index 00000000000000..14b43d4eac08bd --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/media.scss @@ -0,0 +1,17 @@ +@charset "UTF-8"; +@import 'config'; +@import 'mixins'; + + +.media-gallery { border-radius: $card-radius } + +.icon-button.overlayed { + border-radius: 50%; + background: $media-icon-background-color; + color: $media-icon-color; + + &:hover { + background: $media-icon-background-color; + color: $media-icon-hover-color; + } +} \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/mobile.scss b/app/javascript/styles/mastodon-material-dev/mobile.scss new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/app/javascript/styles/mastodon-material-dev/profile/material-v1.scss b/app/javascript/styles/mastodon-material-dev/profile/material-v1.scss new file mode 100644 index 00000000000000..b18ec1b7245e43 --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/profile/material-v1.scss @@ -0,0 +1,52 @@ +@charset "UTF-8"; +@import '../mixins'; + + +// Bar radius settings +$bar-radius: 2px; + + +// Button radius settings +$button-radius: 2px; + + +// Card radius settings +$card-radius: 2px; + + +// Dialog radius settings +$dialog-radius: 2px; + + +// Menu radius settings +$menu-radius: 2px; + + +// Navigation drawer item settings +$nav-drawer-item-radius: 0; + + +// Avater cropping settings +$avater-radius: 50%; // Rounded cropping +//$avater-radius: 2px // Material v1 square + + +// Favorite icon settings +.fa { + &.fa-star:before { content: "star" } // Star + //&.fa-star:before { content: "favorite" } // Heart + //&.fa-star:before { content: "plus_one" } // +1 +} + +.star-icon.active, +.notification__favourite-icon-wrapper .star-icon { + color: #ffd600; // Star + //color: #ff4081; // Heart + //color: #db4437; // +1 +} + + +// Button shadow +// If you want to use material v2 styled non-shadow button, please comment out this section. +.button, +.compose-form .compose-form__publish-button-wrapper { @include shadow-2dp } \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/profile/material-v2.scss b/app/javascript/styles/mastodon-material-dev/profile/material-v2.scss new file mode 100644 index 00000000000000..3e19b60e46af52 --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/profile/material-v2.scss @@ -0,0 +1,66 @@ +@charset "UTF-8"; +@import '../mixins'; + + +// Bar radius settings +$bar-radius: 8px; + + +// Button radius settings +$button-radius: 8px; + + +// Card radius settings +$card-radius: 8px; + + +// Dialog radius settings +$dialog-radius: 8px; + + +// Menu radius settings +$menu-radius: 8px; + + +// Navigation drawer item settings +$nav-drawer-item-radius: 8px; // corner rounded +//$nav-drawer-item-radius: 32px; // full rounded +//$nav-drawer-item-radius: 32px 0 0 32px; // left rounded + + +// Avater cropping settings +$avater-radius: 50%; // Rounded cropping +//$avater-radius: 8px // Material v2 square + + +// Favorite icon settings +.fa { + &.fa-star:before { content: "star" } // Star + //&.fa-star:before { content: "favorite" } // Heart + //&.fa-star:before { content: "plus_one" } // +1 +} + +.star-icon.active, +.notification__favourite-icon-wrapper .star-icon { + color: #ffd600; // Star + //color: #ff4081; // Heart + //color: #db4437; // +1 +} + + +// Chip settings +// If you want to use contained-chip, please comment out below. +.reactions-bar__item { + background: $outlined-chip-color !important; + border: 1px solid $border-color !important; + + &.active { background-color: $outlined-chip-selected-color !important } + + &:hover { background: $outlined-chip-hover-color !important } +} + + +// Button shadow +// If you want to use material v2 styled non-shadow button, please comment out this section. +.button, +.compose-form .compose-form__publish-button-wrapper { @include shadow-2dp } \ No newline at end of file diff --git a/app/javascript/styles/mastodon-material-dev/statuses.scss b/app/javascript/styles/mastodon-material-dev/statuses.scss new file mode 100644 index 00000000000000..5f1da722fccfeb --- /dev/null +++ b/app/javascript/styles/mastodon-material-dev/statuses.scss @@ -0,0 +1,135 @@ +@charset "UTF-8"; +@import 'config'; +@import 'mixins'; + + +.status { + padding: 12px 12px 12px 70px; + border-bottom: 1px solid $border-color; + + &__expand { width: 70px } + + &__info { font-size: 16px } + + &__relative-time { color: $info-text-color } + + &__display-name { + color: $secondary-text-color; + + strong { color: $primary-text-color } + } + + &__avatar { + left: 12px; + top: 12px; + } + + &__content { + font-size: 16px; + padding-top: 4px; + color: $primary-text-color; + + a { + color: $link-text-color; + + &.unhandled-link { color: $link-text-color } + } + + .status__content__spoiler-link { + background: transparent; + + &:hover { background: $text-button-hover-color } + + &:focus { background: $text-button-focus-color } + } + + &__spoiler-link { + border: 0; + color: $text-button-color; + } + + &__read-more-button { + font-size: 14px; + color: $text-button-color; + border-radius: $button-radius; + padding: 4px 6px; + + &:hover { + background: $text-button-hover-color; + text-decoration: none; + } + + &:focus { background: $text-button-focus-color } + } + } + + &__action-bar { + &__counter__label { + font-size: 14px; + color: $info-text-color; + } + } + + &.status-direct:not(.read) { + background: transparent; + border-bottom-color: $border-color; + } +} + +.status-card { + color: $icon-color; + border-color: $border-color; + outline: none; + + &__image { + background: $card-background-color; + + &>.fa { + font-size: 26px; + } + } + + &__title { + color: $primary-text-color; + margin-bottom: 6px; + } + &.compact { + border-color: $border-color; + outline: none; + .status-card { + &__content { padding: 12px } + &__image { flex: 0 0 64px } + } + + &:hover { background-color: $card-background-color !important } + } + + &:hover { background-color: $card-background-color } +} + +.detailed-status { + background: $card-background-color; + padding: 16px; + + &__display-name { + color: $secondary-text-color; + + strong { color: $primary-text-color } + } + + &__meta { + margin-top: 16px; + color: $info-text-color; + } + + &__action-bar { + background: $card-background-color; + border-top: none; + border-bottom: 1px solid $border-color; + padding: 12px 0; + } + + &__button { + .icon-button { font-size: 20px !important } + } +} \ No newline at end of file diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index d49fcfa995a9eb..f82c25cd12c818 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -10,8 +10,6 @@ def host_to_url(str) assets_host = Rails.configuration.action_controller.asset_host assets_host ||= "http#{Rails.configuration.x.use_https ? 's' : ''}://#{base_host}" -google_font_host = "https://fonts.gstatic.com" -gplus_theme_host = "https://raw.githubusercontent.com" assets_host ||= host_to_url(base_host) media_host = host_to_url(ENV['S3_ALIAS_HOST']) diff --git a/config/locales/en.yml b/config/locales/en.yml index 44c116dfb82bc3..0ec250025c68cc 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1192,7 +1192,8 @@ en: contrast: Mastodon (High contrast) default: Mastodon (Dark) mastodon-light: Mastodon (Light) - + # additional theme + mastodon-material-dev: Material Dev (Light) time: formats: default: "%b %d, %Y, %H:%M" diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 24a159e57f5927..2875d4fd7b8f21 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -1173,6 +1173,8 @@ ja: contrast: Mastodon (ハイコントラスト) default: Mastodon (ダーク) mastodon-light: Mastodon (ライト) + # 追加テーマ + mastodon-material: Material Dev (ライト) time: formats: default: "%Y年%m月%d日 %H:%M" diff --git a/config/themes.yml b/config/themes.yml index 9c21c9459f3bcf..e93b9f8f1107cf 100644 --- a/config/themes.yml +++ b/config/themes.yml @@ -1,3 +1,6 @@ default: styles/application.scss contrast: styles/contrast.scss mastodon-light: styles/mastodon-light.scss + +# 追加テーマ +mastodon-material: styles/mastodon-material-dev.scss From 663b2f91e2d0b86f7ad0c6fd2eaaeec1befb9591 Mon Sep 17 00:00:00 2001 From: Rintan Date: Mon, 9 Mar 2020 11:05:55 +0900 Subject: [PATCH 2/9] fix CSP (#268) --- config/initializers/content_security_policy.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index f82c25cd12c818..af7d16aafc521f 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -9,7 +9,6 @@ def host_to_url(str) base_host = Rails.configuration.x.web_domain assets_host = Rails.configuration.action_controller.asset_host -assets_host ||= "http#{Rails.configuration.x.use_https ? 's' : ''}://#{base_host}" assets_host ||= host_to_url(base_host) media_host = host_to_url(ENV['S3_ALIAS_HOST']) @@ -21,7 +20,7 @@ def host_to_url(str) p.base_uri :none p.default_src :none p.frame_ancestors :none - p.font_src :self, assets_host, google_font_host + p.font_src :self, assets_host p.img_src :self, :https, :data, :blob, assets_host p.style_src :self, :unsafe_inline, assets_host p.media_src :self, :https, :data, assets_host From f864de23f4996013e1b05b529214794e581f0611 Mon Sep 17 00:00:00 2001 From: Rintan Date: Mon, 9 Mar 2020 11:58:06 +0900 Subject: [PATCH 3/9] =?UTF-8?q?=E7=9B=B8=E5=AF=BE=E3=83=91=E3=82=B9?= =?UTF-8?q?=E3=81=AE=E4=BF=AE=E6=AD=A3=20(#269)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix CSP * fix icon font path --- .../styles/mastodon-material-dev/config.scss | 4 ++-- .../fonts/MaterialIcons-Regular.woff2 | Bin 2 files changed, 2 insertions(+), 2 deletions(-) rename app/javascript/styles/{ => mastodon-material-dev}/fonts/MaterialIcons-Regular.woff2 (100%) diff --git a/app/javascript/styles/mastodon-material-dev/config.scss b/app/javascript/styles/mastodon-material-dev/config.scss index e733bc8af62f56..cf04ac55b08a8c 100644 --- a/app/javascript/styles/mastodon-material-dev/config.scss +++ b/app/javascript/styles/mastodon-material-dev/config.scss @@ -10,12 +10,12 @@ // Material Design Icon settings -// If you want to use self-hosting font, please place MaterialIcons-Regular.woff2 file in .../fonts folder and configure below. +// If you want to use self-hosting font, please place MaterialIcons-Regular.woff2 file in 'fonts' folder and configure below. @font-face { font-family: "Material Icons"; src: local("Material Icons"), //url("https://raw.githubusercontent.com/google/material-design-icons/master/iconfont/MaterialIcons-Regular.woff2"); // GitHub //url("https://fonts.gstatic.com/s/materialicons/v50/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2"); // Google Fonts - url("../fonts/MaterialIcons-Regular.woff2"); // Self-hosting + url("fonts/MaterialIcons-Regular.woff2"); // Self-hosting } \ No newline at end of file diff --git a/app/javascript/styles/fonts/MaterialIcons-Regular.woff2 b/app/javascript/styles/mastodon-material-dev/fonts/MaterialIcons-Regular.woff2 similarity index 100% rename from app/javascript/styles/fonts/MaterialIcons-Regular.woff2 rename to app/javascript/styles/mastodon-material-dev/fonts/MaterialIcons-Regular.woff2 From 27998a80fe550f3161bf03f76724d01fb56fc2e3 Mon Sep 17 00:00:00 2001 From: Rintan Date: Mon, 9 Mar 2020 12:44:34 +0900 Subject: [PATCH 4/9] =?UTF-8?q?=E7=9B=B8=E5=AF=BE=E3=83=91=E3=82=B9?= =?UTF-8?q?=E3=81=AE=E4=BF=AE=E6=AD=A3=20(#270)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix CSP * fix icon font path * fix font path --- app/javascript/styles/mastodon-material-dev/config.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/styles/mastodon-material-dev/config.scss b/app/javascript/styles/mastodon-material-dev/config.scss index cf04ac55b08a8c..fbd0dd86d5df3f 100644 --- a/app/javascript/styles/mastodon-material-dev/config.scss +++ b/app/javascript/styles/mastodon-material-dev/config.scss @@ -10,7 +10,7 @@ // Material Design Icon settings -// If you want to use self-hosting font, please place MaterialIcons-Regular.woff2 file in 'fonts' folder and configure below. +// If you want to use self-hosting font, please place MaterialIcons-Regular.woff2 file in '../fonts' folder and configure below. @font-face { font-family: "Material Icons"; src: From 8f2dac1d9c6eccfe73966ea123817aa7fe33bf88 Mon Sep 17 00:00:00 2001 From: Rintan Date: Mon, 9 Mar 2020 19:11:50 +0900 Subject: [PATCH 5/9] =?UTF-8?q?Revert=20"=E7=9B=B8=E5=AF=BE=E3=83=91?= =?UTF-8?q?=E3=82=B9=E3=81=AE=E4=BF=AE=E6=AD=A3=20(#270)"=20(#271)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 27998a80fe550f3161bf03f76724d01fb56fc2e3. --- app/javascript/styles/mastodon-material-dev/config.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/styles/mastodon-material-dev/config.scss b/app/javascript/styles/mastodon-material-dev/config.scss index fbd0dd86d5df3f..cf04ac55b08a8c 100644 --- a/app/javascript/styles/mastodon-material-dev/config.scss +++ b/app/javascript/styles/mastodon-material-dev/config.scss @@ -10,7 +10,7 @@ // Material Design Icon settings -// If you want to use self-hosting font, please place MaterialIcons-Regular.woff2 file in '../fonts' folder and configure below. +// If you want to use self-hosting font, please place MaterialIcons-Regular.woff2 file in 'fonts' folder and configure below. @font-face { font-family: "Material Icons"; src: From 088e10354215b5cce7463af8822bb527c339e6f1 Mon Sep 17 00:00:00 2001 From: Rintan Date: Mon, 9 Mar 2020 20:34:06 +0900 Subject: [PATCH 6/9] =?UTF-8?q?Revert=20"=E7=9B=B8=E5=AF=BE=E3=83=91?= =?UTF-8?q?=E3=82=B9=E3=81=AE=E4=BF=AE=E6=AD=A3=20(#269)"=20(#272)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit f864de23f4996013e1b05b529214794e581f0611. --- .../fonts/MaterialIcons-Regular.woff2 | Bin .../styles/mastodon-material-dev/config.scss | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename app/javascript/styles/{mastodon-material-dev => }/fonts/MaterialIcons-Regular.woff2 (100%) diff --git a/app/javascript/styles/mastodon-material-dev/fonts/MaterialIcons-Regular.woff2 b/app/javascript/styles/fonts/MaterialIcons-Regular.woff2 similarity index 100% rename from app/javascript/styles/mastodon-material-dev/fonts/MaterialIcons-Regular.woff2 rename to app/javascript/styles/fonts/MaterialIcons-Regular.woff2 diff --git a/app/javascript/styles/mastodon-material-dev/config.scss b/app/javascript/styles/mastodon-material-dev/config.scss index cf04ac55b08a8c..e733bc8af62f56 100644 --- a/app/javascript/styles/mastodon-material-dev/config.scss +++ b/app/javascript/styles/mastodon-material-dev/config.scss @@ -10,12 +10,12 @@ // Material Design Icon settings -// If you want to use self-hosting font, please place MaterialIcons-Regular.woff2 file in 'fonts' folder and configure below. +// If you want to use self-hosting font, please place MaterialIcons-Regular.woff2 file in .../fonts folder and configure below. @font-face { font-family: "Material Icons"; src: local("Material Icons"), //url("https://raw.githubusercontent.com/google/material-design-icons/master/iconfont/MaterialIcons-Regular.woff2"); // GitHub //url("https://fonts.gstatic.com/s/materialicons/v50/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2"); // Google Fonts - url("fonts/MaterialIcons-Regular.woff2"); // Self-hosting + url("../fonts/MaterialIcons-Regular.woff2"); // Self-hosting } \ No newline at end of file From 0d9aa65dc36a9d0cc859b9b3317a3527801a5092 Mon Sep 17 00:00:00 2001 From: Rintan Date: Mon, 9 Mar 2020 21:44:45 +0900 Subject: [PATCH 7/9] =?UTF-8?q?=E3=83=95=E3=82=A9=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=83=91=E3=82=B9=E3=81=AE=E4=BF=AE=E6=AD=A3=20(#273)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix CSP * fix icon font path * fix relative path --- .../{styles => }/fonts/MaterialIcons-Regular.woff2 | Bin .../styles/mastodon-material-dev/config.scss | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename app/javascript/{styles => }/fonts/MaterialIcons-Regular.woff2 (100%) diff --git a/app/javascript/styles/fonts/MaterialIcons-Regular.woff2 b/app/javascript/fonts/MaterialIcons-Regular.woff2 similarity index 100% rename from app/javascript/styles/fonts/MaterialIcons-Regular.woff2 rename to app/javascript/fonts/MaterialIcons-Regular.woff2 diff --git a/app/javascript/styles/mastodon-material-dev/config.scss b/app/javascript/styles/mastodon-material-dev/config.scss index e733bc8af62f56..3095407d83d8dd 100644 --- a/app/javascript/styles/mastodon-material-dev/config.scss +++ b/app/javascript/styles/mastodon-material-dev/config.scss @@ -10,7 +10,7 @@ // Material Design Icon settings -// If you want to use self-hosting font, please place MaterialIcons-Regular.woff2 file in .../fonts folder and configure below. +// If you want to use self-hosting font, please place MaterialIcons-Regular.woff2 file in '../../fonts' folder and configure below. @font-face { font-family: "Material Icons"; src: From 047567a657353b51712a54cc8180f3720174ee90 Mon Sep 17 00:00:00 2001 From: Rintan Date: Mon, 9 Mar 2020 22:36:11 +0900 Subject: [PATCH 8/9] =?UTF-8?q?=E3=82=AA=E3=83=BC=E3=83=90=E3=83=BC?= =?UTF-8?q?=E3=83=A9=E3=82=A4=E3=83=89=E8=A8=AD=E5=AE=9A=E3=81=AE=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=20(#274)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix CSP * fix icon font path * fix relative path * fix override settings --- app/javascript/styles/mastodon-material-dev.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/app/javascript/styles/mastodon-material-dev.scss b/app/javascript/styles/mastodon-material-dev.scss index 9cc10708dd3411..18935348a3c8b5 100644 --- a/app/javascript/styles/mastodon-material-dev.scss +++ b/app/javascript/styles/mastodon-material-dev.scss @@ -1,5 +1,6 @@ @charset "UTF-8"; +@import 'application'; @import 'mastodon-material-dev/account'; @import 'mastodon-material-dev/basics'; @import 'mastodon-material-dev/button'; From 5676b1e5ad70fa18bb804a77ca205d97d887021a Mon Sep 17 00:00:00 2001 From: YoheiZuho Date: Mon, 6 Apr 2020 20:38:20 +0900 Subject: [PATCH 9/9] 3.1.3 (#275) (#277) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix announcements with fully-qualified mention to local user crashing WebUI (#13164) * [Security] Bump puma from 4.3.1 to 4.3.2 (#13167) Bumps [puma](https://github.com/puma/puma) from 4.3.1 to 4.3.2. **This update includes a security fix.** - [Release notes](https://github.com/puma/puma/releases) - [Changelog](https://github.com/puma/puma/blob/master/History.md) - [Commits](https://github.com/puma/puma/compare/v4.3.1...v4.3.2) Signed-off-by: dependabot-preview[bot] * Fix installation failing when Redis password contains special characters (#13156) * Add support for special characters in Redis passwords Fixes #13154 * Refactor * Fix elasticsearch-api and faraday incompatibilities (#13166) * Bump puma from 4.3.2 to 4.3.3 (#13177) This fixes cookies and devise authentication being broken as a result of upgrading to puma 4.3.2, see https://github.com/puma/puma/issues/2132 * Bump strong_migrations from 0.5.1 to 0.6.2 (#13071) Bumps [strong_migrations](https://github.com/ankane/strong_migrations) from 0.5.1 to 0.6.2. - [Release notes](https://github.com/ankane/strong_migrations/releases) - [Changelog](https://github.com/ankane/strong_migrations/blob/master/CHANGELOG.md) - [Commits](https://github.com/ankane/strong_migrations/compare/v0.5.1...v0.6.2) Signed-off-by: dependabot-preview[bot] * Bump oj from 3.10.1 to 3.10.3 (#13187) Bumps [oj](https://github.com/ohler55/oj) from 3.10.1 to 3.10.3. - [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.10.1...v3.10.3) Signed-off-by: dependabot-preview[bot] * Bump json-ld-preloaded from 3.1.0 to 3.1.1 (#13143) Bumps [json-ld-preloaded](https://github.com/ruby-rdf/json-ld-preloaded) from 3.1.0 to 3.1.1. - [Release notes](https://github.com/ruby-rdf/json-ld-preloaded/releases) - [Commits](https://github.com/ruby-rdf/json-ld-preloaded/compare/3.1.0...3.1.1) Signed-off-by: dependabot-preview[bot] * Bump @babel/core from 7.8.4 to 7.8.6 (#13185) Bumps [@babel/core](https://github.com/babel/babel) from 7.8.4 to 7.8.6. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) - [Commits](https://github.com/babel/babel/compare/v7.8.4...v7.8.6) Signed-off-by: dependabot-preview[bot] * Bump webpack-dev-server from 3.10.1 to 3.10.3 (#13184) Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 3.10.1 to 3.10.3. - [Release notes](https://github.com/webpack/webpack-dev-server/releases) - [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md) - [Commits](https://github.com/webpack/webpack-dev-server/compare/v3.10.1...v3.10.3) Signed-off-by: dependabot-preview[bot] * Bump @babel/runtime from 7.8.3 to 7.8.4 (#13183) Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.8.3 to 7.8.4. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.8.4/packages/babel-runtime) Signed-off-by: dependabot-preview[bot] * Add tooltips to audio/video player buttons (#13203) * Fix "tootctl media remove-orphans" crashing when encountering invalid media (#13170) Fixes #13168 * Change the string "Hide everything from …" to "Block domain …" in web UI (#13178) Blocking a domain is closer to blocking all its users than to a mute action. * Remove useless `respond_to` calls (#13208) * Change GIF label to be displayed even when autoplay is enabled in web UI (#13209) * Fix too large announcements not being scrollable in web UI (#13211) * Add specific rate limits for posting and following (#13172) * Fix text area above/right of emoji picker being accidentally clickable in web UI (#13148) * Add sorting by username, creation and last activity in moderation view (#13076) * Add ability to order accounts in moderation view * Display last status date in “Most recent activity” for remote users * Fix error when searching for URLs that contain the mention syntax (#13151) Fixes #13150 * Set BUNDLE_PATH in CircleCI (#13214) * Change description of privacy levels to be more intuitive in web UI (#13197) * Improve description of privacy levels in compose interface * Change strings in defaultMessage and source as well as english Co-authored-by: Thibaut Girka * Add ability to delete files uploaded for settings in admin UI (#13192) * Allow deleting site uploads * Refactor and move links into hints * Fix i18n tests * Fix HTML output of site_upload_delete_hint * Add `--skip-media-remove` option to `tootctl statuses remove` (#13080) * Add skip_media_remove option to tootctl statuses remove * Add skip_media_remove option to tootctl statuses remove Co-authored-by: tateisu * Code style improvements in JavaScript (#13159) * JS-linter: fix trailing comma's * Configure eslinter to ignore this onchange error. * Add submit button to the top of preferences pages (#13068) * Move submit button to the top of the edit page * Duplicate save button on long form * Fix click submit on profile spec * Update nginx.conf (#13066) * Change wording of media display preferences to be more intuitive (#13198) * Change the tooltip "Toggle visibility" to "Hide media" in web UI (#13199) * Add support for links to statuses in announcements to be opened in web UI (#13212) * Add support for links to public statuses in announcements to be opened in WebUI * Please CodeClimate * Fix public posts from silenced accounts not being changed to unlisted visibility (#13096) * Bump doorkeeper from 5.2.3 to 5.3.1 (#13144) Bumps [doorkeeper](https://github.com/doorkeeper-gem/doorkeeper) from 5.2.3 to 5.3.1. - [Release notes](https://github.com/doorkeeper-gem/doorkeeper/releases) - [Changelog](https://github.com/doorkeeper-gem/doorkeeper/blob/master/CHANGELOG.md) - [Commits](https://github.com/doorkeeper-gem/doorkeeper/compare/v5.2.3...v.5.3.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Change local media attachments to perform heavy processing asynchronously (#13210) Fix #9106 * Add federation support for the "hide network" preference (#11673) * Change ActivityPub follower/following collections to not link first page * Add support for hiding followers and following of remote users * Switch to using a single `hide_collections` column * Address code style remarks * Bump cld3 from 3.2.6 to 3.3.0 (#13107) * Bump cld3 from 3.2.6 to 3.3.0 Bumps [cld3](https://github.com/akihikodaki/cld3-ruby) from 3.2.6 to 3.3.0. - [Release notes](https://github.com/akihikodaki/cld3-ruby/releases) - [Commits](https://github.com/akihikodaki/cld3-ruby/compare/v3.2.6...v3.3.0) Signed-off-by: dependabot-preview[bot] * Fix compatibility with cld3 3.3.0 Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Eugen Rochko * Change video uploads to enforce certain limits (#13218) - Dimensions at most 1920x1200 - Frame rate at most 60 * Change video uploads to always be converted to H264/MP4 (#13220) Even if the container format is the same (.mp4), the codec could be different and not playable in web browsers * Change the string "hidden" to "blocked" in WebUI (#13221) * Change the string "hidden" to "blocked" in WebUI. * update * Bump file-loader from 5.0.2 to 5.1.0 (#13225) Bumps [file-loader](https://github.com/webpack-contrib/file-loader) from 5.0.2 to 5.1.0. - [Release notes](https://github.com/webpack-contrib/file-loader/releases) - [Changelog](https://github.com/webpack-contrib/file-loader/blob/master/CHANGELOG.md) - [Commits](https://github.com/webpack-contrib/file-loader/compare/v5.0.2...v5.1.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump wicg-inert from 3.0.0 to 3.0.2 (#13226) Bumps [wicg-inert](https://github.com/WICG/inert) from 3.0.0 to 3.0.2. - [Release notes](https://github.com/WICG/inert/releases) - [Commits](https://github.com/WICG/inert/compare/v3.0.0...v3.0.2) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump cross-env from 6.0.3 to 7.0.2 (#13228) Bumps [cross-env](https://github.com/kentcdodds/cross-env) from 6.0.3 to 7.0.2. - [Release notes](https://github.com/kentcdodds/cross-env/releases) - [Changelog](https://github.com/kentcdodds/cross-env/blob/master/CHANGELOG.md) - [Commits](https://github.com/kentcdodds/cross-env/compare/v6.0.3...v7.0.2) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump eslint-plugin-react from 7.17.0 to 7.19.0 (#13224) Bumps [eslint-plugin-react](https://github.com/yannickcr/eslint-plugin-react) from 7.17.0 to 7.19.0. - [Release notes](https://github.com/yannickcr/eslint-plugin-react/releases) - [Changelog](https://github.com/yannickcr/eslint-plugin-react/blob/master/CHANGELOG.md) - [Commits](https://github.com/yannickcr/eslint-plugin-react/compare/v7.17.0...v7.19.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Fix MP4 (H264 + AAC) video files being needlessly re-encoded (#13239) * Fix videos with unsupported colorspace not being transcoded (#13242) * Fix regression in “Edit media” modal in web UI (#13243) * [Security] Bump Node.js from 12.14.0 to 12.16.1 in Docker (#13235) * Update Dockerfile * Update Dockerfile * Fix detailed view of direct messages displaying a 0 boost count (#13244) The boost count is already removed from private toots, do the same with direct messages. * Add titles to warning presets in admin UI (#13252) * Add option to include resolved DNS records when blacklisting e-mail domains in admin UI (#13254) * Add shortcuts to blacklist a user's e-mail domain in admin UI * Add option to blacklist resolved MX and IP records for e-mail domains * Fix some timeouts when searching URLs by limiting some database queries (#13253) Only look up private toots from database if the request failed because of 401, 403 or 404 errors, as those may indicate a private toot, rather than something that isn't a toot or cannot be processed. * Fix WebUI crash in single-column mode on prehistoric browsers (#13267) Fixes #13266 * Bump react-immutable-proptypes from 2.1.0 to 2.2.0 (#13259) Bumps [react-immutable-proptypes](https://github.com/HurricaneJames/react-immutable-proptypes) from 2.1.0 to 2.2.0. - [Release notes](https://github.com/HurricaneJames/react-immutable-proptypes/releases) - [Changelog](https://github.com/HurricaneJames/react-immutable-proptypes/blob/master/CHANGELOG.md) - [Commits](https://github.com/HurricaneJames/react-immutable-proptypes/commits) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump babel-jest from 24.9.0 to 25.1.0 (#12973) Bumps [babel-jest](https://github.com/facebook/jest/tree/HEAD/packages/babel-jest) from 24.9.0 to 25.1.0. - [Release notes](https://github.com/facebook/jest/releases) - [Changelog](https://github.com/facebook/jest/blob/master/CHANGELOG.md) - [Commits](https://github.com/facebook/jest/commits/v25.1.0/packages/babel-jest) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump react-dom from 16.12.0 to 16.13.0 (#13181) Bumps [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) from 16.12.0 to 16.13.0. - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/master/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v16.13.0/packages/react-dom) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump react-test-renderer from 16.12.0 to 16.13.0 (#13260) Bumps [react-test-renderer](https://github.com/facebook/react/tree/HEAD/packages/react-test-renderer) from 16.12.0 to 16.13.0. - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/master/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v16.13.0/packages/react-test-renderer) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump sass from 1.25.0 to 1.26.3 (#13263) Bumps [sass](https://github.com/sass/dart-sass) from 1.25.0 to 1.26.3. - [Release notes](https://github.com/sass/dart-sass/releases) - [Changelog](https://github.com/sass/dart-sass/blob/master/CHANGELOG.md) - [Commits](https://github.com/sass/dart-sass/compare/1.25.0...1.26.3) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump mkdirp from 0.5.1 to 1.0.3 (#12979) Bumps [mkdirp](https://github.com/isaacs/node-mkdirp) from 0.5.1 to 1.0.3. - [Release notes](https://github.com/isaacs/node-mkdirp/releases) - [Changelog](https://github.com/isaacs/node-mkdirp/blob/master/CHANGELOG.md) - [Commits](https://github.com/isaacs/node-mkdirp/commits/v1.0.3) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump redis from 2.8.0 to 3.0.2 (#13102) Bumps [redis](https://github.com/NodeRedis/node-redis) from 2.8.0 to 3.0.2. - [Release notes](https://github.com/NodeRedis/node-redis/releases) - [Changelog](https://github.com/NodeRedis/node-redis/blob/master/CHANGELOG.md) - [Commits](https://github.com/NodeRedis/node-redis/compare/v.2.8.0...v3.0.2) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump json-ld from 3.1.0 to 3.1.1 (#13230) Bumps [json-ld](https://github.com/ruby-rdf/json-ld) from 3.1.0 to 3.1.1. - [Release notes](https://github.com/ruby-rdf/json-ld/releases) - [Commits](https://github.com/ruby-rdf/json-ld/compare/3.1.0...3.1.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump simple_form from 5.0.1 to 5.0.2 (#13231) Bumps [simple_form](https://github.com/plataformatec/simple_form) from 5.0.1 to 5.0.2. - [Release notes](https://github.com/plataformatec/simple_form/releases) - [Changelog](https://github.com/heartcombo/simple_form/blob/master/CHANGELOG.md) - [Commits](https://github.com/plataformatec/simple_form/compare/v5.0.1...v5.0.2) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump sidekiq-scheduler from 3.0.0 to 3.0.1 (#13233) Bumps [sidekiq-scheduler](https://github.com/moove-it/sidekiq-scheduler) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/moove-it/sidekiq-scheduler/releases) - [Commits](https://github.com/moove-it/sidekiq-scheduler/compare/v3.0.0...v3.0.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump webmock from 3.8.0 to 3.8.3 (#13265) Bumps [webmock](https://github.com/bblimke/webmock) from 3.8.0 to 3.8.3. - [Release notes](https://github.com/bblimke/webmock/releases) - [Changelog](https://github.com/bblimke/webmock/blob/master/CHANGELOG.md) - [Commits](https://github.com/bblimke/webmock/compare/v3.8.0...v3.8.3) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump capistrano from 3.11.2 to 3.12.1 (#13264) * Bump capistrano from 3.11.2 to 3.12.1 Bumps [capistrano](https://github.com/capistrano/capistrano) from 3.11.2 to 3.12.1. - [Release notes](https://github.com/capistrano/capistrano/releases) - [Commits](https://github.com/capistrano/capistrano/compare/v3.11.2...v3.12.1) Signed-off-by: dependabot-preview[bot] * Bump capistrano from 3.11.2 to 3.12.1 Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Yamagishi Kazutoshi * Fix reported accounts not being whitelisted when resolving a spamcheck report (#13289) * Decommission support for Ruby 2.4 (#13287) * Update Gemfile * Update README.md * Fix frontend crash when deleting announcements (#13283) This two-line change fixes a crash in the front end that occurred under the following circumstances: * A server had more than one announcement, * A user was displaying the announcements, and * An announcement was deleted (or unpublished, which amounts to the same thing.) As might be expected, the bug was caused by attempting to access a notification using an index value outside the bounds of the existing announcements. Specifically, in two places. First, `_markAnnouncementAsRead` attempts to modify announcements based on the current index. This is what caused the front end crash. Second, when rendering the `Announcements` component, the code paginates the announcements and displays the current one. This did not cause a crash, but caused the front end to confusingly display a blank announcement (in situations that would have caused a crash) with no way for the user to navigate back to previous announcements. This commit fixes both issues by adding a check to ensure that the code never attempts to access an announcement with an index greater than or equal to the number of announcements present. * Make bookmarks also searchable (#13271) * Add link to bookmarks in web UI dropdown (#13273) * Migrate Rails ujs as required for Rails 6 Upgrade. (#13280) * Update yarn.lock * Update package.json * Update public.js * Update admin.js * Update log_out.js * Update common.js * [Security] Bump omniauth from 1.9.0 to 1.9.1 (#13229) Bumps [omniauth](https://github.com/omniauth/omniauth) from 1.9.0 to 1.9.1. **This update includes a security fix.** - [Release notes](https://github.com/omniauth/omniauth/releases) - [Commits](https://github.com/omniauth/omniauth/compare/v1.9.0...v1.9.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump sidekiq from 5.2.7 to 6.0.4 (#11727) * Bump sidekiq from 5.2.7 to 6.0.0 Bumps [sidekiq](https://github.com/mperham/sidekiq) from 5.2.7 to 6.0.0. - [Release notes](https://github.com/mperham/sidekiq/releases) - [Changelog](https://github.com/mperham/sidekiq/blob/master/Changes.md) - [Commits](https://github.com/mperham/sidekiq/compare/v5.2.7...v6.0.0) Signed-off-by: dependabot-preview[bot] * Sidekiq::Logger.logger -> Sidekiq.logger * Drop support Ruby 2.4 * update Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Yamagishi Kazutoshi * Fix bookmarks also searchable (#13293) * Bump sidekiq-unique-jobs from 6.0.18 to 6.0.20 (#13294) * Change poll option hover/active styling to be less confusing (#13313) * Fix frontend crash when deleting announcements (#13312) Refactor and fix #13283, which only worked in some cases. * Fix media not being marked sensitive when client sets a CW but no text (#13277) Mastodon enforces the “sensitive” flag on media attachments whenever a toot is posted with a Content Warning. However, it does so *after* potentially converting the Content Warning to toot text (when there is no toot text), which leads to inconsistent and surprising behavior for API clients. This commit fixes this inconsistency. * Bump browser from 3.0.3 to 4.0.0 (#13307) Bumps [browser](https://github.com/fnando/browser) from 3.0.3 to 4.0.0. - [Release notes](https://github.com/fnando/browser/releases) - [Changelog](https://github.com/fnando/browser/blob/master/CHANGELOG.md) - [Commits](https://github.com/fnando/browser/compare/v3.0.3...v4.0.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump i18n-tasks from 0.9.30 to 0.9.31 (#13304) Bumps [i18n-tasks](https://github.com/glebm/i18n-tasks) from 0.9.30 to 0.9.31. - [Release notes](https://github.com/glebm/i18n-tasks/releases) - [Changelog](https://github.com/glebm/i18n-tasks/blob/master/CHANGES.md) - [Commits](https://github.com/glebm/i18n-tasks/compare/v0.9.30...v0.9.31) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump simplecov from 0.18.2 to 0.18.5 (#13310) Bumps [simplecov](https://github.com/colszowka/simplecov) from 0.18.2 to 0.18.5. - [Release notes](https://github.com/colszowka/simplecov/releases) - [Changelog](https://github.com/colszowka/simplecov/blob/master/CHANGELOG.md) - [Commits](https://github.com/colszowka/simplecov/compare/v0.18.2...v0.18.5) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump rspec-rails from 3.9.0 to 3.9.1 (#13305) Bumps [rspec-rails](https://github.com/rspec/rspec-rails) from 3.9.0 to 3.9.1. - [Release notes](https://github.com/rspec/rspec-rails/releases) - [Changelog](https://github.com/rspec/rspec-rails/blob/master/Changelog.md) - [Commits](https://github.com/rspec/rspec-rails/compare/v3.9.0...v3.9.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump discard from 1.1.0 to 1.2.0 (#13308) Bumps [discard](https://github.com/jhawthorn/discard) from 1.1.0 to 1.2.0. - [Release notes](https://github.com/jhawthorn/discard/releases) - [Changelog](https://github.com/jhawthorn/discard/blob/master/CHANGELOG.md) - [Commits](https://github.com/jhawthorn/discard/commits) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump aws-sdk-s3 from 1.60.1 to 1.61.1 (#13306) Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.60.1 to 1.61.1. - [Release notes](https://github.com/aws/aws-sdk-ruby/releases) - [Changelog](https://github.com/aws/aws-sdk-ruby/blob/master/gems/aws-sdk-s3/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-ruby/commits) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * New Crowdin translations (#13064) * New translations en.yml (Russian) [ci skip] * New translations en.yml (Dutch) [ci skip] * New translations en.yml (Greek) [ci skip] * New translations en.json (Dutch) [ci skip] * New translations en.yml (German) [ci skip] * New translations en.yml (Dutch) [ci skip] * New translations en.yml (Spanish) [ci skip] * New translations en.yml (Spanish, Argentina) [ci skip] * New translations simple_form.en.yml (Dutch) [ci skip] * New translations en.yml (Persian) [ci skip] * New translations en.yml (Italian) [ci skip] * New translations en.yml (Icelandic) [ci skip] * New translations en.json (Dutch) [ci skip] * New translations en.json (Dutch) [ci skip] * New translations en.yml (Kabyle) [ci skip] * New translations en.yml (Korean) [ci skip] * New translations en.yml (Persian) [ci skip] * New translations en.yml (Catalan) [ci skip] * New translations en.yml (French) [ci skip] * New translations en.yml (Chinese Traditional) [ci skip] * New translations simple_form.en.yml (Chinese Traditional) [ci skip] * New translations en.yml (Chinese Traditional, Hong Kong) [ci skip] * New translations simple_form.en.yml (Chinese Traditional, Hong Kong) [ci skip] * New translations simple_form.en.yml (Chinese Traditional, Hong Kong) [ci skip] * New translations simple_form.en.yml (Chinese Traditional) [ci skip] * New translations en.yml (Spanish) [ci skip] * New translations simple_form.en.yml (Chinese Traditional) [ci skip] * New translations en.yml (Spanish, Argentina) [ci skip] * New translations simple_form.en.yml (Chinese Traditional, Hong Kong) [ci skip] * New translations en.yml (French) [ci skip] * New translations en.yml (German) [ci skip] * New translations en.yml (Greek) [ci skip] * New translations en.yml (Korean) [ci skip] * New translations en.yml (Swedish) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations en.yml (Galician) [ci skip] * New translations en.yml (Catalan) [ci skip] * New translations en.json (Japanese) [ci skip] * New translations en.yml (Japanese) [ci skip] * New translations simple_form.en.yml (Japanese) [ci skip] * New translations en.yml (Arabic) [ci skip] * New translations en.json (Kabyle) [ci skip] * New translations en.yml (Kabyle) [ci skip] * New translations en.yml (Icelandic) [ci skip] * New translations en.yml (Corsican) [ci skip] * New translations en.yml (French) [ci skip] * New translations en.yml (Portuguese) [ci skip] * New translations en.yml (Portuguese, Brazilian) [ci skip] * New translations en.json (Japanese) [ci skip] * New translations en.yml (Japanese) [ci skip] * New translations en.yml (Hungarian) [ci skip] * New translations en.yml (Portuguese, Brazilian) [ci skip] * New translations en.yml (Persian) [ci skip] * New translations en.yml (Spanish, Argentina) [ci skip] * New translations en.json (Japanese) [ci skip] * New translations en.yml (Chinese Simplified) [ci skip] * New translations en.json (Greek) [ci skip] * New translations en.yml (Greek) [ci skip] * New translations simple_form.en.yml (Greek) [ci skip] * New translations en.json (Breton) [ci skip] * New translations en.yml (Icelandic) [ci skip] * New translations devise.en.yml (Icelandic) [ci skip] * New translations en.json (Italian) [ci skip] * New translations simple_form.en.yml (German) [ci skip] * New translations en.yml (Portuguese, Brazilian) [ci skip] * New translations en.yml (Portuguese, Brazilian) [ci skip] * New translations simple_form.en.yml (Portuguese, Brazilian) [ci skip] * New translations en.yml (Lithuanian) [ci skip] * New translations en.yml (Norwegian) [ci skip] * New translations en.yml (Norwegian Nynorsk) [ci skip] * New translations en.yml (Korean) [ci skip] * New translations en.yml (Hungarian) [ci skip] * New translations en.yml (Indonesian) [ci skip] * New translations en.yml (Japanese) [ci skip] * New translations en.yml (Kazakh) [ci skip] * New translations en.yml (Occitan) [ci skip] * New translations en.yml (Spanish) [ci skip] * New translations en.yml (Slovenian) [ci skip] * New translations en.yml (Thai) [ci skip] * New translations en.yml (Turkish) [ci skip] * New translations en.yml (Ukrainian) [ci skip] * New translations en.yml (Persian) [ci skip] * New translations en.yml (Polish) [ci skip] * New translations en.yml (Portuguese) [ci skip] * New translations en.yml (Serbian (Cyrillic)) [ci skip] * New translations en.yml (Slovak) [ci skip] * New translations en.yml (Icelandic) [ci skip] * New translations en.yml (Albanian) [ci skip] * New translations en.yml (Basque) [ci skip] * New translations en.yml (Spanish, Argentina) [ci skip] * New translations en.yml (Catalan) [ci skip] * New translations en.yml (Arabic) [ci skip] * New translations en.yml (Italian) [ci skip] * New translations en.yml (Portuguese, Brazilian) [ci skip] * New translations en.yml (Swedish) [ci skip] * New translations en.yml (Kabyle) [ci skip] * New translations en.yml (French) [ci skip] * New translations en.yml (Czech) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations en.yml (Esperanto) [ci skip] * New translations en.yml (Estonian) [ci skip] * New translations en.yml (Galician) [ci skip] * New translations en.yml (German) [ci skip] * New translations en.yml (Greek) [ci skip] * New translations en.yml (Chinese Simplified) [ci skip] * New translations en.yml (Chinese Traditional) [ci skip] * New translations en.yml (Chinese Traditional, Hong Kong) [ci skip] * New translations en.yml (Corsican) [ci skip] * New translations en.yml (Dutch) [ci skip] * New translations en.yml (Danish) [ci skip] * New translations en.yml (Welsh) [ci skip] * New translations en.yml (Vietnamese) [ci skip] * New translations simple_form.en.yml (Spanish, Argentina) [ci skip] * New translations simple_form.en.yml (Corsican) [ci skip] * New translations simple_form.en.yml (Spanish) [ci skip] * New translations simple_form.en.yml (Spanish, Argentina) [ci skip] * New translations simple_form.en.yml (Icelandic) [ci skip] * New translations simple_form.en.yml (Italian) [ci skip] * New translations simple_form.en.yml (German) [ci skip] * New translations en.yml (Italian) [ci skip] * New translations simple_form.en.yml (Russian) [ci skip] * New translations simple_form.en.yml (Swedish) [ci skip] * New translations simple_form.en.yml (Portuguese, Brazilian) [ci skip] * New translations simple_form.en.yml (Catalan) [ci skip] * New translations simple_form.en.yml (Persian) [ci skip] * New translations simple_form.en.yml (Portuguese) [ci skip] * New translations simple_form.en.yml (Arabic) [ci skip] * New translations simple_form.en.yml (French) [ci skip] * New translations simple_form.en.yml (Korean) [ci skip] * New translations devise.en.yml (Kabyle) [ci skip] * New translations en.yml (Welsh) [ci skip] * New translations simple_form.en.yml (Welsh) [ci skip] * New translations en.yml (Korean) [ci skip] * New translations simple_form.en.yml (Korean) [ci skip] * New translations simple_form.en.yml (Icelandic) [ci skip] * New translations en.yml (Icelandic) [ci skip] * New translations en.yml (Spanish) [ci skip] * New translations simple_form.en.yml (Spanish) [ci skip] * New translations simple_form.en.yml (Spanish, Argentina) [ci skip] * New translations en.yml (Spanish, Argentina) [ci skip] * New translations en.yml (Persian) [ci skip] * New translations simple_form.en.yml (Persian) [ci skip] * New translations en.yml (Catalan) [ci skip] * New translations en.yml (Portuguese, Brazilian) [ci skip] * New translations simple_form.en.yml (Portuguese, Brazilian) [ci skip] * New translations simple_form.en.yml (Portuguese) [ci skip] * New translations en.yml (Portuguese) [ci skip] * New translations simple_form.en.yml (Catalan) [ci skip] * New translations simple_form.en.yml (Portuguese) [ci skip] * New translations simple_form.en.yml (Portuguese, Brazilian) [ci skip] * New translations en.yml (German) [ci skip] * New translations simple_form.en.yml (German) [ci skip] * New translations en.yml (Chinese Traditional) [ci skip] * New translations en.yml (Chinese Traditional, Hong Kong) [ci skip] * New translations en.yml (Chinese Traditional) [ci skip] * New translations en.yml (Chinese Traditional, Hong Kong) [ci skip] * New translations en.yml (Chinese Traditional) [ci skip] * New translations en.yml (Chinese Traditional, Hong Kong) [ci skip] * New translations en.yml (Korean) [ci skip] * New translations simple_form.en.yml (Korean) [ci skip] * New translations en.yml (Chinese Traditional) [ci skip] * New translations en.yml (Chinese Traditional, Hong Kong) [ci skip] * New translations simple_form.en.yml (Russian) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations en.yml (Spanish, Argentina) [ci skip] * New translations simple_form.en.yml (Spanish, Argentina) [ci skip] * New translations simple_form.en.yml (Galician) [ci skip] * New translations simple_form.en.yml (Icelandic) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations en.yml (Galician) [ci skip] * New translations en.yml (Corsican) [ci skip] * New translations simple_form.en.yml (Corsican) [ci skip] * New translations en.yml (Corsican) [ci skip] * New translations simple_form.en.yml (Corsican) [ci skip] * New translations en.yml (Hungarian) [ci skip] * New translations simple_form.en.yml (Hungarian) [ci skip] * New translations en.json (Kabyle) [ci skip] * New translations simple_form.en.yml (Hungarian) [ci skip] * New translations simple_form.en.yml (Portuguese, Brazilian) [ci skip] * New translations en.yml (Portuguese, Brazilian) [ci skip] * New translations en.yml (Greek) [ci skip] * New translations simple_form.en.yml (Greek) [ci skip] * New translations en.yml (French) [ci skip] * New translations simple_form.en.yml (French) [ci skip] * New translations simple_form.en.yml (Asturian) [ci skip] * New translations en.json (Breton) [ci skip] * New translations en.yml (Italian) [ci skip] * New translations simple_form.en.yml (Italian) [ci skip] * New translations devise.en.yml (Kabyle) [ci skip] * New translations en.yml (Basque) [ci skip] * New translations simple_form.en.yml (Basque) [ci skip] * New translations simple_form.en.yml (Occitan) [ci skip] * New translations en.yml (Slovak) [ci skip] * New translations simple_form.en.yml (Slovak) [ci skip] * New translations en.json (Japanese) [ci skip] * New translations en.json (Japanese) [ci skip] * New translations en.yml (Japanese) [ci skip] * New translations simple_form.en.yml (Japanese) [ci skip] * New translations en.yml (Japanese) [ci skip] * New translations simple_form.en.yml (Japanese) [ci skip] * New translations simple_form.en.yml (Chinese Simplified) [ci skip] * New translations en.yml (Chinese Simplified) [ci skip] * New translations en.json (Japanese) [ci skip] * New translations simple_form.en.yml (Chinese Simplified) [ci skip] * New translations en.yml (Polish) [ci skip] * New translations en.json (Russian) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations en.json (French) [ci skip] * New translations en.yml (Slovak) [ci skip] * New translations doorkeeper.en.yml (Slovak) [ci skip] * New translations en.yml (Polish) [ci skip] * New translations simple_form.en.yml (Polish) [ci skip] * New translations simple_form.en.yml (Polish) [ci skip] * New translations en.yml (Polish) [ci skip] * New translations simple_form.en.yml (Indonesian) [ci skip] * New translations en.yml (Thai) [ci skip] * New translations simple_form.en.yml (Thai) [ci skip] * New translations simple_form.en.yml (Thai) [ci skip] * New translations en.json (Thai) [ci skip] * New translations en.json (Thai) [ci skip] * New translations en.json (Thai) [ci skip] * New translations en.yml (Thai) [ci skip] * New translations en.json (Thai) [ci skip] * New translations simple_form.en.yml (Thai) [ci skip] * New translations simple_form.en.yml (Thai) [ci skip] * New translations en.yml (Thai) [ci skip] * New translations simple_form.en.yml (Thai) [ci skip] * New translations activerecord.en.yml (Occitan) [ci skip] * New translations simple_form.en.yml (Indonesian) [ci skip] * New translations activerecord.en.yml (Kabyle) [ci skip] * New translations en.json (Breton) [ci skip] * New translations en.yml (Breton) [ci skip] * New translations en.yml (Breton) [ci skip] * New translations en.yml (Breton) [ci skip] * New translations en.yml (Breton) [ci skip] * New translations devise.en.yml (Breton) [ci skip] * New translations en.json (Breton) [ci skip] * New translations doorkeeper.en.yml (Breton) [ci skip] * New translations simple_form.en.yml (Breton) [ci skip] * New translations en.yml (Breton) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations devise.en.yml (Russian) [ci skip] * New translations simple_form.en.yml (Russian) [ci skip] * New translations en.json (Russian) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations simple_form.en.yml (Japanese) [ci skip] * i18n-tasks normalize * yarn manage:translations * Bump babel-plugin-preval from 4.0.0 to 5.0.0 (#13297) Bumps [babel-plugin-preval](https://github.com/kentcdodds/babel-plugin-preval) from 4.0.0 to 5.0.0. - [Release notes](https://github.com/kentcdodds/babel-plugin-preval/releases) - [Changelog](https://github.com/kentcdodds/babel-plugin-preval/blob/master/CHANGELOG.md) - [Commits](https://github.com/kentcdodds/babel-plugin-preval/compare/v4.0.0...v5.0.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump @babel/plugin-transform-react-inline-elements from 7.8.3 to 7.9.0 (#13298) Bumps [@babel/plugin-transform-react-inline-elements](https://github.com/babel/babel) from 7.8.3 to 7.9.0. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) - [Commits](https://github.com/babel/babel/compare/v7.8.3...v7.9.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump @babel/core from 7.8.6 to 7.9.0 (#13303) Bumps [@babel/core](https://github.com/babel/babel) from 7.8.6 to 7.9.0. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) - [Commits](https://github.com/babel/babel/compare/v7.8.6...v7.9.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump webpack-bundle-analyzer from 3.6.0 to 3.6.1 (#13300) Bumps [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) from 3.6.0 to 3.6.1. - [Release notes](https://github.com/webpack-contrib/webpack-bundle-analyzer/releases) - [Changelog](https://github.com/webpack-contrib/webpack-bundle-analyzer/blob/master/CHANGELOG.md) - [Commits](https://github.com/webpack-contrib/webpack-bundle-analyzer/compare/v3.6.0...v3.6.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Change `tootctl media remove-orphans` to work for all classes (#13316) Change `tootctl media lookup` to not use an interactive prompt * Bump react-select from 3.0.8 to 3.1.0 (#13296) Bumps [react-select](https://github.com/JedWatson/react-select) from 3.0.8 to 3.1.0. - [Release notes](https://github.com/JedWatson/react-select/releases) - [Changelog](https://github.com/JedWatson/react-select/blob/master/.sweet-changelogs.js) - [Commits](https://github.com/JedWatson/react-select/compare/react-select@3.0.8...react-select@3.1.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump @babel/plugin-transform-runtime from 7.8.3 to 7.9.0 (#13301) Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel) from 7.8.3 to 7.9.0. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) - [Commits](https://github.com/babel/babel/compare/v7.8.3...v7.9.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump webpack from 4.41.5 to 4.42.1 (#13319) Bumps [webpack](https://github.com/webpack/webpack) from 4.41.5 to 4.42.1. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v4.41.5...v4.42.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Fix Paperclip using deprecated URI.escape function (#13320) Monkey-patch Paperclip to perform URL escaping in a slightly more appropriate way, and get rid of runtime deprecation warnings. * Bump brakeman from 4.7.2 to 4.8.0 (#13309) Bumps [brakeman](https://github.com/presidentbeef/brakeman) from 4.7.2 to 4.8.0. - [Release notes](https://github.com/presidentbeef/brakeman/releases) - [Changelog](https://github.com/presidentbeef/brakeman/blob/master/CHANGES.md) - [Commits](https://github.com/presidentbeef/brakeman/compare/v4.7.2...v4.8.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Fix OCR not working on Safari because of unsupported worker-src CSP (#13323) Fixes #13321 * Fix 404 and 410 API errors being silently discarded in WebUI (#13279) * Fix 404 and 410 API errors being silently discarded in WebUI Fixes #13278 * Return more appropriate error when user replies to a deleted toot * Please CodeClimate * Fix 404/410 errors on fetching account timelines & identity proofs * Refactor error handling * Move error message string to statuses.errors * Fix incorrect deletion of local accounts imported by overwriting (#13350) * Fix wrong color for ellipsis in boost confirmation dialog in Web UI (#13355) * Bump pg from 1.2.2 to 1.2.3 (#13344) Bumps [pg](https://github.com/ged/ruby-pg) from 1.2.2 to 1.2.3. - [Release notes](https://github.com/ged/ruby-pg/releases) - [Changelog](https://github.com/ged/ruby-pg/blob/master/History.rdoc) - [Commits](https://github.com/ged/ruby-pg/compare/v1.2.2...v1.2.3) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump oj from 3.10.3 to 3.10.5 (#13345) Bumps [oj](https://github.com/ohler55/oj) from 3.10.3 to 3.10.5. - [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.10.3...v3.10.5) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump iso-639 from 0.2.8 to 0.3.5 (#13343) Bumps [iso-639](https://github.com/xwmx/iso-639) from 0.2.8 to 0.3.5. - [Release notes](https://github.com/xwmx/iso-639/releases) - [Commits](https://github.com/xwmx/iso-639/compare/0.2.8...0.3.5) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump ox from 2.12.1 to 2.13.2 (#13342) Bumps [ox](https://github.com/ohler55/ox) from 2.12.1 to 2.13.2. - [Release notes](https://github.com/ohler55/ox/releases) - [Changelog](https://github.com/ohler55/ox/blob/develop/CHANGELOG.md) - [Commits](https://github.com/ohler55/ox/compare/v2.12.1...v2.13.2) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump better_errors from 2.5.1 to 2.6.0 (#13340) Bumps [better_errors](https://github.com/BetterErrors/better_errors) from 2.5.1 to 2.6.0. - [Release notes](https://github.com/BetterErrors/better_errors/releases) - [Commits](https://github.com/BetterErrors/better_errors/compare/v2.5.1...v2.6.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Fix ImportsController param to permit :mode (#13347) * Bump parallel_tests from 2.30.1 to 2.32.0 (#13341) Bumps [parallel_tests](https://github.com/grosser/parallel_tests) from 2.30.1 to 2.32.0. - [Release notes](https://github.com/grosser/parallel_tests/releases) - [Commits](https://github.com/grosser/parallel_tests/compare/v2.30.1...v2.32.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump uuid from 3.4.0 to 7.0.2 (#13295) Bumps [uuid](https://github.com/uuidjs/uuid) from 3.4.0 to 7.0.2. - [Release notes](https://github.com/uuidjs/uuid/releases) - [Changelog](https://github.com/uuidjs/uuid/blob/master/CHANGELOG.md) - [Commits](https://github.com/uuidjs/uuid/compare/v3.4.0...v7.0.2) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Fix content warning being unnecessarily cleared when enabling/disabling CW (#13348) * Bump concurrent-ruby from 1.1.5 to 1.1.6 (#13346) Bumps [concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby) from 1.1.5 to 1.1.6. - [Release notes](https://github.com/ruby-concurrency/concurrent-ruby/releases) - [Changelog](https://github.com/ruby-concurrency/concurrent-ruby/blob/master/CHANGELOG.md) - [Commits](https://github.com/ruby-concurrency/concurrent-ruby/compare/v1.1.5...v1.1.6) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump react from 16.12.0 to 16.13.1 (#13337) Bumps [react](https://github.com/facebook/react/tree/HEAD/packages/react) from 16.12.0 to 16.13.1. - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/master/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v16.13.1/packages/react) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump stringz from 2.0.0 to 2.1.0 (#13331) Bumps [stringz](https://github.com/sallar/stringz) from 2.0.0 to 2.1.0. - [Release notes](https://github.com/sallar/stringz/releases) - [Changelog](https://github.com/sallar/stringz/blob/master/CHANGELOG.md) - [Commits](https://github.com/sallar/stringz/commits) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump babel-jest from 25.1.0 to 25.2.4 (#13332) Bumps [babel-jest](https://github.com/facebook/jest/tree/HEAD/packages/babel-jest) from 25.1.0 to 25.2.4. - [Release notes](https://github.com/facebook/jest/releases) - [Changelog](https://github.com/facebook/jest/blob/master/CHANGELOG.md) - [Commits](https://github.com/facebook/jest/commits/v25.2.4/packages/babel-jest) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump @babel/preset-env from 7.8.3 to 7.9.0 (#13336) Bumps [@babel/preset-env](https://github.com/babel/babel) from 7.8.3 to 7.9.0. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) - [Commits](https://github.com/babel/babel/compare/v7.8.3...v7.9.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump yargs from 15.1.0 to 15.3.1 (#13334) Bumps [yargs](https://github.com/yargs/yargs) from 15.1.0 to 15.3.1. - [Release notes](https://github.com/yargs/yargs/releases) - [Changelog](https://github.com/yargs/yargs/blob/master/CHANGELOG.md) - [Commits](https://github.com/yargs/yargs/compare/v15.1.0...v15.3.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump babel-loader from 8.0.6 to 8.1.0 (#13333) Bumps [babel-loader](https://github.com/babel/babel-loader) from 8.0.6 to 8.1.0. - [Release notes](https://github.com/babel/babel-loader/releases) - [Changelog](https://github.com/babel/babel-loader/blob/master/CHANGELOG.md) - [Commits](https://github.com/babel/babel-loader/compare/v8.0.6...v8.1.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump @babel/preset-react from 7.8.3 to 7.9.4 (#13335) Bumps [@babel/preset-react](https://github.com/babel/babel) from 7.8.3 to 7.9.4. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) - [Commits](https://github.com/babel/babel/compare/v7.8.3...v7.9.4) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump autoprefixer from 9.7.4 to 9.7.5 (#13338) Bumps [autoprefixer](https://github.com/postcss/autoprefixer) from 9.7.4 to 9.7.5. - [Release notes](https://github.com/postcss/autoprefixer/releases) - [Changelog](https://github.com/postcss/autoprefixer/blob/master/CHANGELOG.md) - [Commits](https://github.com/postcss/autoprefixer/compare/9.7.4...9.7.5) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Fix re-sending of e-mail confirmation not being rate limited (#13360) Fix #13330 * Improve toot clicking areas (#13327) * Make the area to the left “Show Thread” also expand the toot in Web UI * Clicking the left part of a conversation with the avatars now opens it in Web UI * Fix background jobs not using locks like they are supposed to (#13361) Also: - Fix locks not being removed when jobs go to the dead job queue - Add UI for managing locks to the Sidekiq dashboard - Remove unused Sidekiq workers Fix #13349 * Bump sidekiq-unique-jobs from 6.0.20 to 6.0.21 (#13367) Bumps [sidekiq-unique-jobs](https://github.com/mhenrixon/sidekiq-unique-jobs) from 6.0.20 to 6.0.21. - [Release notes](https://github.com/mhenrixon/sidekiq-unique-jobs/releases) - [Changelog](https://github.com/mhenrixon/sidekiq-unique-jobs/blob/master/CHANGELOG.md) - [Commits](https://github.com/mhenrixon/sidekiq-unique-jobs/compare/v6.0.20...v6.0.21) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump faker from 2.10.1 to 2.11.0 (#13363) Bumps [faker](https://github.com/faker-ruby/faker) from 2.10.1 to 2.11.0. - [Release notes](https://github.com/faker-ruby/faker/releases) - [Changelog](https://github.com/faker-ruby/faker/blob/master/CHANGELOG.md) - [Commits](https://github.com/faker-ruby/faker/commits/v2.11.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump tty-prompt from 0.20.0 to 0.21.0 (#13366) Bumps [tty-prompt](https://github.com/piotrmurach/tty-prompt) from 0.20.0 to 0.21.0. - [Release notes](https://github.com/piotrmurach/tty-prompt/releases) - [Changelog](https://github.com/piotrmurach/tty-prompt/blob/master/CHANGELOG.md) - [Commits](https://github.com/piotrmurach/tty-prompt/compare/v0.20.0...v0.21.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump bootsnap from 1.4.5 to 1.4.6 (#13369) Bumps [bootsnap](https://github.com/Shopify/bootsnap) from 1.4.5 to 1.4.6. - [Release notes](https://github.com/Shopify/bootsnap/releases) - [Changelog](https://github.com/Shopify/bootsnap/blob/master/CHANGELOG.md) - [Commits](https://github.com/Shopify/bootsnap/compare/v1.4.5...v1.4.6) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump json-ld-preloaded from 3.1.1 to 3.1.2 (#13365) Bumps [json-ld-preloaded](https://github.com/ruby-rdf/json-ld-preloaded) from 3.1.1 to 3.1.2. - [Release notes](https://github.com/ruby-rdf/json-ld-preloaded/releases) - [Commits](https://github.com/ruby-rdf/json-ld-preloaded/compare/3.1.1...3.1.2) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Bump json-ld from 3.1.1 to 3.1.2 (#13368) Bumps [json-ld](https://github.com/ruby-rdf/json-ld) from 3.1.1 to 3.1.2. - [Release notes](https://github.com/ruby-rdf/json-ld/releases) - [Commits](https://github.com/ruby-rdf/json-ld/compare/3.1.1...3.1.2) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Fix pinning a column in web UI sometimes redirecting out of web UI (#13376) Fix #13216 * Fix returning results when searching for URL with non-zero offset (#13377) Fix #13083 * Fix `tootctl media remove-orphans` ignoring `PAPERCLIP_ROOT_PATH` (#13375) Fix #13371 * Improve polls: option lengths & redesign (#13257) This commit redesign the polls and increases characters limit for the options from 25 to 50 characters, giving pollsters more freedom. Summarizing, the redesign is making the polls more adaptive for upcoming changes to the options characters limit: the bar, or a "chart", is now displayed separately from the option itself; vote check mark is moved next to the option text, making the percentages take less space. Option lengths are taken into account and text is wrapped to multiple lines if necessary to avoid overflow. * Bump rspec-rails from 3.9.1 to 4.0.0 (#13364) Bumps [rspec-rails](https://github.com/rspec/rspec-rails) from 3.9.1 to 4.0.0. - [Release notes](https://github.com/rspec/rspec-rails/releases) - [Changelog](https://github.com/rspec/rspec-rails/blob/master/Changelog.md) - [Commits](https://github.com/rspec/rspec-rails/compare/v3.9.1...v4.0.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Add ability to filter audit log in admin UI (#13381) * Update Vagrant box to Bionic (#13384) * Update config.yml (#13379) * Add explanation as to why unlocked accounts may have follow requests (#13385) * Add explanation as to why unlocked accounts may have follow requests * Change wording to avoid “silenced” * Bump rails from 5.2.4.1 to 5.2.4.2 and kind-of from 6.0.2 to 6.0.3 (#13387) * Bump rails from 5.2.4.1 to 5.2.4.2 * Bump kind-of from 6.0.2 to 6.0.3 * Bump version to 3.1.3 (#13389) * Fix PostgreSQL load when linking in announcements (#13250) * Fix PostgreSQL load when linking in announcements Fixes #13245 by caching status lookups Since statuses are supposed to be known already and we only need their URLs and a few other things, caching them should be fine. Since it's only used by announcements so far, there won't be much statuses to cache. * Perform status lookup when saving announcements, not when rendering them * Change EntityCache#status to fetch URLs instead of looking into the database * Move announcement link lookup to publishing worker * Address issues pointed out during review * [Security] Update Dockerfile for Ruby 2.6.6 (#13393) * Update .ruby-version (#13395) * Fix “Show more” not switching to “Show less” on public pages (#13174) * Fix “Show more” not switching to “Show less” on public pages Fixes #13169 * Fix initial text of CW button on public pages when CW are unfolded by default * Add rate limit for reporting (#13390) * New Crowdin translations (#13317) * New translations en.yml (Italian) [ci skip] * New translations doorkeeper.en.yml (Indonesian) [ci skip] * New translations simple_form.en.yml (Indonesian) [ci skip] * New translations en.yml (Indonesian) [ci skip] * New translations devise.en.yml (Ido) [ci skip] * New translations doorkeeper.en.yml (Ido) [ci skip] * New translations en.json (Hebrew) [ci skip] * New translations activerecord.en.yml (Georgian) [ci skip] * New translations doorkeeper.en.yml (Georgian) [ci skip] * New translations en.yml (German) [ci skip] * New translations simple_form.en.yml (German) [ci skip] * New translations doorkeeper.en.yml (German) [ci skip] * New translations en.yml (Greek) [ci skip] * New translations simple_form.en.yml (Greek) [ci skip] * New translations doorkeeper.en.yml (Greek) [ci skip] * New translations en.yml (Hebrew) [ci skip] * New translations simple_form.en.yml (Hebrew) [ci skip] * New translations activerecord.en.yml (Hebrew) [ci skip] * New translations devise.en.yml (Hebrew) [ci skip] * New translations doorkeeper.en.yml (Hebrew) [ci skip] * New translations en.yml (Hindi) [ci skip] * New translations en.yml (Galician) [ci skip] * New translations doorkeeper.en.yml (Esperanto) [ci skip] * New translations doorkeeper.en.yml (French) [ci skip] * New translations devise.en.yml (French) [ci skip] * New translations simple_form.en.yml (French) [ci skip] * New translations en.yml (French) [ci skip] * New translations doorkeeper.en.yml (Finnish) [ci skip] * New translations simple_form.en.yml (Finnish) [ci skip] * New translations en.yml (Finnish) [ci skip] * New translations en.json (Finnish) [ci skip] * New translations doorkeeper.en.yml (Estonian) [ci skip] * New translations simple_form.en.yml (Estonian) [ci skip] * New translations en.yml (Estonian) [ci skip] * New translations doorkeeper.en.yml (Welsh) [ci skip] * New translations activerecord.en.yml (Serbian (Latin)) [ci skip] * New translations devise.en.yml (Serbian (Latin)) [ci skip] * New translations devise.en.yml (Urdu (Pakistan)) [ci skip] * New translations activerecord.en.yml (Vietnamese) [ci skip] * New translations devise.en.yml (Vietnamese) [ci skip] * New translations en.yml (Tamil) [ci skip] * New translations en.yml (Tamil) [ci skip] * New translations simple_form.en.yml (Tamil) [ci skip] * New translations simple_form.en.yml (Tamil) [ci skip] * New translations en.yml (Thai) [ci skip] * New translations en.yml (Basque) [ci skip] * New translations en.json (Basque) [ci skip] * New translations simple_form.en.yml (Basque) [ci skip] * New translations simple_form.en.yml (Basque) [ci skip] * New translations en.yml (Galician) [ci skip] * New translations en.yml (German) [ci skip] * New translations en.yml (French) [ci skip] * New translations devise.en.yml (German) [ci skip] * New translations en.yml (Catalan) [ci skip] * New translations en.yml (Swedish) [ci skip] * New translations en.yml (Persian) [ci skip] * New translations en.yml (Greek) [ci skip] * New translations en.yml (Chinese Traditional, Hong Kong) [ci skip] * New translations en.yml (Chinese Traditional) [ci skip] * New translations en.yml (Portuguese, Brazilian) [ci skip] * New translations en.yml (Spanish, Argentina) [ci skip] * New translations en.yml (Spanish) [ci skip] * New translations en.yml (Korean) [ci skip] * New translations en.yml (Italian) [ci skip] * New translations simple_form.en.yml (Italian) [ci skip] * New translations en.yml (Corsican) [ci skip] * New translations en.yml (Polish) [ci skip] * New translations en.yml (Korean) [ci skip] * New translations en.yml (Tamil) [ci skip] * New translations en.yml (Spanish) [ci skip] * New translations en.yml (Spanish, Argentina) [ci skip] * New translations simple_form.en.yml (Indonesian) [ci skip] * New translations simple_form.en.yml (Indonesian) [ci skip] * New translations en.yml (Indonesian) [ci skip] * New translations en.yml (Indonesian) [ci skip] * New translations en.yml (Indonesian) [ci skip] * New translations en.yml (Indonesian) [ci skip] * New translations en.yml (Indonesian) [ci skip] * New translations en.yml (Slovak) [ci skip] * New translations en.yml (Spanish, Argentina) [ci skip] * New translations en.yml (Hungarian) [ci skip] * New translations simple_form.en.yml (Slovak) [ci skip] * New translations en.yml (Slovak) [ci skip] * New translations en.json (Slovak) [ci skip] * New translations en.yml (Portuguese) [ci skip] * New translations en.json (Portuguese) [ci skip] * New translations en.json (Portuguese) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations en.yml (Japanese) [ci skip] * New translations en.yml (Chinese Simplified) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations en.json (Galician) [ci skip] * New translations devise.en.yml (Galician) [ci skip] * New translations en.json (Finnish) [ci skip] * New translations en.yml (Finnish) [ci skip] * New translations en.json (Finnish) [ci skip] * New translations en.json (Finnish) [ci skip] * New translations en.yml (Korean) [ci skip] * New translations en.yml (Catalan) [ci skip] * New translations en.yml (Arabic) [ci skip] * New translations en.json (French) [ci skip] * New translations en.yml (French) [ci skip] * New translations en.yml (Spanish, Argentina) [ci skip] * New translations en.yml (Spanish) [ci skip] * New translations en.yml (Persian) [ci skip] * New translations en.yml (Catalan) [ci skip] * New translations en.yml (Arabic) [ci skip] * New translations simple_form.en.yml (Persian) [ci skip] * New translations en.yml (Persian) [ci skip] * New translations en.yml (Spanish) [ci skip] * New translations en.yml (Spanish, Argentina) [ci skip] * New translations en.yml (French) [ci skip] * New translations en.yml (Korean) [ci skip] * New translations en.json (Hungarian) [ci skip] * New translations en.yml (Hungarian) [ci skip] * New translations en.yml (Spanish, Argentina) [ci skip] * New translations en.yml (Spanish) [ci skip] * New translations en.yml (French) [ci skip] * New translations en.yml (French) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations en.yml (Russian) [ci skip] * New translations en.yml (German) [ci skip] * New translations en.yml (Greek) [ci skip] * New translations en.yml (German) [ci skip] * New t… Co-authored-by: ThibG Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Eugen Rochko Co-authored-by: koyu Co-authored-by: Mélanie Chauvel (ariasuni) Co-authored-by: David Cook Co-authored-by: tateisu Co-authored-by: tateisu Co-authored-by: Bèr Kessels Co-authored-by: guigeekz Co-authored-by: Shlee Co-authored-by: mayaeh Co-authored-by: Yamagishi Kazutoshi Co-authored-by: Daniel Sockwell Co-authored-by: Jeong Arm Co-authored-by: Takeshi Umeda Co-authored-by: Sasha Sorokin Co-authored-by: fuyu <54523771+mfmfuyu@users.noreply.github.com> --- .circleci/config.yml | 13 +- .ruby-version | 2 +- CHANGELOG.md | 73 + Dockerfile | 6 +- Gemfile | 32 +- Gemfile.lock | 258 +-- README.md | 4 +- Vagrantfile | 2 +- app/chewy/statuses_index.rb | 5 + app/controllers/account_follow_controller.rb | 2 +- .../admin/action_logs_controller.rb | 14 +- .../admin/email_domain_blocks_controller.rb | 28 +- .../admin/site_uploads_controller.rb | 21 + .../admin/warning_presets_controller.rb | 6 +- app/controllers/api/base_controller.rb | 4 + .../accounts/follower_accounts_controller.rb | 4 +- .../accounts/following_accounts_controller.rb | 4 +- .../v1/accounts/identity_proofs_controller.rb | 2 - .../api/v1/accounts/lists_controller.rb | 2 - .../api/v1/accounts/pins_controller.rb | 2 - .../v1/accounts/relationships_controller.rb | 2 - .../api/v1/accounts/search_controller.rb | 2 - .../api/v1/accounts/statuses_controller.rb | 2 - app/controllers/api/v1/accounts_controller.rb | 4 +- .../api/v1/apps/credentials_controller.rb | 2 - app/controllers/api/v1/blocks_controller.rb | 2 - .../api/v1/bookmarks_controller.rb | 2 - .../api/v1/conversations_controller.rb | 2 - .../api/v1/custom_emojis_controller.rb | 2 - .../api/v1/domain_blocks_controller.rb | 2 - .../api/v1/endorsements_controller.rb | 2 - .../api/v1/favourites_controller.rb | 2 - .../featured_tags/suggestions_controller.rb | 3 - app/controllers/api/v1/filters_controller.rb | 2 - .../api/v1/instances/activity_controller.rb | 2 - .../api/v1/instances/peers_controller.rb | 2 - .../api/v1/instances_controller.rb | 2 - app/controllers/api/v1/media_controller.rb | 31 +- app/controllers/api/v1/mutes_controller.rb | 2 - .../api/v1/notifications_controller.rb | 2 - .../api/v1/polls/votes_controller.rb | 2 - app/controllers/api/v1/polls_controller.rb | 2 - .../api/v1/preferences_controller.rb | 2 - app/controllers/api/v1/reports_controller.rb | 2 +- .../api/v1/statuses/bookmarks_controller.rb | 2 - .../favourited_by_accounts_controller.rb | 2 - .../api/v1/statuses/favourites_controller.rb | 2 - .../api/v1/statuses/mutes_controller.rb | 2 - .../api/v1/statuses/pins_controller.rb | 2 - .../reblogged_by_accounts_controller.rb | 2 - .../api/v1/statuses/reblogs_controller.rb | 3 +- app/controllers/api/v1/statuses_controller.rb | 14 +- .../api/v1/streaming_controller.rb | 2 - .../api/v1/suggestions_controller.rb | 2 - .../api/v1/timelines/home_controller.rb | 2 - .../api/v1/timelines/public_controller.rb | 2 - .../api/v1/timelines/tag_controller.rb | 2 - app/controllers/api/v1/trends_controller.rb | 2 - app/controllers/api/v2/media_controller.rb | 12 + app/controllers/api/v2/search_controller.rb | 2 - app/controllers/api/web/embeds_controller.rb | 2 - .../api/web/push_subscriptions_controller.rb | 2 - .../api/web/settings_controller.rb | 2 - app/controllers/application_controller.rb | 5 + .../authorize_interactions_controller.rb | 2 +- .../concerns/rate_limit_headers.rb | 16 +- .../follower_accounts_controller.rb | 11 +- .../following_accounts_controller.rb | 11 +- .../settings/imports_controller.rb | 2 +- app/helpers/admin/action_logs_helper.rb | 75 +- app/helpers/admin/filter_helper.rb | 1 + app/helpers/admin/settings_helper.rb | 11 + app/javascript/mastodon/actions/accounts.js | 5 +- app/javascript/mastodon/actions/alerts.js | 4 +- app/javascript/mastodon/actions/compose.js | 23 +- .../mastodon/actions/identity_proofs.js | 1 + app/javascript/mastodon/actions/timelines.js | 1 + app/javascript/mastodon/common.js | 2 +- .../mastodon/components/column_header.js | 3 +- app/javascript/mastodon/components/domain.js | 2 +- .../intersection_observer_article.js | 2 +- .../mastodon/components/media_gallery.js | 2 +- app/javascript/mastodon/components/poll.js | 28 +- .../mastodon/components/scrollable_list.js | 20 +- app/javascript/mastodon/components/status.js | 8 +- .../mastodon/components/status_action_bar.js | 4 +- .../mastodon/components/status_content.js | 14 + .../mastodon/containers/domain_container.js | 2 +- .../features/account/components/header.js | 8 +- .../mastodon/features/audio/index.js | 6 +- .../mastodon/features/blocks/index.js | 2 +- .../features/compose/components/action_bar.js | 2 + .../features/compose/components/poll_form.js | 5 +- .../compose/components/privacy_dropdown.js | 8 +- .../components/conversation.js | 2 +- .../mastodon/features/domain_blocks/index.js | 8 +- .../mastodon/features/favourites/index.js | 2 +- .../features/follow_requests/index.js | 19 +- .../mastodon/features/followers/index.js | 2 +- .../mastodon/features/following/index.js | 2 +- .../components/announcements.js | 19 + .../features/getting_started/index.js | 2 +- .../mastodon/features/lists/index.js | 2 +- .../mastodon/features/mutes/index.js | 2 +- .../mastodon/features/reblogs/index.js | 2 +- .../features/status/components/action_bar.js | 4 +- .../features/status/components/card.js | 2 +- .../status/components/detailed_status.js | 2 +- .../ui/components/__tests__/column-test.js | 2 +- .../mastodon/features/video/index.js | 14 +- app/javascript/mastodon/locales/ast.json | 4 +- app/javascript/mastodon/locales/bg.json | 2 +- app/javascript/mastodon/locales/br.json | 486 ++--- app/javascript/mastodon/locales/cs.json | 6 +- app/javascript/mastodon/locales/de.json | 14 +- .../mastodon/locales/defaultMessages.json | 46 +- app/javascript/mastodon/locales/el.json | 12 +- app/javascript/mastodon/locales/en.json | 25 +- app/javascript/mastodon/locales/eo.json | 4 +- app/javascript/mastodon/locales/es-AR.json | 4 +- app/javascript/mastodon/locales/eu.json | 18 +- app/javascript/mastodon/locales/fa.json | 10 +- app/javascript/mastodon/locales/fi.json | 40 +- app/javascript/mastodon/locales/fr.json | 166 +- app/javascript/mastodon/locales/ga.json | 2 +- app/javascript/mastodon/locales/gl.json | 36 +- app/javascript/mastodon/locales/hi.json | 2 +- app/javascript/mastodon/locales/hu.json | 2 +- app/javascript/mastodon/locales/hy.json | 124 +- app/javascript/mastodon/locales/it.json | 4 +- app/javascript/mastodon/locales/ja.json | 24 +- app/javascript/mastodon/locales/kab.json | 124 +- app/javascript/mastodon/locales/kn.json | 2 +- app/javascript/mastodon/locales/ko.json | 12 +- 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 | 32 +- app/javascript/mastodon/locales/nn.json | 16 +- app/javascript/mastodon/locales/pt-BR.json | 20 +- app/javascript/mastodon/locales/pt-PT.json | 34 +- app/javascript/mastodon/locales/ru.json | 18 +- app/javascript/mastodon/locales/sk.json | 12 +- app/javascript/mastodon/locales/sr.json | 130 +- app/javascript/mastodon/locales/sv.json | 6 +- app/javascript/mastodon/locales/th.json | 40 +- app/javascript/mastodon/locales/ur.json | 2 +- app/javascript/mastodon/locales/zh-CN.json | 2 +- app/javascript/mastodon/locales/zh-HK.json | 14 +- app/javascript/mastodon/locales/zh-TW.json | 14 +- app/javascript/mastodon/middleware/errors.js | 2 +- app/javascript/mastodon/reducers/compose.js | 1 - .../mastodon/reducers/notifications.js | 4 +- app/javascript/mastodon/reducers/timelines.js | 4 +- app/javascript/mastodon/selectors/index.js | 2 +- .../service_worker/web_push_notifications.js | 2 +- .../mastodon/store/configureStore.js | 2 +- app/javascript/mastodon/utils/log_out.js | 2 +- app/javascript/packs/admin.js | 6 +- app/javascript/packs/public.js | 38 +- .../styles/mastodon-light/diff.scss | 2 +- app/javascript/styles/mastodon/admin.scss | 68 +- .../styles/mastodon/components.scss | 39 +- app/javascript/styles/mastodon/polls.scss | 42 +- app/lib/activitypub/tag_manager.rb | 2 + app/lib/entity_cache.rb | 4 + app/lib/exceptions.rb | 1 + app/lib/language_detector.rb | 4 +- app/lib/rate_limiter.rb | 64 + app/models/account.rb | 21 +- app/models/account_filter.rb | 27 +- app/models/account_warning_preset.rb | 3 + app/models/admin/account_action.rb | 12 - app/models/admin/action_log_filter.rb | 81 + app/models/announcement.rb | 11 + app/models/concerns/account_interactions.rb | 16 +- app/models/concerns/attachmentable.rb | 2 +- app/models/concerns/rate_limitable.rb | 36 + app/models/email_domain_block.rb | 14 + app/models/follow.rb | 3 + app/models/follow_request.rb | 3 + app/models/media_attachment.rb | 122 +- app/models/report.rb | 11 + app/models/status.rb | 20 + app/policies/settings_policy.rb | 4 + .../rest/announcement_serializer.rb | 13 + .../rest/media_attachment_serializer.rb | 4 +- app/services/account_search_service.rb | 2 +- .../activitypub/process_account_service.rb | 25 +- app/services/fetch_resource_service.rb | 3 + app/services/follow_service.rb | 78 +- app/services/import_service.rb | 3 +- app/services/post_status_service.rb | 17 +- app/services/reblog_service.rb | 16 +- app/services/resolve_url_service.rb | 10 +- app/services/search_service.rb | 4 +- app/validators/poll_validator.rb | 2 +- app/views/admin/account_actions/new.html.haml | 2 +- app/views/admin/accounts/_account.html.haml | 2 + app/views/admin/accounts/index.html.haml | 6 + app/views/admin/accounts/show.html.haml | 15 +- .../admin/action_logs/_action_log.html.haml | 6 - app/views/admin/action_logs/index.html.haml | 24 +- .../_email_domain_block.html.haml | 10 + .../admin/email_domain_blocks/new.html.haml | 5 +- app/views/admin/settings/edit.html.haml | 11 +- .../warning_presets/_warning_preset.html.haml | 10 + .../admin/warning_presets/edit.html.haml | 3 + .../admin/warning_presets/index.html.haml | 24 +- app/views/errors/429.html.haml | 5 + .../preferences/appearance/show.html.haml | 5 +- .../preferences/notifications/show.html.haml | 8 +- .../settings/preferences/other/show.html.haml | 5 +- app/views/settings/profiles/show.html.haml | 5 +- app/views/statuses/_poll.html.haml | 10 +- .../distribute_poll_update_worker.rb | 2 +- .../synchronize_featured_collection_worker.rb | 2 +- .../after_remote_follow_request_worker.rb | 9 - app/workers/after_remote_follow_worker.rb | 9 - app/workers/backup_worker.rb | 8 +- app/workers/notification_worker.rb | 9 - app/workers/poll_expiration_notify_worker.rb | 2 +- app/workers/post_process_media_worker.rb | 34 + app/workers/processing_worker.rb | 9 - .../publish_scheduled_announcement_worker.rb | 15 +- .../publish_scheduled_status_worker.rb | 2 +- .../pubsubhubbub/confirmation_worker.rb | 9 - app/workers/pubsubhubbub/delivery_worker.rb | 9 - .../pubsubhubbub/distribution_worker.rb | 9 - .../pubsubhubbub/raw_distribution_worker.rb | 9 - app/workers/pubsubhubbub/subscribe_worker.rb | 9 - .../pubsubhubbub/unsubscribe_worker.rb | 9 - app/workers/regeneration_worker.rb | 2 +- app/workers/remote_profile_update_worker.rb | 9 - app/workers/resolve_account_worker.rb | 2 +- app/workers/salmon_worker.rb | 9 - .../scheduler/backup_cleanup_scheduler.rb | 2 +- .../scheduler/doorkeeper_cleanup_scheduler.rb | 2 +- app/workers/scheduler/email_scheduler.rb | 2 +- .../scheduler/feed_cleanup_scheduler.rb | 2 +- app/workers/scheduler/ip_cleanup_scheduler.rb | 2 +- .../scheduler/media_cleanup_scheduler.rb | 2 +- app/workers/scheduler/pghero_scheduler.rb | 2 +- .../scheduler/scheduled_statuses_scheduler.rb | 2 +- .../subscriptions_cleanup_scheduler.rb | 9 - .../scheduler/subscriptions_scheduler.rb | 9 - .../scheduler/trending_tags_scheduler.rb | 2 +- .../scheduler/user_cleanup_scheduler.rb | 2 +- app/workers/verify_account_links_worker.rb | 2 +- config/application.rb | 2 + config/deploy.rb | 2 +- .../initializers/content_security_policy.rb | 2 + config/initializers/kaminari_config.rb | 2 +- config/initializers/rack_attack.rb | 2 +- config/initializers/sidekiq.rb | 7 +- config/locales/activerecord.br.yml | 6 +- config/locales/activerecord.hy.yml | 16 + config/locales/activerecord.kab.yml | 5 + config/locales/activerecord.zh-HK.yml | 4 + config/locales/ar.yml | 70 +- config/locales/ast.yml | 3 +- config/locales/bg.yml | 2 +- config/locales/bn.yml | 2 +- config/locales/br.yml | 219 ++- config/locales/ca.yml | 50 +- config/locales/co.yml | 50 +- config/locales/cs.yml | 4 +- config/locales/cy.yml | 6 +- config/locales/da.yml | 1 - config/locales/de.yml | 50 +- config/locales/devise.br.yml | 8 + config/locales/devise.fr.yml | 20 +- config/locales/devise.hy.yml | 6 + config/locales/devise.is.yml | 4 +- config/locales/devise.kab.yml | 9 +- config/locales/devise.nn.yml | 62 +- config/locales/devise.pt-BR.yml | 106 +- config/locales/devise.pt-PT.yml | 4 +- config/locales/devise.ru.yml | 24 +- config/locales/devise.zh-HK.yml | 16 + config/locales/doorkeeper.br.yml | 51 + config/locales/doorkeeper.fr.yml | 10 +- config/locales/doorkeeper.kab.yml | 10 +- config/locales/doorkeeper.ko.yml | 4 +- config/locales/doorkeeper.nn.yml | 24 +- config/locales/doorkeeper.pt-BR.yml | 2 +- config/locales/doorkeeper.sk.yml | 4 +- config/locales/doorkeeper.th.yml | 2 +- config/locales/el.yml | 60 +- config/locales/en.yml | 51 +- config/locales/en_GB.yml | 1 - config/locales/eo.yml | 13 +- config/locales/es-AR.yml | 52 +- config/locales/es.yml | 50 +- config/locales/et.yml | 1 - config/locales/eu.yml | 21 +- config/locales/fa.yml | 59 +- config/locales/fi.yml | 19 + config/locales/fr.yml | 194 +- config/locales/gl.yml | 50 +- config/locales/hi.yml | 2 +- config/locales/hr.yml | 2 +- config/locales/hu.yml | 88 +- config/locales/hy.yml | 7 +- config/locales/id.yml | 31 +- config/locales/io.yml | 2 +- config/locales/is.yml | 54 +- config/locales/it.yml | 52 +- config/locales/ja.yml | 50 +- config/locales/kab.yml | 105 +- config/locales/kk.yml | 1 - config/locales/kn.yml | 2 +- config/locales/ko.yml | 50 +- config/locales/lt.yml | 1 - config/locales/lv.yml | 2 +- config/locales/mk.yml | 2 +- config/locales/ml.yml | 2 +- config/locales/mr.yml | 2 +- config/locales/ms.yml | 2 +- config/locales/nl.yml | 5 +- config/locales/nn.yml | 5 +- config/locales/no.yml | 1 - config/locales/oc.yml | 31 +- config/locales/pl.yml | 212 ++- config/locales/pt-BR.yml | 76 +- config/locales/pt-PT.yml | 84 +- config/locales/ru.yml | 81 +- config/locales/simple_form.ar.yml | 2 + config/locales/simple_form.ast.yml | 2 + config/locales/simple_form.br.yml | 22 + config/locales/simple_form.ca.yml | 7 + config/locales/simple_form.co.yml | 7 + config/locales/simple_form.cy.yml | 2 + config/locales/simple_form.de.yml | 9 +- config/locales/simple_form.el.yml | 20 +- config/locales/simple_form.en.yml | 11 +- config/locales/simple_form.eo.yml | 6 +- config/locales/simple_form.es-AR.yml | 7 + config/locales/simple_form.es.yml | 7 + config/locales/simple_form.eu.yml | 25 +- config/locales/simple_form.fa.yml | 13 +- config/locales/simple_form.fr.yml | 43 +- config/locales/simple_form.gl.yml | 7 + config/locales/simple_form.hu.yml | 7 + config/locales/simple_form.id.yml | 7 + config/locales/simple_form.is.yml | 7 + config/locales/simple_form.it.yml | 9 + config/locales/simple_form.ja.yml | 13 +- config/locales/simple_form.kab.yml | 20 +- config/locales/simple_form.ko.yml | 7 + config/locales/simple_form.nl.yml | 2 +- config/locales/simple_form.oc.yml | 4 + config/locales/simple_form.pl.yml | 24 + config/locales/simple_form.pt-BR.yml | 13 +- config/locales/simple_form.pt-PT.yml | 17 +- config/locales/simple_form.ru.yml | 9 +- config/locales/simple_form.sk.yml | 8 +- config/locales/simple_form.sv.yml | 3 + config/locales/simple_form.ta.yml | 9 + config/locales/simple_form.th.yml | 20 +- config/locales/simple_form.zh-CN.yml | 7 + config/locales/simple_form.zh-HK.yml | 33 + config/locales/simple_form.zh-TW.yml | 33 + config/locales/sk.yml | 29 +- config/locales/sl.yml | 1 - config/locales/sq.yml | 1 - config/locales/sr.yml | 1 - config/locales/sv.yml | 9 +- config/locales/ta.yml | 15 +- config/locales/te.yml | 2 +- config/locales/th.yml | 67 +- config/locales/tr.yml | 1 - config/locales/uk.yml | 1 - config/locales/ur.yml | 2 +- config/locales/vi.yml | 1 - config/locales/zh-CN.yml | 17 +- config/locales/zh-HK.yml | 89 +- config/locales/zh-TW.yml | 89 +- config/routes.rb | 6 +- config/webpack/development.js | 2 +- config/webpack/shared.js | 4 +- ...163405_add_hide_collections_to_accounts.rb | 5 + ...625_add_processing_to_media_attachments.rb | 5 + ...58_add_title_to_account_warning_presets.rb | 15 + ...2162302_add_status_ids_to_announcements.rb | 6 + ...43_add_parent_id_to_email_domain_blocks.rb | 5 + db/schema.rb | 8 +- dist/nginx.conf | 12 +- lib/mastodon/media_cli.rb | 113 +- lib/mastodon/redis_config.rb | 4 +- lib/mastodon/statuses_cli.rb | 8 +- lib/mastodon/version.rb | 2 +- lib/paperclip/attachment_extensions.rb | 43 + lib/paperclip/url_generator_extensions.rb | 17 + lib/paperclip/video_transcoder.rb | 18 +- lib/tasks/mastodon.rake | 15 +- package.json | 61 +- .../account_follow_controller_spec.rb | 2 +- .../admin/reports_controller_spec.rb | 20 + .../api/v1/statuses_controller_spec.rb | 46 +- spec/features/profile_spec.rb | 2 +- spec/helpers/admin/action_log_helper_spec.rb | 238 --- spec/rails_helper.rb | 2 +- spec/services/import_service_spec.rb | 8 - spec/services/post_status_service_spec.rb | 7 + yarn.lock | 1651 +++++++++++------ 409 files changed, 6167 insertions(+), 3062 deletions(-) create mode 100644 app/controllers/admin/site_uploads_controller.rb create mode 100644 app/controllers/api/v2/media_controller.rb create mode 100644 app/helpers/admin/settings_helper.rb create mode 100644 app/lib/rate_limiter.rb create mode 100644 app/models/admin/action_log_filter.rb create mode 100644 app/models/concerns/rate_limitable.rb create mode 100644 app/views/admin/warning_presets/_warning_preset.html.haml create mode 100644 app/views/errors/429.html.haml delete mode 100644 app/workers/after_remote_follow_request_worker.rb delete mode 100644 app/workers/after_remote_follow_worker.rb delete mode 100644 app/workers/notification_worker.rb create mode 100644 app/workers/post_process_media_worker.rb delete mode 100644 app/workers/processing_worker.rb delete mode 100644 app/workers/pubsubhubbub/confirmation_worker.rb delete mode 100644 app/workers/pubsubhubbub/delivery_worker.rb delete mode 100644 app/workers/pubsubhubbub/distribution_worker.rb delete mode 100644 app/workers/pubsubhubbub/raw_distribution_worker.rb delete mode 100644 app/workers/pubsubhubbub/subscribe_worker.rb delete mode 100644 app/workers/pubsubhubbub/unsubscribe_worker.rb delete mode 100644 app/workers/remote_profile_update_worker.rb delete mode 100644 app/workers/salmon_worker.rb delete mode 100644 app/workers/scheduler/subscriptions_cleanup_scheduler.rb delete mode 100644 app/workers/scheduler/subscriptions_scheduler.rb create mode 100644 db/migrate/20191212163405_add_hide_collections_to_accounts.rb create mode 100644 db/migrate/20200306035625_add_processing_to_media_attachments.rb create mode 100644 db/migrate/20200312144258_add_title_to_account_warning_presets.rb create mode 100644 db/migrate/20200312162302_add_status_ids_to_announcements.rb create mode 100644 db/migrate/20200312185443_add_parent_id_to_email_domain_blocks.rb create mode 100644 lib/paperclip/attachment_extensions.rb create mode 100644 lib/paperclip/url_generator_extensions.rb diff --git a/.circleci/config.yml b/.circleci/config.yml index 3ba027d953003c..dd943e32795e40 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,6 +6,7 @@ aliases: - image: circleci/ruby:2.7-buster-node environment: &ruby_environment BUNDLE_APP_CONFIG: ./.bundle/ + BUNDLE_PATH: ./vendor/bundle/ DB_HOST: localhost DB_USER: root RAILS_ENV: test @@ -138,9 +139,10 @@ jobs: docker: - image: circleci/ruby:2.7-buster-node environment: *ruby_environment - - image: circleci/postgres:10.6-alpine + - image: circleci/postgres:12.2 environment: POSTGRES_USER: root + POSTGRES_HOST_AUTH_METHOD: trust - image: circleci/redis:5-alpine steps: - *attach_workspace @@ -157,9 +159,10 @@ jobs: docker: - image: circleci/ruby:2.7-buster-node environment: *ruby_environment - - image: circleci/postgres:10.6-alpine + - image: circleci/postgres:12.2 environment: POSTGRES_USER: root + POSTGRES_HOST_AUTH_METHOD: trust - image: circleci/redis:5-alpine <<: *test_steps @@ -168,9 +171,10 @@ jobs: docker: - image: circleci/ruby:2.6-buster-node environment: *ruby_environment - - image: circleci/postgres:10.6-alpine + - image: circleci/postgres:12.2 environment: POSTGRES_USER: root + POSTGRES_HOST_AUTH_METHOD: trust - image: circleci/redis:5-alpine <<: *test_steps @@ -179,9 +183,10 @@ jobs: docker: - image: circleci/ruby:2.5-buster-node environment: *ruby_environment - - image: circleci/postgres:10.6-alpine + - image: circleci/postgres:12.2 environment: POSTGRES_USER: root + POSTGRES_HOST_AUTH_METHOD: trust - image: circleci/redis:5-alpine <<: *test_steps diff --git a/.ruby-version b/.ruby-version index 57cf282ebbc41e..338a5b5d8fec49 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.6.5 +2.6.6 diff --git a/CHANGELOG.md b/CHANGELOG.md index 33663c2ad9dfe7..ad353e2ad656b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,79 @@ Changelog All notable changes to this project will be documented in this file. +## [v3.1.3] - 2020-04-05 +### Added + +- Add ability to filter audit log in admin UI ([Gargron](https://github.com/tootsuite/mastodon/pull/13381)) +- Add titles to warning presets in admin UI ([Gargron](https://github.com/tootsuite/mastodon/pull/13252)) +- Add option to include resolved DNS records when blacklisting e-mail domains in admin UI ([Gargron](https://github.com/tootsuite/mastodon/pull/13254)) +- Add ability to delete files uploaded for settings in admin UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13192)) +- Add sorting by username, creation and last activity in admin UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13076)) +- Add explanation as to why unlocked accounts may have follow requests in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13385)) +- Add link to bookmarks to dropdown in web UI ([mayaeh](https://github.com/tootsuite/mastodon/pull/13273)) +- Add support for links to statuses in announcements to be opened in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13212), [ThibG](https://github.com/tootsuite/mastodon/pull/13250)) +- Add tooltips to audio/video player buttons in web UI ([ariasuni](https://github.com/tootsuite/mastodon/pull/13203)) +- Add submit button to the top of preferences pages ([guigeekz](https://github.com/tootsuite/mastodon/pull/13068)) +- Add specific rate limits for posting, following and reporting ([Gargron](https://github.com/tootsuite/mastodon/pull/13172), [Gargron](https://github.com/tootsuite/mastodon/pull/13390)) + - 300 posts every 3 hours + - 400 follows or follow requests every 24 hours + - 400 reports every 24 hours +- Add federation support for the "hide network" preference ([ThibG](https://github.com/tootsuite/mastodon/pull/11673)) +- Add `--skip-media-remove` option to `tootctl statuses remove` ([tateisu](https://github.com/tootsuite/mastodon/pull/13080)) + +### Changed + +- **Change design of polls in web UI** ([Sasha-Sorokin](https://github.com/tootsuite/mastodon/pull/13257), [ThibG](https://github.com/tootsuite/mastodon/pull/13313)) +- Change status click areas in web UI to be bigger ([ariasuni](https://github.com/tootsuite/mastodon/pull/13327)) +- **Change `tootctl media remove-orphans` to work for all classes** ([Gargron](https://github.com/tootsuite/mastodon/pull/13316)) +- **Change local media attachments to perform heavy processing asynchronously** ([Gargron](https://github.com/tootsuite/mastodon/pull/13210)) +- Change video uploads to always be converted to H264/MP4 ([Gargron](https://github.com/tootsuite/mastodon/pull/13220), [ThibG](https://github.com/tootsuite/mastodon/pull/13239), [ThibG](https://github.com/tootsuite/mastodon/pull/13242)) +- Change video uploads to enforce certain limits ([Gargron](https://github.com/tootsuite/mastodon/pull/13218)) + - Dimensions smaller than 1920x1200px + - Frame rate at most 60fps +- Change the tooltip "Toggle visibility" to "Hide media" in web UI ([ariasuni](https://github.com/tootsuite/mastodon/pull/13199)) +- Change description of privacy levels to be more intuitive in web UI ([ariasuni](https://github.com/tootsuite/mastodon/pull/13197)) +- Change GIF label to be displayed even when autoplay is enabled in web UI ([koyuawsmbrtn](https://github.com/tootsuite/mastodon/pull/13209)) +- Change the string "Hide everything from …" to "Block domain …" in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13178), [mayaeh](https://github.com/tootsuite/mastodon/pull/13221)) +- Change wording of media display preferences to be more intuitive ([ariasuni](https://github.com/tootsuite/mastodon/pull/13198)) + +### Deprecated + +- `POST /api/v1/media` → `POST /api/v2/media` ([Gargron](https://github.com/tootsuite/mastodon/pull/13210)) + +### Fixed + +- Fix `tootctl media remove-orphans` ignoring `PAPERCLIP_ROOT_PATH` ([Gargron](https://github.com/tootsuite/mastodon/pull/13375)) +- Fix returning results when searching for URL with non-zero offset ([Gargron](https://github.com/tootsuite/mastodon/pull/13377)) +- Fix pinning a column in web UI sometimes redirecting out of web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/13376)) +- Fix background jobs not using locks like they are supposed to ([Gargron](https://github.com/tootsuite/mastodon/pull/13361)) +- Fix content warning being unnecessarily cleared when hiding content warning input in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13348)) +- Fix "Show more" not switching to "Show less" on public pages ([ThibG](https://github.com/tootsuite/mastodon/pull/13174)) +- Fix import overwrite option not being selectable ([noellabo](https://github.com/tootsuite/mastodon/pull/13347)) +- Fix wrong color for ellipsis in boost confirmation dialog in web UI ([ariasuni](https://github.com/tootsuite/mastodon/pull/13355)) +- Fix unnecessary unfollowing when importing follows with overwrite option ([noellabo](https://github.com/tootsuite/mastodon/pull/13350)) +- Fix 404 and 410 API errors being silently discarded in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13279)) +- Fix OCR not working on Safari because of unsupported worker-src CSP ([ThibG](https://github.com/tootsuite/mastodon/pull/13323)) +- Fix media not being marked sensitive when a content warning is set with no text ([ThibG](https://github.com/tootsuite/mastodon/pull/13277)) +- Fix crash after deleting announcements in web UI ([codesections](https://github.com/tootsuite/mastodon/pull/13283), [ThibG](https://github.com/tootsuite/mastodon/pull/13312)) +- Fix bookmarks not being searchable ([Kjwon15](https://github.com/tootsuite/mastodon/pull/13271), [noellabo](https://github.com/tootsuite/mastodon/pull/13293)) +- Fix reported accounts not being whitelisted from further spam checks when resolving a spam check report ([ThibG](https://github.com/tootsuite/mastodon/pull/13289)) +- Fix web UI crash in single-column mode on prehistoric browsers ([ThibG](https://github.com/tootsuite/mastodon/pull/13267)) +- Fix some timeouts when searching for URLs ([ThibG](https://github.com/tootsuite/mastodon/pull/13253)) +- Fix detailed view of direct messages displaying a 0 boost count in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13244)) +- Fix regression in “Edit media” modal in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13243)) +- Fix public posts from silenced accounts not being changed to unlisted visibility ([ThibG](https://github.com/tootsuite/mastodon/pull/13096)) +- Fix error when searching for URLs that contain the mention syntax ([ThibG](https://github.com/tootsuite/mastodon/pull/13151)) +- Fix text area above/right of emoji picker being accidentally clickable in web UI ([ariasuni](https://github.com/tootsuite/mastodon/pull/13148)) +- Fix too large announcements not being scrollable in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13211)) +- Fix `tootctl media remove-orphans` crashing when encountering invalid media ([ThibG](https://github.com/tootsuite/mastodon/pull/13170)) +- Fix installation failing when Redis password contains special characters ([ThibG](https://github.com/tootsuite/mastodon/pull/13156)) +- Fix announcements with fully-qualified mentions to local users crashing web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13164)) + +### Security + +- Fix re-sending of e-mail confirmation not being rate limited ([Gargron](https://github.com/tootsuite/mastodon/pull/13360)) + ## [v3.1.2] - 2020-02-27 ### Added diff --git a/Dockerfile b/Dockerfile index a22efe67234edd..0537d8facdd416 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ FROM ubuntu:18.04 as build-dep SHELL ["bash", "-c"] # Install Node v12 (LTS) -ENV NODE_VER="12.14.0" +ENV NODE_VER="12.16.1" RUN ARCH= && \ dpkgArch="$(dpkg --print-architecture)" && \ case "${dpkgArch##*-}" in \ @@ -38,8 +38,8 @@ RUN apt update && \ make -j$(nproc) > /dev/null && \ make install_bin install_include install_lib -# Install ruby -ENV RUBY_VER="2.6.5" +# Install Ruby +ENV RUBY_VER="2.6.6" ENV CPPFLAGS="-I/opt/jemalloc/include" ENV LDFLAGS="-L/opt/jemalloc/lib/" RUN apt update && \ diff --git a/Gemfile b/Gemfile index c35b21be49e55d..57bf27183ec6e6 100644 --- a/Gemfile +++ b/Gemfile @@ -1,12 +1,12 @@ # frozen_string_literal: true source 'https://rubygems.org' -ruby '>= 2.4.0', '< 3.0.0' +ruby '>= 2.5.0', '< 3.0.0' gem 'pkg-config', '~> 1.4' gem 'puma', '~> 4.3' -gem 'rails', '~> 5.2.4' +gem 'rails', '~> 5.2.4.2' gem 'sprockets', '~> 3.7.2' gem 'thor', '~> 0.20' gem 'rack', '~> 2.2.2' @@ -20,7 +20,7 @@ gem 'makara', '~> 0.4' gem 'pghero', '~> 2.4' gem 'dotenv-rails', '~> 2.7' -gem 'aws-sdk-s3', '~> 1.60', require: false +gem 'aws-sdk-s3', '~> 1.61', require: false gem 'fog-core', '<= 2.1.0' gem 'fog-openstack', '~> 0.3', require: false gem 'paperclip', '~> 6.0' @@ -35,7 +35,7 @@ gem 'browser' gem 'charlock_holmes', '~> 0.7.7' gem 'iso-639' gem 'chewy', '~> 5.1' -gem 'cld3', '~> 3.2.6' +gem 'cld3', '~> 3.3.0' gem 'devise', '~> 4.7' gem 'devise-two-factor', '~> 3.1' @@ -48,8 +48,8 @@ gem 'omniauth-cas', '~> 1.1' gem 'omniauth-saml', '~> 1.10' gem 'omniauth', '~> 1.9' -gem 'discard', '~> 1.1' -gem 'doorkeeper', '~> 5.2' +gem 'discard', '~> 1.2' +gem 'doorkeeper', '~> 5.3' gem 'fast_blank', '~> 1.0' gem 'fastimage' gem 'goldfinger', '~> 2.1' @@ -69,7 +69,7 @@ gem 'nilsimsa', git: 'https://github.com/witgo/nilsimsa', ref: 'fd184883048b922b gem 'nokogiri', '~> 1.10' gem 'nsa', '~> 0.2' gem 'oj', '~> 3.10' -gem 'ox', '~> 2.12' +gem 'ox', '~> 2.13' gem 'parslet' gem 'parallel', '~> 1.19' gem 'posix-spawn', git: 'https://github.com/rtomayko/posix-spawn', ref: '58465d2e213991f8afb13b984854a49fcdcc980c' @@ -84,7 +84,7 @@ gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' gem 'rqrcode', '~> 1.1' gem 'ruby-progressbar', '~> 1.10' gem 'sanitize', '~> 5.1' -gem 'sidekiq', '~> 5.2' +gem 'sidekiq', '~> 6.0' gem 'sidekiq-scheduler', '~> 3.0' gem 'sidekiq-unique-jobs', '~> 6.0' gem 'sidekiq-bulk', '~>0.2.0' @@ -92,9 +92,9 @@ gem 'simple-navigation', '~> 4.1' gem 'simple_form', '~> 5.0' gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie' gem 'stoplight', '~> 2.2.0' -gem 'strong_migrations', '~> 0.5' +gem 'strong_migrations', '~> 0.6' gem 'tty-command', '~> 0.9', require: false -gem 'tty-prompt', '~> 0.20', require: false +gem 'tty-prompt', '~> 0.21', require: false gem 'twitter-text', '~> 1.14' gem 'tzinfo-data', '~> 1.2019' gem 'webpacker', '~> 4.2' @@ -112,7 +112,7 @@ group :development, :test do gem 'i18n-tasks', '~> 0.9', require: false gem 'pry-byebug', '~> 3.8' gem 'pry-rails', '~> 0.3' - gem 'rspec-rails', '~> 3.9' + gem 'rspec-rails', '~> 4.0' end group :production, :test do @@ -122,19 +122,19 @@ end group :test do gem 'capybara', '~> 3.31' gem 'climate_control', '~> 0.2' - gem 'faker', '~> 2.10' + gem 'faker', '~> 2.11' gem 'microformats', '~> 4.2' gem 'rails-controller-testing', '~> 1.0' gem 'rspec-sidekiq', '~> 3.0' gem 'simplecov', '~> 0.18', require: false gem 'webmock', '~> 3.8' - gem 'parallel_tests', '~> 2.30' + gem 'parallel_tests', '~> 2.32' end group :development do gem 'active_record_query_trace', '~> 1.7' gem 'annotate', '~> 3.0' - gem 'better_errors', '~> 2.5' + gem 'better_errors', '~> 2.6' gem 'binding_of_caller', '~> 0.7' gem 'bullet', '~> 6.1' gem 'letter_opener', '~> 1.7' @@ -142,10 +142,10 @@ group :development do gem 'memory_profiler' gem 'rubocop', '~> 0.79', require: false gem 'rubocop-rails', '~> 2.4', require: false - gem 'brakeman', '~> 4.7', require: false + gem 'brakeman', '~> 4.8', require: false gem 'bundler-audit', '~> 0.6', require: false - gem 'capistrano', '~> 3.11' + gem 'capistrano', '~> 3.12' gem 'capistrano-rails', '~> 1.4' gem 'capistrano-rbenv', '~> 2.1' gem 'capistrano-yarn', '~> 2.0' diff --git a/Gemfile.lock b/Gemfile.lock index 9d0b75f911d951..3ac0a06ed0a404 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -31,25 +31,25 @@ GIT GEM remote: https://rubygems.org/ specs: - actioncable (5.2.4.1) - actionpack (= 5.2.4.1) + actioncable (5.2.4.2) + actionpack (= 5.2.4.2) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.4.1) - actionpack (= 5.2.4.1) - actionview (= 5.2.4.1) - activejob (= 5.2.4.1) + actionmailer (5.2.4.2) + actionpack (= 5.2.4.2) + actionview (= 5.2.4.2) + activejob (= 5.2.4.2) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.4.1) - actionview (= 5.2.4.1) - activesupport (= 5.2.4.1) + actionpack (5.2.4.2) + actionview (= 5.2.4.2) + activesupport (= 5.2.4.2) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.4.1) - activesupport (= 5.2.4.1) + actionview (5.2.4.2) + activesupport (= 5.2.4.2) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) @@ -60,20 +60,20 @@ GEM case_transform (>= 0.2) jsonapi-renderer (>= 0.1.1.beta1, < 0.3) active_record_query_trace (1.7) - activejob (5.2.4.1) - activesupport (= 5.2.4.1) + activejob (5.2.4.2) + activesupport (= 5.2.4.2) globalid (>= 0.3.6) - activemodel (5.2.4.1) - activesupport (= 5.2.4.1) - activerecord (5.2.4.1) - activemodel (= 5.2.4.1) - activesupport (= 5.2.4.1) + activemodel (5.2.4.2) + activesupport (= 5.2.4.2) + activerecord (5.2.4.2) + activemodel (= 5.2.4.2) + activesupport (= 5.2.4.2) arel (>= 9.0) - activestorage (5.2.4.1) - actionpack (= 5.2.4.1) - activerecord (= 5.2.4.1) + activestorage (5.2.4.2) + actionpack (= 5.2.4.2) + activerecord (= 5.2.4.2) marcel (~> 0.3.1) - activesupport (5.2.4.1) + activesupport (5.2.4.2) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -92,23 +92,23 @@ GEM av (0.9.0) cocaine (~> 0.5.3) aws-eventstream (1.0.3) - aws-partitions (1.261.0) - aws-sdk-core (3.86.0) + aws-partitions (1.286.0) + aws-sdk-core (3.92.0) aws-eventstream (~> 1.0, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-kms (1.27.0) + aws-sdk-kms (1.30.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.60.1) + aws-sdk-s3 (1.61.1) aws-sdk-core (~> 3, >= 3.83.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) - aws-sigv4 (1.1.0) + aws-sigv4 (1.1.1) aws-eventstream (~> 1.0, >= 1.0.2) bcrypt (3.1.12) - better_errors (2.5.1) + better_errors (2.6.0) coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) @@ -116,10 +116,10 @@ GEM debug_inspector (>= 0.0.1) blurhash (0.1.4) ffi (~> 1.10.0) - bootsnap (1.4.5) + bootsnap (1.4.6) msgpack (~> 1.0) - brakeman (4.7.2) - browser (3.0.3) + brakeman (4.8.0) + browser (4.0.0) builder (3.2.4) bullet (6.1.0) activesupport (>= 3.0.0) @@ -128,7 +128,7 @@ GEM bundler (>= 1.2.0, < 3) thor (~> 0.18) byebug (11.1.1) - capistrano (3.11.2) + capistrano (3.12.1) airbrussh (>= 1.0.0) i18n rake (>= 10.0.0) @@ -160,13 +160,13 @@ GEM elasticsearch (>= 2.0.0) elasticsearch-dsl chunky_png (1.3.11) - cld3 (3.2.6) + cld3 (3.3.0) ffi (>= 1.1.0, < 1.12.0) climate_control (0.2.0) cocaine (0.5.8) climate_control (>= 0.0.3, < 1.0) coderay (1.1.2) - concurrent-ruby (1.1.5) + concurrent-ruby (1.1.6) connection_pool (2.2.2) crack (0.4.3) safe_yaml (~> 1.0.0) @@ -190,37 +190,37 @@ GEM devise (>= 4.0.0) rpam2 (~> 4.0) diff-lcs (1.3) - discard (1.1.0) + discard (1.2.0) activerecord (>= 4.2, < 7) docile (1.3.2) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) - doorkeeper (5.2.3) + doorkeeper (5.3.1) railties (>= 5) dotenv (2.7.5) dotenv-rails (2.7.5) dotenv (= 2.7.5) railties (>= 3.2, < 6.1) e2mmap (0.1.0) - elasticsearch (7.3.0) - elasticsearch-api (= 7.3.0) - elasticsearch-transport (= 7.3.0) - elasticsearch-api (7.3.0) + elasticsearch (7.5.0) + elasticsearch-api (= 7.5.0) + elasticsearch-transport (= 7.5.0) + elasticsearch-api (7.5.0) multi_json elasticsearch-dsl (0.1.8) - elasticsearch-transport (7.3.0) - faraday + elasticsearch-transport (7.5.0) + faraday (>= 0.14, < 1) multi_json encryptor (3.0.0) equatable (0.6.1) erubi (1.9.0) - et-orbi (1.1.6) + et-orbi (1.2.3) tzinfo excon (0.71.0) fabrication (2.21.0) - faker (2.10.1) + faker (2.11.0) i18n (>= 1.6, < 2) - faraday (1.0.0) + faraday (0.17.3) multipart-post (>= 1.2, < 3) fast_blank (1.0.0) fastimage (2.1.7) @@ -241,8 +241,8 @@ GEM fog-json (>= 1.0) ipaddress (>= 0.8) formatador (0.2.5) - fugit (1.1.6) - et-orbi (~> 1.1, >= 1.1.6) + fugit (1.3.3) + et-orbi (~> 1.1, >= 1.1.8) raabro (~> 1.1) fuubar (2.5.0) rspec-core (~> 3.0) @@ -265,8 +265,8 @@ GEM railties (>= 4.0.1) hamster (3.0.0) concurrent-ruby (~> 1.0) - hashdiff (1.0.0) - hashie (3.6.0) + hashdiff (1.0.1) + hashie (4.1.0) highline (2.0.3) hiredis (0.6.3) hkdf (0.3.0) @@ -287,7 +287,7 @@ GEM rainbow (>= 2.0.0) i18n (1.8.2) concurrent-ruby (~> 1.0) - i18n-tasks (0.9.30) + i18n-tasks (0.9.31) activesupport (>= 4.0.2) ast (>= 2.1.0) erubi @@ -299,19 +299,19 @@ GEM terminal-table (>= 1.5.1) idn-ruby (0.1.0) ipaddress (0.8.3) - iso-639 (0.2.8) + iso-639 (0.3.5) jaro_winkler (1.5.4) jmespath (1.4.0) json (2.3.0) json-canonicalization (0.2.0) - json-ld (3.1.0) + json-ld (3.1.2) htmlentities (~> 4.3) - json-canonicalization (~> 0.1) + json-canonicalization (~> 0.2) link_header (~> 0.0, >= 0.0.8) multi_json (~> 1.14) rack (~> 2.0) rdf (~> 3.1) - json-ld-preloaded (3.1.0) + json-ld-preloaded (3.1.2) json-ld (~> 3.1) rdf (~> 3.1) jsonapi-renderer (0.2.2) @@ -361,11 +361,11 @@ GEM mime-types (3.3.1) mime-types-data (~> 3.2015) mime-types-data (3.2019.1009) - mimemagic (0.3.3) + mimemagic (0.3.4) mini_mime (1.0.2) mini_portile2 (2.4.0) minitest (5.14.0) - msgpack (1.3.1) + msgpack (1.3.3) multi_json (1.14.1) multipart-post (2.1.1) necromancer (0.5.1) @@ -374,7 +374,7 @@ GEM net-ssh (>= 2.6.5, < 6.0.0) net-ssh (5.2.0) nio4r (2.5.2) - nokogiri (1.10.8) + nokogiri (1.10.9) mini_portile2 (~> 2.4.0) nokogumbo (2.0.1) nokogiri (~> 1.8, >= 1.8.4) @@ -383,9 +383,9 @@ GEM concurrent-ruby (~> 1.0, >= 1.0.2) sidekiq (>= 3.5) statsd-ruby (~> 1.4, >= 1.4.0) - oj (3.10.1) - omniauth (1.9.0) - hashie (>= 3.4.6, < 3.7.0) + oj (3.10.5) + omniauth (1.9.1) + hashie (>= 3.4.6) rack (>= 1.6.2, < 3) omniauth-cas (1.1.1) addressable (~> 2.3) @@ -395,7 +395,7 @@ GEM omniauth (~> 1.3, >= 1.3.2) ruby-saml (~> 1.7) orm_adapter (0.5.0) - ox (2.12.1) + ox (2.13.2) paperclip (6.0.0) activemodel (>= 4.2.0) activesupport (>= 4.2.0) @@ -406,15 +406,15 @@ GEM av (~> 0.9.0) paperclip (>= 2.5.2) parallel (1.19.1) - parallel_tests (2.30.1) + parallel_tests (2.32.0) parallel - parser (2.7.0.2) + parser (2.7.0.5) ast (~> 2.4.0) parslet (1.8.2) pastel (0.7.3) equatable (~> 0.6) tty-color (~> 0.5) - pg (1.2.2) + pg (1.2.3) pghero (2.4.1) activerecord (>= 5) pkg-config (1.4.1) @@ -435,7 +435,7 @@ GEM pry-rails (0.3.9) pry (>= 0.10.4) public_suffix (4.0.3) - puma (4.3.1) + puma (4.3.3) nio4r (~> 2.0) pundit (2.1.0) activesupport (>= 3.0.0) @@ -445,24 +445,24 @@ GEM rack (>= 1.0, < 3) rack-cors (1.1.1) rack (>= 2.0.0) - rack-protection (2.0.7) + rack-protection (2.0.8.1) rack rack-proxy (0.6.5) rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.2.4.1) - actioncable (= 5.2.4.1) - actionmailer (= 5.2.4.1) - actionpack (= 5.2.4.1) - actionview (= 5.2.4.1) - activejob (= 5.2.4.1) - activemodel (= 5.2.4.1) - activerecord (= 5.2.4.1) - activestorage (= 5.2.4.1) - activesupport (= 5.2.4.1) + rails (5.2.4.2) + actioncable (= 5.2.4.2) + actionmailer (= 5.2.4.2) + actionpack (= 5.2.4.2) + actionview (= 5.2.4.2) + activejob (= 5.2.4.2) + activemodel (= 5.2.4.2) + activerecord (= 5.2.4.2) + activestorage (= 5.2.4.2) + activesupport (= 5.2.4.2) bundler (>= 1.3.0) - railties (= 5.2.4.1) + railties (= 5.2.4.2) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.4) actionpack (>= 5.0.1.x) @@ -478,9 +478,9 @@ GEM railties (>= 5.0, < 6) rails-settings-cached (0.6.6) rails (>= 4.2.0) - railties (5.2.4.1) - actionpack (= 5.2.4.1) - activesupport (= 5.2.4.1) + railties (5.2.4.2) + actionpack (= 5.2.4.2) + activesupport (= 5.2.4.2) method_source rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) @@ -523,26 +523,26 @@ GEM chunky_png (~> 1.0) rqrcode_core (~> 0.1) rqrcode_core (0.1.1) - rspec-core (3.9.0) - rspec-support (~> 3.9.0) - rspec-expectations (3.9.0) + rspec-core (3.9.1) + rspec-support (~> 3.9.1) + rspec-expectations (3.9.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.9.0) - rspec-mocks (3.9.0) + rspec-mocks (3.9.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.9.0) - rspec-rails (3.9.0) - actionpack (>= 3.0) - activesupport (>= 3.0) - railties (>= 3.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) - rspec-support (~> 3.9.0) + rspec-rails (4.0.0) + actionpack (>= 4.2) + activesupport (>= 4.2) + railties (>= 4.2) + rspec-core (~> 3.9) + rspec-expectations (~> 3.9) + rspec-mocks (~> 3.9) + rspec-support (~> 3.9) rspec-sidekiq (3.0.3) rspec-core (~> 3.0, >= 3.0.0) sidekiq (>= 2.4.0) - rspec-support (3.9.0) + rspec-support (3.9.2) rubocop (0.79.0) jaro_winkler (~> 1.5.1) parallel (~> 1.10) @@ -556,38 +556,40 @@ GEM ruby-progressbar (1.10.1) ruby-saml (1.9.0) nokogiri (>= 1.5.10) - rufus-scheduler (3.5.2) - fugit (~> 1.1, >= 1.1.5) + rufus-scheduler (3.6.0) + fugit (~> 1.1, >= 1.1.6) safe_yaml (1.0.5) sanitize (5.1.0) crass (~> 1.0.2) nokogiri (>= 1.8.0) nokogumbo (~> 2.0) - sidekiq (5.2.7) - connection_pool (~> 2.2, >= 2.2.2) - rack (>= 1.5.0) - rack-protection (>= 1.5.0) - redis (>= 3.3.5, < 5) + sidekiq (6.0.4) + connection_pool (>= 2.2.2) + rack (>= 2.0.0) + rack-protection (>= 2.0.0) + redis (>= 4.1.0) sidekiq-bulk (0.2.0) sidekiq - sidekiq-scheduler (3.0.0) + sidekiq-scheduler (3.0.1) + e2mmap redis (>= 3, < 5) rufus-scheduler (~> 3.2) sidekiq (>= 3) + thwait tilt (>= 1.4.0) - sidekiq-unique-jobs (6.0.18) + sidekiq-unique-jobs (6.0.21) concurrent-ruby (~> 1.0, >= 1.0.5) sidekiq (>= 4.0, < 7.0) thor (~> 0) simple-navigation (4.1.0) activesupport (>= 2.3.2) - simple_form (5.0.1) + simple_form (5.0.2) actionpack (>= 5.0) activemodel (>= 5.0) - simplecov (0.18.2) + simplecov (0.18.5) docile (~> 1.1) simplecov-html (~> 0.11) - simplecov-html (0.12.0) + simplecov-html (0.12.2) sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -595,7 +597,7 @@ GEM actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - sshkit (1.20.0) + sshkit (1.21.0) net-scp (>= 1.1.2) net-ssh (>= 2.8.0) stackprof (0.2.15) @@ -603,7 +605,7 @@ GEM stoplight (2.2.0) streamio-ffmpeg (3.0.2) multi_json (~> 1.8) - strong_migrations (0.5.1) + strong_migrations (0.6.2) activerecord (>= 5) temple (0.8.2) terminal-table (1.8.0) @@ -614,11 +616,11 @@ GEM thread_safe (0.3.6) thwait (0.1.0) tilt (2.0.10) - tty-color (0.5.0) + tty-color (0.5.1) tty-command (0.9.0) pastel (~> 0.7.0) - tty-cursor (0.7.0) - tty-prompt (0.20.0) + tty-cursor (0.7.1) + tty-prompt (0.21.0) necromancer (~> 0.5.0) pastel (~> 0.7.0) tty-reader (~> 0.7.0) @@ -626,10 +628,10 @@ GEM tty-cursor (~> 0.7) tty-screen (~> 0.7) wisper (~> 2.0.0) - tty-screen (0.7.0) + tty-screen (0.7.1) twitter-text (1.14.7) unf (~> 0.1.0) - tzinfo (1.2.6) + tzinfo (1.2.7) thread_safe (~> 0.1) tzinfo-data (1.2019.3) tzinfo (>= 1.0.0) @@ -640,7 +642,7 @@ GEM uniform_notifier (1.13.0) warden (1.2.8) rack (>= 2.0.6) - webmock (3.8.0) + webmock (3.8.3) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -666,35 +668,35 @@ DEPENDENCIES active_record_query_trace (~> 1.7) addressable (~> 2.7) annotate (~> 3.0) - aws-sdk-s3 (~> 1.60) - better_errors (~> 2.5) + aws-sdk-s3 (~> 1.61) + better_errors (~> 2.6) binding_of_caller (~> 0.7) blurhash (~> 0.1) bootsnap (~> 1.4) - brakeman (~> 4.7) + brakeman (~> 4.8) browser bullet (~> 6.1) bundler-audit (~> 0.6) - capistrano (~> 3.11) + capistrano (~> 3.12) capistrano-rails (~> 1.4) capistrano-rbenv (~> 2.1) capistrano-yarn (~> 2.0) capybara (~> 3.31) charlock_holmes (~> 0.7.7) chewy (~> 5.1) - cld3 (~> 3.2.6) + cld3 (~> 3.3.0) climate_control (~> 0.2) concurrent-ruby connection_pool devise (~> 4.7) devise-two-factor (~> 3.1) devise_pam_authenticatable2 (~> 9.2) - discard (~> 1.1) - doorkeeper (~> 5.2) + discard (~> 1.2) + doorkeeper (~> 5.3) dotenv-rails (~> 2.7) e2mmap (~> 0.1.0) fabrication (~> 2.21) - faker (~> 2.10) + faker (~> 2.11) fast_blank (~> 1.0) fastimage fog-core (<= 2.1.0) @@ -732,11 +734,11 @@ DEPENDENCIES omniauth (~> 1.9) omniauth-cas (~> 1.1) omniauth-saml (~> 1.10) - ox (~> 2.12) + ox (~> 2.13) paperclip (~> 6.0) paperclip-av-transcoder (~> 0.6) parallel (~> 1.19) - parallel_tests (~> 2.30) + parallel_tests (~> 2.32) parslet pg (~> 1.2) pghero (~> 2.4) @@ -751,7 +753,7 @@ DEPENDENCIES rack (~> 2.2.2) rack-attack (~> 6.2) rack-cors (~> 1.1) - rails (~> 5.2.4) + rails (~> 5.2.4.2) rails-controller-testing (~> 1.0) rails-i18n (~> 5.1) rails-settings-cached (~> 0.6) @@ -761,13 +763,13 @@ DEPENDENCIES redis-namespace (~> 1.7) redis-rails (~> 5.0) rqrcode (~> 1.1) - rspec-rails (~> 3.9) + rspec-rails (~> 4.0) rspec-sidekiq (~> 3.0) rubocop (~> 0.79) rubocop-rails (~> 2.4) ruby-progressbar (~> 1.10) sanitize (~> 5.1) - sidekiq (~> 5.2) + sidekiq (~> 6.0) sidekiq-bulk (~> 0.2.0) sidekiq-scheduler (~> 3.0) sidekiq-unique-jobs (~> 6.0) @@ -779,11 +781,11 @@ DEPENDENCIES stackprof stoplight (~> 2.2.0) streamio-ffmpeg (~> 3.0) - strong_migrations (~> 0.5) + strong_migrations (~> 0.6) thor (~> 0.20) thwait (~> 0.1.0) tty-command (~> 0.9) - tty-prompt (~> 0.20) + tty-prompt (~> 0.21) twitter-text (~> 1.14) tzinfo-data (~> 1.2019) webmock (~> 3.8) diff --git a/README.md b/README.md index 7db66abfa02c14..9ef4acb177b9b9 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,8 @@ Mastodon acts as an OAuth2 provider so 3rd party apps can use the REST and Strea **Requirements:** - **PostgreSQL** 9.5+ -- **Redis** -- **Ruby** 2.4+ +- **Redis** 4+ +- **Ruby** 2.5+ - **Node.js** 10.13+ The repository includes deployment configurations for **Docker and docker-compose**, but also a few specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. The [**stand-alone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation. diff --git a/Vagrantfile b/Vagrantfile index 79af1dc5d70dbc..7d0f7b3defc1cf 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -91,7 +91,7 @@ VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| - config.vm.box = "ubuntu/xenial64" + config.vm.box = "ubuntu/bionic64" config.vm.provider :virtualbox do |vb| vb.name = "mastodon" diff --git a/app/chewy/statuses_index.rb b/app/chewy/statuses_index.rb index f5735421c7c90b..bec9ed88b22b94 100644 --- a/app/chewy/statuses_index.rb +++ b/app/chewy/statuses_index.rb @@ -47,6 +47,11 @@ class StatusesIndex < Chewy::Index data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) } end + crutch :bookmarks do |collection| + data = ::Bookmark.where(status_id: collection.map(&:id)).where(account: Account.local).pluck(:status_id, :account_id) + data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) } + end + root date_detection: false do field :id, type: 'long' field :account_id, type: 'long' diff --git a/app/controllers/account_follow_controller.rb b/app/controllers/account_follow_controller.rb index 185a355f8f3ac0..33394074db4453 100644 --- a/app/controllers/account_follow_controller.rb +++ b/app/controllers/account_follow_controller.rb @@ -6,7 +6,7 @@ class AccountFollowController < ApplicationController before_action :authenticate_user! def create - FollowService.new.call(current_user.account, @account.acct) + FollowService.new.call(current_user.account, @account, with_rate_limit: true) redirect_to account_path(@account) end end diff --git a/app/controllers/admin/action_logs_controller.rb b/app/controllers/admin/action_logs_controller.rb index e273dfeaef196f..2d77620df7b8d9 100644 --- a/app/controllers/admin/action_logs_controller.rb +++ b/app/controllers/admin/action_logs_controller.rb @@ -2,8 +2,18 @@ module Admin class ActionLogsController < BaseController - def index - @action_logs = Admin::ActionLog.page(params[:page]) + before_action :set_action_logs + + def index; end + + private + + def set_action_logs + @action_logs = Admin::ActionLogFilter.new(filter_params).results.page(params[:page]) + end + + def filter_params + params.slice(:page, *Admin::ActionLogFilter::KEYS).permit(:page, *Admin::ActionLogFilter::KEYS) end end end diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb index 9fe85064e34e30..c2591972624e30 100644 --- a/app/controllers/admin/email_domain_blocks_controller.rb +++ b/app/controllers/admin/email_domain_blocks_controller.rb @@ -6,12 +6,12 @@ class EmailDomainBlocksController < BaseController def index authorize :email_domain_block, :index? - @email_domain_blocks = EmailDomainBlock.page(params[:page]) + @email_domain_blocks = EmailDomainBlock.where(parent_id: nil).includes(:children).order(id: :desc).page(params[:page]) end def new authorize :email_domain_block, :create? - @email_domain_block = EmailDomainBlock.new + @email_domain_block = EmailDomainBlock.new(domain: params[:_domain]) end def create @@ -21,6 +21,28 @@ def create if @email_domain_block.save log_action :create, @email_domain_block + + if @email_domain_block.with_dns_records? + hostnames = [] + ips = [] + + Resolv::DNS.open do |dns| + dns.timeouts = 1 + + hostnames = dns.getresources(@email_domain_block.domain, Resolv::DNS::Resource::IN::MX).to_a.map { |e| e.exchange.to_s } + + ([@email_domain_block.domain] + hostnames).uniq.each do |hostname| + ips.concat(dns.getresources(hostname, Resolv::DNS::Resource::IN::A).to_a.map { |e| e.address.to_s }) + ips.concat(dns.getresources(hostname, Resolv::DNS::Resource::IN::AAAA).to_a.map { |e| e.address.to_s }) + end + end + + (hostnames + ips).each do |hostname| + another_email_domain_block = EmailDomainBlock.new(domain: hostname, parent: @email_domain_block) + log_action :create, another_email_domain_block if another_email_domain_block.save + end + end + redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.created_msg') else render :new @@ -41,7 +63,7 @@ def set_email_domain_block end def resource_params - params.require(:email_domain_block).permit(:domain) + params.require(:email_domain_block).permit(:domain, :with_dns_records) end end end diff --git a/app/controllers/admin/site_uploads_controller.rb b/app/controllers/admin/site_uploads_controller.rb new file mode 100644 index 00000000000000..cacecedb0a1255 --- /dev/null +++ b/app/controllers/admin/site_uploads_controller.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Admin + class SiteUploadsController < BaseController + before_action :set_site_upload + + def destroy + authorize :settings, :destroy? + + @site_upload.destroy! + + redirect_to edit_admin_settings_path, notice: I18n.t('admin.site_uploads.destroyed_msg') + end + + private + + def set_site_upload + @site_upload = SiteUpload.find(params[:id]) + end + end +end diff --git a/app/controllers/admin/warning_presets_controller.rb b/app/controllers/admin/warning_presets_controller.rb index 37be842c5b055f..b376f8d9b1e905 100644 --- a/app/controllers/admin/warning_presets_controller.rb +++ b/app/controllers/admin/warning_presets_controller.rb @@ -7,7 +7,7 @@ class WarningPresetsController < BaseController def index authorize :account_warning_preset, :index? - @warning_presets = AccountWarningPreset.all + @warning_presets = AccountWarningPreset.alphabetic @warning_preset = AccountWarningPreset.new end @@ -19,7 +19,7 @@ def create if @warning_preset.save redirect_to admin_warning_presets_path else - @warning_presets = AccountWarningPreset.all + @warning_presets = AccountWarningPreset.alphabetic render :index end end @@ -52,7 +52,7 @@ def set_warning_preset end def warning_preset_params - params.require(:account_warning_preset).permit(:text) + params.require(:account_warning_preset).permit(:title, :text) end end end diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 68bf425f4d0254..153ade253d69b0 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -44,6 +44,10 @@ class Api::BaseController < ApplicationController render json: { error: 'There was a temporary problem serving your request, please try again' }, status: 503 end + rescue_from Mastodon::RateLimitExceededError do + render json: { error: I18n.t('errors.429') }, status: 429 + end + rescue_from ActionController::ParameterMissing do |e| render json: { error: e.to_s }, status: 400 end diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb index e360b8a9296b2c..1daa1ed0d3a393 100644 --- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb @@ -5,8 +5,6 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController before_action :set_account after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer @@ -27,7 +25,7 @@ def load_accounts end def hide_results? - (@account.user_hides_network? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) + (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) end def default_accounts diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb index a405b365f2c244..6fc23cf75e562b 100644 --- a/app/controllers/api/v1/accounts/following_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb @@ -5,8 +5,6 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController before_action :set_account after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer @@ -27,7 +25,7 @@ def load_accounts end def hide_results? - (@account.user_hides_network? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) + (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) end def default_accounts diff --git a/app/controllers/api/v1/accounts/identity_proofs_controller.rb b/app/controllers/api/v1/accounts/identity_proofs_controller.rb index bea51ae1194c73..8dad6fee962748 100644 --- a/app/controllers/api/v1/accounts/identity_proofs_controller.rb +++ b/app/controllers/api/v1/accounts/identity_proofs_controller.rb @@ -4,8 +4,6 @@ class Api::V1::Accounts::IdentityProofsController < Api::BaseController before_action :require_user! before_action :set_account - respond_to :json - def index @proofs = @account.identity_proofs.active render json: @proofs, each_serializer: REST::IdentityProofSerializer diff --git a/app/controllers/api/v1/accounts/lists_controller.rb b/app/controllers/api/v1/accounts/lists_controller.rb index 72392453c4e35b..ccb751f8f7dc64 100644 --- a/app/controllers/api/v1/accounts/lists_controller.rb +++ b/app/controllers/api/v1/accounts/lists_controller.rb @@ -5,8 +5,6 @@ class Api::V1::Accounts::ListsController < Api::BaseController before_action :require_user! before_action :set_account - respond_to :json - def index @lists = @account.lists.where(account: current_account) render json: @lists, each_serializer: REST::ListSerializer diff --git a/app/controllers/api/v1/accounts/pins_controller.rb b/app/controllers/api/v1/accounts/pins_controller.rb index 0a0239c424e8bf..3915b566933501 100644 --- a/app/controllers/api/v1/accounts/pins_controller.rb +++ b/app/controllers/api/v1/accounts/pins_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Accounts::PinsController < Api::BaseController before_action :require_user! before_action :set_account - respond_to :json - def create AccountPin.create!(account: current_account, target_account: @account) render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter diff --git a/app/controllers/api/v1/accounts/relationships_controller.rb b/app/controllers/api/v1/accounts/relationships_controller.rb index ab8a0461f5e0d3..1d3992a285770c 100644 --- a/app/controllers/api/v1/accounts/relationships_controller.rb +++ b/app/controllers/api/v1/accounts/relationships_controller.rb @@ -4,8 +4,6 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController before_action -> { doorkeeper_authorize! :read, :'read:follows' } before_action :require_user! - respond_to :json - def index accounts = Account.where(id: account_ids).select('id') # .where doesn't guarantee that our results are in the same order diff --git a/app/controllers/api/v1/accounts/search_controller.rb b/app/controllers/api/v1/accounts/search_controller.rb index 4217b527a59377..3061fcb7e715c1 100644 --- a/app/controllers/api/v1/accounts/search_controller.rb +++ b/app/controllers/api/v1/accounts/search_controller.rb @@ -4,8 +4,6 @@ class Api::V1::Accounts::SearchController < Api::BaseController before_action -> { doorkeeper_authorize! :read, :'read:accounts' } before_action :require_user! - respond_to :json - def show @accounts = account_search render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb index 333db96186cf67..114ee0a8244b9b 100644 --- a/app/controllers/api/v1/accounts/statuses_controller.rb +++ b/app/controllers/api/v1/accounts/statuses_controller.rb @@ -6,8 +6,6 @@ class Api::V1::Accounts::StatusesController < Api::BaseController after_action :insert_pagination_headers, unless: -> { truthy_param?(:pinned) } - respond_to :json - def index @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index d68d2715f71541..0080faf33071c5 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -14,7 +14,7 @@ class Api::V1::AccountsController < Api::BaseController skip_before_action :require_authenticated_user!, only: :create - respond_to :json + override_rate_limit_headers :follow, family: :follows def show render json: @account, serializer: REST::AccountSerializer @@ -31,7 +31,7 @@ def create end def follow - FollowService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs)) + FollowService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs), with_rate_limit: true) options = @account.locked? || current_user.account.silenced? ? {} : { following_map: { @account.id => { reblogs: truthy_param?(:reblogs) } }, requested_map: { @account.id => false } } diff --git a/app/controllers/api/v1/apps/credentials_controller.rb b/app/controllers/api/v1/apps/credentials_controller.rb index 8b63d0490d173a..0475b2d4a208d4 100644 --- a/app/controllers/api/v1/apps/credentials_controller.rb +++ b/app/controllers/api/v1/apps/credentials_controller.rb @@ -3,8 +3,6 @@ class Api::V1::Apps::CredentialsController < Api::BaseController before_action -> { doorkeeper_authorize! :read } - respond_to :json - def show render json: doorkeeper_token.application, serializer: REST::ApplicationSerializer, fields: %i(name website vapid_key) end diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb index 4cff04cad7fd15..a2baeef900cbf6 100644 --- a/app/controllers/api/v1/blocks_controller.rb +++ b/app/controllers/api/v1/blocks_controller.rb @@ -5,8 +5,6 @@ class Api::V1::BlocksController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/bookmarks_controller.rb b/app/controllers/api/v1/bookmarks_controller.rb index e1b244e76fea8d..c15212f0a91dd4 100644 --- a/app/controllers/api/v1/bookmarks_controller.rb +++ b/app/controllers/api/v1/bookmarks_controller.rb @@ -5,8 +5,6 @@ class Api::V1::BookmarksController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers - respond_to :json - def index @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) diff --git a/app/controllers/api/v1/conversations_controller.rb b/app/controllers/api/v1/conversations_controller.rb index b19f27ebfb6c47..bc801337945d6d 100644 --- a/app/controllers/api/v1/conversations_controller.rb +++ b/app/controllers/api/v1/conversations_controller.rb @@ -9,8 +9,6 @@ class Api::V1::ConversationsController < Api::BaseController before_action :set_conversation, except: :index after_action :insert_pagination_headers, only: :index - respond_to :json - def index @conversations = paginated_conversations render json: @conversations, each_serializer: REST::ConversationSerializer diff --git a/app/controllers/api/v1/custom_emojis_controller.rb b/app/controllers/api/v1/custom_emojis_controller.rb index 4e6d5d7c613a65..08b3474cc85865 100644 --- a/app/controllers/api/v1/custom_emojis_controller.rb +++ b/app/controllers/api/v1/custom_emojis_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Api::V1::CustomEmojisController < Api::BaseController - respond_to :json - skip_before_action :set_cache_headers def index diff --git a/app/controllers/api/v1/domain_blocks_controller.rb b/app/controllers/api/v1/domain_blocks_controller.rb index af9e7a20f75bf9..5bb02d834cf6fe 100644 --- a/app/controllers/api/v1/domain_blocks_controller.rb +++ b/app/controllers/api/v1/domain_blocks_controller.rb @@ -8,8 +8,6 @@ class Api::V1::DomainBlocksController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers, only: :show - respond_to :json - def show @blocks = load_domain_blocks render json: @blocks.map(&:domain) diff --git a/app/controllers/api/v1/endorsements_controller.rb b/app/controllers/api/v1/endorsements_controller.rb index 2770c7aef67825..c87dbc4ce836a7 100644 --- a/app/controllers/api/v1/endorsements_controller.rb +++ b/app/controllers/api/v1/endorsements_controller.rb @@ -5,8 +5,6 @@ class Api::V1::EndorsementsController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/favourites_controller.rb b/app/controllers/api/v1/favourites_controller.rb index db827f9d4aa2aa..3e242905da753f 100644 --- a/app/controllers/api/v1/favourites_controller.rb +++ b/app/controllers/api/v1/favourites_controller.rb @@ -5,8 +5,6 @@ class Api::V1::FavouritesController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers - respond_to :json - def index @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) diff --git a/app/controllers/api/v1/featured_tags/suggestions_controller.rb b/app/controllers/api/v1/featured_tags/suggestions_controller.rb index fb27ef88b93a95..8c1b81a0f007ad 100644 --- a/app/controllers/api/v1/featured_tags/suggestions_controller.rb +++ b/app/controllers/api/v1/featured_tags/suggestions_controller.rb @@ -2,12 +2,9 @@ class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController before_action -> { doorkeeper_authorize! :read, :'read:accounts' }, only: :index - before_action :require_user! before_action :set_most_used_tags, only: :index - respond_to :json - def index render json: @most_used_tags, each_serializer: REST::TagSerializer end diff --git a/app/controllers/api/v1/filters_controller.rb b/app/controllers/api/v1/filters_controller.rb index e5ebaff4d3b1d1..b0ace3af04c2f7 100644 --- a/app/controllers/api/v1/filters_controller.rb +++ b/app/controllers/api/v1/filters_controller.rb @@ -7,8 +7,6 @@ class Api::V1::FiltersController < Api::BaseController before_action :set_filters, only: :index before_action :set_filter, only: [:show, :update, :destroy] - respond_to :json - def index render json: @filters, each_serializer: REST::FilterSerializer end diff --git a/app/controllers/api/v1/instances/activity_controller.rb b/app/controllers/api/v1/instances/activity_controller.rb index b30e8464c3eb5d..4f6b4bcbfa0878 100644 --- a/app/controllers/api/v1/instances/activity_controller.rb +++ b/app/controllers/api/v1/instances/activity_controller.rb @@ -6,8 +6,6 @@ class Api::V1::Instances::ActivityController < Api::BaseController skip_before_action :set_cache_headers skip_before_action :require_authenticated_user!, unless: :whitelist_mode? - respond_to :json - def show expires_in 1.day, public: true render_with_cache json: :activity, expires_in: 1.day diff --git a/app/controllers/api/v1/instances/peers_controller.rb b/app/controllers/api/v1/instances/peers_controller.rb index cc00d8a6bc3ae1..9fa4409357b62d 100644 --- a/app/controllers/api/v1/instances/peers_controller.rb +++ b/app/controllers/api/v1/instances/peers_controller.rb @@ -6,8 +6,6 @@ class Api::V1::Instances::PeersController < Api::BaseController skip_before_action :set_cache_headers skip_before_action :require_authenticated_user!, unless: :whitelist_mode? - respond_to :json - def index expires_in 1.day, public: true render_with_cache(expires_in: 1.day) { Account.remote.domains } diff --git a/app/controllers/api/v1/instances_controller.rb b/app/controllers/api/v1/instances_controller.rb index c323b60b4292c8..5b5058a7bf7516 100644 --- a/app/controllers/api/v1/instances_controller.rb +++ b/app/controllers/api/v1/instances_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Api::V1::InstancesController < Api::BaseController - respond_to :json - skip_before_action :set_cache_headers skip_before_action :require_authenticated_user!, unless: :whitelist_mode? diff --git a/app/controllers/api/v1/media_controller.rb b/app/controllers/api/v1/media_controller.rb index 81825db1552a1d..0bb3d0d27b7ec2 100644 --- a/app/controllers/api/v1/media_controller.rb +++ b/app/controllers/api/v1/media_controller.rb @@ -3,27 +3,42 @@ class Api::V1::MediaController < Api::BaseController before_action -> { doorkeeper_authorize! :write, :'write:media' } before_action :require_user! - - respond_to :json + before_action :set_media_attachment, except: [:create] + before_action :check_processing, except: [:create] def create - @media = current_account.media_attachments.create!(media_params) - render json: @media, serializer: REST::MediaAttachmentSerializer + @media_attachment = current_account.media_attachments.create!(media_attachment_params) + render json: @media_attachment, serializer: REST::MediaAttachmentSerializer rescue Paperclip::Errors::NotIdentifiedByImageMagickError render json: file_type_error, status: 422 rescue Paperclip::Error render json: processing_error, status: 500 end + def show + render json: @media_attachment, serializer: REST::MediaAttachmentSerializer, status: status_code_for_media_attachment + end + def update - @media = current_account.media_attachments.where(status_id: nil).find(params[:id]) - @media.update!(media_params) - render json: @media, serializer: REST::MediaAttachmentSerializer + @media_attachment.update!(media_attachment_params) + render json: @media_attachment, serializer: REST::MediaAttachmentSerializer, status: status_code_for_media_attachment end private - def media_params + def status_code_for_media_attachment + @media_attachment.not_processed? ? 206 : 200 + end + + def set_media_attachment + @media_attachment = current_account.media_attachments.unattached.find(params[:id]) + end + + def check_processing + render json: processing_error, status: 422 if @media_attachment.processing_failed? + end + + def media_attachment_params params.permit(:file, :description, :focus) end diff --git a/app/controllers/api/v1/mutes_controller.rb b/app/controllers/api/v1/mutes_controller.rb index df6c8e86c59609..65439fe9bc1505 100644 --- a/app/controllers/api/v1/mutes_controller.rb +++ b/app/controllers/api/v1/mutes_controller.rb @@ -5,8 +5,6 @@ class Api::V1::MutesController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb index bf3002e79f5a52..8ac22776500b9b 100644 --- a/app/controllers/api/v1/notifications_controller.rb +++ b/app/controllers/api/v1/notifications_controller.rb @@ -6,8 +6,6 @@ class Api::V1::NotificationsController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers, only: :index - respond_to :json - DEFAULT_NOTIFICATIONS_LIMIT = 15 def index diff --git a/app/controllers/api/v1/polls/votes_controller.rb b/app/controllers/api/v1/polls/votes_controller.rb index 3fa0b6a760787c..e1d26106afb16f 100644 --- a/app/controllers/api/v1/polls/votes_controller.rb +++ b/app/controllers/api/v1/polls/votes_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Polls::VotesController < Api::BaseController before_action :require_user! before_action :set_poll - respond_to :json - def create VoteService.new.call(current_account, @poll, vote_params[:choices]) render json: @poll, serializer: REST::PollSerializer diff --git a/app/controllers/api/v1/polls_controller.rb b/app/controllers/api/v1/polls_controller.rb index 031e6d42d668e3..744baf7bb428a6 100644 --- a/app/controllers/api/v1/polls_controller.rb +++ b/app/controllers/api/v1/polls_controller.rb @@ -7,8 +7,6 @@ class Api::V1::PollsController < Api::BaseController before_action :set_poll before_action :refresh_poll - respond_to :json - def show render json: @poll, serializer: REST::PollSerializer, include_results: true end diff --git a/app/controllers/api/v1/preferences_controller.rb b/app/controllers/api/v1/preferences_controller.rb index 077d39f5d740a4..1640a8224be681 100644 --- a/app/controllers/api/v1/preferences_controller.rb +++ b/app/controllers/api/v1/preferences_controller.rb @@ -4,8 +4,6 @@ class Api::V1::PreferencesController < Api::BaseController before_action -> { doorkeeper_authorize! :read, :'read:accounts' } before_action :require_user! - respond_to :json - def index render json: current_account, serializer: REST::PreferencesSerializer end diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb index 1b0b4b05b2e72d..e10083d450f1a5 100644 --- a/app/controllers/api/v1/reports_controller.rb +++ b/app/controllers/api/v1/reports_controller.rb @@ -4,7 +4,7 @@ class Api::V1::ReportsController < Api::BaseController before_action -> { doorkeeper_authorize! :write, :'write:reports' }, only: [:create] before_action :require_user! - respond_to :json + override_rate_limit_headers :create, family: :reports def create @report = ReportService.new.call( diff --git a/app/controllers/api/v1/statuses/bookmarks_controller.rb b/app/controllers/api/v1/statuses/bookmarks_controller.rb index a7f1eed003be2e..3954af3c9bf2f1 100644 --- a/app/controllers/api/v1/statuses/bookmarks_controller.rb +++ b/app/controllers/api/v1/statuses/bookmarks_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController before_action :require_user! before_action :set_status - respond_to :json - def create current_account.bookmarks.find_or_create_by!(account: current_account, status: @status) render json: @status, serializer: REST::StatusSerializer diff --git a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb index 05f4acc331b89d..8229786d6cccab 100644 --- a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController before_action :set_status after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/statuses/favourites_controller.rb b/app/controllers/api/v1/statuses/favourites_controller.rb index f18ace996c101c..7afa822ed8740c 100644 --- a/app/controllers/api/v1/statuses/favourites_controller.rb +++ b/app/controllers/api/v1/statuses/favourites_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController before_action :require_user! before_action :set_status - respond_to :json - def create FavouriteService.new.call(current_account, @status) render json: @status, serializer: REST::StatusSerializer diff --git a/app/controllers/api/v1/statuses/mutes_controller.rb b/app/controllers/api/v1/statuses/mutes_controller.rb index b02469b4f4b674..43c7a525ad646b 100644 --- a/app/controllers/api/v1/statuses/mutes_controller.rb +++ b/app/controllers/api/v1/statuses/mutes_controller.rb @@ -8,8 +8,6 @@ class Api::V1::Statuses::MutesController < Api::BaseController before_action :set_status before_action :set_conversation - respond_to :json - def create current_account.mute_conversation!(@conversation) @mutes_map = { @conversation.id => true } diff --git a/app/controllers/api/v1/statuses/pins_controller.rb b/app/controllers/api/v1/statuses/pins_controller.rb index 4118a8ce4e51be..51b1621b6f125a 100644 --- a/app/controllers/api/v1/statuses/pins_controller.rb +++ b/app/controllers/api/v1/statuses/pins_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Statuses::PinsController < Api::BaseController before_action :require_user! before_action :set_status - respond_to :json - def create StatusPin.create!(account: current_account, status: @status) distribute_add_activity! diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb index fa60e7d84685e8..6c9e49d903a412 100644 --- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController before_action :set_status after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/statuses/reblogs_controller.rb b/app/controllers/api/v1/statuses/reblogs_controller.rb index 67106ccbe8101a..7fa774a4d727b6 100644 --- a/app/controllers/api/v1/statuses/reblogs_controller.rb +++ b/app/controllers/api/v1/statuses/reblogs_controller.rb @@ -7,10 +7,11 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController before_action :require_user! before_action :set_reblog - respond_to :json + override_rate_limit_headers :create, family: :statuses def create @status = ReblogService.new.call(current_account, @reblog, reblog_params) + render json: @status, serializer: REST::StatusSerializer end diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index bba3c0651beedb..93a253cbb2434c 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -7,8 +7,9 @@ class Api::V1::StatusesController < Api::BaseController before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [:create, :destroy] before_action :require_user!, except: [:show, :context] before_action :set_status, only: [:show, :context] + before_action :set_thread, only: [:create] - respond_to :json + override_rate_limit_headers :create, family: :statuses # This API was originally unlimited, pagination cannot be introduced without # breaking backwards-compatibility. Arbitrarily high number to cover most @@ -36,7 +37,7 @@ def context def create @status = PostStatusService.new.call(current_user.account, text: status_params[:status], - thread: status_params[:in_reply_to_id].blank? ? nil : Status.find(status_params[:in_reply_to_id]), + thread: @thread, media_ids: status_params[:media_ids], sensitive: status_params[:sensitive], spoiler_text: status_params[:spoiler_text], @@ -44,7 +45,8 @@ def create scheduled_at: status_params[:scheduled_at], application: doorkeeper_token.application, poll: status_params[:poll], - idempotency: request.headers['Idempotency-Key']) + idempotency: request.headers['Idempotency-Key'], + with_rate_limit: true) render json: @status, serializer: @status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer end @@ -68,6 +70,12 @@ def set_status raise ActiveRecord::RecordNotFound end + def set_thread + @thread = status_params[:in_reply_to_id].blank? ? nil : Status.find(status_params[:in_reply_to_id]) + rescue ActiveRecord::RecordNotFound + render json: { error: I18n.t('statuses.errors.in_reply_not_found') }, status: 404 + end + def status_params params.permit( :status, diff --git a/app/controllers/api/v1/streaming_controller.rb b/app/controllers/api/v1/streaming_controller.rb index ebb17608c107df..7cd60615ab554f 100644 --- a/app/controllers/api/v1/streaming_controller.rb +++ b/app/controllers/api/v1/streaming_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Api::V1::StreamingController < Api::BaseController - respond_to :json - def index if Rails.configuration.x.streaming_api_base_url != request.host redirect_to streaming_api_url, status: 301 diff --git a/app/controllers/api/v1/suggestions_controller.rb b/app/controllers/api/v1/suggestions_controller.rb index 9da2b60ae206e7..52054160dfc3c8 100644 --- a/app/controllers/api/v1/suggestions_controller.rb +++ b/app/controllers/api/v1/suggestions_controller.rb @@ -7,8 +7,6 @@ class Api::V1::SuggestionsController < Api::BaseController before_action :require_user! before_action :set_accounts - respond_to :json - def index render json: @accounts, each_serializer: REST::AccountSerializer end diff --git a/app/controllers/api/v1/timelines/home_controller.rb b/app/controllers/api/v1/timelines/home_controller.rb index ff5ede1385234e..ae6dbcb8b378ee 100644 --- a/app/controllers/api/v1/timelines/home_controller.rb +++ b/app/controllers/api/v1/timelines/home_controller.rb @@ -5,8 +5,6 @@ class Api::V1::Timelines::HomeController < Api::BaseController before_action :require_user!, only: [:show] after_action :insert_pagination_headers, unless: -> { @statuses.empty? } - respond_to :json - def show @statuses = load_statuses diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb index ccc10f966ca647..581befef13e084 100644 --- a/app/controllers/api/v1/timelines/public_controller.rb +++ b/app/controllers/api/v1/timelines/public_controller.rb @@ -4,8 +4,6 @@ class Api::V1::Timelines::PublicController < Api::BaseController before_action :require_user!, only: [:show], if: :require_auth? after_action :insert_pagination_headers, unless: -> { @statuses.empty? } - respond_to :json - def show @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb index 9adc4ad2912924..2d6ad5a80c5bc3 100644 --- a/app/controllers/api/v1/timelines/tag_controller.rb +++ b/app/controllers/api/v1/timelines/tag_controller.rb @@ -4,8 +4,6 @@ class Api::V1::Timelines::TagController < Api::BaseController before_action :load_tag after_action :insert_pagination_headers, unless: -> { @statuses.empty? } - respond_to :json - def show @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) diff --git a/app/controllers/api/v1/trends_controller.rb b/app/controllers/api/v1/trends_controller.rb index bcea9857e8fa71..c875e90414de37 100644 --- a/app/controllers/api/v1/trends_controller.rb +++ b/app/controllers/api/v1/trends_controller.rb @@ -3,8 +3,6 @@ class Api::V1::TrendsController < Api::BaseController before_action :set_tags - respond_to :json - def index render json: @tags, each_serializer: REST::TagSerializer end diff --git a/app/controllers/api/v2/media_controller.rb b/app/controllers/api/v2/media_controller.rb new file mode 100644 index 00000000000000..0c1baf01d0bbd6 --- /dev/null +++ b/app/controllers/api/v2/media_controller.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class Api::V2::MediaController < Api::V1::MediaController + def create + @media_attachment = current_account.media_attachments.create!({ delay_processing: true }.merge(media_attachment_params)) + render json: @media_attachment, serializer: REST::MediaAttachmentSerializer, status: 202 + rescue Paperclip::Errors::NotIdentifiedByImageMagickError + render json: file_type_error, status: 422 + rescue Paperclip::Error + render json: processing_error, status: 500 + end +end diff --git a/app/controllers/api/v2/search_controller.rb b/app/controllers/api/v2/search_controller.rb index cbd9b551d091ba..f17431dd10b8e9 100644 --- a/app/controllers/api/v2/search_controller.rb +++ b/app/controllers/api/v2/search_controller.rb @@ -8,8 +8,6 @@ class Api::V2::SearchController < Api::BaseController before_action -> { doorkeeper_authorize! :read, :'read:search' } before_action :require_user! - respond_to :json - def index @search = Search.new(search_results) render json: @search, serializer: REST::SearchSerializer diff --git a/app/controllers/api/web/embeds_controller.rb b/app/controllers/api/web/embeds_controller.rb index 4aa31695c70146..741ba910fb8769 100644 --- a/app/controllers/api/web/embeds_controller.rb +++ b/app/controllers/api/web/embeds_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Api::Web::EmbedsController < Api::Web::BaseController - respond_to :json - before_action :require_user! def create diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb index f388b17e5de2c2..7916b82fa08153 100644 --- a/app/controllers/api/web/push_subscriptions_controller.rb +++ b/app/controllers/api/web/push_subscriptions_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Api::Web::PushSubscriptionsController < Api::Web::BaseController - respond_to :json - before_action :require_user! def create diff --git a/app/controllers/api/web/settings_controller.rb b/app/controllers/api/web/settings_controller.rb index e3178bf48bdd66..3d65e46ed95717 100644 --- a/app/controllers/api/web/settings_controller.rb +++ b/app/controllers/api/web/settings_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Api::Web::SettingsController < Api::Web::BaseController - respond_to :json - before_action :require_user! def update diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0cfa2b38606f2e..973db6aca97654 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -29,6 +29,7 @@ class ApplicationController < ActionController::Base rescue_from Mastodon::NotPermittedError, with: :forbidden rescue_from HTTP::Error, OpenSSL::SSL::SSLError, with: :internal_server_error rescue_from Mastodon::RaceConditionError, with: :service_unavailable + rescue_from Mastodon::RateLimitExceededError, with: :too_many_requests before_action :store_current_location, except: :raise_not_found, unless: :devise_controller? before_action :require_functional!, if: :user_signed_in? @@ -111,6 +112,10 @@ def service_unavailable respond_with_error(503) end + def too_many_requests + respond_with_error(429) + end + def single_user_mode? @single_user_mode ||= Rails.configuration.x.single_user_mode && Account.where('id > 0').exists? end diff --git a/app/controllers/authorize_interactions_controller.rb b/app/controllers/authorize_interactions_controller.rb index e27366ea363880..29c0288d09dc9c 100644 --- a/app/controllers/authorize_interactions_controller.rb +++ b/app/controllers/authorize_interactions_controller.rb @@ -20,7 +20,7 @@ def show end def create - if @resource.is_a?(Account) && FollowService.new.call(current_account, @resource) + if @resource.is_a?(Account) && FollowService.new.call(current_account, @resource, with_rate_limit: true) render :success else render :error diff --git a/app/controllers/concerns/rate_limit_headers.rb b/app/controllers/concerns/rate_limit_headers.rb index b79c558d8157ec..86fe58a71c9964 100644 --- a/app/controllers/concerns/rate_limit_headers.rb +++ b/app/controllers/concerns/rate_limit_headers.rb @@ -3,6 +3,20 @@ module RateLimitHeaders extend ActiveSupport::Concern + class_methods do + def override_rate_limit_headers(method_name, options = {}) + around_action(only: method_name, if: :current_account) do |_controller, block| + begin + block.call + ensure + rate_limiter = RateLimiter.new(current_account, options) + rate_limit_headers = rate_limiter.to_headers + response.headers.merge!(rate_limit_headers) unless response.headers['X-RateLimit-Remaining'].present? && rate_limit_headers['X-RateLimit-Remaining'].to_i > response.headers['X-RateLimit-Remaining'].to_i + end + end + end + end + included do before_action :set_rate_limit_headers, if: :rate_limited_request? end @@ -44,7 +58,7 @@ def rate_limit_reset end def api_throttle_data - most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] } + most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] - v[:count] } request.env['rack.attack.throttle_data'][most_limited_type] end diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb index 7103749adecf3d..14e22dd1ec1bce 100644 --- a/app/controllers/follower_accounts_controller.rb +++ b/app/controllers/follower_accounts_controller.rb @@ -28,7 +28,8 @@ def index render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, - content_type: 'application/activity+json' + content_type: 'application/activity+json', + fields: restrict_fields_to end end end @@ -71,4 +72,12 @@ def collection_presenter ) end end + + def restrict_fields_to + if page_requested? || !@account.user_hides_network? + # Return all fields + else + %i(id type totalItems) + end + end end diff --git a/app/controllers/following_accounts_controller.rb b/app/controllers/following_accounts_controller.rb index 6c8fb84d86b47c..95849ffb983ac6 100644 --- a/app/controllers/following_accounts_controller.rb +++ b/app/controllers/following_accounts_controller.rb @@ -28,7 +28,8 @@ def index render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, - content_type: 'application/activity+json' + content_type: 'application/activity+json', + fields: restrict_fields_to end end end @@ -71,4 +72,12 @@ def collection_presenter ) end end + + def restrict_fields_to + if page_requested? || !@account.user_hides_network? + # Return all fields + else + %i(id type totalItems) + end + end end diff --git a/app/controllers/settings/imports_controller.rb b/app/controllers/settings/imports_controller.rb index 38f2e39c1d179c..7b8c4ae235050a 100644 --- a/app/controllers/settings/imports_controller.rb +++ b/app/controllers/settings/imports_controller.rb @@ -29,6 +29,6 @@ def set_account end def import_params - params.require(:import).permit(:data, :type) + params.require(:import).permit(:data, :type, :mode) end end diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb index 6bc75aa56658f3..88d6e4580d3250 100644 --- a/app/helpers/admin/action_logs_helper.rb +++ b/app/helpers/admin/action_logs_helper.rb @@ -9,79 +9,8 @@ def log_target(log) end end - def relevant_log_changes(log) - if log.target_type == 'CustomEmoji' && [:enable, :disable, :destroy].include?(log.action) - log.recorded_changes.slice('domain') - elsif log.target_type == 'CustomEmoji' && log.action == :update - log.recorded_changes.slice('domain', 'visible_in_picker') - elsif log.target_type == 'User' && [:promote, :demote].include?(log.action) - log.recorded_changes.slice('moderator', 'admin') - elsif log.target_type == 'User' && [:change_email].include?(log.action) - log.recorded_changes.slice('email', 'unconfirmed_email') - elsif log.target_type == 'DomainBlock' - log.recorded_changes.slice('severity', 'reject_media') - elsif log.target_type == 'Status' && log.action == :update - log.recorded_changes.slice('sensitive') - elsif log.target_type == 'Announcement' && log.action == :update - log.recorded_changes.slice('text', 'starts_at', 'ends_at', 'all_day') - end - end - - def log_extra_attributes(hash) - safe_join(hash.to_a.map { |key, value| safe_join([content_tag(:span, key, class: 'diff-key'), '=', log_change(value)]) }, ' ') - end - - def log_change(val) - return content_tag(:span, val, class: 'diff-neutral') unless val.is_a?(Array) - safe_join([content_tag(:span, val.first, class: 'diff-old'), content_tag(:span, val.last, class: 'diff-new')], '→') - end - - def icon_for_log(log) - case log.target_type - when 'Account', 'User' - 'user' - when 'CustomEmoji' - 'file' - when 'Report' - 'flag' - when 'DomainBlock' - 'lock' - when 'DomainAllow' - 'plus-circle' - when 'EmailDomainBlock' - 'envelope' - when 'Status' - 'pencil' - when 'AccountWarning' - 'warning' - when 'Announcement' - 'bullhorn' - end - end - - def class_for_log_icon(log) - case log.action - when :enable, :unsuspend, :unsilence, :confirm, :promote, :resolve - 'positive' - when :create - opposite_verbs?(log) ? 'negative' : 'positive' - when :update, :reset_password, :disable_2fa, :memorialize, :change_email - 'neutral' - when :demote, :silence, :disable, :suspend, :remove_avatar, :remove_header, :reopen - 'negative' - when :destroy - opposite_verbs?(log) ? 'positive' : 'negative' - else - '' - end - end - private - def opposite_verbs?(log) - %w(DomainBlock EmailDomainBlock AccountWarning).include?(log.target_type) - end - def linkable_log_target(record) case record.class.name when 'Account' @@ -99,7 +28,7 @@ def linkable_log_target(record) when 'AccountWarning' link_to record.target_account.acct, admin_account_path(record.target_account_id) when 'Announcement' - link_to "##{record.id}", edit_admin_announcement_path(record.id) + link_to truncate(record.text), edit_admin_announcement_path(record.id) end end @@ -118,7 +47,7 @@ def log_target_from_history(type, attributes) I18n.t('admin.action_logs.deleted_status') end when 'Announcement' - "##{attributes['id']}" + truncate(attributes['text']) end end end diff --git a/app/helpers/admin/filter_helper.rb b/app/helpers/admin/filter_helper.rb index 6ab92939d82a6b..ba0ca963895efb 100644 --- a/app/helpers/admin/filter_helper.rb +++ b/app/helpers/admin/filter_helper.rb @@ -10,6 +10,7 @@ module Admin::FilterHelper InviteFilter::KEYS, RelationshipFilter::KEYS, AnnouncementFilter::KEYS, + Admin::ActionLogFilter::KEYS, ].flatten.freeze def filter_link_to(text, link_to_params, link_class_params = link_to_params) diff --git a/app/helpers/admin/settings_helper.rb b/app/helpers/admin/settings_helper.rb new file mode 100644 index 00000000000000..baf14ab2574e3f --- /dev/null +++ b/app/helpers/admin/settings_helper.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Admin::SettingsHelper + def site_upload_delete_hint(hint, var) + upload = SiteUpload.find_by(var: var.to_s) + return hint unless upload + + link = link_to t('admin.site_uploads.delete'), admin_site_upload_path(upload), data: { method: :delete } + safe_join([hint, link], '
'.html_safe) + end +end diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js index d4a824e2c9d646..cb2c682a45ba18 100644 --- a/app/javascript/mastodon/actions/accounts.js +++ b/app/javascript/mastodon/actions/accounts.js @@ -106,7 +106,7 @@ export function fetchAccount(id) { dispatch, getState, db.transaction('accounts', 'read').objectStore('accounts').index('id'), - id + id, ).then(() => db.close(), error => { db.close(); throw error; @@ -396,6 +396,7 @@ export function fetchFollowersFail(id, error) { type: FOLLOWERS_FETCH_FAIL, id, error, + skipNotFound: true, }; }; @@ -482,6 +483,7 @@ export function fetchFollowingFail(id, error) { type: FOLLOWING_FETCH_FAIL, id, error, + skipNotFound: true, }; }; @@ -571,6 +573,7 @@ export function fetchRelationshipsFail(error) { type: RELATIONSHIPS_FETCH_FAIL, error, skipLoading: true, + skipNotFound: true, }; }; diff --git a/app/javascript/mastodon/actions/alerts.js b/app/javascript/mastodon/actions/alerts.js index cd36d8007bccee..1670f9c10de9f5 100644 --- a/app/javascript/mastodon/actions/alerts.js +++ b/app/javascript/mastodon/actions/alerts.js @@ -34,11 +34,11 @@ export function showAlert(title = messages.unexpectedTitle, message = messages.u }; }; -export function showAlertForError(error) { +export function showAlertForError(error, skipNotFound = false) { if (error.response) { const { data, status, statusText, headers } = error.response; - if (status === 404 || status === 410) { + if (skipNotFound && (status === 404 || status === 410)) { // Skip these errors as they are reflected in the UI return { type: ALERT_NOOP }; } diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index c3c6ff1a1de704..6b73fc90e09a18 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -230,12 +230,31 @@ export function uploadCompose(files) { // Account for disparity in size of original image and resized data total += file.size - f.size; - return api(getState).post('/api/v1/media', data, { + return api(getState).post('/api/v2/media', data, { onUploadProgress: function({ loaded }){ progress[i] = loaded; dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total)); }, - }).then(({ data }) => dispatch(uploadComposeSuccess(data, f))); + }).then(({ status, data }) => { + // If server-side processing of the media attachment has not completed yet, + // poll the server until it is, before showing the media attachment as uploaded + + if (status === 200) { + dispatch(uploadComposeSuccess(data, f)); + } else if (status === 202) { + const poll = () => { + api(getState).get(`/api/v1/media/${data.id}`).then(response => { + if (response.status === 200) { + dispatch(uploadComposeSuccess(response.data, f)); + } else if (response.status === 206) { + setTimeout(() => poll(), 1000); + } + }).catch(error => dispatch(uploadComposeFail(error))); + }; + + poll(); + } + }); }).catch(error => dispatch(uploadComposeFail(error))); }; }; diff --git a/app/javascript/mastodon/actions/identity_proofs.js b/app/javascript/mastodon/actions/identity_proofs.js index 449debf616fa5f..10398395660345 100644 --- a/app/javascript/mastodon/actions/identity_proofs.js +++ b/app/javascript/mastodon/actions/identity_proofs.js @@ -27,4 +27,5 @@ export const fetchAccountIdentityProofsFail = (accountId, err) => ({ type: IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL, accountId, err, + skipNotFound: true, }); diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js index 05466865597d47..cdd2111f8e539a 100644 --- a/app/javascript/mastodon/actions/timelines.js +++ b/app/javascript/mastodon/actions/timelines.js @@ -149,6 +149,7 @@ export function expandTimelineFail(timeline, error, isLoadingMore) { timeline, error, skipLoading: !isLoadingMore, + skipNotFound: timeline.startsWith('account:'), }; }; diff --git a/app/javascript/mastodon/common.js b/app/javascript/mastodon/common.js index fba21316a77dc9..6818aa5d540ddb 100644 --- a/app/javascript/mastodon/common.js +++ b/app/javascript/mastodon/common.js @@ -1,4 +1,4 @@ -import Rails from 'rails-ujs'; +import Rails from '@rails/ujs'; export function start() { require('font-awesome/css/font-awesome.css'); diff --git a/app/javascript/mastodon/components/column_header.js b/app/javascript/mastodon/components/column_header.js index ea82f9ef9d3fe3..1bb583583a3558 100644 --- a/app/javascript/mastodon/components/column_header.js +++ b/app/javascript/mastodon/components/column_header.js @@ -76,8 +76,9 @@ class ColumnHeader extends React.PureComponent { handlePin = () => { if (!this.props.pinned) { - this.historyBack(); + this.context.router.history.replace('/'); } + this.props.onPin(); } diff --git a/app/javascript/mastodon/components/domain.js b/app/javascript/mastodon/components/domain.js index 85729ca9438ea2..697065d874d1f6 100644 --- a/app/javascript/mastodon/components/domain.js +++ b/app/javascript/mastodon/components/domain.js @@ -5,7 +5,7 @@ import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; const messages = defineMessages({ - unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' }, + unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' }, }); export default @injectIntl diff --git a/app/javascript/mastodon/components/intersection_observer_article.js b/app/javascript/mastodon/components/intersection_observer_article.js index e453730ba4fccd..124b34b02f9eca 100644 --- a/app/javascript/mastodon/components/intersection_observer_article.js +++ b/app/javascript/mastodon/components/intersection_observer_article.js @@ -44,7 +44,7 @@ export default class IntersectionObserverArticle extends React.Component { intersectionObserverWrapper.observe( id, this.node, - this.handleIntersection + this.handleIntersection, ); this.componentMounted = true; diff --git a/app/javascript/mastodon/components/media_gallery.js b/app/javascript/mastodon/components/media_gallery.js index cfe164a507d822..283d7e0a502634 100644 --- a/app/javascript/mastodon/components/media_gallery.js +++ b/app/javascript/mastodon/components/media_gallery.js @@ -10,7 +10,7 @@ import { autoPlayGif, cropImages, displayMedia, useBlurhash } from '../initial_s import { decode } from 'blurhash'; const messages = defineMessages({ - toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Toggle visibility' }, + toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Hide media' }, }); class Item extends React.PureComponent { diff --git a/app/javascript/mastodon/components/poll.js b/app/javascript/mastodon/components/poll.js index 3a17e80e726795..7525a1030a5d5f 100644 --- a/app/javascript/mastodon/components/poll.js +++ b/app/javascript/mastodon/components/poll.js @@ -127,15 +127,7 @@ class Poll extends ImmutablePureComponent { return (
  • - {showResults && ( - - {({ width }) => - - } - - )} - -
  • ); } diff --git a/app/javascript/mastodon/components/scrollable_list.js b/app/javascript/mastodon/components/scrollable_list.js index 3a490e78ea76ad..65ca43911c78ef 100644 --- a/app/javascript/mastodon/components/scrollable_list.js +++ b/app/javascript/mastodon/components/scrollable_list.js @@ -82,15 +82,19 @@ export default class ScrollableList extends PureComponent { lastScrollWasSynthetic = false; scrollToTopOnMouseIdle = false; + _getScrollingElement = () => { + if (this.props.bindToDocument) { + return (document.scrollingElement || document.body); + } else { + return this.node; + } + } + setScrollTop = newScrollTop => { if (this.getScrollTop() !== newScrollTop) { this.lastScrollWasSynthetic = true; - if (this.props.bindToDocument) { - document.scrollingElement.scrollTop = newScrollTop; - } else { - this.node.scrollTop = newScrollTop; - } + this._getScrollingElement().scrollTop = newScrollTop; } }; @@ -151,15 +155,15 @@ export default class ScrollableList extends PureComponent { } getScrollTop = () => { - return this.props.bindToDocument ? document.scrollingElement.scrollTop : this.node.scrollTop; + return this._getScrollingElement().scrollTop; } getScrollHeight = () => { - return this.props.bindToDocument ? document.scrollingElement.scrollHeight : this.node.scrollHeight; + return this._getScrollingElement().scrollHeight; } getClientHeight = () => { - return this.props.bindToDocument ? document.scrollingElement.clientHeight : this.node.clientHeight; + return this._getScrollingElement().clientHeight; } updateScrollBottom = (snapshot) => { diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index 0dc00cb98d59b5..075ee1b870c6db 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -432,16 +432,10 @@ class Status extends ImmutablePureComponent { - + {media} - {showThread && status.get('in_reply_to_id') && status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) && ( - - )} - diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js index ea303a58ba1994..c3fc6c8536c521 100644 --- a/app/javascript/mastodon/components/status_action_bar.js +++ b/app/javascript/mastodon/components/status_action_bar.js @@ -36,8 +36,8 @@ const messages = defineMessages({ admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, admin_status: { id: 'status.admin_status', defaultMessage: 'Open this status in the moderation interface' }, copy: { id: 'status.copy', defaultMessage: 'Copy link to status' }, - blockDomain: { id: 'account.block_domain', defaultMessage: 'Hide everything from {domain}' }, - unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' }, + blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' }, + unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' }, unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, }); diff --git a/app/javascript/mastodon/components/status_content.js b/app/javascript/mastodon/components/status_content.js index 5d921fd412f42d..3200f2d82f6d7f 100644 --- a/app/javascript/mastodon/components/status_content.js +++ b/app/javascript/mastodon/components/status_content.js @@ -20,6 +20,7 @@ export default class StatusContent extends React.PureComponent { static propTypes = { status: ImmutablePropTypes.map.isRequired, expanded: PropTypes.bool, + showThread: PropTypes.bool, onExpandedToggle: PropTypes.func, onClick: PropTypes.func, collapsable: PropTypes.bool, @@ -181,6 +182,7 @@ export default class StatusContent extends React.PureComponent { const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden; const renderReadMore = this.props.onClick && status.get('collapsed'); + const renderViewThread = this.props.showThread && status.get('in_reply_to_id') && status.get('in_reply_to_account_id') === status.getIn(['account', 'id']); const content = { __html: status.get('contentHtml') }; const spoilerContent = { __html: status.get('spoilerHtml') }; @@ -195,6 +197,12 @@ export default class StatusContent extends React.PureComponent { directionStyle.direction = 'rtl'; } + const showThreadButton = ( + + ); + const readMoreButton = ( - + +
      @@ -236,7 +236,7 @@ class Audio extends React.PureComponent {
    - + {/* eslint-disable-next-line jsx-a11y/no-onchange */}