Remove text requirement when media attached from statuses (#6672)
This commit is contained in:
parent
e26d5ca923
commit
cfa9b6e13a
|
@ -96,8 +96,9 @@ export function mentionCompose(account, router) {
|
||||||
export function submitCompose() {
|
export function submitCompose() {
|
||||||
return function (dispatch, getState) {
|
return function (dispatch, getState) {
|
||||||
const status = getState().getIn(['compose', 'text'], '');
|
const status = getState().getIn(['compose', 'text'], '');
|
||||||
|
const media = getState().getIn(['compose', 'media_attachments']);
|
||||||
|
|
||||||
if (!status || !status.length) {
|
if ((!status || !status.length) && media.size === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +107,7 @@ export function submitCompose() {
|
||||||
api(getState).post('/api/v1/statuses', {
|
api(getState).post('/api/v1/statuses', {
|
||||||
status,
|
status,
|
||||||
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
|
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
|
||||||
media_ids: getState().getIn(['compose', 'media_attachments']).map(item => item.get('id')),
|
media_ids: media.map(item => item.get('id')),
|
||||||
sensitive: getState().getIn(['compose', 'sensitive']),
|
sensitive: getState().getIn(['compose', 'sensitive']),
|
||||||
spoiler_text: getState().getIn(['compose', 'spoiler_text'], ''),
|
spoiler_text: getState().getIn(['compose', 'spoiler_text'], ''),
|
||||||
visibility: getState().getIn(['compose', 'privacy']),
|
visibility: getState().getIn(['compose', 'privacy']),
|
||||||
|
|
|
@ -24,7 +24,12 @@ export default class StatusContent extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
_updateStatusLinks () {
|
_updateStatusLinks () {
|
||||||
const node = this.node;
|
const node = this.node;
|
||||||
|
|
||||||
|
if (!node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const links = node.querySelectorAll('a');
|
const links = node.querySelectorAll('a');
|
||||||
|
|
||||||
for (var i = 0; i < links.length; ++i) {
|
for (var i = 0; i < links.length; ++i) {
|
||||||
|
@ -115,6 +120,10 @@ export default class StatusContent extends React.PureComponent {
|
||||||
render () {
|
render () {
|
||||||
const { status } = this.props;
|
const { status } = this.props;
|
||||||
|
|
||||||
|
if (status.get('content').length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden;
|
const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden;
|
||||||
|
|
||||||
const content = { __html: status.get('contentHtml') };
|
const content = { __html: status.get('contentHtml') };
|
||||||
|
|
|
@ -50,6 +50,7 @@ export default class ComposeForm extends ImmutablePureComponent {
|
||||||
onPaste: PropTypes.func.isRequired,
|
onPaste: PropTypes.func.isRequired,
|
||||||
onPickEmoji: PropTypes.func.isRequired,
|
onPickEmoji: PropTypes.func.isRequired,
|
||||||
showSearch: PropTypes.bool,
|
showSearch: PropTypes.bool,
|
||||||
|
anyMedia: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -142,10 +143,10 @@ export default class ComposeForm extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, onPaste, showSearch } = this.props;
|
const { intl, onPaste, showSearch, anyMedia } = this.props;
|
||||||
const disabled = this.props.is_submitting;
|
const disabled = this.props.is_submitting;
|
||||||
const text = [this.props.spoiler_text, countableText(this.props.text)].join('');
|
const text = [this.props.spoiler_text, countableText(this.props.text)].join('');
|
||||||
|
const disabledButton = disabled || this.props.is_uploading || length(text) > 500 || (text.length !== 0 && text.trim().length === 0 && !anyMedia);
|
||||||
let publishText = '';
|
let publishText = '';
|
||||||
|
|
||||||
if (this.props.privacy === 'private' || this.props.privacy === 'direct') {
|
if (this.props.privacy === 'private' || this.props.privacy === 'direct') {
|
||||||
|
@ -203,7 +204,7 @@ export default class ComposeForm extends ImmutablePureComponent {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='compose-form__publish'>
|
<div className='compose-form__publish'>
|
||||||
<div className='compose-form__publish-button-wrapper'><Button text={publishText} onClick={this.handleSubmit} disabled={disabled || this.props.is_uploading || length(text) > 500 || (text.length !== 0 && text.trim().length === 0)} block /></div>
|
<div className='compose-form__publish-button-wrapper'><Button text={publishText} onClick={this.handleSubmit} disabled={disabledButton} block /></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -23,6 +23,7 @@ const mapStateToProps = state => ({
|
||||||
is_submitting: state.getIn(['compose', 'is_submitting']),
|
is_submitting: state.getIn(['compose', 'is_submitting']),
|
||||||
is_uploading: state.getIn(['compose', 'is_uploading']),
|
is_uploading: state.getIn(['compose', 'is_uploading']),
|
||||||
showSearch: state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']),
|
showSearch: state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']),
|
||||||
|
anyMedia: state.getIn(['compose', 'media_attachments']).size > 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
|
|
@ -90,7 +90,6 @@ function appendMedia(state, media) {
|
||||||
map.update('media_attachments', list => list.push(media));
|
map.update('media_attachments', list => list.push(media));
|
||||||
map.set('is_uploading', false);
|
map.set('is_uploading', false);
|
||||||
map.set('resetFileKey', Math.floor((Math.random() * 0x10000)));
|
map.set('resetFileKey', Math.floor((Math.random() * 0x10000)));
|
||||||
map.update('text', oldText => `${oldText.trim()} ${media.get('text_url')}`);
|
|
||||||
map.set('focusDate', new Date());
|
map.set('focusDate', new Date());
|
||||||
map.set('idempotencyKey', uuid());
|
map.set('idempotencyKey', uuid());
|
||||||
|
|
||||||
|
@ -101,12 +100,10 @@ function appendMedia(state, media) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function removeMedia(state, mediaId) {
|
function removeMedia(state, mediaId) {
|
||||||
const media = state.get('media_attachments').find(item => item.get('id') === mediaId);
|
|
||||||
const prevSize = state.get('media_attachments').size;
|
const prevSize = state.get('media_attachments').size;
|
||||||
|
|
||||||
return state.withMutations(map => {
|
return state.withMutations(map => {
|
||||||
map.update('media_attachments', list => list.filterNot(item => item.get('id') === mediaId));
|
map.update('media_attachments', list => list.filterNot(item => item.get('id') === mediaId));
|
||||||
map.update('text', text => text.replace(media.get('text_url'), '').trim());
|
|
||||||
map.set('idempotencyKey', uuid());
|
map.set('idempotencyKey', uuid());
|
||||||
|
|
||||||
if (prevSize === 1) {
|
if (prevSize === 1) {
|
||||||
|
|
|
@ -19,6 +19,8 @@ class Formatter
|
||||||
|
|
||||||
raw_content = status.text
|
raw_content = status.text
|
||||||
|
|
||||||
|
return '' if raw_content.blank?
|
||||||
|
|
||||||
unless status.local?
|
unless status.local?
|
||||||
html = reformat(raw_content)
|
html = reformat(raw_content)
|
||||||
html = encode_custom_emojis(html, status.emojis) if options[:custom_emojify]
|
html = encode_custom_emojis(html, status.emojis) if options[:custom_emojify]
|
||||||
|
|
|
@ -57,7 +57,7 @@ class Status < ApplicationRecord
|
||||||
has_one :stream_entry, as: :activity, inverse_of: :status
|
has_one :stream_entry, as: :activity, inverse_of: :status
|
||||||
|
|
||||||
validates :uri, uniqueness: true, presence: true, unless: :local?
|
validates :uri, uniqueness: true, presence: true, unless: :local?
|
||||||
validates :text, presence: true, unless: :reblog?
|
validates :text, presence: true, unless: -> { with_media? || reblog? }
|
||||||
validates_with StatusLengthValidator
|
validates_with StatusLengthValidator
|
||||||
validates :reblog, uniqueness: { scope: :account }, if: :reblog?
|
validates :reblog, uniqueness: { scope: :account }, if: :reblog?
|
||||||
|
|
||||||
|
@ -150,8 +150,12 @@ class Status < ApplicationRecord
|
||||||
private_visibility? || direct_visibility?
|
private_visibility? || direct_visibility?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def with_media?
|
||||||
|
media_attachments.any?
|
||||||
|
end
|
||||||
|
|
||||||
def non_sensitive_with_media?
|
def non_sensitive_with_media?
|
||||||
!sensitive? && media_attachments.any?
|
!sensitive? && with_media?
|
||||||
end
|
end
|
||||||
|
|
||||||
def emojis
|
def emojis
|
||||||
|
|
|
@ -21,17 +21,17 @@ class PostStatusService < BaseService
|
||||||
|
|
||||||
media = validate_media!(options[:media_ids])
|
media = validate_media!(options[:media_ids])
|
||||||
status = nil
|
status = nil
|
||||||
|
text = options.delete(:spoiler_text) if text.blank? && options[:spoiler_text].present?
|
||||||
|
|
||||||
ApplicationRecord.transaction do
|
ApplicationRecord.transaction do
|
||||||
status = account.statuses.create!(text: text,
|
status = account.statuses.create!(text: text,
|
||||||
|
media_attachments: media || [],
|
||||||
thread: in_reply_to,
|
thread: in_reply_to,
|
||||||
sensitive: options[:sensitive],
|
sensitive: options[:sensitive],
|
||||||
spoiler_text: options[:spoiler_text] || '',
|
spoiler_text: options[:spoiler_text] || '',
|
||||||
visibility: options[:visibility] || account.user&.setting_default_privacy,
|
visibility: options[:visibility] || account.user&.setting_default_privacy,
|
||||||
language: LanguageDetector.instance.detect(text, account),
|
language: LanguageDetector.instance.detect(text, account),
|
||||||
application: options[:application])
|
application: options[:application])
|
||||||
|
|
||||||
attach_media(status, media)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
process_mentions_service.call(status)
|
process_mentions_service.call(status)
|
||||||
|
@ -64,11 +64,6 @@ class PostStatusService < BaseService
|
||||||
media
|
media
|
||||||
end
|
end
|
||||||
|
|
||||||
def attach_media(status, media)
|
|
||||||
return if media.nil?
|
|
||||||
media.update(status_id: status.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def process_mentions_service
|
def process_mentions_service
|
||||||
ProcessMentionsService.new
|
ProcessMentionsService.new
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue