diff --git a/.env.production.sample b/.env.production.sample index b604c4b04d..8a446d9cdc 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -251,6 +251,11 @@ SMTP_FROM_ADDRESS=notifications@example.com # Maximum allowed character count MAX_TOOT_CHARS=500 +# Maximum allowed hashtags to follow in a feed column +# Note that setting this value higher may cause significant +# database load +MAX_FEED_HASHTAGS=4 + # Maximum number of pinned posts MAX_PINNED_TOOTS=5 diff --git a/Gemfile b/Gemfile index cd0ef255b1..ad7f0b3d40 100644 --- a/Gemfile +++ b/Gemfile @@ -26,7 +26,7 @@ gem 'blurhash', '~> 0.1' gem 'active_model_serializers', '~> 0.10' gem 'addressable', '~> 2.8' -gem 'bootsnap', '~> 1.17.0', require: false +gem 'bootsnap', '~> 1.18.0', require: false gem 'browser' gem 'charlock_holmes', '~> 0.7.7' gem 'chewy', '~> 7.3' @@ -63,7 +63,7 @@ gem 'kaminari', '~> 1.2' gem 'link_header', '~> 0.0' gem 'mime-types', '~> 3.5.0', require: 'mime/types/columnar' gem 'nokogiri', '~> 1.15' -gem 'nsa', github: 'jhawthorn/nsa', ref: 'e020fcc3a54d993ab45b7194d89ab720296c111b' +gem 'nsa' gem 'oj', '~> 3.14' gem 'ox', '~> 2.14' gem 'parslet' diff --git a/Gemfile.lock b/Gemfile.lock index 57b2580722..b76f449b26 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,17 +7,6 @@ GIT hkdf (~> 0.2) jwt (~> 2.0) -GIT - remote: https://github.com/jhawthorn/nsa.git - revision: e020fcc3a54d993ab45b7194d89ab720296c111b - ref: e020fcc3a54d993ab45b7194d89ab720296c111b - specs: - nsa (0.2.8) - activesupport (>= 4.2, < 7.2) - concurrent-ruby (~> 1.0, >= 1.0.2) - sidekiq (>= 3.5) - statsd-ruby (~> 1.4, >= 1.4.0) - GEM remote: https://rubygems.org/ specs: @@ -155,9 +144,9 @@ GEM binding_of_caller (1.0.0) debug_inspector (>= 0.0.1) blurhash (0.1.7) - bootsnap (1.17.1) + bootsnap (1.18.3) msgpack (~> 1.2) - brakeman (6.1.1) + brakeman (6.1.2) racc browser (5.3.1) brpoplpush-redis_script (0.1.3) @@ -167,11 +156,11 @@ GEM bundler-audit (0.9.1) bundler (>= 1.2.0, < 3) thor (~> 1.0) - capybara (3.39.2) + capybara (3.40.0) addressable matrix mini_mime (>= 0.1.3) - nokogiri (~> 1.8) + nokogiri (~> 1.11) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) @@ -180,7 +169,7 @@ GEM activesupport cbor (0.5.9.6) charlock_holmes (0.7.7) - chewy (7.5.0) + chewy (7.5.1) activesupport (>= 5.2) elasticsearch (>= 7.12.0, < 7.14.0) elasticsearch-dsl @@ -319,7 +308,7 @@ GEM activesupport (>= 5.1) haml (>= 4.0.6) railties (>= 5.1) - haml_lint (0.55.0) + haml_lint (0.56.0) haml (>= 5.0) parallel (~> 1.10) rainbow @@ -465,9 +454,14 @@ GEM net-smtp (0.4.0.1) net-protocol nio4r (2.5.9) - nokogiri (1.16.0) + nokogiri (1.16.2) mini_portile2 (~> 2.8.2) racc (~> 1.4) + nsa (0.3.0) + activesupport (>= 4.2, < 7.2) + concurrent-ruby (~> 1.0, >= 1.0.2) + sidekiq (>= 3.5) + statsd-ruby (~> 1.4, >= 1.4.0) oj (3.16.3) bigdecimal (>= 3.0) omniauth (2.1.1) @@ -771,7 +765,7 @@ GEM unf (~> 0.1.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - tzinfo-data (1.2023.4) + tzinfo-data (1.2024.1) tzinfo (>= 1.0.0) unf (0.1.4) unf_ext @@ -829,7 +823,7 @@ DEPENDENCIES better_errors (~> 2.9) binding_of_caller (~> 1.0) blurhash (~> 0.1) - bootsnap (~> 1.17.0) + bootsnap (~> 1.18.0) brakeman (~> 6.0) browser bundler-audit (~> 0.9) @@ -886,7 +880,7 @@ DEPENDENCIES net-http (~> 0.4.0) net-ldap (~> 0.18) nokogiri (~> 1.15) - nsa! + nsa oj (~> 3.14) omniauth (~> 2.0) omniauth-cas (~> 3.0.0.beta.1) diff --git a/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.jsx b/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.jsx index c60de4c518..4488c5b2a0 100644 --- a/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.jsx +++ b/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.jsx @@ -9,6 +9,8 @@ import { NonceProvider } from 'react-select'; import AsyncSelect from 'react-select/async'; import Toggle from 'react-toggle'; +import { maxFeedHashtags } from 'flavours/glitch/initial_state'; + import SettingToggle from '../../notifications/components/setting_toggle'; const messages = defineMessages({ @@ -46,9 +48,9 @@ class ColumnSettings extends PureComponent { onSelect = mode => value => { const oldValue = this.tags(mode); - // Prevent changes that add more than 4 tags, but allow removing - // tags that were already added before - if ((value.length > 4) && !(value < oldValue)) { + // Prevent changes that add more than the number of configured + // tags, but allow removing tags that were already added before + if ((value.length > maxFeedHashtags) && !(value < oldValue)) { return; } diff --git a/app/javascript/flavours/glitch/initial_state.js b/app/javascript/flavours/glitch/initial_state.js index 588faa0fb0..2265a0f362 100644 --- a/app/javascript/flavours/glitch/initial_state.js +++ b/app/javascript/flavours/glitch/initial_state.js @@ -69,6 +69,7 @@ export const hasMultiColumnPath = initialPath === '/' * @property {InitialStateMeta} meta * @property {object} local_settings * @property {number} max_toot_chars + * @property {number} max_feed_hashtags * @property {number} poll_limits * @property {number} max_reactions */ @@ -135,6 +136,7 @@ export const sso_redirect = getMeta('sso_redirect'); // Glitch-soc-specific settings export const maxChars = (initialState && initialState.max_toot_chars) || 500; +export const maxFeedHashtags = (initialState && initialState.max_feed_hashtags) || 4; export const favouriteModal = getMeta('favourite_modal'); export const pollLimits = (initialState && initialState.poll_limits); export const defaultContentType = getMeta('default_content_type'); diff --git a/app/javascript/flavours/glitch/locales/id.json b/app/javascript/flavours/glitch/locales/id.json index d360fed722..f37788bc80 100644 --- a/app/javascript/flavours/glitch/locales/id.json +++ b/app/javascript/flavours/glitch/locales/id.json @@ -1,4 +1,51 @@ { + "about.fork_disclaimer": "Glitch-soc adalah perangkat lunak sumber terbuka yang merupakan fork dari Mastodon.", + "account.disclaimer_full": "Informasi di bawah ini mungkin tidak mencerminkan profil pengguna secara lengkap.", + "account.follows": "Mengikuti", + "account.joined": "Bergabung {date}", + "account.suspended_disclaimer_full": "Pengguna ini telah ditangguhkan oleh moderator.", + "account.view_full_profile": "Tampilkan profil lengkap", + "advanced_options.icon_title": "Opsi lanjutan", + "advanced_options.local-only.long": "Jangan mengunggah ke instance lain", + "advanced_options.local-only.short": "Hanya lokal", + "advanced_options.local-only.tooltip": "Postingan ini hanya untuk lokal", + "advanced_options.threaded_mode.long": "Secara otomatis membuka balasan pada postingan", + "advanced_options.threaded_mode.short": "Mode Utasan", + "advanced_options.threaded_mode.tooltip": "Mode utasan dinyalakan", + "boost_modal.missing_description": "Toot ini berisi beberapa media tanpa deskripsi", + "column.favourited_by": "Disukai oleh", + "column.heading": "Lainnya", + "column.reblogged_by": "Dibagikan oleh", + "column.subheading": "Opsi lain-lain", + "column_header.profile": "Profil", + "column_subheading.lists": "Daftar", + "column_subheading.navigation": "Penelusuran", + "community.column_settings.allow_local_only": "Tampilkan toot lokal saja", + "compose.attach": "Lampirkan...", + "compose.attach.doodle": "Gambar sesuatu", + "compose.attach.upload": "Unggah file", + "compose.content-type.html": "HTML", + "compose.content-type.markdown": "Bahasa Markdown", + "compose.content-type.plain": "Teks biasa", + "compose_form.poll.multiple_choices": "Izinkan beberapa pilihan", + "compose_form.poll.single_choice": "Izinkan hanya satu pilihan", + "compose_form.spoiler": "Sembunyikan teks di balik peringatan", + "confirmation_modal.do_not_ask_again": "Jangan minta konfirmasi lagi", + "confirmations.deprecated_settings.confirm": "Gunakan preferensi Mastodon", + "confirmations.deprecated_settings.message": "Beberapa {app_settings} khusus perangkat Glitch-soc yang Anda gunakan telah digantikan oleh {preferences} Mastodon dan akan diganti:", + "confirmations.missing_media_description.confirm": "Tetap kirim", + "confirmations.missing_media_description.edit": "Sunting media", + "confirmations.missing_media_description.message": "Setidaknya satu lampiran media tidak memiliki deskripsi. Pertimbangkan untuk mendeskripsikan semua lampiran media untuk pengguna tunanetra sebelum mengirim toot Anda.", + "confirmations.unfilter.author": "Penulis", + "confirmations.unfilter.confirm": "Tampilkan", + "confirmations.unfilter.edit_filter": "Ubah saringan", + "content-type.change": "Jenis konten", + "direct.group_by_conversations": "Grupkan berdasarkan percakapan", + "endorsed_accounts_editor.endorsed_accounts": "Akun pilihan", + "favourite_modal.combo": "Anda dapat menekan {combo} untuk melewati ini lain kali", + "firehose.column_settings.allow_local_only": "Tampilkan postingan khusus lokal di \"Semua\"", + "home.column_settings.advanced": "Lanjutan", + "home.column_settings.filter_regex": "Saring dengan ekspresi reguler", "settings.content_warnings": "Content warnings", "settings.preferences": "Preferences" } diff --git a/app/javascript/flavours/glitch/locales/sv.json b/app/javascript/flavours/glitch/locales/sv.json index d360fed722..3212f7ff88 100644 --- a/app/javascript/flavours/glitch/locales/sv.json +++ b/app/javascript/flavours/glitch/locales/sv.json @@ -1,4 +1,52 @@ { + "account.follows": "Följer", + "account.joined": "Gick med {date}", + "account.suspended_disclaimer_full": "Denna användare har stängts av av en moderator.", + "account.view_full_profile": "Visa full profil", + "advanced_options.icon_title": "Avancerade inställningar", + "advanced_options.local-only.long": "Lägg inte ut på andra instanser", + "advanced_options.local-only.short": "Endast lokalt", + "advanced_options.local-only.tooltip": "Detta inlägg är endast tillgängligt lokalt", + "advanced_options.threaded_mode.long": "Öppnar automatiskt ett svar vid publicering", + "advanced_options.threaded_mode.short": "Tråd-läge", + "advanced_options.threaded_mode.tooltip": "Tråd-läge på", + "boost_modal.missing_description": "Denna toot innehåller viss media utan beskrivning", + "column.favourited_by": "Favoritmarkerad av", + "column.heading": "Övrigt", + "column.reblogged_by": "Boostad av", + "column.subheading": "Övriga val", + "column_header.profile": "Profil", + "column_subheading.lists": "Listor", + "column_subheading.navigation": "Navigering", + "community.column_settings.allow_local_only": "Visa endast lokala toots", + "compose.attach": "Bifoga...", + "compose.attach.doodle": "Rita något", + "compose.attach.upload": "Ladda upp en fil", + "compose.content-type.html": "HTML", + "compose.content-type.markdown": "Markdown", + "compose.content-type.plain": "Klartext", + "compose_form.poll.multiple_choices": "Tillåt flera val", + "compose_form.poll.single_choice": "Tillåt ett val", + "compose_form.spoiler": "Göm text bakom varning", + "confirmation_modal.do_not_ask_again": "Fråga mig inte igen", + "confirmations.deprecated_settings.confirm": "Använd Mastodon-preferenser", + "confirmations.deprecated_settings.message": "Några av de glitch-soc-enhetsspecifika {app_settings} som du använder har ersatts av Mastodon-{preferences} och kommer att åsidosättas:", + "confirmations.missing_media_description.confirm": "Lägg ut ändå", + "confirmations.missing_media_description.edit": "Redigera media", + "confirmations.missing_media_description.message": "Minst en mediebilaga saknar beskrivning. Överväg att beskriva all media för synskadade innan du skickar din toot.", + "confirmations.unfilter.author": "Användare", + "confirmations.unfilter.confirm": "Visa", + "confirmations.unfilter.edit_filter": "Redigera filter", + "confirmations.unfilter.filters": "Matchande {count, plural, one {filter} other {filters}}", + "content-type.change": "Innehållstyp", + "direct.group_by_conversations": "Sortera efter konversation", + "endorsed_accounts_editor.endorsed_accounts": "Utvalda konton", + "favourite_modal.combo": "Du kan trycka på {combo} för att skippa detta nästa gång", + "firehose.column_settings.allow_local_only": "Visa endast lokala inlägg i \"Alla\"", + "home.column_settings.advanced": "Avancerat", + "home.column_settings.filter_regex": "Filtrera bort med reguljära uttryck", + "home.column_settings.show_direct": "Visa privata omnämningar", + "home.settings": "Kolumninställningar", "settings.content_warnings": "Content warnings", "settings.preferences": "Preferences" } diff --git a/app/models/tag_feed.rb b/app/models/tag_feed.rb index fbbdbaae27..051b0d1306 100644 --- a/app/models/tag_feed.rb +++ b/app/models/tag_feed.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class TagFeed < PublicFeed - LIMIT_PER_MODE = 4 + LIMIT_PER_MODE = (ENV['MAX_FEED_HASHTAGS'] || 4).to_i # @param [Tag] tag # @param [Account] account diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index f96246f6eb..315dcb0914 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -5,7 +5,7 @@ class InitialStateSerializer < ActiveModel::Serializer attributes :meta, :compose, :accounts, :media_attachments, :settings, - :max_toot_chars, :poll_limits, + :max_toot_chars, :max_feed_hashtags, :poll_limits, :languages, :max_reactions attribute :critical_updates_pending, if: -> { object&.role&.can?(:view_devops) && SoftwareUpdate.check_enabled? } @@ -21,6 +21,10 @@ class InitialStateSerializer < ActiveModel::Serializer StatusReactionValidator::LIMIT end + def max_feed_hashtags + TagFeed::LIMIT_PER_MODE + end + def poll_limits { max_options: PollValidator::MAX_OPTIONS, @@ -33,8 +37,8 @@ class InitialStateSerializer < ActiveModel::Serializer def meta store = default_meta_store - if object.current_account - store[:me] = object.current_account.id.to_s + if object_account + store[:me] = object_account.id.to_s store[:unfollow_modal] = object_account_user.setting_unfollow_modal store[:boost_modal] = object_account_user.setting_boost_modal store[:favourite_modal] = object_account_user.setting_favourite_modal @@ -134,6 +138,10 @@ class InitialStateSerializer < ActiveModel::Serializer } end + def object_account + object.current_account + end + def object_account_user object.current_account.user end diff --git a/app/views/user_mailer/confirmation_instructions.html.haml b/app/views/user_mailer/confirmation_instructions.html.haml index 74b2d49a47..13e68c722b 100644 --- a/app/views/user_mailer/confirmation_instructions.html.haml +++ b/app/views/user_mailer/confirmation_instructions.html.haml @@ -8,9 +8,7 @@ %td.email-inner-card-td.email-prose %p= t @resource.approved? ? 'devise.mailer.confirmation_instructions.explanation' : 'devise.mailer.confirmation_instructions.explanation_when_pending', host: site_hostname - if @resource.created_by_application - = render 'application/mailer/button', text: t('settings.account_settings'), url: edit_user_registration_url - = link_to confirmation_url(@resource, confirmation_token: @token, redirect_to_app: 'true') do - %span= t 'devise.mailer.confirmation_instructions.action_with_app', app: @resource.created_by_application.name + = render 'application/mailer/button', text: t('devise.mailer.confirmation_instructions.action_with_app', app: @resource.created_by_application.name), url: confirmation_url(@resource, confirmation_token: @token, redirect_to_app: 'true') - else = render 'application/mailer/button', text: t('devise.mailer.confirmation_instructions.action'), url: confirmation_url(@resource, confirmation_token: @token) %p= t 'devise.mailer.confirmation_instructions.extra_html', terms_path: about_more_url, policy_path: privacy_policy_url diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 9a2743ed5b..53b02edc40 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -26,6 +26,7 @@ Sidekiq.configure_server do |config| 'queue' => 'scheduler', }, } + SidekiqScheduler::Scheduler.instance.reload_schedule! end end