Fix to hide mute and blocked quotes
This commit is contained in:
parent
e9ee34d3f4
commit
6fd2947b92
22 changed files with 219 additions and 105 deletions
|
@ -7,8 +7,9 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
|
|||
after_action :insert_pagination_headers, unless: -> { truthy_param?(:pinned) }
|
||||
|
||||
def index
|
||||
@statuses = load_statuses
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||
@statuses = load_statuses
|
||||
accountIds = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id), account_relationships: AccountRelationshipsPresenter.new(accountIds, current_user&.account_id)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -6,8 +6,9 @@ class Api::V1::BookmarksController < Api::BaseController
|
|||
after_action :insert_pagination_headers
|
||||
|
||||
def index
|
||||
@statuses = load_statuses
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||
@statuses = load_statuses
|
||||
accountIds = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id), account_relationships: AccountRelationshipsPresenter.new(accountIds, current_user&.account_id)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -6,8 +6,9 @@ class Api::V1::FavouritesController < Api::BaseController
|
|||
after_action :insert_pagination_headers
|
||||
|
||||
def index
|
||||
@statuses = load_statuses
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||
@statuses = load_statuses
|
||||
accountIds = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id), account_relationships: AccountRelationshipsPresenter.new(accountIds, current_user&.account_id)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -30,8 +30,9 @@ class Api::V1::StatusesController < Api::BaseController
|
|||
|
||||
@context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
|
||||
statuses = [@status] + @context.ancestors + @context.descendants
|
||||
accountIds = statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
|
||||
render json: @context, serializer: REST::ContextSerializer, relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id)
|
||||
render json: @context, serializer: REST::ContextSerializer, relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id), account_relationships: AccountRelationshipsPresenter.new(accountIds, current_user&.account_id)
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
@ -6,11 +6,13 @@ class Api::V1::Timelines::HomeController < Api::BaseController
|
|||
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
||||
|
||||
def show
|
||||
@statuses = load_statuses
|
||||
@statuses = load_statuses
|
||||
accountIds = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
|
||||
render json: @statuses,
|
||||
each_serializer: REST::StatusSerializer,
|
||||
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
||||
account_relationships: AccountRelationshipsPresenter.new(accountIds, current_user&.account_id),
|
||||
status: account_home_feed.regenerating? ? 206 : 200
|
||||
end
|
||||
|
||||
|
|
|
@ -9,9 +9,12 @@ class Api::V1::Timelines::ListController < Api::BaseController
|
|||
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
||||
|
||||
def show
|
||||
accountIds = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
|
||||
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(accountIds, current_user&.account_id)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -5,8 +5,10 @@ class Api::V1::Timelines::PublicController < Api::BaseController
|
|||
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
||||
|
||||
def show
|
||||
@statuses = load_statuses
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||
@statuses = load_statuses
|
||||
accountIds = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id), account_relationships: AccountRelationshipsPresenter.new(accountIds, current_user&.account_id)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -5,8 +5,9 @@ class Api::V1::Timelines::TagController < Api::BaseController
|
|||
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
||||
|
||||
def show
|
||||
@statuses = load_statuses
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||
@statuses = load_statuses
|
||||
accountIds = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id), account_relationships: AccountRelationshipsPresenter.new(accountIds, current_user&.account_id)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { fetchRelationships } from './accounts';
|
||||
import api, { getLinks } from '../api';
|
||||
import { importFetchedStatuses } from './importer';
|
||||
import { uniq } from '../utils/uniq';
|
||||
|
||||
export const BOOKMARKED_STATUSES_FETCH_REQUEST = 'BOOKMARKED_STATUSES_FETCH_REQUEST';
|
||||
export const BOOKMARKED_STATUSES_FETCH_SUCCESS = 'BOOKMARKED_STATUSES_FETCH_SUCCESS';
|
||||
|
@ -20,6 +22,7 @@ export function fetchBookmarkedStatuses() {
|
|||
api(getState).get('/api/v1/bookmarks').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
dispatch(fetchRelationships(uniq(response.data.map(item => item.reblog ? item.reblog.account.id : item.account.id))));
|
||||
dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null));
|
||||
}).catch(error => {
|
||||
dispatch(fetchBookmarkedStatusesFail(error));
|
||||
|
@ -61,6 +64,7 @@ export function expandBookmarkedStatuses() {
|
|||
api(getState).get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
dispatch(fetchRelationships(uniq(response.data.map(item => item.reblog ? item.reblog.account.id : item.account.id))));
|
||||
dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null));
|
||||
}).catch(error => {
|
||||
dispatch(expandBookmarkedStatusesFail(error));
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { fetchRelationships } from './accounts';
|
||||
import api, { getLinks } from '../api';
|
||||
import { importFetchedStatuses } from './importer';
|
||||
import { uniq } from '../utils/uniq';
|
||||
|
||||
export const FAVOURITED_STATUSES_FETCH_REQUEST = 'FAVOURITED_STATUSES_FETCH_REQUEST';
|
||||
export const FAVOURITED_STATUSES_FETCH_SUCCESS = 'FAVOURITED_STATUSES_FETCH_SUCCESS';
|
||||
|
@ -20,6 +22,7 @@ export function fetchFavouritedStatuses() {
|
|||
api(getState).get('/api/v1/favourites').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
dispatch(fetchRelationships(uniq(response.data.map(item => item.reblog ? item.reblog.account.id : item.account.id))));
|
||||
dispatch(fetchFavouritedStatusesSuccess(response.data, next ? next.uri : null));
|
||||
}).catch(error => {
|
||||
dispatch(fetchFavouritedStatusesFail(error));
|
||||
|
@ -64,6 +67,7 @@ export function expandFavouritedStatuses() {
|
|||
api(getState).get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
dispatch(fetchRelationships(uniq(response.data.map(item => item.reblog ? item.reblog.account.id : item.account.id))));
|
||||
dispatch(expandFavouritedStatusesSuccess(response.data, next ? next.uri : null));
|
||||
}).catch(error => {
|
||||
dispatch(expandFavouritedStatusesFail(error));
|
||||
|
|
|
@ -70,6 +70,10 @@ export function importFetchedStatuses(statuses) {
|
|||
processStatus(status.reblog);
|
||||
}
|
||||
|
||||
if (status.quote && status.quote.id) {
|
||||
processStatus(status.quote);
|
||||
}
|
||||
|
||||
if (status.poll && status.poll.id) {
|
||||
pushUnique(polls, normalizePoll(status.poll));
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ defineMessages({
|
|||
});
|
||||
|
||||
const fetchRelatedRelationships = (dispatch, notifications) => {
|
||||
const accountIds = notifications.filter(item => item.type === 'follow').map(item => item.account.id);
|
||||
const accountIds = notifications.map(item => item.account.id);
|
||||
|
||||
if (accountIds.length > 0) {
|
||||
dispatch(fetchRelationships(accountIds));
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { fetchRelationships } from './accounts';
|
||||
import { importFetchedStatus, importFetchedStatuses } from './importer';
|
||||
import { submitMarkers } from './markers';
|
||||
import api, { getLinks } from 'mastodon/api';
|
||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
import compareId from 'mastodon/compare_id';
|
||||
import { usePendingItems as preferPendingItems } from 'mastodon/initial_state';
|
||||
import { uniq } from '../utils/uniq';
|
||||
|
||||
export const TIMELINE_UPDATE = 'TIMELINE_UPDATE';
|
||||
export const TIMELINE_DELETE = 'TIMELINE_DELETE';
|
||||
|
@ -39,6 +41,7 @@ export function updateTimeline(timeline, status, accept) {
|
|||
}
|
||||
|
||||
dispatch(importFetchedStatus(status));
|
||||
dispatch(fetchRelationships([status.reblog ? status.reblog.account.id : status.account.id, status.quote ? status.quote.account.id : null].filter(function(e){return e})));
|
||||
|
||||
dispatch({
|
||||
type: TIMELINE_UPDATE,
|
||||
|
@ -111,6 +114,7 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
|
|||
api(getState).get(path, { params }).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
dispatch(fetchRelationships(uniq(response.data.map(item => item.reblog ? item.reblog.account.id : item.account.id).concat(response.data.map(item => item.quote ? item.quote.account.id : null)).filter(function(e){return e}))));
|
||||
dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.status === 206, isLoadingRecent, isLoadingMore, isLoadingRecent && preferPendingItems));
|
||||
|
||||
if (timelineId === 'home') {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import PropTypes from 'prop-types';
|
||||
import Avatar from './avatar';
|
||||
|
@ -23,6 +24,29 @@ import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_
|
|||
// to use the progress bar to show download progress
|
||||
import Bundle from '../features/ui/components/bundle';
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
let status = props.status;
|
||||
|
||||
if (status === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (status.get('reblog', null) !== null && typeof status.get('reblog') === 'object') {
|
||||
status = status.get('reblog');
|
||||
}
|
||||
|
||||
if (status.get('quote', null) === null) {
|
||||
return {
|
||||
quote_muted: status.get('quote_id', null) ? true : false,
|
||||
};
|
||||
}
|
||||
const id = status.getIn(['quote', 'account', 'id'], null);
|
||||
|
||||
return {
|
||||
quote_muted: id !== null && (state.getIn(['relationships', id, 'muting']) || state.getIn(['relationships', id, 'blocking']) || state.getIn(['relationships', id, 'blocked_by']) || state.getIn(['relationships', id, 'domain_blocking'])) || status.getIn(['quote', 'quote_muted']),
|
||||
};
|
||||
};
|
||||
|
||||
export const textForScreenReader = (intl, status, rebloggedByText = false) => {
|
||||
const displayName = status.getIn(['account', 'display_name']);
|
||||
|
||||
|
@ -59,7 +83,8 @@ const messages = defineMessages({
|
|||
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Direct' },
|
||||
});
|
||||
|
||||
export default @injectIntl
|
||||
export default @connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class Status extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
|
@ -70,6 +95,7 @@ class Status extends ImmutablePureComponent {
|
|||
status: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.map,
|
||||
otherAccounts: ImmutablePropTypes.list,
|
||||
quote_muted: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
onReply: PropTypes.func,
|
||||
onFavourite: PropTypes.func,
|
||||
|
@ -114,6 +140,7 @@ class Status extends ImmutablePureComponent {
|
|||
'hidden',
|
||||
'unread',
|
||||
'pictureInPicture',
|
||||
'quote_muted',
|
||||
];
|
||||
|
||||
state = {
|
||||
|
@ -308,9 +335,9 @@ class Status extends ImmutablePureComponent {
|
|||
|
||||
render () {
|
||||
let media = null;
|
||||
let statusAvatar, prepend, rebloggedByText, unlistedQuoteText;
|
||||
let statusAvatar, prepend, rebloggedByText;
|
||||
|
||||
const { intl, hidden, featured, otherAccounts, unread, showThread, scrollKey, pictureInPicture, contextType } = this.props;
|
||||
const { intl, hidden, featured, otherAccounts, unread, showThread, scrollKey, pictureInPicture, contextType, quote_muted } = this.props;
|
||||
|
||||
let { status, account, ...other } = this.props;
|
||||
|
||||
|
@ -569,12 +596,21 @@ class Status extends ImmutablePureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
if (quote_status.get('visibility') === 'unlisted' && contextType !== 'home') {
|
||||
unlistedQuoteText = intl.formatMessage({ id: 'status.unlisted_quote', defaultMessage: 'Unlisted quote' });
|
||||
if (quote_muted) {
|
||||
quote = (
|
||||
<div className={classNames('quote-status', `status-${quote_status.get('visibility')}`, { muted: this.props.muted })} data-id={quote_status.get('id')}>
|
||||
<div className={classNames('status__content muted-quote', { 'status__content--with-action': this.context.router })}>
|
||||
<FormattedMessage id='status.muted_quote' defaultMessage='Muted quote' />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else if (quote_status.get('visibility') === 'unlisted' && contextType !== 'home') {
|
||||
quote = (
|
||||
<div className={classNames('quote-status', `status-${quote_status.get('visibility')}`, { muted: this.props.muted })} data-id={quote_status.get('id')}>
|
||||
<div className={classNames('status__content unlisted-quote', { 'status__content--with-action': this.context.router })}>
|
||||
<button onClick={this.handleQuoteClick}>{unlistedQuoteText}</button>
|
||||
<button onClick={this.handleQuoteClick}>
|
||||
<FormattedMessage id='status.unlisted_quote' defaultMessage='Unlisted quote' />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -592,6 +628,14 @@ class Status extends ImmutablePureComponent {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
} else if (quote_muted) {
|
||||
quote = (
|
||||
<div className={classNames('quote-status', { muted: this.props.muted })}>
|
||||
<div className={classNames('status__content muted-quote', { 'status__content--with-action': this.context.router })}>
|
||||
<FormattedMessage id='status.muted_quote' defaultMessage='Muted quote' />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import Avatar from '../../../components/avatar';
|
||||
|
@ -6,7 +7,7 @@ import DisplayName from '../../../components/display_name';
|
|||
import StatusContent from '../../../components/status_content';
|
||||
import MediaGallery from '../../../components/media_gallery';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { injectIntl, defineMessages, FormattedDate } from 'react-intl';
|
||||
import { injectIntl, defineMessages, FormattedDate, FormattedMessage } from 'react-intl';
|
||||
import Card from './card';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import Video from '../../video';
|
||||
|
@ -24,7 +25,31 @@ const messages = defineMessages({
|
|||
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Direct' },
|
||||
});
|
||||
|
||||
export default @injectIntl
|
||||
const mapStateToProps = (state, props) => {
|
||||
let status = props.status;
|
||||
|
||||
if (status === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (status.get('reblog', null) !== null && typeof status.get('reblog') === 'object') {
|
||||
status = status.get('reblog');
|
||||
}
|
||||
|
||||
if (status.get('quote', null) === null) {
|
||||
return {
|
||||
quote_muted: status.get('quote_id', null) ? true : false,
|
||||
};
|
||||
}
|
||||
const id = status.getIn(['quote', 'account', 'id'], null);
|
||||
|
||||
return {
|
||||
quote_muted: id !== null && (state.getIn(['relationships', id, 'muting']) || state.getIn(['relationships', id, 'blocking']) || state.getIn(['relationships', id, 'blocked_by']) || state.getIn(['relationships', id, 'domain_blocking'])) || status.getIn(['quote', 'quote_muted']),
|
||||
};
|
||||
};
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class DetailedStatus extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
|
@ -33,6 +58,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map,
|
||||
quote_muted: PropTypes.bool,
|
||||
onOpenMedia: PropTypes.func.isRequired,
|
||||
onOpenVideo: PropTypes.func.isRequired,
|
||||
onToggleHidden: PropTypes.func.isRequired,
|
||||
|
@ -120,6 +146,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||
|
||||
render () {
|
||||
const status = (this.props.status && this.props.status.get('reblog')) ? this.props.status.get('reblog') : this.props.status;
|
||||
const quote_muted = this.props.quote_muted
|
||||
const outerStyle = { boxSizing: 'border-box' };
|
||||
const { intl, compact, pictureInPicture } = this.props;
|
||||
|
||||
|
@ -194,15 +221,33 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
quote = (
|
||||
<div className='quote-status'>
|
||||
<a href={quote_status.getIn(['account', 'url'])} onClick={this.handleAccountClick} className='detailed-status__display-name'>
|
||||
<div className='detailed-status__display-avatar'><Avatar account={quote_status.get('account')} size={18} /></div>
|
||||
<DisplayName account={quote_status.get('account')} localDomain={this.props.domain} />
|
||||
</a>
|
||||
if (quote_muted) {
|
||||
quote = (
|
||||
<div className='quote-status'>
|
||||
<div className='status__content muted-quote'>
|
||||
<FormattedMessage id='status.muted_quote' defaultMessage='Muted quote' />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
quote = (
|
||||
<div className='quote-status'>
|
||||
<a href={quote_status.getIn(['account', 'url'])} onClick={this.handleAccountClick} className='detailed-status__display-name'>
|
||||
<div className='detailed-status__display-avatar'><Avatar account={quote_status.get('account')} size={18} /></div>
|
||||
<DisplayName account={quote_status.get('account')} localDomain={this.props.domain} />
|
||||
</a>
|
||||
|
||||
<StatusContent status={quote_status} onClick={this.handleQuoteClick} expanded={!status.get('quote_hidden')} onExpandedToggle={this.handleExpandedQuoteToggle} quote />
|
||||
{quote_media}
|
||||
<StatusContent status={quote_status} onClick={this.handleQuoteClick} expanded={!status.get('quote_hidden')} onExpandedToggle={this.handleExpandedQuoteToggle} quote />
|
||||
{quote_media}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
} else if (quote_muted) {
|
||||
quote = (
|
||||
<div className={classNames('quote-status', { muted: this.props.muted })}>
|
||||
<div className={classNames('status__content muted-quote', { 'status__content--with-action': this.context.router })}>
|
||||
<FormattedMessage id='status.muted_quote' defaultMessage='Muted quote' />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -457,6 +457,10 @@
|
|||
"defaultMessage": "Unlisted quote",
|
||||
"id": "status.unlisted_quote"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Muted quote",
|
||||
"id": "status.muted_quote"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Favourite",
|
||||
"id": "status.favourite"
|
||||
|
|
|
@ -401,11 +401,12 @@
|
|||
"status.more": "More",
|
||||
"status.mute": "Mute @{name}",
|
||||
"status.mute_conversation": "Mute conversation",
|
||||
"status.muted_quote": "Muted quote",
|
||||
"status.open": "Expand this post",
|
||||
"status.pin": "Pin on profile",
|
||||
"status.pinned": "Pinned post",
|
||||
"status.read_more": "Read more",
|
||||
"status.quote": "Quote",
|
||||
"status.read_more": "Read more",
|
||||
"status.reblog": "Boost",
|
||||
"status.reblog_private": "Boost with original visibility",
|
||||
"status.reblogged_by": "{name} boosted",
|
||||
|
@ -424,6 +425,7 @@
|
|||
"status.show_poll": "Show poll",
|
||||
"status.show_thread": "Show thread",
|
||||
"status.uncached_media_warning": "Not available",
|
||||
"status.unlisted_quote": "Unlisted quote",
|
||||
"status.unmute_conversation": "Unmute conversation",
|
||||
"status.unpin": "Unpin from profile",
|
||||
"suggestions.dismiss": "Dismiss suggestion",
|
||||
|
|
|
@ -401,12 +401,12 @@
|
|||
"status.more": "もっと見る",
|
||||
"status.mute": "@{name}さんをミュート",
|
||||
"status.mute_conversation": "会話をミュート",
|
||||
"status.muted_quote": "ミュートされた引用",
|
||||
"status.open": "詳細を表示",
|
||||
"status.pin": "プロフィールに固定表示",
|
||||
"status.pinned": "固定された投稿",
|
||||
"status.read_more": "もっと見る",
|
||||
"status.quote": "引用",
|
||||
"status.unlisted_quote": "未収載の引用",
|
||||
"status.read_more": "もっと見る",
|
||||
"status.reblog": "ブースト",
|
||||
"status.reblog_private": "ブースト",
|
||||
"status.reblogged_by": "{name}さんがブースト",
|
||||
|
@ -425,6 +425,7 @@
|
|||
"status.show_poll": "アンケートを表示",
|
||||
"status.show_thread": "スレッドを表示",
|
||||
"status.uncached_media_warning": "利用できません",
|
||||
"status.unlisted_quote": "未収載の引用",
|
||||
"status.unmute_conversation": "会話のミュートを解除",
|
||||
"status.unpin": "プロフィールへの固定を解除",
|
||||
"suggestions.dismiss": "隠す",
|
||||
|
|
|
@ -88,22 +88,49 @@ export const makeGetStatus = () => {
|
|||
[
|
||||
(state, { id }) => state.getIn(['statuses', id]),
|
||||
(state, { id }) => state.getIn(['statuses', state.getIn(['statuses', id, 'reblog'])]),
|
||||
(state, { id }) => state.getIn(['statuses', state.getIn(['statuses', id, 'quote_id'])]),
|
||||
(state, { id }) => state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]),
|
||||
(state, { id }) => state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), 'account'])]),
|
||||
(state, { id }) => state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'quote_id']), 'account'])]),
|
||||
(state, { id }) => state.getIn(['relationships', state.getIn(['statuses', id, 'account'])]),
|
||||
(state, { id }) => state.getIn(['relationships', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), 'account'])]),
|
||||
(state, { id }) => state.getIn(['relationships', state.getIn(['statuses', state.getIn(['statuses', id, 'quote_id']), 'account'])]),
|
||||
(state, { id }) => state.getIn(['accounts', state.getIn(['accounts', state.getIn(['statuses', id, 'account']), 'moved'])]),
|
||||
(state, { id }) => state.getIn(['accounts', state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), 'account']), 'moved'])]),
|
||||
(state, { id }) => state.getIn(['accounts', state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'quote_id']), 'account']), 'moved'])]),
|
||||
getFiltersRegex,
|
||||
],
|
||||
|
||||
(statusBase, statusReblog, accountBase, accountReblog, filtersRegex) => {
|
||||
(statusBase, statusReblog, statusQuote, accountBase, accountReblog, accountQuote, relationship, reblogRelationship, quoteRelationship, moved, reblogMoved, quoteMoved, filtersRegex) => {
|
||||
if (!statusBase) {
|
||||
return null;
|
||||
}
|
||||
|
||||
accountBase = accountBase.withMutations(map => {
|
||||
map.set('relationship', relationship);
|
||||
map.set('moved', moved);
|
||||
});
|
||||
|
||||
if (statusReblog) {
|
||||
accountReblog = accountReblog.withMutations(map => {
|
||||
map.set('relationship', reblogRelationship);
|
||||
map.set('moved', reblogMoved);
|
||||
});
|
||||
statusReblog = statusReblog.set('account', accountReblog);
|
||||
} else {
|
||||
statusReblog = null;
|
||||
}
|
||||
|
||||
if (statusQuote) {
|
||||
accountQuote = accountQuote.withMutations(map => {
|
||||
map.set('relationship', quoteRelationship);
|
||||
map.set('moved', quoteMoved);
|
||||
});
|
||||
statusQuote = statusQuote.set('account', accountQuote);
|
||||
} else {
|
||||
statusQuote = null;
|
||||
}
|
||||
|
||||
const dropRegex = (accountReblog || accountBase).get('id') !== me && filtersRegex[0];
|
||||
if (dropRegex && dropRegex.test(statusBase.get('reblog') ? statusReblog.get('search_index') : statusBase.get('search_index'))) {
|
||||
return null;
|
||||
|
@ -114,6 +141,7 @@ export const makeGetStatus = () => {
|
|||
|
||||
return statusBase.withMutations(map => {
|
||||
map.set('reblog', statusReblog);
|
||||
map.set('quote', statusQuote);
|
||||
map.set('account', accountBase);
|
||||
map.set('filtered', filtered);
|
||||
});
|
||||
|
|
3
app/javascript/mastodon/utils/uniq.js
Normal file
3
app/javascript/mastodon/utils/uniq.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
export const uniq = array => {
|
||||
return array.filter((x, i, self) => self.indexOf(x) === i)
|
||||
};
|
|
@ -1036,6 +1036,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
& > .muted-quote {
|
||||
color: $dark-text-color;
|
||||
font-weight: 500;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
.status__avatar,
|
||||
.detailed-status__display-avatar {
|
||||
height: 18px;
|
||||
|
@ -1531,77 +1537,6 @@ a .account__avatar {
|
|||
}
|
||||
}
|
||||
|
||||
.account__action-bar {
|
||||
border-top: 1px solid lighten($ui-base-color, 8%);
|
||||
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
||||
line-height: 36px;
|
||||
overflow: hidden;
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.account__action-bar-dropdown {
|
||||
padding: 10px;
|
||||
|
||||
.icon-button {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.dropdown--active {
|
||||
.dropdown__content.dropdown__right {
|
||||
left: 6px;
|
||||
right: initial;
|
||||
}
|
||||
|
||||
&::after {
|
||||
bottom: initial;
|
||||
margin-left: 11px;
|
||||
margin-top: -7px;
|
||||
right: initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.account__action-bar-links {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
line-height: 18px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.account__action-bar__tab {
|
||||
text-decoration: none;
|
||||
overflow: hidden;
|
||||
flex: 0 1 100%;
|
||||
border-right: 1px solid lighten($ui-base-color, 8%);
|
||||
padding: 10px 0;
|
||||
border-bottom: 4px solid transparent;
|
||||
|
||||
&.active {
|
||||
border-bottom: 4px solid $ui-highlight-color;
|
||||
}
|
||||
|
||||
& > span {
|
||||
display: block;
|
||||
text-transform: uppercase;
|
||||
font-size: 11px;
|
||||
color: $darker-text-color;
|
||||
}
|
||||
|
||||
strong {
|
||||
display: block;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: $primary-text-color;
|
||||
|
||||
@each $lang in $cjk-langs {
|
||||
&:lang(#{$lang}) {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.account-authorize {
|
||||
padding: 14px 10px;
|
||||
|
||||
|
@ -1688,6 +1623,15 @@ a.account__display-name {
|
|||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.account__action-bar {
|
||||
position: absolute;
|
||||
height: 24px;
|
||||
width: 48px;
|
||||
top: 60px;
|
||||
left: 10px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.status__avatar {
|
||||
height: 48px;
|
||||
left: 10px;
|
||||
|
@ -2456,6 +2400,11 @@ a.account__display-name {
|
|||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.account__action-bar {
|
||||
top: 67px;
|
||||
left: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,6 +178,16 @@ class REST::NestedQuoteSerializer < REST::StatusSerializer
|
|||
attribute :quote do
|
||||
nil
|
||||
end
|
||||
attribute :quote_muted, if: :current_user?
|
||||
|
||||
def quote_muted
|
||||
if instance_options && instance_options[:account_relationships]
|
||||
instance_options[:account_relationships].muting[object.account_id] ? true : false || instance_options[:account_relationships].blocking[object.account_id] || instance_options[:account_relationships].blocked_by[object.account_id] || instance_options[:account_relationships].domain_blocking[object.account_id] || false
|
||||
else
|
||||
current_user.account.muting?(object.account) || object.account.blocking?(current_user.account) || current_user.account.blocking?(object.account) || current_user.account.domain_blocking?(object.account.domain)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class REST::StatusSerializer < ActiveModel::Serializer
|
||||
|
|
Loading…
Reference in a new issue