parent
cbfeb105a8
commit
73706b289e
@ -0,0 +1,86 @@
|
|||||||
|
// Package imports.
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
|
// Components.
|
||||||
|
import AccountContainer from 'flavours/glitch/containers/account_container';
|
||||||
|
import Icon from 'flavours/glitch/components/icon';
|
||||||
|
import IconButton from 'flavours/glitch/components/icon_button';
|
||||||
|
import AttachmentList from 'flavours/glitch/components/attachment_list';
|
||||||
|
|
||||||
|
// Messages.
|
||||||
|
const messages = defineMessages({
|
||||||
|
cancel: {
|
||||||
|
defaultMessage: 'Cancel',
|
||||||
|
id: 'quote_indicator.cancel',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
export default @injectIntl
|
||||||
|
class QuoteIndicator extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
status: ImmutablePropTypes.map,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
onCancel: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleClick = () => {
|
||||||
|
const { onCancel } = this.props;
|
||||||
|
if (onCancel) {
|
||||||
|
onCancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rendering.
|
||||||
|
render () {
|
||||||
|
const { status, intl } = this.props;
|
||||||
|
|
||||||
|
if (!status) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const account = status.get('account');
|
||||||
|
const content = status.get('content');
|
||||||
|
const attachments = status.get('media_attachments');
|
||||||
|
|
||||||
|
// The result.
|
||||||
|
return (
|
||||||
|
<article className='quote-indicator'>
|
||||||
|
<header className='quote-indicator__header'>
|
||||||
|
<IconButton
|
||||||
|
className='quote-indicator__cancel'
|
||||||
|
icon='times'
|
||||||
|
onClick={this.handleClick}
|
||||||
|
title={intl.formatMessage(messages.cancel)}
|
||||||
|
inverted
|
||||||
|
/>
|
||||||
|
<Icon
|
||||||
|
className='quote-indicator__cancel icon-button inverted'
|
||||||
|
id='quote-right' />
|
||||||
|
{account && (
|
||||||
|
<AccountContainer
|
||||||
|
id={account}
|
||||||
|
small
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</header>
|
||||||
|
<div
|
||||||
|
className='quote-indicator__content icon-button translate'
|
||||||
|
dangerouslySetInnerHTML={{ __html: content || '' }}
|
||||||
|
/>
|
||||||
|
{attachments.size > 0 && (
|
||||||
|
<AttachmentList
|
||||||
|
compact
|
||||||
|
media={attachments}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</article>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { cancelQuoteCompose } from 'flavours/glitch/actions/compose';
|
||||||
|
import QuoteIndicator from '../components/quote_indicator';
|
||||||
|
|
||||||
|
const makeMapStateToProps = () => {
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
const statusId = state.getIn(['compose', 'quote_id']);
|
||||||
|
const editing = false;
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: state.getIn(['statuses', statusId]),
|
||||||
|
editing,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return mapStateToProps;
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
|
||||||
|
onCancel () {
|
||||||
|
dispatch(cancelQuoteCompose());
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(makeMapStateToProps, mapDispatchToProps)(QuoteIndicator);
|
@ -0,0 +1,35 @@
|
|||||||
|
.status.quote-status{ dataurl: ActivityPub::TagManager.instance.url_for(status) }
|
||||||
|
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'status__display-name u-url', target: stream_link_target, rel: 'noopener' do
|
||||||
|
.status__avatar
|
||||||
|
%div
|
||||||
|
= image_tag status.account.avatar_static_url, width: 18, height: 18, alt: '', class: 'u-photo account__avatar'
|
||||||
|
%span.display-name
|
||||||
|
%bdi
|
||||||
|
%strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true)
|
||||||
|
|
||||||
|
%span.display-name__account
|
||||||
|
= acct(status.account)
|
||||||
|
= fa_icon('lock') if status.account.locked?
|
||||||
|
|
||||||
|
.status__content.emojify<
|
||||||
|
- if status.spoiler_text?
|
||||||
|
%p{ :style => ('margin-bottom: 0' unless current_account&.user&.setting_expand_spoilers) }<
|
||||||
|
%span.p-summary> #{Formatter.instance.format_spoiler(status)}
|
||||||
|
%button.status__content__spoiler-link= t('statuses.show_more')
|
||||||
|
.e-content{ lang: status.language, style: "display: #{!current_account&.user&.setting_expand_spoilers && status.spoiler_text? ? 'none' : 'block'}" }
|
||||||
|
= Formatter.instance.format_in_quote(status, custom_emojify: true)
|
||||||
|
|
||||||
|
- if !status.media_attachments.empty?
|
||||||
|
- if status.media_attachments.first.video?
|
||||||
|
- video = status.media_attachments.first
|
||||||
|
= react_component :video, src: video.file.url(:original), preview: video.file.url(:small), blurhash: video.blurhash, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, width: 610, height: 343, inline: true, alt: video.description, quote: true do
|
||||||
|
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
||||||
|
- elsif status.media_attachments.first.audio?
|
||||||
|
- audio = status.media_attachments.first
|
||||||
|
= react_component :audio, src: audio.file.url(:original), height: 60, alt: audio.description, duration: audio.file.meta.dig(:original, :duration) do
|
||||||
|
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
||||||
|
- else
|
||||||
|
= react_component :media_gallery, height: 343, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }, quote: true do
|
||||||
|
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
||||||
|
- elsif status.preview_card
|
||||||
|
= react_component :card, maxDescription: 10, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json, quote: true
|
@ -0,0 +1,5 @@
|
|||||||
|
class AddQuoteIdToStatuses < ActiveRecord::Migration[6.1]
|
||||||
|
def change
|
||||||
|
add_column :statuses, :quote_id, :bigint, null: true, default: nil
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,7 @@
|
|||||||
|
class AddIndexToStatusesQuoteId < ActiveRecord::Migration[6.1]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def change
|
||||||
|
add_index :statuses, :quote_id, algorithm: :concurrently
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in new issue