Merge branch 'scalybiz-3.3' into HEAD
This commit is contained in:
commit
8a8a6b559b
|
@ -86,7 +86,7 @@ class ComposeForm extends ImmutablePureComponent {
|
|||
const fulltext = this.getFulltextForCharacterCounting();
|
||||
const isOnlyWhitespace = fulltext.length !== 0 && fulltext.trim().length === 0;
|
||||
|
||||
return !(isSubmitting || isUploading || isChangingUpload || length(fulltext) > 500 || (isOnlyWhitespace && !anyMedia));
|
||||
return !(isSubmitting || isUploading || isChangingUpload || length(fulltext) > 4096 || (isOnlyWhitespace && !anyMedia));
|
||||
}
|
||||
|
||||
handleSubmit = () => {
|
||||
|
@ -196,6 +196,11 @@ class ComposeForm extends ImmutablePureComponent {
|
|||
render () {
|
||||
const { intl, onPaste, showSearch } = this.props;
|
||||
const disabled = this.props.isSubmitting;
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
const text = [this.props.spoilerText, countableText(this.props.text)].join('');
|
||||
const disabledButton = disabled || this.props.isUploading || this.props.isChangingUpload || length(text) > 4096 || (text.length !== 0 && text.trim().length === 0 && !anyMedia);
|
||||
>>>>>>> scalybiz-3.2rc
|
||||
let publishText = '';
|
||||
|
||||
if (this.props.privacy === 'private' || this.props.privacy === 'direct') {
|
||||
|
@ -257,7 +262,7 @@ class ComposeForm extends ImmutablePureComponent {
|
|||
<PrivacyDropdownContainer />
|
||||
<SpoilerButtonContainer />
|
||||
</div>
|
||||
<div className='character-counter__wrapper'><CharacterCounter max={500} text={this.getFulltextForCharacterCounting()} /></div>
|
||||
<div className='character-counter__wrapper'><CharacterCounter max={4096} text={this.getFulltextForCharacterCounting()} /></div>
|
||||
</div>
|
||||
|
||||
<div className='compose-form__publish'>
|
||||
|
|
|
@ -102,7 +102,7 @@ class Option extends React.PureComponent {
|
|||
</label>
|
||||
|
||||
<div className='poll__cancel'>
|
||||
<IconButton disabled={index <= 1} title={intl.formatMessage(messages.remove_option)} icon='times' onClick={this.handleOptionRemove} />
|
||||
<IconButton disabled={index < 1} title={intl.formatMessage(messages.remove_option)} icon='times' onClick={this.handleOptionRemove} />
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
|
@ -157,7 +157,7 @@ class PollForm extends ImmutablePureComponent {
|
|||
</ul>
|
||||
|
||||
<div className='poll__footer'>
|
||||
<button disabled={options.size >= 4} className='button button-secondary' onClick={this.handleAddOption}><Icon id='plus' /> <FormattedMessage {...messages.add_option} /></button>
|
||||
<button disabled={options.size >= 12} className='button button-secondary' onClick={this.handleAddOption}><Icon id='plus' /> <FormattedMessage {...messages.add_option} /></button>
|
||||
|
||||
{/* eslint-disable-next-line jsx-a11y/no-onchange */}
|
||||
<select value={expiresIn} onChange={this.handleSelectDuration}>
|
||||
|
|
|
@ -132,7 +132,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
|||
# If there is at least one silent mention, then the status can be considered
|
||||
# as a limited-audience status, and not strictly a direct message, but only
|
||||
# if we considered a direct message in the first place
|
||||
next unless @params[:visibility] == :direct
|
||||
next unless @params[:visibility] == :direct && direct_message.nil?
|
||||
|
||||
@params[:visibility] = :limited
|
||||
end
|
||||
|
@ -143,7 +143,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
|||
|
||||
@mentions << Mention.new(account_id: @options[:delivered_to_account_id], silent: true)
|
||||
|
||||
return unless @params[:visibility] == :direct
|
||||
return unless @params[:visibility] == :direct && direct_message.nil?
|
||||
|
||||
@params[:visibility] = :limited
|
||||
end
|
||||
|
@ -154,7 +154,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
|||
delivered_to_account = Account.find(@options[:delivered_to_account_id])
|
||||
|
||||
@status.mentions.create(account: delivered_to_account, silent: true)
|
||||
@status.update(visibility: :limited) if @status.direct_visibility?
|
||||
@status.update(visibility: :limited) if @status.direct_visibility? && direct_message.nil?
|
||||
|
||||
return unless delivered_to_account.following?(@account)
|
||||
|
||||
|
@ -353,6 +353,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
|||
:unlisted
|
||||
elsif audience_to.include?(@account.followers_url)
|
||||
:private
|
||||
elsif direct_message == false
|
||||
:limited
|
||||
else
|
||||
:direct
|
||||
end
|
||||
|
@ -363,6 +365,10 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
|||
audience_to.include?(uri) || audience_cc.include?(uri)
|
||||
end
|
||||
|
||||
def direct_message
|
||||
@object['directMessage']
|
||||
end
|
||||
|
||||
def replied_to_status
|
||||
return @replied_to_status if defined?(@replied_to_status)
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
|
|||
}.freeze
|
||||
|
||||
CONTEXT_EXTENSION_MAP = {
|
||||
direct_message: { 'litepub': 'http://litepub.social/ns#', 'directMessage': 'litepub:directMessage' },
|
||||
manually_approves_followers: { 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers' },
|
||||
sensitive: { 'sensitive' => 'as:sensitive' },
|
||||
hashtag: { 'Hashtag' => 'as:Hashtag' },
|
||||
|
|
|
@ -88,9 +88,9 @@ class Account < ApplicationRecord
|
|||
validates :username, format: { with: /\A#{USERNAME_RE}\z/i }, if: -> { !local? && will_save_change_to_username? }
|
||||
|
||||
# Local user validations
|
||||
validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? && actor_type != 'Application' }
|
||||
validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: 100 }, if: -> { local? && will_save_change_to_username? && actor_type != 'Application' }
|
||||
validates_with UnreservedUsernameValidator, if: -> { local? && will_save_change_to_username? }
|
||||
validates :display_name, length: { maximum: 30 }, if: -> { local? && will_save_change_to_display_name? }
|
||||
validates :display_name, length: { maximum: 100 }, if: -> { local? && will_save_change_to_display_name? }
|
||||
validates :note, note_length: { maximum: 500 }, if: -> { local? && will_save_change_to_note? }
|
||||
validates :fields, length: { maximum: 4 }, if: -> { local? && will_save_change_to_fields? }
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::NoteSerializer < ActivityPub::Serializer
|
||||
context_extensions :atom_uri, :conversation, :sensitive, :voters_count
|
||||
context_extensions :atom_uri, :conversation, :sensitive, :voters_count, :direct_message
|
||||
|
||||
attributes :id, :type, :summary,
|
||||
:in_reply_to, :published, :url,
|
||||
|
@ -12,6 +12,8 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
|
|||
attribute :content
|
||||
attribute :content_map, if: :language?
|
||||
|
||||
attribute :direct_message, if: :non_public?
|
||||
|
||||
has_many :media_attachments, key: :attachment
|
||||
has_many :virtual_tags, key: :tag
|
||||
|
||||
|
@ -37,6 +39,14 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
|
|||
object.spoiler_text.presence
|
||||
end
|
||||
|
||||
def direct_message
|
||||
object.direct_visibility?
|
||||
end
|
||||
|
||||
def non_public?
|
||||
!object.distributable?
|
||||
end
|
||||
|
||||
def content
|
||||
Formatter.instance.format(object)
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class PollValidator < ActiveModel::Validator
|
||||
MAX_OPTIONS = 4
|
||||
MAX_OPTIONS = 20
|
||||
MAX_OPTION_CHARS = 50
|
||||
MAX_EXPIRATION = 1.month.freeze
|
||||
MIN_EXPIRATION = 5.minutes.freeze
|
||||
|
@ -9,7 +9,6 @@ class PollValidator < ActiveModel::Validator
|
|||
def validate(poll)
|
||||
current_time = Time.now.utc
|
||||
|
||||
poll.errors.add(:options, I18n.t('polls.errors.too_few_options')) unless poll.options.size > 1
|
||||
poll.errors.add(:options, I18n.t('polls.errors.too_many_options', max: MAX_OPTIONS)) if poll.options.size > MAX_OPTIONS
|
||||
poll.errors.add(:options, I18n.t('polls.errors.over_character_limit', max: MAX_OPTION_CHARS)) if poll.options.any? { |option| option.mb_chars.grapheme_length > MAX_OPTION_CHARS }
|
||||
poll.errors.add(:options, I18n.t('polls.errors.duplicate_options')) unless poll.options.uniq.size == poll.options.size
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class StatusLengthValidator < ActiveModel::Validator
|
||||
MAX_CHARS = 500
|
||||
MAX_CHARS = 4096
|
||||
URL_PLACEHOLDER = "\1#{'x' * 23}"
|
||||
|
||||
def validate(status)
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
.fields-row
|
||||
.fields-row__column.fields-group.fields-row__column-6
|
||||
= f.input :display_name, wrapper: :with_label, input_html: { maxlength: 30, data: { default: @account.username } }, hint: false
|
||||
= f.input :display_name, wrapper: :with_label, input_html: { maxlength: 100, data: { default: @account.username } }, hint: false
|
||||
= f.input :note, wrapper: :with_label, input_html: { maxlength: 500 }, hint: false
|
||||
|
||||
.fields-row
|
||||
|
|
|
@ -240,6 +240,31 @@ RSpec.describe ActivityPub::Activity::Create do
|
|||
end
|
||||
end
|
||||
|
||||
context 'limited when direct message assertion is false' do
|
||||
let(:recipient) { Fabricate(:account) }
|
||||
|
||||
let(:object_json) do
|
||||
{
|
||||
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
|
||||
type: 'Note',
|
||||
content: 'Lorem ipsum',
|
||||
directMessage: false,
|
||||
to: ActivityPub::TagManager.instance.uri_for(recipient),
|
||||
tag: {
|
||||
type: 'Mention',
|
||||
href: ActivityPub::TagManager.instance.uri_for(recipient),
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates status' do
|
||||
status = sender.statuses.first
|
||||
|
||||
expect(status).to_not be_nil
|
||||
expect(status.visibility).to eq 'limited'
|
||||
end
|
||||
end
|
||||
|
||||
context 'direct' do
|
||||
let(:recipient) { Fabricate(:account) }
|
||||
|
||||
|
@ -264,6 +289,27 @@ RSpec.describe ActivityPub::Activity::Create do
|
|||
end
|
||||
end
|
||||
|
||||
context 'direct when direct message assertion is true' do
|
||||
let(:recipient) { Fabricate(:account) }
|
||||
|
||||
let(:object_json) do
|
||||
{
|
||||
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
|
||||
type: 'Note',
|
||||
content: 'Lorem ipsum',
|
||||
to: ActivityPub::TagManager.instance.uri_for(recipient),
|
||||
directMessage: true,
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates status' do
|
||||
status = sender.statuses.first
|
||||
|
||||
expect(status).to_not be_nil
|
||||
expect(status.visibility).to eq 'direct'
|
||||
end
|
||||
end
|
||||
|
||||
context 'as a reply' do
|
||||
let(:original_status) { Fabricate(:status) }
|
||||
|
||||
|
|
Loading…
Reference in New Issue