Merge pull request #132 from Y-zu-don-maintenance-org/features/quote
Features/quote
This commit is contained in:
commit
c4712ed22c
@ -8,9 +8,9 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
|
|||||||
|
|
||||||
def index
|
def index
|
||||||
cache_if_unauthenticated!
|
cache_if_unauthenticated!
|
||||||
@statuses = load_statuses
|
@statuses = load_statuses
|
||||||
|
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||||
accounts = Account.where(id: account_ids)
|
|
||||||
render json: @statuses, each_serializer: REST::StatusSerializer,
|
render json: @statuses, each_serializer: REST::StatusSerializer,
|
||||||
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
||||||
account_relationships: AccountRelationshipsPresenter.new(accounts, current_user&.account_id)
|
account_relationships: AccountRelationshipsPresenter.new(accounts, current_user&.account_id)
|
||||||
|
@ -6,9 +6,9 @@ class Api::V1::BookmarksController < Api::BaseController
|
|||||||
after_action :insert_pagination_headers
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@statuses = load_statuses
|
@statuses = load_statuses
|
||||||
|
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||||
accounts = Account.where(id: account_ids)
|
|
||||||
render json: @statuses, each_serializer: REST::StatusSerializer,
|
render json: @statuses, each_serializer: REST::StatusSerializer,
|
||||||
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
||||||
account_relationships: AccountRelationshipsPresenter.new(accounts, current_user&.account_id)
|
account_relationships: AccountRelationshipsPresenter.new(accounts, current_user&.account_id)
|
||||||
|
@ -6,9 +6,9 @@ class Api::V1::FavouritesController < Api::BaseController
|
|||||||
after_action :insert_pagination_headers
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@statuses = load_statuses
|
@statuses = load_statuses
|
||||||
|
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||||
accounts = Account.where(id: account_ids)
|
|
||||||
render json: @statuses, each_serializer: REST::StatusSerializer,
|
render json: @statuses, each_serializer: REST::StatusSerializer,
|
||||||
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
||||||
account_relationships: AccountRelationshipsPresenter.new(accounts, current_user&.account_id)
|
account_relationships: AccountRelationshipsPresenter.new(accounts, current_user&.account_id)
|
||||||
|
@ -47,10 +47,10 @@ class Api::V1::StatusesController < Api::BaseController
|
|||||||
loaded_ancestors = cache_collection(ancestors_results, Status)
|
loaded_ancestors = cache_collection(ancestors_results, Status)
|
||||||
loaded_descendants = cache_collection(descendants_results, Status)
|
loaded_descendants = cache_collection(descendants_results, Status)
|
||||||
|
|
||||||
@context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
|
@context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
|
||||||
statuses = [@status] + @context.ancestors + @context.descendants
|
statuses = [@status] + @context.ancestors + @context.descendants
|
||||||
|
accounts = statuses.filter_map { |status| status.quote&.account }.uniq
|
||||||
account_ids = statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
account_ids = statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||||
accounts = Account.where(id: account_ids)
|
|
||||||
|
|
||||||
render json: @context, serializer: REST::ContextSerializer,
|
render json: @context, serializer: REST::ContextSerializer,
|
||||||
relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id),
|
relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id),
|
||||||
|
@ -10,8 +10,8 @@ class Api::V1::Timelines::HomeController < Api::V1::Timelines::BaseController
|
|||||||
with_read_replica do
|
with_read_replica do
|
||||||
@statuses = load_statuses
|
@statuses = load_statuses
|
||||||
@relationships = StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
@relationships = StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||||
|
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||||
accounts = Account.where(id: account_ids)
|
|
||||||
|
|
||||||
@account_relationships = AccountRelationshipsPresenter.new(accounts, current_user&.account_id)
|
@account_relationships = AccountRelationshipsPresenter.new(accounts, current_user&.account_id)
|
||||||
end
|
end
|
||||||
|
@ -9,8 +9,8 @@ class Api::V1::Timelines::ListController < Api::V1::Timelines::BaseController
|
|||||||
PERMITTED_PARAMS = %i(limit).freeze
|
PERMITTED_PARAMS = %i(limit).freeze
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||||
accounts = Account.where(id: account_ids)
|
|
||||||
|
|
||||||
render json: @statuses,
|
render json: @statuses,
|
||||||
each_serializer: REST::StatusSerializer,
|
each_serializer: REST::StatusSerializer,
|
||||||
|
@ -7,9 +7,9 @@ class Api::V1::Timelines::PublicController < Api::V1::Timelines::BaseController
|
|||||||
|
|
||||||
def show
|
def show
|
||||||
cache_if_unauthenticated!
|
cache_if_unauthenticated!
|
||||||
@statuses = load_statuses
|
@statuses = load_statuses
|
||||||
|
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||||
accounts = Account.where(id: account_ids)
|
|
||||||
|
|
||||||
render json: @statuses, each_serializer: REST::StatusSerializer,
|
render json: @statuses, each_serializer: REST::StatusSerializer,
|
||||||
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
||||||
|
@ -8,9 +8,9 @@ class Api::V1::Timelines::TagController < Api::V1::Timelines::BaseController
|
|||||||
|
|
||||||
def show
|
def show
|
||||||
cache_if_unauthenticated!
|
cache_if_unauthenticated!
|
||||||
@statuses = load_statuses
|
@statuses = load_statuses
|
||||||
|
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||||
accounts = Account.where(id: account_ids)
|
|
||||||
|
|
||||||
render json: @statuses, each_serializer: REST::StatusSerializer,
|
render json: @statuses, each_serializer: REST::StatusSerializer,
|
||||||
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
||||||
|
@ -25,7 +25,6 @@ export const COMPOSE_SUBMIT_FAIL = 'COMPOSE_SUBMIT_FAIL';
|
|||||||
export const COMPOSE_REPLY = 'COMPOSE_REPLY';
|
export const COMPOSE_REPLY = 'COMPOSE_REPLY';
|
||||||
export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL';
|
export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL';
|
||||||
export const COMPOSE_QUOTE = 'COMPOSE_QUOTE';
|
export const COMPOSE_QUOTE = 'COMPOSE_QUOTE';
|
||||||
export const COMPOSE_QUOTE_CANCEL = 'COMPOSE_QUOTE_CANCEL';
|
|
||||||
export const COMPOSE_DIRECT = 'COMPOSE_DIRECT';
|
export const COMPOSE_DIRECT = 'COMPOSE_DIRECT';
|
||||||
export const COMPOSE_MENTION = 'COMPOSE_MENTION';
|
export const COMPOSE_MENTION = 'COMPOSE_MENTION';
|
||||||
export const COMPOSE_RESET = 'COMPOSE_RESET';
|
export const COMPOSE_RESET = 'COMPOSE_RESET';
|
||||||
@ -137,13 +136,7 @@ export function quoteCompose(status, routerHistory) {
|
|||||||
|
|
||||||
ensureComposeIsVisible(getState, routerHistory);
|
ensureComposeIsVisible(getState, routerHistory);
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
export function cancelQuoteCompose() {
|
|
||||||
return {
|
|
||||||
type: COMPOSE_QUOTE_CANCEL,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function resetCompose() {
|
export function resetCompose() {
|
||||||
return {
|
return {
|
||||||
|
@ -361,7 +361,7 @@ export function hideQuote(ids) {
|
|||||||
type: QUOTE_HIDE,
|
type: QUOTE_HIDE,
|
||||||
ids,
|
ids,
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
export function revealQuote(ids) {
|
export function revealQuote(ids) {
|
||||||
if (!Array.isArray(ids)) {
|
if (!Array.isArray(ids)) {
|
||||||
@ -372,4 +372,4 @@ export function revealQuote(ids) {
|
|||||||
type: QUOTE_REVEAL,
|
type: QUOTE_REVEAL,
|
||||||
ids,
|
ids,
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
@ -134,7 +134,7 @@ export const quote = (status, muted, quoteMuted, handleQuoteClick, handleExpande
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className='status__info'>
|
<div className='status__info'>
|
||||||
{identity(quoteStatus, null, null, true)}
|
{identity(quoteStatus, null, true)}
|
||||||
</div>
|
</div>
|
||||||
<StatusContent status={quoteStatus} onClick={handleQuoteClick} expanded={!status.get('quote_hidden')} onExpandedToggle={handleExpandedQuoteToggle} quote />
|
<StatusContent status={quoteStatus} onClick={handleQuoteClick} expanded={!status.get('quote_hidden')} onExpandedToggle={handleExpandedQuoteToggle} quote />
|
||||||
{media(quoteStatus, true)}
|
{media(quoteStatus, true)}
|
||||||
@ -146,7 +146,6 @@ export const quote = (status, muted, quoteMuted, handleQuoteClick, handleExpande
|
|||||||
<div
|
<div
|
||||||
className={classNames('quote-status', `status-${quoteStatus.get('visibility')}`, { muted: muted })}
|
className={classNames('quote-status', `status-${quoteStatus.get('visibility')}`, { muted: muted })}
|
||||||
data-id={quoteStatus.get('id')}
|
data-id={quoteStatus.get('id')}
|
||||||
dataurl={quoteStatus.get('url')}
|
|
||||||
>
|
>
|
||||||
{quoteInner}
|
{quoteInner}
|
||||||
</div>
|
</div>
|
||||||
@ -238,7 +237,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
|
|
||||||
handleToggleQuoteMediaVisibility = () => {
|
handleToggleQuoteMediaVisibility = () => {
|
||||||
this.setState({ showQuoteMedia: !this.state.showQuoteMedia });
|
this.setState({ showQuoteMedia: !this.state.showQuoteMedia });
|
||||||
}
|
};
|
||||||
|
|
||||||
handleClick = e => {
|
handleClick = e => {
|
||||||
if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) {
|
if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) {
|
||||||
@ -253,10 +252,6 @@ class Status extends ImmutablePureComponent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
handlePrependAccountClick = e => {
|
handlePrependAccountClick = e => {
|
||||||
this.handleAccountClick(e, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
handleAccountClick = (e, proper = true) => {
|
|
||||||
if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) {
|
if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -266,17 +261,29 @@ class Status extends ImmutablePureComponent {
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
this._openProfile(proper);
|
this._openProfile(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleQuoteClick = () => {
|
handleAccountClick = (e) => {
|
||||||
if (!this.props) {
|
if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { status } = this.props;
|
if (e) {
|
||||||
this.props.history.push(`/statuses/${status.getIn(['reblog', 'quote', 'id'], status.getIn(['quote', 'id']))}`);
|
e.preventDefault();
|
||||||
}
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
const acct = e.currentTarget.getAttribute('data-acct');
|
||||||
|
this.props.history.push(`/@${acct}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
handleQuoteClick = () => {
|
||||||
|
if (this.props.history) {
|
||||||
|
const status = this._properStatus();
|
||||||
|
this.props.history.push(`/@${status.getIn(['quote', 'account', 'acct'])}/${status.getIn(['quote', 'id'])}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
handleQuoteUserClick = () =>{
|
handleQuoteUserClick = () =>{
|
||||||
if (!this.props) {
|
if (!this.props) {
|
||||||
@ -301,7 +308,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
|
|
||||||
handleExpandedQuoteToggle = () => {
|
handleExpandedQuoteToggle = () => {
|
||||||
this.props.onQuoteToggleHidden(this._properStatus());
|
this.props.onQuoteToggleHidden(this._properStatus());
|
||||||
}
|
};
|
||||||
|
|
||||||
getAttachmentAspectRatio () {
|
getAttachmentAspectRatio () {
|
||||||
const attachments = this._properStatus().get('media_attachments');
|
const attachments = this._properStatus().get('media_attachments');
|
||||||
@ -554,9 +561,10 @@ class Status extends ImmutablePureComponent {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const media = (status, quote = false) => {
|
const media = (status, quote = false) => {
|
||||||
if (pictureInPicture.get('inUse')) {
|
if (pictureInPicture.get('inUse')) {
|
||||||
return <PictureInPicturePlaceholder aspectRatio={this.getAttachmentAspectRatio()} />;
|
return <PictureInPicturePlaceholder aspectRatio={this.getAttachmentAspectRatio()} width={this.props.cachedMediaWidth} />;
|
||||||
} else if (status.get('media_attachments').size > 0) {
|
} else if (status.get('media_attachments').size > 0) {
|
||||||
const language = status.getIn(['translation', 'language']) || status.get('language');
|
const language = status.getIn(['translation', 'language']) || status.get('language');
|
||||||
|
|
||||||
@ -655,9 +663,9 @@ class Status extends ImmutablePureComponent {
|
|||||||
return <AvatarOverlay account={status.get('account')} friend={account} />;
|
return <AvatarOverlay account={status.get('account')} friend={account} />;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const identity = (status, account, _0, quote = false) => (
|
const identity = (status, account) => (
|
||||||
<a onClick={quote ? this.handleQuoteUserClick : this.handleAccountClick} href={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} className='status__display-name' rel='noopener noreferrer'>
|
<a onClick={this.handleAccountClick} data-acct={status.getIn(['account', 'acct'])} href={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} className='status__display-name' target='_blank' rel='noopener noreferrer'>
|
||||||
<div className='status__avatar'>
|
<div className='status__avatar'>
|
||||||
{statusAvatar(status, account)}
|
{statusAvatar(status, account)}
|
||||||
</div>
|
</div>
|
||||||
@ -721,4 +729,4 @@ class Status extends ImmutablePureComponent {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withOptionalRouter(injectIntl(Status));
|
export default connect(mapStateToProps)(withOptionalRouter(injectIntl(Status)));
|
||||||
|
@ -11,6 +11,7 @@ import { connect } from 'react-redux';
|
|||||||
|
|
||||||
import BookmarkIcon from '@/material-icons/400-24px/bookmark-fill.svg';
|
import BookmarkIcon from '@/material-icons/400-24px/bookmark-fill.svg';
|
||||||
import BookmarkBorderIcon from '@/material-icons/400-24px/bookmark.svg?react';
|
import BookmarkBorderIcon from '@/material-icons/400-24px/bookmark.svg?react';
|
||||||
|
import FormatQuoteIcon from '@/material-icons/400-24px/format_quote.svg?react';
|
||||||
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||||
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
|
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
|
||||||
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
|
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
|
||||||
@ -160,8 +161,8 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
handleQuoteClick = () => {
|
handleQuoteClick = () => {
|
||||||
this.props.onQuote(this.props.status, this.props.history);
|
this.props.onQuote(this.props.status);
|
||||||
}
|
};
|
||||||
|
|
||||||
handleBookmarkClick = () => {
|
handleBookmarkClick = () => {
|
||||||
this.props.onBookmark(this.props.status);
|
this.props.onBookmark(this.props.status);
|
||||||
@ -262,7 +263,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||||||
} else {
|
} else {
|
||||||
return intl.formatMessage(messages.cannot_quote);
|
return intl.formatMessage(messages.cannot_quote);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { status, relationship, intl, withDismiss, withCounters, scrollKey } = this.props;
|
const { status, relationship, intl, withDismiss, withCounters, scrollKey } = this.props;
|
||||||
@ -406,8 +407,8 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||||||
<div className='status__action-bar'>
|
<div className='status__action-bar'>
|
||||||
<IconButton className='status__action-bar__button' title={replyTitle} icon={isReply ? 'reply' : replyIcon} iconComponent={isReply ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} counter={status.get('replies_count')} />
|
<IconButton className='status__action-bar__button' title={replyTitle} icon={isReply ? 'reply' : replyIcon} iconComponent={isReply ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} counter={status.get('replies_count')} />
|
||||||
<IconButton className={classNames('status__action-bar__button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={reblogIconComponent} onClick={this.handleReblogClick} counter={withCounters ? status.get('reblogs_count') : undefined} />
|
<IconButton className={classNames('status__action-bar__button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={reblogIconComponent} onClick={this.handleReblogClick} counter={withCounters ? status.get('reblogs_count') : undefined} />
|
||||||
<IconButton className='status__action-bar__button star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} counter={withCounters ? status.get('favourites_count') : undefined} />
|
<IconButton className='status__action-bar__button star-icon' animate active={status.get('favourited')} pressed={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} counter={withCounters ? status.get('favourites_count') : undefined} />
|
||||||
<IconButton className='status__action-bar__button' disabled={!publicStatus} title={StatusActionBar.quoteTitle(intl, messages, publicStatus)} icon='quote' iconComponent={QuoteIcon} onClick={this.handleQuoteClick} />
|
<IconButton className='status__action-bar__button' disabled={!publicStatus} title={StatusActionBar.quoteTitle(intl, messages, publicStatus)} icon='format-quote' iconComponent={FormatQuoteIcon} onClick={this.handleQuoteClick} />
|
||||||
<IconButton className='status__action-bar__button bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} />
|
<IconButton className='status__action-bar__button bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} />
|
||||||
|
|
||||||
{filterButton}
|
{filterButton}
|
||||||
|
@ -241,7 +241,7 @@ class StatusContent extends PureComponent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { status, intl, statusContent, quote } = this.props;
|
const { status, intl, quote, statusContent } = this.props;
|
||||||
|
|
||||||
const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden;
|
const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden;
|
||||||
const renderReadMore = this.props.onClick && status.get('collapsed');
|
const renderReadMore = this.props.onClick && status.get('collapsed');
|
||||||
|
@ -29,6 +29,7 @@ import { CharacterCounter } from './character_counter';
|
|||||||
import { EditIndicator } from './edit_indicator';
|
import { EditIndicator } from './edit_indicator';
|
||||||
import { NavigationBar } from './navigation_bar';
|
import { NavigationBar } from './navigation_bar';
|
||||||
import { PollForm } from "./poll_form";
|
import { PollForm } from "./poll_form";
|
||||||
|
import { QuoteIndicator } from './quote_indicator';
|
||||||
import { ReplyIndicator } from './reply_indicator';
|
import { ReplyIndicator } from './reply_indicator';
|
||||||
|
|
||||||
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 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';
|
||||||
@ -296,6 +297,8 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
<UploadFormContainer />
|
<UploadFormContainer />
|
||||||
<PollForm />
|
<PollForm />
|
||||||
|
|
||||||
|
<QuoteIndicator />
|
||||||
|
|
||||||
<div className='compose-form__footer'>
|
<div className='compose-form__footer'>
|
||||||
<div className='compose-form__dropdowns'>
|
<div className='compose-form__dropdowns'>
|
||||||
<PrivacyDropdownContainer disabled={this.props.isEditing} />
|
<PrivacyDropdownContainer disabled={this.props.isEditing} />
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
|
import { FormattedMessage, defineMessages, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
|
import BarChart4BarsIcon from 'mastodon/../material-icons/400-24px/bar_chart_4_bars.svg?react';
|
||||||
|
import CloseIcon from 'mastodon/../material-icons/400-24px/close.svg?react';
|
||||||
|
import PhotoLibraryIcon from 'mastodon/../material-icons/400-24px/photo_library.svg?react';
|
||||||
|
import { cancelReplyCompose } from "mastodon/actions/compose";
|
||||||
|
import { Avatar } from "mastodon/components/avatar";
|
||||||
|
import { DisplayName } from "mastodon/components/display_name";
|
||||||
|
import { Icon } from "mastodon/components/icon";
|
||||||
|
import { IconButton } from "mastodon/components/icon_button";
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const QuoteIndicator = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const id = useSelector(state => state.getIn(['compose', 'quote_from']));
|
||||||
|
const status = useSelector(state => state.getIn(['statuses', id]));
|
||||||
|
const account = useSelector(state => state.getIn(['accounts', status?.get('account')]));
|
||||||
|
|
||||||
|
const handleCancelClick = useCallback(() => {
|
||||||
|
dispatch(cancelReplyCompose());
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
if (!status) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = { __html: status.get('contentHtml') };
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='edit-indicator'>
|
||||||
|
<div className='edit-indicator__header'>
|
||||||
|
<Link to={`/@${account.get('acct')}`} className='status__display-name'>
|
||||||
|
<Avatar account={account} size={46} />
|
||||||
|
<DisplayName account={account} />
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<div className='edit-indicator__cancel'>
|
||||||
|
<IconButton title={intl.formatMessage(messages.cancel)} icon='times' iconComponent={CloseIcon} onClick={handleCancelClick} inverted />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='edit-indicator__content translate' dangerouslySetInnerHTML={content} />
|
||||||
|
|
||||||
|
{(status.get('poll') || status.get('media_attachments').size > 0) && (
|
||||||
|
<div className='edit-indicator__attachments'>
|
||||||
|
{status.get('poll') && <><Icon icon={BarChart4BarsIcon} /><FormattedMessage id='reply_indicator.poll' defaultMessage='Poll' /></>}
|
||||||
|
{status.get('media_attachments').size > 0 && <><Icon icon={PhotoLibraryIcon} /><FormattedMessage id='reply_indicator.attachments' defaultMessage='{count, plural, one {# attachment} other {# attachments}}' values={{ count: status.get('media_attachments').size }} /></>}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -167,7 +167,7 @@ class Footer extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch(quoteCompose(status, router.history));
|
dispatch(quoteCompose(status, router.history));
|
||||||
}
|
};
|
||||||
|
|
||||||
handleQuoteClick = () => {
|
handleQuoteClick = () => {
|
||||||
const { dispatch, askReplyConfirmation, intl } = this.props;
|
const { dispatch, askReplyConfirmation, intl } = this.props;
|
||||||
@ -181,7 +181,7 @@ class Footer extends ImmutablePureComponent {
|
|||||||
} else {
|
} else {
|
||||||
this._performQuote();
|
this._performQuote();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleOpenClick = e => {
|
handleOpenClick = e => {
|
||||||
if (e.button !== 0 || !history) {
|
if (e.button !== 0 || !history) {
|
||||||
|
@ -11,6 +11,7 @@ import { connect } from 'react-redux';
|
|||||||
|
|
||||||
import BookmarkIcon from '@/material-icons/400-24px/bookmark-fill.svg?react';
|
import BookmarkIcon from '@/material-icons/400-24px/bookmark-fill.svg?react';
|
||||||
import BookmarkBorderIcon from '@/material-icons/400-24px/bookmark.svg?react';
|
import BookmarkBorderIcon from '@/material-icons/400-24px/bookmark.svg?react';
|
||||||
|
import FormatQuoteIcon from '@/material-icons/400-24px/format_quote.svg?react';
|
||||||
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||||
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
|
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
|
||||||
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
|
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
|
||||||
@ -111,8 +112,8 @@ class ActionBar extends PureComponent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
handleQuoteClick = () => {
|
handleQuoteClick = () => {
|
||||||
this.props.onQuote(this.props.status, this.props.history);
|
this.props.onQuote(this.props.status);
|
||||||
}
|
};
|
||||||
|
|
||||||
handleFavouriteClick = () => {
|
handleFavouriteClick = () => {
|
||||||
this.props.onFavourite(this.props.status);
|
this.props.onFavourite(this.props.status);
|
||||||
@ -324,7 +325,7 @@ class ActionBar extends PureComponent {
|
|||||||
<div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.reply)} icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon} iconComponent={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} /></div>
|
<div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.reply)} icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon} iconComponent={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} /></div>
|
||||||
<div className='detailed-status__button'><IconButton className={classNames({ reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={reblogIconComponent} onClick={this.handleReblogClick} /></div>
|
<div className='detailed-status__button'><IconButton className={classNames({ reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={reblogIconComponent} onClick={this.handleReblogClick} /></div>
|
||||||
<div className='detailed-status__button'><IconButton className='star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} /></div>
|
<div className='detailed-status__button'><IconButton className='star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} /></div>
|
||||||
<div className='detailed-status__button'><IconButton disabled={!publicStatus} title={StatusActionBar.quoteTitle(intl, messages, publicStatus)} icon='quote' iconComponent={QuoteIcon} onClick={this.handleQuoteClick} /></div>
|
<div className='detailed-status__button'><IconButton disabled={!publicStatus} title={StatusActionBar.quoteTitle(intl, messages, publicStatus)} icon='format-quote' iconComponent={FormatQuoteIcon} onClick={this.handleQuoteClick} /></div>
|
||||||
<div className='detailed-status__button'><IconButton className='bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} /></div>
|
<div className='detailed-status__button'><IconButton className='bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} /></div>
|
||||||
<div className='detailed-status__action-bar-dropdown'>
|
<div className='detailed-status__action-bar-dropdown'>
|
||||||
<DropdownMenuContainer icon='ellipsis-h' iconComponent={MoreHorizIcon} status={status} items={menu} direction='left' title={intl.formatMessage(messages.more)} />
|
<DropdownMenuContainer icon='ellipsis-h' iconComponent={MoreHorizIcon} status={status} items={menu} direction='left' title={intl.formatMessage(messages.more)} />
|
||||||
|
@ -152,9 +152,9 @@ export default class Card extends PureComponent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (largeImage && card.get('type') === 'video') {
|
if (largeImage && card.get('type') === 'video') {
|
||||||
thumbnailStyle.aspectRatio = `16 / 9`;
|
thumbnailStyle.aspectRatio = `${quote ? 8 : 16} / 9`;
|
||||||
} else if (largeImage) {
|
} else if (largeImage) {
|
||||||
thumbnailStyle.aspectRatio = '1.91 / 1';
|
thumbnailStyle.aspectRatio = `1.91 / ${quote ? 2 : 1}`;
|
||||||
} else {
|
} else {
|
||||||
thumbnailStyle.aspectRatio = 1;
|
thumbnailStyle.aspectRatio = 1;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { FormattedDate, FormattedMessage } from 'react-intl';
|
import { FormattedDate, FormattedMessage, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Link, withRouter } from 'react-router-dom';
|
import { Link, withRouter } from 'react-router-dom';
|
||||||
@ -62,7 +62,8 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||||||
handleAccountClick = (e) => {
|
handleAccountClick = (e) => {
|
||||||
if (e.button === 0 && !(e.ctrlKey || e.metaKey) && this.props.history) {
|
if (e.button === 0 && !(e.ctrlKey || e.metaKey) && this.props.history) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.props.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
|
const acct = e.currentTarget.getAttribute('data-acct');
|
||||||
|
this.props.history.push(`/@${acct}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@ -78,17 +79,15 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||||||
|
|
||||||
handleExpandedQuoteToggle = () => {
|
handleExpandedQuoteToggle = () => {
|
||||||
this.props.onQuoteToggleHidden(this.props.status);
|
this.props.onQuoteToggleHidden(this.props.status);
|
||||||
}
|
};
|
||||||
|
|
||||||
handleQuoteClick = () => {
|
handleQuoteClick = () => {
|
||||||
if (!this.props) {
|
if (this.props.history) {
|
||||||
return;
|
const status = this._properStatus();
|
||||||
|
this.props.history.push(`/@${status.getIn(['quote', 'account', 'acct'])}/${status.getIn(['quote', 'id'])}`);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const { status } = this.props;
|
|
||||||
this.props.history.push(`/statuses/${status.getIn(['quote', 'id'])}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleQuoteUserClick = () =>{
|
handleQuoteUserClick = () =>{
|
||||||
if (!this.props) {
|
if (!this.props) {
|
||||||
return;
|
return;
|
||||||
@ -161,7 +160,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||||||
render () {
|
render () {
|
||||||
const status = this._properStatus();
|
const status = this._properStatus();
|
||||||
const outerStyle = { boxSizing: 'border-box' };
|
const outerStyle = { boxSizing: 'border-box' };
|
||||||
const { compact, pictureInPicture, quoteMuted } = this.props;
|
const { compact, pictureInPicture, quoteMuted } = this.props;
|
||||||
|
|
||||||
if (!status) {
|
if (!status) {
|
||||||
return null;
|
return null;
|
||||||
@ -180,11 +179,19 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||||||
|
|
||||||
const language = status.getIn(['translation', 'language']) || status.get('language');
|
const language = status.getIn(['translation', 'language']) || status.get('language');
|
||||||
|
|
||||||
const identity = (status, _0, _1, quote = false) => (
|
const identity = (status, _, quote) => (
|
||||||
<a href={`/@${status.getIn(['account', 'acct'])}`} onClick={quote ? this.handleQuoteUserClick : this.handleAccountClick} data-acct={status.getIn(['account', 'acct'])} className='detailed-status__display-name'>
|
<>
|
||||||
<div className='detailed-status__display-avatar'><Avatar account={status.get('account')} size={46} /></div>
|
{status.get('visibility') === 'direct' && (
|
||||||
<DisplayName account={status.get('account')} localDomain={this.props.domain} />
|
<div className='status__prepend'>
|
||||||
</a>
|
<div className='status__prepend-icon-wrapper'><Icon id='at' className='status__prepend-icon' fixedWidth /></div>
|
||||||
|
<FormattedMessage id='status.direct_indicator' defaultMessage='Private mention' />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<a href={`/@${status.getIn(['account', 'acct'])}`} data-acct={status.getIn(['account', 'acct'])} onClick={this.handleAccountClick} className='detailed-status__display-name'>
|
||||||
|
<div className='detailed-status__display-avatar'><Avatar account={status.get('account')} size={quote ? 20 : 48} /></div>
|
||||||
|
<DisplayName account={status.get('account')} localDomain={this.props.domain} />
|
||||||
|
</a>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const media = (status, quote = false) => {
|
const media = (status, quote = false) => {
|
||||||
@ -251,7 +258,8 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (status.get('spoiler_text').length === 0) {
|
} else if (status.get('spoiler_text').length === 0) {
|
||||||
return <Card sensitive={status.get('sensitive')} onOpenMedia={this.props.onOpenMedia} card={status.get('card', null)} quote={quote} />;
|
return (<Card sensitive={status.get('sensitive')} onOpenMedia={this.props.onOpenMedia}
|
||||||
|
card={status.get('card', null)} quote={quote} />);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -331,10 +339,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||||||
<FormattedMessage id='status.direct_indicator' defaultMessage='Private mention' />
|
<FormattedMessage id='status.direct_indicator' defaultMessage='Private mention' />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<a href={`/@${status.getIn(['account', 'acct'])}`} onClick={this.handleAccountClick} className='detailed-status__display-name'>
|
{identity(status, null, false)}
|
||||||
<div className='detailed-status__display-avatar'><Avatar account={status.get('account')} size={46} /></div>
|
|
||||||
<DisplayName account={status.get('account')} localDomain={this.props.domain} />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<StatusContent
|
<StatusContent
|
||||||
status={status}
|
status={status}
|
||||||
@ -362,4 +367,4 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withRouter(DetailedStatus);
|
export default connect(mapStateToProps)(withRouter(injectIntl(DetailedStatus)));
|
||||||
|
@ -255,7 +255,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
|
|
||||||
handleToggleQuoteMediaVisibility = () => {
|
handleToggleQuoteMediaVisibility = () => {
|
||||||
this.setState({ showQuoteMedia: !this.state.showQuoteMedia });
|
this.setState({ showQuoteMedia: !this.state.showQuoteMedia });
|
||||||
}
|
};
|
||||||
|
|
||||||
handleFavouriteClick = (status) => {
|
handleFavouriteClick = (status) => {
|
||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
@ -327,7 +327,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
} else {
|
} else {
|
||||||
dispatch(quoteCompose(status, this.props.history));
|
dispatch(quoteCompose(status, this.props.history));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleModalReblog = (status, privacy) => {
|
handleModalReblog = (status, privacy) => {
|
||||||
this.props.dispatch(reblog(status, privacy));
|
this.props.dispatch(reblog(status, privacy));
|
||||||
@ -450,7 +450,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
} else {
|
} else {
|
||||||
this.props.dispatch(hideQuote(status.get('id')));
|
this.props.dispatch(hideQuote(status.get('id')));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleToggleAll = () => {
|
handleToggleAll = () => {
|
||||||
const { status, ancestorsIds, descendantsIds } = this.props;
|
const { status, ancestorsIds, descendantsIds } = this.props;
|
||||||
|
@ -683,6 +683,7 @@
|
|||||||
"status.translate": "翻訳",
|
"status.translate": "翻訳",
|
||||||
"status.translated_from_with": "{provider}を使って{lang}から翻訳",
|
"status.translated_from_with": "{provider}を使って{lang}から翻訳",
|
||||||
"status.uncached_media_warning": "プレビューは使用できません",
|
"status.uncached_media_warning": "プレビューは使用できません",
|
||||||
|
"status.unlisted_quote": "未収載の引用",
|
||||||
"status.unmute_conversation": "会話のミュートを解除",
|
"status.unmute_conversation": "会話のミュートを解除",
|
||||||
"status.unpin": "プロフィールへの固定を解除",
|
"status.unpin": "プロフィールへの固定を解除",
|
||||||
"subscribed_languages.lead": "選択した言語のトゥートだけがホームとリストのタイムラインに表示されます。全ての言語のトゥートを受け取る場合は全てのチェックを外して下さい。",
|
"subscribed_languages.lead": "選択した言語のトゥートだけがホームとリストのタイムラインに表示されます。全ての言語のトゥートを受け取る場合は全てのチェックを外して下さい。",
|
||||||
|
@ -7,7 +7,6 @@ import {
|
|||||||
COMPOSE_REPLY,
|
COMPOSE_REPLY,
|
||||||
COMPOSE_REPLY_CANCEL,
|
COMPOSE_REPLY_CANCEL,
|
||||||
COMPOSE_QUOTE,
|
COMPOSE_QUOTE,
|
||||||
COMPOSE_QUOTE_CANCEL,
|
|
||||||
COMPOSE_DIRECT,
|
COMPOSE_DIRECT,
|
||||||
COMPOSE_MENTION,
|
COMPOSE_MENTION,
|
||||||
COMPOSE_SUBMIT_REQUEST,
|
COMPOSE_SUBMIT_REQUEST,
|
||||||
@ -397,7 +396,6 @@ export default function compose(state = initialState, action) {
|
|||||||
case COMPOSE_UPLOAD_CHANGE_REQUEST:
|
case COMPOSE_UPLOAD_CHANGE_REQUEST:
|
||||||
return state.set('is_changing_upload', true);
|
return state.set('is_changing_upload', true);
|
||||||
case COMPOSE_REPLY_CANCEL:
|
case COMPOSE_REPLY_CANCEL:
|
||||||
case COMPOSE_QUOTE_CANCEL:
|
|
||||||
case COMPOSE_RESET:
|
case COMPOSE_RESET:
|
||||||
case COMPOSE_SUBMIT_SUCCESS:
|
case COMPOSE_SUBMIT_SUCCESS:
|
||||||
return clearAll(state);
|
return clearAll(state);
|
||||||
@ -530,6 +528,8 @@ export default function compose(state = initialState, action) {
|
|||||||
map.set('id', action.status.get('id'));
|
map.set('id', action.status.get('id'));
|
||||||
map.set('text', action.text);
|
map.set('text', action.text);
|
||||||
map.set('in_reply_to', action.status.get('in_reply_to_id'));
|
map.set('in_reply_to', action.status.get('in_reply_to_id'));
|
||||||
|
map.set('quote_from', action.status.getIn(['quote', 'id']));
|
||||||
|
map.set('quote_from_url', action.status.getIn(['quote', 'url']));
|
||||||
map.set('privacy', action.status.get('visibility'));
|
map.set('privacy', action.status.get('visibility'));
|
||||||
map.set('media_attachments', action.status.get('media_attachments'));
|
map.set('media_attachments', action.status.get('media_attachments'));
|
||||||
map.set('focusDate', new Date());
|
map.set('focusDate', new Date());
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m228-240 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T458-480L320-240h-92Zm360 0 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T818-480L680-240h-92Z"/></svg>
|
After Width: | Height: | Size: 322 B |
1
app/javascript/material-icons/400-24px/format_quote.svg
Normal file
1
app/javascript/material-icons/400-24px/format_quote.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m228-240 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T458-480L320-240h-92Zm360 0 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T818-480L680-240h-92ZM320-500q25 0 42.5-17.5T380-560q0-25-17.5-42.5T320-620q-25 0-42.5 17.5T260-560q0 25 17.5 42.5T320-500Zm360 0q25 0 42.5-17.5T740-560q0-25-17.5-42.5T680-620q-25 0-42.5 17.5T620-560q0 25 17.5 42.5T680-500Zm0-60Zm-360 0Z"/></svg>
|
After Width: | Height: | Size: 538 B |
@ -1105,6 +1105,10 @@ body > [data-popper-placement] {
|
|||||||
grid-template-rows: 46px max-content;
|
grid-template-rows: 46px max-content;
|
||||||
gap: 0 10px;
|
gap: 0 10px;
|
||||||
|
|
||||||
|
&.quote-indicator {
|
||||||
|
background: $success-green;
|
||||||
|
}
|
||||||
|
|
||||||
.detailed-status__display-name {
|
.detailed-status__display-name {
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
@ -1422,17 +1426,6 @@ body > [data-popper-placement] {
|
|||||||
appearance: none;
|
appearance: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status__avatar,
|
|
||||||
.detailed-status__display-avatar {
|
|
||||||
position: absolute;
|
|
||||||
top: 5px !important;
|
|
||||||
left: 5px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.display-name {
|
|
||||||
padding-left: 56px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detailed-status__display-name {
|
.detailed-status__display-name {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
line-height: unset;
|
line-height: unset;
|
||||||
@ -1630,7 +1623,8 @@ body > [data-popper-placement] {
|
|||||||
color: $dark-text-color;
|
color: $dark-text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status__info .status__display-name {
|
.status__info .status__display-name,
|
||||||
|
.edit-indicator .status__display-name {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
%span.display-name
|
%span.display-name
|
||||||
%bdi
|
%bdi
|
||||||
%strong.display-name__html.p-name.emojify= display_name(author, custom_emojify: true, autoplay: prefers_autoplay?)
|
%strong.display-name__html.p-name.emojify= display_name(author, custom_emojify: true, autoplay: prefers_autoplay?)
|
||||||
|
|
||||||
%span.display-name__account
|
%span.display-name__account
|
||||||
= acct(author)
|
= acct(author)
|
||||||
- if !inline && author.locked?
|
- if !inline && author.locked?
|
||||||
|
@ -12,21 +12,8 @@
|
|||||||
*
|
*
|
||||||
%data.dt-published{ value: status.created_at.to_time.iso8601 }
|
%data.dt-published{ value: status.created_at.to_time.iso8601 }
|
||||||
|
|
||||||
.p-author.h-card
|
= render 'statuses/author', author: status.account
|
||||||
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'status__display-name u-url', target: stream_link_target, rel: 'noopener noreferrer' do
|
|
||||||
.status__avatar
|
|
||||||
%div
|
|
||||||
- if prefers_autoplay?
|
|
||||||
= image_tag status.account.avatar_original_url, alt: '', class: 'u-photo account__avatar'
|
|
||||||
- else
|
|
||||||
= image_tag status.account.avatar_static_url, alt: '', class: 'u-photo account__avatar'
|
|
||||||
%span.display-name
|
|
||||||
%bdi
|
|
||||||
%strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: prefers_autoplay?)
|
|
||||||
|
|
||||||
%span.display-name__account
|
|
||||||
= acct(status.account)
|
|
||||||
= fa_icon('lock') if status.account.locked?
|
|
||||||
.status__content.emojify{ data: ({ spoiler: current_account&.user&.setting_expand_spoilers ? 'expanded' : 'folded' } if status.spoiler_text?) }<
|
.status__content.emojify{ data: ({ spoiler: current_account&.user&.setting_expand_spoilers ? 'expanded' : 'folded' } if status.spoiler_text?) }<
|
||||||
- if status.spoiler_text?
|
- if status.spoiler_text?
|
||||||
%p<
|
%p<
|
||||||
|
Loading…
Reference in New Issue
Block a user