From e7f54209c2c9872dc5a296ed509a87815457851e Mon Sep 17 00:00:00 2001 From: wuyingren Date: Fri, 1 May 2020 00:33:13 +0800 Subject: [PATCH] Make character limit configurable https://github.com/tootsuite/mastodon/pull/5697/ --- .env.production.sample | 3 +++ .../mastodon/features/compose/components/compose_form.js | 8 +++++--- app/serializers/initial_state_serializer.rb | 7 ++++++- app/serializers/rest/instance_serializer.rb | 7 ++++++- app/validators/status_length_validator.rb | 2 +- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/.env.production.sample b/.env.production.sample index 8a6888621..096e8fb87 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -260,3 +260,6 @@ STREAMING_CLUSTER_NUM=1 # Only allow federation with whitelisted domains, see # https://docs.joinmastodon.org/admin/config/#whitelist_mode # WHITELIST_MODE=true + +# Maximum allowed character count +# MAX_TOOT_CHARS=500 \ No newline at end of file diff --git a/app/javascript/mastodon/features/compose/components/compose_form.js b/app/javascript/mastodon/features/compose/components/compose_form.js index 0b7731940..2bee5666b 100644 --- a/app/javascript/mastodon/features/compose/components/compose_form.js +++ b/app/javascript/mastodon/features/compose/components/compose_form.js @@ -20,7 +20,9 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { length } from 'stringz'; import { countableText } from '../util/counter'; import Icon from 'mastodon/components/icon'; +import initialState from '../../../initial_state'; +const maxChars = initialState.max_toot_chars; const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d'; const messages = defineMessages({ @@ -88,7 +90,7 @@ class ComposeForm extends ImmutablePureComponent { const { isSubmitting, isChangingUpload, isUploading, anyMedia } = this.props; const fulltext = [this.props.spoilerText, countableText(this.props.text)].join(''); - if (isSubmitting || isUploading || isChangingUpload || length(fulltext) > 10000 || (fulltext.length !== 0 && fulltext.trim().length === 0 && !anyMedia)) { + if (isSubmitting || isUploading || isChangingUpload || length(fulltext) > maxChars || (fulltext.length !== 0 && fulltext.trim().length === 0 && !anyMedia)) { return; } @@ -181,7 +183,7 @@ class ComposeForm extends ImmutablePureComponent { const { intl, onPaste, showSearch, anyMedia } = this.props; const disabled = this.props.isSubmitting; const text = [this.props.spoilerText, countableText(this.props.text)].join(''); - const disabledButton = disabled || this.props.isUploading || this.props.isChangingUpload || length(text) > 10000 || (text.length !== 0 && text.trim().length === 0 && !anyMedia); + const disabledButton = disabled || this.props.isUploading || this.props.isChangingUpload || length(text) > maxChars || (text.length !== 0 && text.trim().length === 0 && !anyMedia); let publishText = ''; if (this.props.privacy === 'private' || this.props.privacy === 'direct') { @@ -243,7 +245,7 @@ class ComposeForm extends ImmutablePureComponent { -
+
diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 392fc891a..a37f38885 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -2,10 +2,15 @@ class InitialStateSerializer < ActiveModel::Serializer attributes :meta, :compose, :accounts, - :media_attachments, :settings + :media_attachments, :settings, + :max_toot_chars has_one :push_subscription, serializer: REST::WebPushSubscriptionSerializer + def max_toot_chars + StatusLengthValidator::MAX_CHARS + end + def meta store = { streaming_api_base_url: Rails.configuration.x.streaming_api_base_url, diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb index 1bd71683c..b97a0df3c 100644 --- a/app/serializers/rest/instance_serializer.rb +++ b/app/serializers/rest/instance_serializer.rb @@ -5,12 +5,17 @@ class REST::InstanceSerializer < ActiveModel::Serializer attributes :uri, :title, :short_description, :description, :email, :version, :urls, :stats, :thumbnail, - :languages, :registrations, :approval_required + :languages, :registrations, :approval_required, + :max_toot_chars has_one :contact_account, serializer: REST::AccountSerializer delegate :contact_account, to: :instance_presenter + def max_toot_chars + StatusLengthValidator::MAX_CHARS + end + def uri Rails.configuration.x.local_domain end diff --git a/app/validators/status_length_validator.rb b/app/validators/status_length_validator.rb index ba34c68a9..92ee5e643 100644 --- a/app/validators/status_length_validator.rb +++ b/app/validators/status_length_validator.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class StatusLengthValidator < ActiveModel::Validator - MAX_CHARS = 10000 + MAX_CHARS = (ENV['MAX_TOOT_CHARS'] || 500).to_i def validate(status) return unless status.local? && !status.reblog?