diff --git a/.env.production.sample b/.env.production.sample index 7bcce0f7e..5939c1214 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/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.jsx b/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.jsx index c60de4c51..4488c5b2a 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 fabe0a72e..a281dbaf3 100644 --- a/app/javascript/flavours/glitch/initial_state.js +++ b/app/javascript/flavours/glitch/initial_state.js @@ -67,6 +67,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 */ @@ -130,6 +131,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/models/tag_feed.rb b/app/models/tag_feed.rb index fbbdbaae2..051b0d130 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 ee79c3819..4135d8ed3 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 attribute :critical_updates_pending, if: -> { object&.role&.can?(:view_devops) && SoftwareUpdate.check_enabled? } @@ -17,6 +17,10 @@ class InitialStateSerializer < ActiveModel::Serializer StatusLengthValidator::MAX_CHARS end + def max_feed_hashtags + TagFeed::LIMIT_PER_MODE + end + def poll_limits { max_options: PollValidator::MAX_OPTIONS,