Merge commit '36b46ea3b5b4a4fb51cf1cd103b5a3c1103c300e' into glitch-soc/merge-upstream

Conflicts:
- `app/views/settings/preferences/appearance/show.html.haml`:
  Conflict because of a code style fix, while some changed lines are
  absent from glitch-soc.
  Ignored the deleted lines.
main
Claire 2024-01-11 13:17:13 +01:00
commit 63acdebc5d
25 changed files with 338 additions and 60 deletions

View File

@ -1,20 +1,13 @@
# This configuration was generated by # This configuration was generated by
# `haml-lint --auto-gen-config` # `haml-lint --auto-gen-config`
# on 2024-01-08 14:02:57 -0500 using Haml-Lint version 0.53.0. # on 2024-01-09 11:30:07 -0500 using Haml-Lint version 0.53.0.
# The point is for the user to remove these configuration records # The point is for the user to remove these configuration records
# one by one as the lints are removed from the code base. # one by one as the lints are removed from the code base.
# Note that changes in the inspected code, or installation of new # Note that changes in the inspected code, or installation of new
# versions of Haml-Lint, may require this file to be generated again. # versions of Haml-Lint, may require this file to be generated again.
linters: linters:
# Offense count: 10 # Offense count: 1
LineLength: LineLength:
exclude: exclude:
- 'app/views/admin/roles/_form.html.haml' - 'app/views/admin/roles/_form.html.haml'
- 'app/views/auth/registrations/edit.html.haml'
- 'app/views/auth/registrations/new.html.haml'
- 'app/views/media/player.html.haml'
- 'app/views/settings/applications/_fields.html.haml'
- 'app/views/settings/imports/index.html.haml'
- 'app/views/settings/preferences/appearance/show.html.haml'
- 'app/views/settings/preferences/other/show.html.haml'

View File

@ -48,6 +48,7 @@ gem 'omniauth', '~> 2.0'
gem 'omniauth-rails_csrf_protection', '~> 1.0' gem 'omniauth-rails_csrf_protection', '~> 1.0'
gem 'color_diff', '~> 0.1' gem 'color_diff', '~> 0.1'
gem 'csv', '~> 3.2'
gem 'discard', '~> 1.2' gem 'discard', '~> 1.2'
gem 'doorkeeper', '~> 5.6' gem 'doorkeeper', '~> 5.6'
gem 'ed25519', '~> 1.3' gem 'ed25519', '~> 1.3'

View File

@ -208,6 +208,7 @@ GEM
crass (1.0.6) crass (1.0.6)
css_parser (1.14.0) css_parser (1.14.0)
addressable addressable
csv (3.2.8)
database_cleaner-active_record (2.1.0) database_cleaner-active_record (2.1.0)
activerecord (>= 5.a) activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0) database_cleaner-core (~> 2.0.0)
@ -716,7 +717,7 @@ GEM
rufus-scheduler (~> 3.2) rufus-scheduler (~> 3.2)
sidekiq (>= 6, < 8) sidekiq (>= 6, < 8)
tilt (>= 1.4.0) tilt (>= 1.4.0)
sidekiq-unique-jobs (7.1.30) sidekiq-unique-jobs (7.1.31)
brpoplpush-redis_script (> 0.1.1, <= 2.0.0) brpoplpush-redis_script (> 0.1.1, <= 2.0.0)
concurrent-ruby (~> 1.0, >= 1.0.5) concurrent-ruby (~> 1.0, >= 1.0.5)
redis (< 5.0) redis (< 5.0)
@ -845,6 +846,7 @@ DEPENDENCIES
color_diff (~> 0.1) color_diff (~> 0.1)
concurrent-ruby concurrent-ruby
connection_pool connection_pool
csv (~> 3.2)
database_cleaner-active_record database_cleaner-active_record
debug (~> 1.8) debug (~> 1.8)
devise (~> 4.9) devise (~> 4.9)

View File

@ -5,7 +5,11 @@
= f.input :return_to, as: :hidden = f.input :return_to, as: :hidden
.field-group .field-group
= f.input :current_password, wrapper: :with_block_label, input_html: { autocomplete: 'current-password', autofocus: true }, label: t('challenge.prompt'), required: true = f.input :current_password,
input_html: { autocomplete: 'current-password', autofocus: true },
label: t('challenge.prompt'),
required: true,
wrapper: :with_block_label
.actions .actions
= f.button :button, t('challenge.confirm'), type: :submit = f.button :button, t('challenge.confirm'), type: :submit

View File

@ -21,7 +21,13 @@
= render 'shared/error_messages', object: resource = render 'shared/error_messages', object: resource
.fields-group .fields-group
= f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label': t('simple_form.labels.defaults.email') }, readonly: current_user.present?, hint: current_user.present? && t('auth.confirmations.wrong_email_hint') = f.input :email,
autofocus: true,
hint: current_user.present? && t('auth.confirmations.wrong_email_hint'),
input_html: { 'aria-label': t('simple_form.labels.defaults.email') },
label: t('simple_form.labels.defaults.email'),
readonly: current_user.present?,
wrapper: :with_label
.actions .actions
= f.button :button, t('auth.resend_confirmation'), type: :submit = f.button :button, t('auth.resend_confirmation'), type: :submit

View File

@ -8,9 +8,18 @@
= f.input :reset_password_token, as: :hidden = f.input :reset_password_token, as: :hidden
.fields-group .fields-group
= f.input :password, wrapper: :with_label, autofocus: true, label: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label': t('simple_form.labels.defaults.new_password'), autocomplete: 'new-password', minlength: User.password_length.first, maxlength: User.password_length.last }, required: true = f.input :password,
autofocus: true,
input_html: { 'aria-label': t('simple_form.labels.defaults.new_password'), autocomplete: 'new-password', minlength: User.password_length.first, maxlength: User.password_length.last },
label: t('simple_form.labels.defaults.new_password'),
required: true,
wrapper: :with_label
.fields-group .fields-group
= f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label': t('simple_form.labels.defaults.confirm_new_password'), autocomplete: 'new-password' }, required: true = f.input :password_confirmation,
input_html: { 'aria-label': t('simple_form.labels.defaults.confirm_new_password'), autocomplete: 'new-password' },
label: t('simple_form.labels.defaults.confirm_new_password'),
required: true,
wrapper: :with_label
.actions .actions
= f.button :button, t('auth.set_new_password'), type: :submit = f.button :button, t('auth.set_new_password'), type: :submit

View File

@ -5,7 +5,12 @@
= render 'shared/error_messages', object: resource = render 'shared/error_messages', object: resource
.fields-group .fields-group
= f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label': t('simple_form.labels.defaults.email') }, hint: false = f.input :email,
autofocus: true,
hint: false,
input_html: { 'aria-label': t('simple_form.labels.defaults.email') },
label: t('simple_form.labels.defaults.email'),
wrapper: :with_label
.actions .actions
= f.button :button, t('auth.reset_password'), type: :submit = f.button :button, t('auth.reset_password'), type: :submit

View File

@ -5,7 +5,9 @@
= fa_icon 'warning' = fa_icon 'warning'
.log-entry__content .log-entry__content
.log-entry__title .log-entry__title
= t('disputes.strikes.title', action: t(account_warning.action, scope: 'disputes.strikes.title_actions'), date: l(account_warning.created_at.to_date)) = t 'disputes.strikes.title',
action: t(account_warning.action, scope: 'disputes.strikes.title_actions'),
date: l(account_warning.created_at.to_date)
.log-entry__timestamp .log-entry__timestamp
%time.formatted{ datetime: account_warning.created_at.iso8601 }= l(account_warning.created_at) %time.formatted{ datetime: account_warning.created_at.iso8601 }= l(account_warning.created_at)

View File

@ -3,7 +3,9 @@
%span{ title: session.user_agent }< %span{ title: session.user_agent }<
= fa_icon "#{session_device_icon(session)} fw", 'aria-label': session_device_icon(session) = fa_icon "#{session_device_icon(session)} fw", 'aria-label': session_device_icon(session)
&nbsp; &nbsp;
= t 'sessions.description', browser: t("sessions.browsers.#{session.browser}", default: session.browser.to_s), platform: t("sessions.platforms.#{session.platform}", default: session.platform.to_s) = t 'sessions.description',
browser: t("sessions.browsers.#{session.browser}", default: session.browser.to_s),
platform: t("sessions.platforms.#{session.platform}", default: session.platform.to_s)
%td %td
%samp= session.ip %samp= session.ip
%td %td

View File

@ -15,15 +15,33 @@
- if (!use_seamless_external_login? || resource.encrypted_password.present?) && !omniauth_only? - if (!use_seamless_external_login? || resource.encrypted_password.present?) && !omniauth_only?
.fields-row .fields-row
.fields-row__column.fields-group.fields-row__column-6 .fields-row__column.fields-group.fields-row__column-6
= f.input :email, wrapper: :with_label, input_html: { 'aria-label': t('simple_form.labels.defaults.email') }, required: true, disabled: current_account.suspended? = f.input :email,
disabled: current_account.suspended?,
input_html: { 'aria-label': t('simple_form.labels.defaults.email') },
required: true,
wrapper: :with_label
.fields-row__column.fields-group.fields-row__column-6 .fields-row__column.fields-group.fields-row__column-6
= f.input :current_password, wrapper: :with_label, input_html: { 'aria-label': t('simple_form.labels.defaults.current_password'), autocomplete: 'current-password' }, required: true, disabled: current_account.suspended?, hint: false = f.input :current_password,
disabled: current_account.suspended?,
hint: false,
input_html: { 'aria-label': t('simple_form.labels.defaults.current_password'), autocomplete: 'current-password' },
required: true,
wrapper: :with_label
.fields-row .fields-row
.fields-row__column.fields-group.fields-row__column-6 .fields-row__column.fields-group.fields-row__column-6
= f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label': t('simple_form.labels.defaults.new_password'), autocomplete: 'new-password', minlength: User.password_length.first, maxlength: User.password_length.last }, hint: t('simple_form.hints.defaults.password'), disabled: current_account.suspended? = f.input :password,
disabled: current_account.suspended?,
hint: t('simple_form.hints.defaults.password'),
input_html: { 'aria-label': t('simple_form.labels.defaults.new_password'), autocomplete: 'new-password', minlength: User.password_length.first, maxlength: User.password_length.last },
label: t('simple_form.labels.defaults.new_password'),
wrapper: :with_label
.fields-row__column.fields-group.fields-row__column-6 .fields-row__column.fields-group.fields-row__column-6
= f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label': t('simple_form.labels.defaults.confirm_new_password'), autocomplete: 'new-password' }, disabled: current_account.suspended? = f.input :password_confirmation,
disabled: current_account.suspended?,
input_html: { 'aria-label': t('simple_form.labels.defaults.confirm_new_password'), autocomplete: 'new-password' },
label: t('simple_form.labels.defaults.confirm_new_password'),
wrapper: :with_label
.actions .actions
= f.button :button, t('generic.save_changes'), type: :submit, class: 'button', disabled: current_account.suspended? = f.button :button, t('generic.save_changes'), type: :submit, class: 'button', disabled: current_account.suspended?

View File

@ -19,25 +19,61 @@
.fields-group .fields-group
= f.simple_fields_for :account do |ff| = f.simple_fields_for :account do |ff|
= ff.input :username, wrapper: :with_label, label: false, required: true, input_html: { 'aria-label': t('simple_form.labels.defaults.username'), autocomplete: 'off', placeholder: t('simple_form.labels.defaults.username'), pattern: '[a-zA-Z0-9_]+', maxlength: 30 }, append: "@#{site_hostname}" = ff.input :username,
= f.input :email, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label': t('simple_form.labels.defaults.email'), autocomplete: 'username' }, hint: false append: "@#{site_hostname}",
= f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label': t('simple_form.labels.defaults.password'), autocomplete: 'new-password', minlength: User.password_length.first, maxlength: User.password_length.last }, hint: false input_html: { 'aria-label': t('simple_form.labels.defaults.username'), autocomplete: 'off', placeholder: t('simple_form.labels.defaults.username'), pattern: '[a-zA-Z0-9_]+', maxlength: 30 },
= f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label': t('simple_form.labels.defaults.confirm_password'), autocomplete: 'new-password' }, hint: false label: false,
= f.input :confirm_password, as: :string, placeholder: t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), required: false, input_html: { 'aria-label': t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), autocomplete: 'off' }, hint: false required: true,
= f.input :website, as: :url, wrapper: :with_label, label: t('simple_form.labels.defaults.honeypot', label: 'Website'), required: false, input_html: { 'aria-label': t('simple_form.labels.defaults.honeypot', label: 'Website'), autocomplete: 'off' } wrapper: :with_label
= f.input :email,
hint: false,
input_html: { 'aria-label': t('simple_form.labels.defaults.email'), autocomplete: 'username' },
placeholder: t('simple_form.labels.defaults.email'),
required: true
= f.input :password,
hint: false,
input_html: { 'aria-label': t('simple_form.labels.defaults.password'), autocomplete: 'new-password', minlength: User.password_length.first, maxlength: User.password_length.last },
placeholder: t('simple_form.labels.defaults.password'),
required: true
= f.input :password_confirmation,
hint: false,
input_html: { 'aria-label': t('simple_form.labels.defaults.confirm_password'), autocomplete: 'new-password' },
placeholder: t('simple_form.labels.defaults.confirm_password'),
required: true
= f.input :confirm_password,
as: :string,
hint: false,
input_html: { 'aria-label': t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), autocomplete: 'off' },
placeholder: t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')),
required: false
= f.input :website,
as: :url,
input_html: { 'aria-label': t('simple_form.labels.defaults.honeypot', label: 'Website'), autocomplete: 'off' },
label: t('simple_form.labels.defaults.honeypot', label: 'Website'),
required: false,
wrapper: :with_label
- if approved_registrations? && @invite.blank? - if approved_registrations? && @invite.blank?
%p.lead= t('auth.sign_up.manual_review', domain: site_hostname) %p.lead= t('auth.sign_up.manual_review', domain: site_hostname)
.fields-group .fields-group
= f.simple_fields_for :invite_request, resource.invite_request || resource.build_invite_request do |invite_request_fields| = f.simple_fields_for :invite_request, resource.invite_request || resource.build_invite_request do |invite_request_fields|
= invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: Setting.require_invite_text, label: false, hint: false = invite_request_fields.input :text,
as: :text,
hint: false,
label: false,
required: Setting.require_invite_text,
wrapper: :with_block_label
= hidden_field_tag :accept, params[:accept] = hidden_field_tag :accept, params[:accept]
= f.input :invite_code, as: :hidden = f.input :invite_code, as: :hidden
.fields-group .fields-group
= f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.privacy_policy_agreement_html', rules_path: about_more_path, privacy_policy_path: privacy_policy_path), required: true = f.input :agreement,
as: :boolean,
label: t('auth.privacy_policy_agreement_html', rules_path: about_more_path, privacy_policy_path: privacy_policy_path),
required: true,
wrapper: :with_label
.actions .actions
= f.button :button, @invite.present? ? t('auth.register') : sign_up_message, type: :submit = f.button :button, @invite.present? ? t('auth.register') : sign_up_message, type: :submit

View File

@ -10,11 +10,25 @@
%p.lead= t('auth.sign_in.preamble_html', domain: site_hostname) %p.lead= t('auth.sign_in.preamble_html', domain: site_hostname)
.fields-group .fields-group
- if use_seamless_external_login? - if use_seamless_external_login?
= f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.username_or_email'), input_html: { 'aria-label': t('simple_form.labels.defaults.username_or_email') }, hint: false = f.input :email,
autofocus: true,
hint: false,
input_html: { 'aria-label': t('simple_form.labels.defaults.username_or_email') },
label: t('simple_form.labels.defaults.username_or_email'),
wrapper: :with_label
- else - else
= f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label': t('simple_form.labels.defaults.email') }, hint: false = f.input :email,
autofocus: true,
hint: false,
input_html: { 'aria-label': t('simple_form.labels.defaults.email') },
label: t('simple_form.labels.defaults.email'),
wrapper: :with_label
.fields-group .fields-group
= f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.password'), input_html: { 'aria-label': t('simple_form.labels.defaults.password'), autocomplete: 'current-password' }, hint: false = f.input :password,
hint: false,
input_html: { 'aria-label': t('simple_form.labels.defaults.password'), autocomplete: 'current-password' },
label: t('simple_form.labels.defaults.password'),
wrapper: :with_label
.actions .actions
= f.button :button, t('auth.login'), type: :submit = f.button :button, t('auth.login'), type: :submit

View File

@ -5,7 +5,12 @@
%p.hint.authentication-hint= t('simple_form.hints.sessions.otp') %p.hint.authentication-hint= t('simple_form.hints.sessions.otp')
.fields-group .fields-group
= f.input :otp_attempt, type: :number, wrapper: :with_label, label: t('simple_form.labels.defaults.otp_attempt'), input_html: { 'aria-label': t('simple_form.labels.defaults.otp_attempt'), autocomplete: 'one-time-code' }, autofocus: true = f.input :otp_attempt,
autofocus: true,
input_html: { 'aria-label': t('simple_form.labels.defaults.otp_attempt'), autocomplete: 'one-time-code' },
label: t('simple_form.labels.defaults.otp_attempt'),
type: :number,
wrapper: :with_label
.actions .actions
= f.button :button, t('auth.login'), type: :submit = f.button :button, t('auth.login'), type: :submit

View File

@ -14,7 +14,10 @@
%p.lead= t('auth.setup.email_below_hint_html') %p.lead= t('auth.setup.email_below_hint_html')
.fields-group .fields-group
= f.input :email, required: true, hint: false, input_html: { 'aria-label': t('simple_form.labels.defaults.email'), autocomplete: 'off' } = f.input :email,
hint: false,
input_html: { 'aria-label': t('simple_form.labels.defaults.email'), autocomplete: 'off' },
required: true
.actions .actions
= f.button :button, t('auth.resend_confirmation'), type: :submit, class: 'button timer-button', disabled: true = f.button :button, t('auth.resend_confirmation'), type: :submit, class: 'button timer-button', disabled: true

View File

@ -13,14 +13,39 @@
meta = @media_attachment.file.meta || {} meta = @media_attachment.file.meta || {}
- if @media_attachment.video? - if @media_attachment.video?
= react_component :video, src: @media_attachment.file.url(:original), preview: @media_attachment.thumbnail.present? ? @media_attachment.thumbnail.url : @media_attachment.file.url(:small), frameRate: meta.dig('original', 'frame_rate'), blurhash: @media_attachment.blurhash, width: 670, height: 380, editable: true, detailed: true, inline: true, alt: @media_attachment.description, media: [ActiveModelSerializers::SerializableResource.new(@media_attachment, serializer: REST::MediaAttachmentSerializer)].as_json do = react_component :video,
alt: @media_attachment.description,
blurhash: @media_attachment.blurhash,
detailed: true,
editable: true,
frameRate: meta.dig('original', 'frame_rate'),
height: 380,
inline: true,
media: [ActiveModelSerializers::SerializableResource.new(@media_attachment, serializer: REST::MediaAttachmentSerializer)].as_json,
preview: @media_attachment.thumbnail.present? ? @media_attachment.thumbnail.url : @media_attachment.file.url(:small),
src: @media_attachment.file.url(:original),
width: 670 do
%video{ controls: 'controls' } %video{ controls: 'controls' }
%source{ src: @media_attachment.file.url(:original) } %source{ src: @media_attachment.file.url(:original) }
- elsif @media_attachment.gifv? - elsif @media_attachment.gifv?
= react_component :media_gallery, height: 380, standalone: true, autoplay: true, media: [ActiveModelSerializers::SerializableResource.new(@media_attachment, serializer: REST::MediaAttachmentSerializer).as_json] do = react_component :media_gallery,
autoplay: true,
height: 380,
media: [ActiveModelSerializers::SerializableResource.new(@media_attachment, serializer: REST::MediaAttachmentSerializer).as_json],
standalone: true do
%video{ autoplay: 'autoplay', muted: 'muted', loop: 'loop' } %video{ autoplay: 'autoplay', muted: 'muted', loop: 'loop' }
%source{ src: @media_attachment.file.url(:original) } %source{ src: @media_attachment.file.url(:original) }
- elsif @media_attachment.audio? - elsif @media_attachment.audio?
= react_component :audio, src: @media_attachment.file.url(:original), poster: @media_attachment.thumbnail.present? ? @media_attachment.thumbnail.url : @media_attachment.account.avatar_static_url, backgroundColor: meta.dig('colors', 'background'), foregroundColor: meta.dig('colors', 'foreground'), accentColor: meta.dig('colors', 'accent'), width: 670, height: 380, fullscreen: true, alt: @media_attachment.description, duration: meta.dig(:original, :duration) do = react_component :audio,
accentColor: meta.dig('colors', 'accent'),
alt: @media_attachment.description,
backgroundColor: meta.dig('colors', 'background'),
duration: meta.dig(:original, :duration),
foregroundColor: meta.dig('colors', 'foreground'),
fullscreen: true,
height: 380,
poster: @media_attachment.thumbnail.present? ? @media_attachment.thumbnail.url : @media_attachment.account.avatar_static_url,
src: @media_attachment.file.url(:original),
width: 670 do
%audio{ controls: 'controls' } %audio{ controls: 'controls' }
%source{ src: @media_attachment.file.url(:original) } %source{ src: @media_attachment.file.url(:original) }

View File

@ -1,11 +1,17 @@
.fields-group .fields-group
= f.input :name, wrapper: :with_label, label: t('activerecord.attributes.doorkeeper/application.name') = f.input :name,
label: t('activerecord.attributes.doorkeeper/application.name'),
wrapper: :with_label
.fields-group .fields-group
= f.input :website, wrapper: :with_label, label: t('activerecord.attributes.doorkeeper/application.website') = f.input :website,
label: t('activerecord.attributes.doorkeeper/application.website'),
wrapper: :with_label
.fields-group .fields-group
= f.input :redirect_uri, wrapper: :with_block_label, label: t('activerecord.attributes.doorkeeper/application.redirect_uri'), hint: t('doorkeeper.applications.help.redirect_uri') = f.input :redirect_uri,
label: t('activerecord.attributes.doorkeeper/application.redirect_uri'), hint: t('doorkeeper.applications.help.redirect_uri'),
wrapper: :with_block_label
%p.hint= t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code, Doorkeeper.configuration.native_redirect_uri)).html_safe %p.hint= t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code, Doorkeeper.configuration.native_redirect_uri)).html_safe
@ -15,4 +21,15 @@
%span.hint= t('simple_form.hints.defaults.scopes') %span.hint= t('simple_form.hints.defaults.scopes')
- Doorkeeper.configuration.scopes.group_by { |s| s.split(':').first }.each_value do |value| - Doorkeeper.configuration.scopes.group_by { |s| s.split(':').first }.each_value do |value|
= f.input :scopes, label: false, hint: false, collection: value.sort, wrapper: :with_block_label, include_blank: false, label_method: ->(scope) { safe_join([content_tag(:samp, scope, class: class_for_scope(scope)), content_tag(:span, t("doorkeeper.scopes.#{scope}"), class: 'hint')]) }, selected: f.object.scopes.all, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li' = f.input :scopes,
as: :check_boxes,
collection_wrapper_tag: 'ul',
collection: value.sort,
hint: false,
include_blank: false,
item_wrapper_tag: 'li',
label_method: ->(scope) { safe_join([content_tag(:samp, scope, class: class_for_scope(scope)), content_tag(:span, t("doorkeeper.scopes.#{scope}"), class: 'hint')]) },
label: false,
required: false,
selected: f.object.scopes.all,
wrapper: :with_block_label

View File

@ -11,7 +11,9 @@
%p.lead= t('featured_tags.hint_html') %p.lead= t('featured_tags.hint_html')
.fields-group .fields-group
= f.input :name, wrapper: :with_block_label, hint: safe_join([t('simple_form.hints.featured_tag.name'), safe_join(@recently_used_tags.map { |tag| link_to("##{tag.display_name}", settings_featured_tags_path(featured_tag: { name: tag.name }), method: :post) }, ', ')], ' ') = f.input :name,
hint: safe_join([t('simple_form.hints.featured_tag.name'), safe_join(@recently_used_tags.map { |tag| link_to("##{tag.display_name}", settings_featured_tags_path(featured_tag: { name: tag.name }), method: :post) }, ', ')], ' '),
wrapper: :with_block_label
.actions .actions
= f.button :button, t('featured_tags.add_new'), type: :submit = f.button :button, t('featured_tags.add_new'), type: :submit

View File

@ -3,13 +3,29 @@
= simple_form_for @import, url: settings_imports_path do |f| = simple_form_for @import, url: settings_imports_path do |f|
.field-group .field-group
= f.input :type, as: :grouped_select, collection: { constructive: %i(following bookmarks lists), destructive: %i(muting blocking domain_blocking) }, wrapper: :with_block_label, include_blank: false, label_method: ->(type) { I18n.t("imports.types.#{type}") }, group_label_method: ->(group) { I18n.t("imports.type_groups.#{group.first}") }, group_method: :last, hint: t('imports.preface') = f.input :type,
as: :grouped_select,
collection: { constructive: %i(following bookmarks lists), destructive: %i(muting blocking domain_blocking) },
group_label_method: ->(group) { I18n.t("imports.type_groups.#{group.first}") },
group_method: :last,
hint: t('imports.preface'),
include_blank: false,
label_method: ->(type) { I18n.t("imports.types.#{type}") },
wrapper: :with_block_label
.fields-row .fields-row
.fields-group.fields-row__column.fields-row__column-6 .fields-group.fields-row__column.fields-row__column-6
= f.input :data, as: :file, wrapper: :with_block_label, hint: t('simple_form.hints.imports.data') = f.input :data,
as: :file,
hint: t('simple_form.hints.imports.data'),
wrapper: :with_block_label
.fields-group.fields-row__column.fields-row__column-6 .fields-group.fields-row__column.fields-row__column-6
= f.input :mode, as: :radio_buttons, collection: Import::MODES, label_method: ->(mode) { safe_join([I18n.t("imports.modes.#{mode}"), content_tag(:span, I18n.t("imports.modes.#{mode}_long"), class: 'hint')]) }, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li' = f.input :mode,
as: :radio_buttons,
collection_wrapper_tag: 'ul',
collection: Import::MODES,
item_wrapper_tag: 'li',
label_method: ->(mode) { safe_join([I18n.t("imports.modes.#{mode}"), content_tag(:span, I18n.t("imports.modes.#{mode}_long"), class: 'hint')]) }
.actions .actions
= f.button :button, t('imports.upload'), type: :submit = f.button :button, t('imports.upload'), type: :submit

View File

@ -15,7 +15,11 @@
.fields-row .fields-row
.fields-row__column.fields-group.fields-row__column-6 .fields-row__column.fields-group.fields-row__column-6
= f.input :acct, wrapper: :with_block_label, input_html: { autocapitalize: 'none', autocorrect: 'off' }, label: t('simple_form.labels.account_migration.acct'), hint: t('simple_form.hints.account_migration.acct') = f.input :acct,
hint: t('simple_form.hints.account_migration.acct'),
input_html: { autocapitalize: 'none', autocorrect: 'off' },
label: t('simple_form.labels.account_migration.acct'),
wrapper: :with_block_label
.fields-row__column.fields-group.fields-row__column-6 .fields-row__column.fields-group.fields-row__column-6
- if current_user.encrypted_password.present? - if current_user.encrypted_password.present?

View File

@ -7,9 +7,18 @@
= simple_form_for current_user, url: settings_preferences_appearance_path, html: { method: :put, id: 'edit_user' } do |f| = simple_form_for current_user, url: settings_preferences_appearance_path, html: { method: :put, id: 'edit_user' } do |f|
.fields-row .fields-row
.fields-group.fields-row__column.fields-row__column-6 .fields-group.fields-row__column.fields-row__column-6
= f.input :locale, collection: ui_languages, wrapper: :with_label, include_blank: false, label_method: ->(locale) { native_locale_name(locale) }, selected: I18n.locale, hint: false = f.input :locale,
collection: ui_languages,
hint: false,
include_blank: false,
label_method: ->(locale) { native_locale_name(locale) },
selected: I18n.locale,
wrapper: :with_label
.fields-group.fields-row__column.fields-row__column-6 .fields-group.fields-row__column.fields-row__column-6
= f.input :time_zone, wrapper: :with_label, collection: ActiveSupport::TimeZone.all.map { |tz| ["(GMT#{tz.formatted_offset}) #{tz.name}", tz.tzinfo.name] }, hint: false = f.input :time_zone,
collection: ActiveSupport::TimeZone.all.map { |tz| ["(GMT#{tz.formatted_offset}) #{tz.name}", tz.tzinfo.name] },
hint: false,
wrapper: :with_label
- unless I18n.locale == :en - unless I18n.locale == :en
.flash-message.translation-prompt .flash-message.translation-prompt
@ -23,11 +32,17 @@
%p.hint= t 'appearance.advanced_web_interface_hint' %p.hint= t 'appearance.advanced_web_interface_hint'
.fields-group .fields-group
= ff.input :'web.advanced_layout', wrapper: :with_label, hint: false, label: I18n.t('simple_form.labels.defaults.setting_advanced_layout') = ff.input :'web.advanced_layout',
hint: false,
label: I18n.t('simple_form.labels.defaults.setting_advanced_layout'),
wrapper: :with_label
%h4= t 'appearance.animations_and_accessibility' %h4= t 'appearance.animations_and_accessibility'
.fields-group .fields-group
= ff.input :'web.use_pending_items', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_use_pending_items'), hint: I18n.t('simple_form.hints.defaults.setting_use_pending_items') = ff.input :'web.use_pending_items',
hint: I18n.t('simple_form.hints.defaults.setting_use_pending_items'),
label: I18n.t('simple_form.labels.defaults.setting_use_pending_items'),
wrapper: :with_label
.fields-group .fields-group
= ff.input :'web.auto_play', wrapper: :with_label, recommended: true, label: I18n.t('simple_form.labels.defaults.setting_auto_play_gif') = ff.input :'web.auto_play', wrapper: :with_label, recommended: true, label: I18n.t('simple_form.labels.defaults.setting_auto_play_gif')
@ -52,10 +67,21 @@
%h4= t 'appearance.sensitive_content' %h4= t 'appearance.sensitive_content'
.fields-group .fields-group
= ff.input :'web.display_media', collection: %w(default show_all hide_all), label_method: ->(item) { t("simple_form.hints.defaults.setting_display_media_#{item}") }, hint: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', wrapper: :with_floating_label, label: I18n.t('simple_form.labels.defaults.setting_display_media') = ff.input :'web.display_media',
as: :radio_buttons,
collection_wrapper_tag: 'ul',
collection: %w(default show_all hide_all),
hint: false,
item_wrapper_tag: 'li',
label_method: ->(item) { t("simple_form.hints.defaults.setting_display_media_#{item}") },
label: I18n.t('simple_form.labels.defaults.setting_display_media'),
wrapper: :with_floating_label
.fields-group .fields-group
= ff.input :'web.use_blurhash', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_use_blurhash'), hint: I18n.t('simple_form.hints.defaults.setting_use_blurhash') = ff.input :'web.use_blurhash',
hint: I18n.t('simple_form.hints.defaults.setting_use_blurhash'),
label: I18n.t('simple_form.labels.defaults.setting_use_blurhash'),
wrapper: :with_label
.fields-group .fields-group
= ff.input :'web.expand_content_warnings', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_expand_spoilers') = ff.input :'web.expand_content_warnings', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_expand_spoilers')

View File

@ -9,19 +9,40 @@
= f.simple_fields_for :settings, current_user.settings do |ff| = f.simple_fields_for :settings, current_user.settings do |ff|
.fields-group .fields-group
= ff.input :aggregate_reblogs, wrapper: :with_label, recommended: true, label: I18n.t('simple_form.labels.defaults.setting_aggregate_reblogs'), hint: I18n.t('simple_form.hints.defaults.setting_aggregate_reblogs') = ff.input :aggregate_reblogs,
hint: I18n.t('simple_form.hints.defaults.setting_aggregate_reblogs'),
label: I18n.t('simple_form.labels.defaults.setting_aggregate_reblogs'),
recommended: true,
wrapper: :with_label
%h4= t 'preferences.posting_defaults' %h4= t 'preferences.posting_defaults'
.fields-row .fields-row
.fields-group.fields-row__column.fields-row__column-6 .fields-group.fields-row__column.fields-row__column-6
= ff.input :default_privacy, collection: Status.selectable_visibilities, wrapper: :with_label, include_blank: false, label_method: ->(visibility) { safe_join([I18n.t("statuses.visibilities.#{visibility}"), I18n.t("statuses.visibilities.#{visibility}_long")], ' - ') }, required: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_privacy') = ff.input :default_privacy,
collection: Status.selectable_visibilities,
hint: false,
include_blank: false,
label_method: ->(visibility) { safe_join([I18n.t("statuses.visibilities.#{visibility}"), I18n.t("statuses.visibilities.#{visibility}_long")], ' - ') },
label: I18n.t('simple_form.labels.defaults.setting_default_privacy'),
required: false,
wrapper: :with_label
.fields-group.fields-row__column.fields-row__column-6 .fields-group.fields-row__column.fields-row__column-6
= ff.input :default_language, collection: [nil] + filterable_languages, wrapper: :with_label, label_method: ->(locale) { locale.nil? ? I18n.t('statuses.default_language') : native_locale_name(locale) }, required: false, include_blank: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_language') = ff.input :default_language,
collection: [nil] + filterable_languages,
hint: false,
include_blank: false,
label_method: ->(locale) { locale.nil? ? I18n.t('statuses.default_language') : native_locale_name(locale) },
label: I18n.t('simple_form.labels.defaults.setting_default_language'),
required: false,
wrapper: :with_label
.fields-group .fields-group
= ff.input :default_sensitive, wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_default_sensitive'), hint: I18n.t('simple_form.hints.defaults.setting_default_sensitive') = ff.input :default_sensitive,
hint: I18n.t('simple_form.hints.defaults.setting_default_sensitive'),
label: I18n.t('simple_form.labels.defaults.setting_default_sensitive'),
wrapper: :with_label
.fields-group .fields-group
= ff.input :default_content_type, collection: ['text/plain', 'text/markdown', 'text/html'], wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_default_content_type'), include_blank: false, label_method: ->(item) { safe_join([t("simple_form.labels.defaults.setting_default_content_type_#{item.split('/')[1]}"), content_tag(:span, t("simple_form.hints.defaults.setting_default_content_type_#{item.split('/')[1]}"), class: 'hint')]) }, required: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', glitch_only: true = ff.input :default_content_type, collection: ['text/plain', 'text/markdown', 'text/html'], wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_default_content_type'), include_blank: false, label_method: ->(item) { safe_join([t("simple_form.labels.defaults.setting_default_content_type_#{item.split('/')[1]}"), content_tag(:span, t("simple_form.hints.defaults.setting_default_content_type_#{item.split('/')[1]}"), class: 'hint')]) }, required: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', glitch_only: true
@ -29,7 +50,15 @@
%h4= t 'preferences.public_timelines' %h4= t 'preferences.public_timelines'
.fields-group .fields-group
= f.input :chosen_languages, collection: filterable_languages, wrapper: :with_block_label, include_blank: false, label_method: ->(locale) { native_locale_name(locale) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li' = f.input :chosen_languages,
as: :check_boxes,
collection_wrapper_tag: 'ul',
collection: filterable_languages,
include_blank: false,
item_wrapper_tag: 'li',
label_method: ->(locale) { native_locale_name(locale) },
required: false,
wrapper: :with_block_label
.actions .actions
= f.button :button, t('generic.save_changes'), type: :submit = f.button :button, t('generic.save_changes'), type: :submit

View File

@ -33,7 +33,10 @@
.fields-row .fields-row
.fields-row__column.fields-row__column-6 .fields-row__column.fields-row__column-6
.fields-group .fields-group
= f.input :avatar, wrapper: :with_block_label, input_html: { accept: Account::Avatar::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.avatar', dimensions: '400x400', size: number_to_human_size(Account::Avatar::LIMIT)) = f.input :avatar,
hint: t('simple_form.hints.defaults.avatar', dimensions: '400x400', size: number_to_human_size(Account::Avatar::LIMIT)),
input_html: { accept: Account::Avatar::IMAGE_MIME_TYPES.join(',') },
wrapper: :with_block_label
.fields-row__column.fields-row__column-6 .fields-row__column.fields-row__column-6
.fields-group .fields-group
@ -46,7 +49,10 @@
.fields-row .fields-row
.fields-row__column.fields-row__column-6 .fields-row__column.fields-row__column-6
.fields-group .fields-group
= f.input :header, wrapper: :with_block_label, input_html: { accept: Account::Header::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.header', dimensions: '1500x500', size: number_to_human_size(Account::Header::LIMIT)) = f.input :header,
hint: t('simple_form.hints.defaults.header', dimensions: '1500x500', size: number_to_human_size(Account::Header::LIMIT)),
input_html: { accept: Account::Header::IMAGE_MIME_TYPES.join(',') },
wrapper: :with_block_label
.fields-row__column.fields-row__column-6 .fields-row__column.fields-row__column-6
.fields-group .fields-group

View File

@ -12,7 +12,12 @@
%samp.qr-alternative__code= @new_otp_secret.scan(/.{4}/).join(' ') %samp.qr-alternative__code= @new_otp_secret.scan(/.{4}/).join(' ')
.fields-group .fields-group
= f.input :otp_attempt, wrapper: :with_label, hint: t('otp_authentication.code_hint'), label: t('simple_form.labels.defaults.otp_attempt'), input_html: { autocomplete: 'off' }, required: true = f.input :otp_attempt,
hint: t('otp_authentication.code_hint'),
input_html: { autocomplete: 'off' },
label: t('simple_form.labels.defaults.otp_attempt'),
required: true,
wrapper: :with_label
.actions .actions
= f.button :button, t('otp_authentication.enable'), type: :submit = f.button :button, t('otp_authentication.enable'), type: :submit

View File

@ -183,6 +183,21 @@ describe Mastodon::CLI::Media do
.to output_results('Downloaded 1 media') .to output_results('Downloaded 1 media')
end end
end end
context 'with --days option' do
before do
Fabricate(:media_attachment, remote_url: 'https://example.com/image.jpg', id: Mastodon::Snowflake.id_at(50.days.ago))
Fabricate(:media_attachment, remote_url: 'https://example.com/image.jpg', id: Mastodon::Snowflake.id_at(5.days.ago))
Fabricate(:media_attachment, remote_url: '', id: Mastodon::Snowflake.id_at(5.days.ago))
end
let(:options) { { days: 10 } }
it 'redownloads the attachment file for the remote records more recent than the option' do
expect { subject }
.to output_results('Downloaded 1 media')
end
end
end end
describe '#remove_orphans' do describe '#remove_orphans' do

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
require 'rails_helper'
describe 'ShareEntrypoint' do
include ProfileStories
subject { page }
let(:email) { 'test@example.com' }
let(:password) { 'password' }
let(:confirmed_at) { Time.zone.now }
let(:finished_onboarding) { true }
before do
as_a_logged_in_user
visit share_path
end
it 'can be used to post a new status' do
expect(subject).to have_css('div#mastodon-compose')
expect(subject).to have_css('.compose-form__publish-button-wrapper > button')
status_text = 'This is a new status!'
within('.compose-form') do
fill_in "What's on your mind?", with: status_text
click_on 'Publish!'
end
expect(subject).to have_css('.notification-bar-message', text: 'Post published.')
end
end