diff --git a/.github/ISSUE_TEMPLATE/2.server_bug_report.yml b/.github/ISSUE_TEMPLATE/2.server_bug_report.yml index 98801f07f1..743c32b79e 100644 --- a/.github/ISSUE_TEMPLATE/2.server_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/2.server_bug_report.yml @@ -59,7 +59,7 @@ body: Any additional technical details you may have, like logs or error traces value: | If this is happening on your own Mastodon server, please fill out those: - - Ruby version: (from `ruby --version`, eg. v4.0.3) + - Ruby version: (from `ruby --version`, eg. v4.0.4) - Node.js version: (from `node --version`, eg. v22.16.0) validations: required: false diff --git a/.github/ISSUE_TEMPLATE/3.troubleshooting.yml b/.github/ISSUE_TEMPLATE/3.troubleshooting.yml index 9856ae4428..ebd8485071 100644 --- a/.github/ISSUE_TEMPLATE/3.troubleshooting.yml +++ b/.github/ISSUE_TEMPLATE/3.troubleshooting.yml @@ -60,7 +60,7 @@ body: value: | Please at least include those informations: - Operating system: (eg. Ubuntu 24.04.2) - - Ruby version: (from `ruby --version`, eg. v4.0.3) + - Ruby version: (from `ruby --version`, eg. v4.0.4) - Node.js version: (from `node --version`, eg. v22.16.0) validations: required: false diff --git a/.github/actions/setup-ruby/action.yml b/.github/actions/setup-ruby/action.yml index 317c1256d5..aaf6dc752a 100644 --- a/.github/actions/setup-ruby/action.yml +++ b/.github/actions/setup-ruby/action.yml @@ -14,10 +14,16 @@ runs: shell: bash run: | sudo apt-get update - sudo apt-get install --no-install-recommends -y libicu-dev libidn11-dev libvips42 ${{ inputs.additional-system-dependencies }} + sudo apt-get install --no-install-recommends -y \ + libicu-dev \ + libidn11-dev \ + libvips42 \ + libheif-plugin-aomdec \ + libheif-plugin-libde265 \ + ${{ inputs.additional-system-dependencies }} - name: Set up Ruby - uses: ruby/setup-ruby@94e4d89d3e6c1c7599e0210d114c5ffb23f1a866 # v1 + uses: ruby/setup-ruby@6aaa311d81eba98ae12eaffbcb63296ace0efcde # v1 with: ruby-version: ${{ inputs.ruby-version }} bundler-cache: true diff --git a/.github/workflows/bundler-audit.yml b/.github/workflows/bundler-audit.yml index 0cbbeb5878..797dd5687e 100644 --- a/.github/workflows/bundler-audit.yml +++ b/.github/workflows/bundler-audit.yml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Set up Ruby - uses: ruby/setup-ruby@94e4d89d3e6c1c7599e0210d114c5ffb23f1a866 # v1 + uses: ruby/setup-ruby@6aaa311d81eba98ae12eaffbcb63296ace0efcde # v1 with: bundler-cache: true diff --git a/.github/workflows/lint-haml.yml b/.github/workflows/lint-haml.yml index b59a4b2d69..a453091c1a 100644 --- a/.github/workflows/lint-haml.yml +++ b/.github/workflows/lint-haml.yml @@ -36,7 +36,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Set up Ruby - uses: ruby/setup-ruby@94e4d89d3e6c1c7599e0210d114c5ffb23f1a866 # v1 + uses: ruby/setup-ruby@6aaa311d81eba98ae12eaffbcb63296ace0efcde # v1 with: bundler-cache: true diff --git a/.github/workflows/lint-ruby.yml b/.github/workflows/lint-ruby.yml index ae4cc6faf2..942192faa1 100644 --- a/.github/workflows/lint-ruby.yml +++ b/.github/workflows/lint-ruby.yml @@ -38,7 +38,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Set up Ruby - uses: ruby/setup-ruby@94e4d89d3e6c1c7599e0210d114c5ffb23f1a866 # v1 + uses: ruby/setup-ruby@6aaa311d81eba98ae12eaffbcb63296ace0efcde # v1 with: bundler-cache: true diff --git a/.ruby-version b/.ruby-version index c4e41f9459..c5106e6d13 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -4.0.3 +4.0.4 diff --git a/Dockerfile b/Dockerfile index 6159df35e4..feb5b34b80 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ ARG BASE_REGISTRY="docker.io" # Ruby image to use for base image, change with [--build-arg RUBY_VERSION="4.0.x"] # renovate: datasource=docker depName=docker.io/ruby -ARG RUBY_VERSION="4.0.3" +ARG RUBY_VERSION="4.0.4" # # Node.js version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="22"] # renovate: datasource=node-version depName=node ARG NODE_MAJOR_VERSION="24" diff --git a/Gemfile.lock b/Gemfile.lock index 9afbcb7920..2387c5dafd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -99,8 +99,8 @@ GEM ast (2.4.3) attr_required (1.0.2) aws-eventstream (1.4.0) - aws-partitions (1.1245.0) - aws-sdk-core (3.246.0) + aws-partitions (1.1249.0) + aws-sdk-core (3.247.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) @@ -108,11 +108,11 @@ GEM bigdecimal jmespath (~> 1, >= 1.6.1) logger - aws-sdk-kms (1.124.0) - aws-sdk-core (~> 3, >= 3.244.0) + aws-sdk-kms (1.125.0) + aws-sdk-core (~> 3, >= 3.247.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.221.0) - aws-sdk-core (~> 3, >= 3.244.0) + aws-sdk-s3 (1.222.0) + aws-sdk-core (~> 3, >= 3.247.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) aws-sigv4 (1.12.1) @@ -132,7 +132,7 @@ GEM binding_of_caller (2.0.0) debug_inspector (>= 1.2.0) blurhash (0.1.8) - bootsnap (1.24.1) + bootsnap (1.24.4) msgpack (~> 1.2) brakeman (8.0.4) racc @@ -816,12 +816,12 @@ GEM securerandom (0.4.1) shoulda-matchers (7.0.1) activesupport (>= 7.1) - sidekiq (8.1.4) + sidekiq (8.1.5) connection_pool (>= 3.0.0) json (>= 2.16.0) logger (>= 1.7.0) rack (>= 3.2.0) - redis-client (>= 0.26.0) + redis-client (>= 0.29.0) sidekiq-bulk (0.2.0) sidekiq sidekiq-scheduler (6.0.2) @@ -851,7 +851,7 @@ GEM concurrent-ruby zeitwerk stringio (3.2.0) - strong_migrations (2.7.0) + strong_migrations (2.8.0) activerecord (>= 7.2) swd (2.0.3) activesupport (>= 3) @@ -1097,7 +1097,7 @@ DEPENDENCIES xorcist (~> 1.1) RUBY VERSION - ruby 4.0.3 + ruby 4.0.4 BUNDLED WITH 4.0.11 diff --git a/app/controllers/admin/collections_controller.rb b/app/controllers/admin/collections_controller.rb index 2698abbd45..405c779e3d 100644 --- a/app/controllers/admin/collections_controller.rb +++ b/app/controllers/admin/collections_controller.rb @@ -20,7 +20,7 @@ module Admin def batch authorize [:admin, :collection], :index? - @collection_batch_action = Admin::CollectionBatchAction.new(admin_collection_batch_action_params.merge(current_account: current_account, report_id: params[:report_id], type: 'report')) + @collection_batch_action = Admin::CollectionBatchAction.new(admin_collection_batch_action_params.merge(current_account: current_account, report_id: params[:report_id], type: action_from_button)) @collection_batch_action.save! rescue ActionController::ParameterMissing @@ -57,5 +57,13 @@ module Admin def set_collections @collections = @account.collections.includes(accepted_collection_items: :account).page(params[:page]).per(PER_PAGE) end + + def action_from_button + if params[:report] + 'report' + elsif params[:remove_from_report] + 'remove_from_report' + end + end end end diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb index 44ee7206bf..f12e3da4e1 100644 --- a/app/controllers/admin/reports_controller.rb +++ b/app/controllers/admin/reports_controller.rb @@ -16,6 +16,8 @@ module Admin @report_notes = @report.notes.chronological.includes(:account) @action_logs = @report.history.includes(:target) @form = Admin::StatusBatchAction.new + @collection_form = Admin::CollectionBatchAction.new + @collections = @report.collections @statuses = @report.statuses.with_includes end diff --git a/app/javascript/entrypoints/admin.tsx b/app/javascript/entrypoints/admin.tsx index 91c3bd640a..49ab58cc5b 100644 --- a/app/javascript/entrypoints/admin.tsx +++ b/app/javascript/entrypoints/admin.tsx @@ -69,8 +69,9 @@ on('change', '#batch_checkbox_all', ({ target }) => { '.batch-table__select-all', ); - document - .querySelectorAll(batchCheckboxClassName) + target + .closest('.batch-table') + ?.querySelectorAll(batchCheckboxClassName) .forEach((content) => { content.checked = target.checked; }); @@ -112,17 +113,20 @@ on('click', '.batch-table__select-all button', () => { } }); -on('change', batchCheckboxClassName, () => { - const checkAllElement = document.querySelector( +on('change', batchCheckboxClassName, (event) => { + const targetTable = (event.target as HTMLElement).closest('.batch-table'); + if (!targetTable) return; + + const checkAllElement = targetTable.querySelector( 'input#batch_checkbox_all', ); - const selectAllMatchingElement = document.querySelector( + const selectAllMatchingElement = targetTable.querySelector( '.batch-table__select-all', ); if (checkAllElement) { const allCheckboxes = Array.from( - document.querySelectorAll(batchCheckboxClassName), + targetTable.querySelectorAll(batchCheckboxClassName), ); checkAllElement.checked = allCheckboxes.every((content) => content.checked); checkAllElement.indeterminate = diff --git a/app/javascript/mastodon/components/account_header/styles.module.scss b/app/javascript/mastodon/components/account_header/styles.module.scss index a54ca18c8a..2daf386734 100644 --- a/app/javascript/mastodon/components/account_header/styles.module.scss +++ b/app/javascript/mastodon/components/account_header/styles.module.scss @@ -21,7 +21,7 @@ height: 160px; } - :global(.inactive) & { + .moved & { filter: grayscale(100%); } } @@ -275,9 +275,14 @@ $button-fallback-breakpoint: $button-breakpoint + 55px; font-size: 15px; color: var(--color-text-primary); unicode-bidi: plaintext; - display: flex; - flex-direction: column; - gap: 20px; + + p { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } :any-link { color: var(--color-text-status-links); diff --git a/app/javascript/mastodon/components/button/button.stories.tsx b/app/javascript/mastodon/components/button/button.stories.tsx index 6827097c50..cb60ca3296 100644 --- a/app/javascript/mastodon/components/button/button.stories.tsx +++ b/app/javascript/mastodon/components/button/button.stories.tsx @@ -74,6 +74,24 @@ export const Compact: Story = { play: buttonTest, }; +export const CompactSecondary: Story = { + args: { + compact: true, + secondary: true, + children: 'Compact secondary button', + }, + play: buttonTest, +}; + +export const CompactPlain: Story = { + args: { + compact: true, + plain: true, + children: 'Compact plain button', + }, + play: buttonTest, +}; + export const Dangerous: Story = { args: { dangerous: true, diff --git a/app/javascript/mastodon/components/empty_state/empty_state.module.scss b/app/javascript/mastodon/components/empty_state/empty_state.module.scss index 96aea81d1c..64d9a4e584 100644 --- a/app/javascript/mastodon/components/empty_state/empty_state.module.scss +++ b/app/javascript/mastodon/components/empty_state/empty_state.module.scss @@ -35,6 +35,10 @@ color: var(--color-text-secondary); text-wrap: pretty; } + + a { + color: var(--color-text-status-links); + } } [data-color-scheme='dark'] .defaultImage { diff --git a/app/javascript/mastodon/components/form_fields/form_field_wrapper.module.scss b/app/javascript/mastodon/components/form_fields/form_field_wrapper.module.scss index cff93be8a6..43b672a2a1 100644 --- a/app/javascript/mastodon/components/form_fields/form_field_wrapper.module.scss +++ b/app/javascript/mastodon/components/form_fields/form_field_wrapper.module.scss @@ -48,10 +48,14 @@ .status { // If there's no content, we need to compensate for the parent's - // flex gap to avoid extra spacing below the field. + // flex gap to avoid extra spacing below or next to the field. &:empty { margin-top: calc(-1 * var(--form-field-label-gap)); } + + [data-input-placement^='inline'] &:empty { + margin-inline-start: calc(-1 * var(--form-field-label-gap)); + } } .inputWrapper { diff --git a/app/javascript/mastodon/components/form_fields/form_field_wrapper.tsx b/app/javascript/mastodon/components/form_fields/form_field_wrapper.tsx index ffa7f491bc..579d6e814c 100644 --- a/app/javascript/mastodon/components/form_fields/form_field_wrapper.tsx +++ b/app/javascript/mastodon/components/form_fields/form_field_wrapper.tsx @@ -24,7 +24,7 @@ export interface FieldStatus { message?: string; } -interface FieldWrapperProps { +export interface FieldWrapperProps { label: ReactNode; hint?: ReactNode; required?: boolean; diff --git a/app/javascript/mastodon/components/form_fields/select_field.tsx b/app/javascript/mastodon/components/form_fields/select_field.tsx index 7c1bfdf47d..f2e9e5c8d3 100644 --- a/app/javascript/mastodon/components/form_fields/select_field.tsx +++ b/app/javascript/mastodon/components/form_fields/select_field.tsx @@ -4,11 +4,17 @@ import { forwardRef } from 'react'; import classNames from 'classnames'; import { FormFieldWrapper } from './form_field_wrapper'; -import type { CommonFieldWrapperProps } from './form_field_wrapper'; +import type { + CommonFieldWrapperProps, + FieldWrapperProps, +} from './form_field_wrapper'; import classes from './select.module.scss'; interface Props - extends ComponentPropsWithoutRef<'select'>, CommonFieldWrapperProps {} + extends + ComponentPropsWithoutRef<'select'>, + CommonFieldWrapperProps, + Pick {} /** * A simple form field for single-item selections. @@ -19,13 +25,28 @@ interface Props */ export const SelectField = forwardRef( - ({ id, label, hint, required, status, children, ...otherProps }, ref) => ( + ( + { + id, + label, + hint, + required, + status, + inputPlacement, + children, + wrapperClassName, + ...otherProps + }, + ref, + ) => ( {(inputProps) => (