1
0
Fork 0
forked from gitea/nas

Remove: kmyblue独自機能の引用

This commit is contained in:
KMY 2025-04-24 08:48:28 +09:00
parent 620a895184
commit d845d1e9fb
70 changed files with 812 additions and 1788 deletions

View file

@ -56,11 +56,11 @@ class Api::V1::FiltersController < Api::BaseController
end
def resource_params
params.permit(:phrase, :expires_in, :irreversible, :exclude_follows, :exclude_localusers, :with_quote, :with_profile, :whole_word, context: [])
params.permit(:phrase, :expires_in, :irreversible, :exclude_follows, :exclude_localusers, :with_profile, :whole_word, context: [])
end
def filter_params
resource_params.slice(:phrase, :expires_in, :irreversible, :exclude_follows, :exclude_localusers, :with_quote, :with_profile, :context)
resource_params.slice(:phrase, :expires_in, :irreversible, :exclude_follows, :exclude_localusers, :with_profile, :context)
end
def keyword_params

View file

@ -43,6 +43,6 @@ class Api::V2::FiltersController < Api::BaseController
end
def resource_params
params.permit(:title, :expires_in, :filter_action, :exclude_follows, :exclude_localusers, :with_quote, :with_profile, context: [], keywords_attributes: [:id, :keyword, :whole_word, :_destroy])
params.permit(:title, :expires_in, :filter_action, :exclude_follows, :exclude_localusers, :with_profile, context: [], keywords_attributes: [:id, :keyword, :whole_word, :_destroy])
end
end

View file

@ -47,6 +47,6 @@ class FiltersController < ApplicationController
end
def resource_params
params.expect(custom_filter: [:title, :expires_in, :filter_action, :exclude_follows, :exclude_localusers, :exclude_quote, :exclude_profile, context: [], keywords_attributes: [[:id, :keyword, :whole_word, :_destroy]]])
params.expect(custom_filter: [:title, :expires_in, :filter_action, :exclude_follows, :exclude_localusers, :exclude_profile, context: [], keywords_attributes: [[:id, :keyword, :whole_word, :_destroy]]])
end
end

View file

@ -29,7 +29,6 @@ module ContextHelper
limited_scope: { 'kmyblue' => 'http://kmy.blue/ns#', 'limitedScope' => 'kmyblue:limitedScope' },
other_setting: { 'fedibird' => 'http://fedibird.com/ns#', 'otherSetting' => 'fedibird:otherSetting' },
references: { 'fedibird' => 'http://fedibird.com/ns#', 'references' => { '@id' => 'fedibird:references', '@type' => '@id' } },
quote_uri: { 'fedibird' => 'http://fedibird.com/ns#', 'quoteUri' => 'fedibird:quoteUri' },
keywords: { 'schema' => 'http://schema.org#', 'keywords' => 'schema:keywords' },
license: { 'schema' => 'http://schema.org#', 'license' => 'schema:license' },
suspended: { 'toot' => 'http://joinmastodon.org/ns#', 'suspended' => 'toot:suspended' },

View file

@ -15,7 +15,6 @@ module KmyblueCapabilitiesHelper
kmyblue_limited_scope
kmyblue_antenna
kmyblue_bookmark_category
kmyblue_quote
kmyblue_searchability_limited
kmyblue_circle_history
kmyblue_list_notification
@ -41,7 +40,6 @@ module KmyblueCapabilitiesHelper
capabilities = %i(
enable_wide_emoji
status_reference
quote
emoji_keywords
circle
)

View file

@ -70,10 +70,6 @@ export function importFetchedStatuses(statuses) {
processStatus(status.reblog);
}
if (status.quote?.id && !getState().getIn(['statuses', status.id])) {
processStatus(status.quote);
}
if (status.poll?.id) {
pushUnique(polls, createPollFromServerJSON(status.poll, getState().polls[status.poll.id]));
}

View file

@ -66,11 +66,6 @@ export function normalizeStatus(status, normalOldStatus) {
normalStatus.spoiler_text = normalOldStatus.get('spoiler_text');
normalStatus.hidden = normalOldStatus.get('hidden');
// for quoted post
if (!normalStatus.filtered && normalOldStatus.get('filtered')) {
normalStatus.filtered = normalOldStatus.get('filtered');
}
if (normalOldStatus.get('translation')) {
normalStatus.translation = normalOldStatus.get('translation');
}

View file

@ -33,7 +33,7 @@ const messages = defineMessages({
message_poll: { id: 'notification.poll', defaultMessage: 'A poll you voted in has ended' },
message_reblog: { id: 'notification.reblog', defaultMessage: '{name} boosted your post' },
message_status: { id: 'notification.status', defaultMessage: '{name} just posted' },
message_status_reference: { id: 'notification.status_reference', defaultMessage: '{name} quoted your post' },
message_status_reference: { id: 'notification.status_reference', defaultMessage: '{name} linked your post' },
message_update: { id: 'notification.update', defaultMessage: '{name} edited a post' },
});

View file

@ -20,7 +20,6 @@ export interface ApiAccountOtherSettingsJSON {
hide_followers_count: boolean;
translatable_private: boolean;
link_preview: boolean;
allow_quote: boolean;
emoji_reaction_policy:
| 'allow'
| 'outside_only'
@ -34,7 +33,6 @@ export interface ApiAccountOtherSettingsJSON {
export interface ApiServerFeaturesJSON {
circle: boolean;
emoji_reaction: boolean;
quote: boolean;
status_reference: boolean;
}

View file

@ -1,580 +0,0 @@
import PropTypes from 'prop-types';
import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { HotKeys } from 'react-hotkeys';
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react';
import PushPinIcon from '@/material-icons/400-24px/push_pin.svg?react';
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
import AttachmentList from 'mastodon/components/attachment_list';
import { ContentWarning } from 'mastodon/components/content_warning';
import { Icon } from 'mastodon/components/icon';
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
import { withOptionalRouter, WithOptionalRouterPropTypes } from 'mastodon/utils/react_router';
import Card from '../features/status/components/card';
// We use the component (and not the container) since we do not want
// to use the progress bar to show download progress
import Bundle from '../features/ui/components/bundle';
import { MediaGallery, Video, Audio } from '../features/ui/util/async-components';
import { SensitiveMediaContext } from '../features/ui/util/sensitive_media_context';
import { displayMedia } from '../initial_state';
import { Avatar } from './avatar';
import { DisplayName } from './display_name';
import { getHashtagBarForStatus } from './hashtag_bar';
import { RelativeTimestamp } from './relative_timestamp';
import StatusContent from './status_content';
import { VisibilityIcon } from './visibility_icon';
const domParser = new DOMParser();
export const textForScreenReader = (intl, status, rebloggedByText = false) => {
const displayName = status.getIn(['account', 'display_name']);
const spoilerText = status.getIn(['translation', 'spoiler_text']) || status.get('spoiler_text');
const contentHtml = status.getIn(['translation', 'contentHtml']) || status.get('contentHtml');
const contentText = domParser.parseFromString(contentHtml, 'text/html').documentElement.textContent;
const values = [
displayName.length === 0 ? status.getIn(['account', 'acct']).split('@')[0] : displayName,
spoilerText && status.get('hidden') ? spoilerText : contentText,
intl.formatDate(status.get('created_at'), { hour: '2-digit', minute: '2-digit', month: 'short', day: 'numeric' }),
status.getIn(['account', 'acct']),
];
if (rebloggedByText) {
values.push(rebloggedByText);
}
return values.join(', ');
};
export const defaultMediaVisibility = (status) => {
if (!status) {
return undefined;
}
if (status.get('reblog', null) !== null && typeof status.get('reblog') === 'object') {
status = status.get('reblog');
}
return (displayMedia !== 'hide_all' && !status.get('sensitive') || displayMedia === 'show_all');
};
const messages = defineMessages({
limited_short: { id: 'privacy.limited.short', defaultMessage: 'Limited' },
edited: { id: 'status.edited', defaultMessage: 'Edited {date}' },
});
class CompactedStatus extends ImmutablePureComponent {
static contextType = SensitiveMediaContext;
static propTypes = {
status: ImmutablePropTypes.map,
account: ImmutablePropTypes.record,
previousId: PropTypes.string,
nextInReplyToId: PropTypes.string,
rootId: PropTypes.string,
onClick: PropTypes.func,
onReply: PropTypes.func,
onFavourite: PropTypes.func,
onEmojiReact: PropTypes.func,
onUnEmojiReact: PropTypes.func,
onReblog: PropTypes.func,
onReblogForceModal: PropTypes.func,
onDelete: PropTypes.func,
onDirect: PropTypes.func,
onMention: PropTypes.func,
onPin: PropTypes.func,
onOpenMedia: PropTypes.func,
onOpenVideo: PropTypes.func,
onBlock: PropTypes.func,
onAddFilter: PropTypes.func,
onEmbed: PropTypes.func,
onHeightChange: PropTypes.func,
onToggleHidden: PropTypes.func,
onToggleCollapsed: PropTypes.func,
onTranslate: PropTypes.func,
onInteractionModal: PropTypes.func,
muted: PropTypes.bool,
hidden: PropTypes.bool,
unread: PropTypes.bool,
onMoveUp: PropTypes.func,
onMoveDown: PropTypes.func,
showThread: PropTypes.bool,
getScrollPosition: PropTypes.func,
updateScrollBottom: PropTypes.func,
cacheMediaWidth: PropTypes.func,
cachedMediaWidth: PropTypes.number,
scrollKey: PropTypes.string,
skipPrepend: PropTypes.bool,
deployPictureInPicture: PropTypes.func,
unfocusable: PropTypes.bool,
pictureInPicture: ImmutablePropTypes.contains({
inUse: PropTypes.bool,
available: PropTypes.bool,
}),
withoutEmojiReactions: PropTypes.bool,
...WithOptionalRouterPropTypes,
};
// Avoid checking props that are functions (and whose equality will always
// evaluate to false. See react-immutable-pure-component for usage.
updateOnProps = [
'status',
'account',
'muted',
'hidden',
'unread',
'pictureInPicture',
];
state = {
showMedia: defaultMediaVisibility(this.props.status) && !(this.context?.hideMediaByDefault),
};
componentDidUpdate (prevProps) {
// This will potentially cause a wasteful redraw, but in most cases `Status` components are used
// with a `key` directly depending on their `id`, preventing re-use of the component across
// different IDs.
// But just in case this does change, reset the state on status change.
if (this.props.status?.get('id') !== prevProps.status?.get('id')) {
this.setState({
showMedia: defaultMediaVisibility(this.props.status) && !(this.context?.hideMediaByDefault),
});
}
}
handleToggleMediaVisibility = () => {
this.setState({ showMedia: !this.state.showMedia });
};
handleClick = e => {
if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) {
return;
}
if (e) {
e.preventDefault();
}
this.handleHotkeyOpen();
};
handlePrependAccountClick = e => {
this.handleAccountClick(e, false);
};
handleAccountClick = (e, proper = true) => {
if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) {
return;
}
if (e) {
e.preventDefault();
e.stopPropagation();
}
this._openProfile(proper);
};
handleExpandedToggle = () => {
this.props.onToggleHidden(this._properStatus());
};
handleCollapsedToggle = isCollapsed => {
this.props.onToggleCollapsed(this._properStatus(), isCollapsed);
};
handleTranslate = () => {
this.props.onTranslate(this._properStatus());
};
getAttachmentAspectRatio () {
const attachments = this._properStatus().get('media_attachments');
if (attachments.getIn([0, 'type']) === 'video') {
return `${attachments.getIn([0, 'meta', 'original', 'width'])} / ${attachments.getIn([0, 'meta', 'original', 'height'])}`;
} else if (attachments.getIn([0, 'type']) === 'audio') {
return '16 / 9';
} else {
return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2';
}
}
renderLoadingMediaGallery = () => {
return (
<div className='media-gallery' style={{ aspectRatio: this.getAttachmentAspectRatio() }} />
);
};
renderLoadingVideoPlayer = () => {
return (
<div className='video-player' style={{ aspectRatio: this.getAttachmentAspectRatio() }} />
);
};
renderLoadingAudioPlayer = () => {
return (
<div className='audio-player' style={{ aspectRatio: this.getAttachmentAspectRatio() }} />
);
};
handleOpenVideo = (options) => {
const status = this._properStatus();
const lang = status.getIn(['translation', 'language']) || status.get('language');
this.props.onOpenVideo(status.get('id'), status.getIn(['media_attachments', 0]), lang, options);
};
handleOpenMedia = (media, index) => {
const status = this._properStatus();
const lang = status.getIn(['translation', 'language']) || status.get('language');
this.props.onOpenMedia(status.get('id'), media, index, lang);
};
handleHotkeyOpenMedia = e => {
const { onOpenMedia, onOpenVideo } = this.props;
const status = this._properStatus();
e.preventDefault();
if (status.get('media_attachments').size > 0) {
const lang = status.getIn(['translation', 'language']) || status.get('language');
if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
onOpenVideo(status.get('id'), status.getIn(['media_attachments', 0]), lang, { startTime: 0 });
} else {
onOpenMedia(status.get('id'), status.get('media_attachments'), 0, lang);
}
}
};
handleDeployPictureInPicture = (type, mediaProps) => {
const { deployPictureInPicture } = this.props;
const status = this._properStatus();
deployPictureInPicture(status, type, mediaProps);
};
handleHotkeyReply = e => {
e.preventDefault();
this.props.onReply(this._properStatus());
};
handleHotkeyFavourite = () => {
this.props.onFavourite(this._properStatus());
};
handleHotkeyBoost = e => {
this.props.onReblog(this._properStatus(), e);
};
handleHotkeyMention = e => {
e.preventDefault();
this.props.onMention(this._properStatus().get('account'));
};
handleHotkeyOpen = () => {
if (this.props.onClick) {
this.props.onClick();
return;
}
const { history } = this.props;
const status = this._properStatus();
if (!history) {
return;
}
history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);
};
handleHotkeyOpenProfile = () => {
this._openProfile();
};
_openProfile = (proper = true) => {
const { history } = this.props;
const status = proper ? this._properStatus() : this.props.status;
if (!history) {
return;
}
history.push(`/@${status.getIn(['account', 'acct'])}`);
};
handleHotkeyMoveUp = e => {
this.props.onMoveUp(this.props.status.get('id'), e.target.getAttribute('data-featured'));
};
handleHotkeyMoveDown = e => {
this.props.onMoveDown(this.props.status.get('id'), e.target.getAttribute('data-featured'));
};
handleHotkeyToggleHidden = () => {
const { onToggleHidden } = this.props;
const status = this._properStatus();
onToggleHidden(status);
};
handleHotkeyToggleSensitive = () => {
this.handleToggleMediaVisibility();
};
_properStatus () {
const { status } = this.props;
if (status.get('reblog', null) !== null && typeof status.get('reblog') === 'object') {
return status.get('reblog');
} else {
return status;
}
}
handleRef = c => {
this.node = c;
};
render () {
const { intl, hidden, featured, unfocusable, unread, showThread, pictureInPicture, previousId, nextInReplyToId, rootId, skipPrepend } = this.props;
let { status } = this.props;
if (status === null) {
return null;
}
const handlers = this.props.muted ? {} : {
reply: this.handleHotkeyReply,
favourite: this.handleHotkeyFavourite,
boost: this.handleHotkeyBoost,
mention: this.handleHotkeyMention,
open: this.handleHotkeyOpen,
openProfile: this.handleHotkeyOpenProfile,
moveUp: this.handleHotkeyMoveUp,
moveDown: this.handleHotkeyMoveDown,
toggleHidden: this.handleHotkeyToggleHidden,
toggleSensitive: this.handleHotkeyToggleSensitive,
openMedia: this.handleHotkeyOpenMedia,
};
let media, prepend, rebloggedByText;
if (hidden) {
return (
<HotKeys handlers={handlers} tabIndex={unfocusable ? null : -1}>
<div ref={this.handleRef} className={classNames('status__wrapper', { focusable: !this.props.muted })} tabIndex={unfocusable ? null : 0}>
<span>{status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])}</span>
<span>{status.get('content')}</span>
</div>
</HotKeys>
);
}
const connectUp = previousId && previousId === status.get('in_reply_to_id');
const connectToRoot = rootId && rootId === status.get('in_reply_to_id');
const connectReply = nextInReplyToId && nextInReplyToId === status.get('id');
let visibilityName = status.get('limited_scope') || status.get('visibility_ex') || status.get('visibility');
if (featured) {
prepend = (
<div className='status__prepend'>
<div className='status__prepend-icon-wrapper'><Icon id='thumb-tack' icon={PushPinIcon} className='status__prepend-icon' /></div>
<FormattedMessage id='status.pinned' defaultMessage='Pinned post' />
</div>
);
} else if (status.get('reblog', null) !== null && typeof status.get('reblog') === 'object') {
const display_name_html = { __html: status.getIn(['account', 'display_name_html']) };
prepend = (
<div className='status__prepend'>
<div className='status__prepend-icon-wrapper'><Icon id='retweet' icon={RepeatIcon} className='status__prepend-icon' /></div>
<div className='status__prepend-icon-wrapper'><VisibilityIcon visibility={visibilityName} className='status__prepend-icon' /></div>
<FormattedMessage id='status.reblogged_by' defaultMessage='{name} boosted' values={{ name: <a onClick={this.handlePrependAccountClick} data-id={status.getIn(['account', 'id'])} data-hover-card-account={status.getIn(['account', 'id'])} href={`/@${status.getIn(['account', 'acct'])}`} className='status__display-name muted'><bdi><strong dangerouslySetInnerHTML={display_name_html} /></bdi></a> }} />
</div>
);
rebloggedByText = intl.formatMessage({ id: 'status.reblogged_by', defaultMessage: '{name} boosted' }, { name: status.getIn(['account', 'acct']) });
status = status.get('reblog');
} else if (status.get('visibility') === 'direct') {
prepend = (
<div className='status__prepend'>
<div className='status__prepend-icon-wrapper'><Icon id='at' icon={AlternateEmailIcon} className='status__prepend-icon' /></div>
<FormattedMessage id='status.direct_indicator' defaultMessage='Private mention' />
</div>
);
} else if (showThread && status.get('in_reply_to_id') && status.get('in_reply_to_account_id') === status.getIn(['account', 'id'])) {
const display_name_html = { __html: status.getIn(['account', 'display_name_html']) };
prepend = (
<div className='status__prepend'>
<div className='status__prepend-icon-wrapper'><Icon id='reply' icon={ReplyIcon} className='status__prepend-icon' /></div>
<FormattedMessage id='status.replied_to' defaultMessage='Replied to {name}' values={{ name: <a onClick={this.handlePrependAccountClick} data-id={status.getIn(['account', 'id'])} data-hover-card-account={status.getIn(['account', 'id'])} href={`/@${status.getIn(['account', 'acct'])}`} className='status__display-name muted'><bdi><strong dangerouslySetInnerHTML={display_name_html} /></bdi></a> }} />
</div>
);
}
if (pictureInPicture.get('inUse')) {
media = <PictureInPicturePlaceholder aspectRatio={this.getAttachmentAspectRatio()} />;
} else if (status.get('media_attachments').size > 0) {
const language = status.getIn(['translation', 'language']) || status.get('language');
if (this.props.muted) {
media = (
<AttachmentList
compact
media={status.get('media_attachments')}
/>
);
} else if (status.getIn(['media_attachments', 0, 'type']) === 'audio') {
const attachment = status.getIn(['media_attachments', 0]);
const description = attachment.getIn(['translation', 'description']) || attachment.get('description');
media = (
<Bundle fetchComponent={Audio} loading={this.renderLoadingAudioPlayer} >
{Component => (
<Component
src={attachment.get('url')}
alt={description}
lang={language}
poster={attachment.get('preview_url') || status.getIn(['account', 'avatar_static'])}
backgroundColor={attachment.getIn(['meta', 'colors', 'background'])}
foregroundColor={attachment.getIn(['meta', 'colors', 'foreground'])}
accentColor={attachment.getIn(['meta', 'colors', 'accent'])}
duration={attachment.getIn(['meta', 'original', 'duration'], 0)}
width={this.props.cachedMediaWidth}
height={110}
cacheWidth={this.props.cacheMediaWidth}
deployPictureInPicture={pictureInPicture.get('available') ? this.handleDeployPictureInPicture : undefined}
sensitive={status.get('sensitive')}
blurhash={attachment.get('blurhash')}
visible={this.state.showMedia}
onToggleVisibility={this.handleToggleMediaVisibility}
/>
)}
</Bundle>
);
} else if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
const attachment = status.getIn(['media_attachments', 0]);
const description = attachment.getIn(['translation', 'description']) || attachment.get('description');
media = (
<Bundle fetchComponent={Video} loading={this.renderLoadingVideoPlayer} >
{Component => (
<Component
preview={attachment.get('preview_url')}
frameRate={attachment.getIn(['meta', 'original', 'frame_rate'])}
aspectRatio={`${attachment.getIn(['meta', 'original', 'width'])} / ${attachment.getIn(['meta', 'original', 'height'])}`}
blurhash={attachment.get('blurhash')}
src={attachment.get('url')}
alt={description}
lang={language}
sensitive={status.get('sensitive')}
onOpenVideo={this.handleOpenVideo}
deployPictureInPicture={pictureInPicture.get('available') ? this.handleDeployPictureInPicture : undefined}
visible={this.state.showMedia}
onToggleVisibility={this.handleToggleMediaVisibility}
/>
)}
</Bundle>
);
} else {
media = (
<Bundle fetchComponent={MediaGallery} loading={this.renderLoadingMediaGallery}>
{Component => (
<Component
media={status.get('media_attachments')}
lang={language}
sensitive={status.get('sensitive')}
height={110}
onOpenMedia={this.handleOpenMedia}
cacheWidth={this.props.cacheMediaWidth}
defaultWidth={this.props.cachedMediaWidth}
visible={this.state.showMedia}
onToggleVisibility={this.handleToggleMediaVisibility}
/>
)}
</Bundle>
);
}
} else if (status.get('card') && !this.props.muted) {
media = (
<Card
onOpenMedia={this.handleOpenMedia}
card={status.get('card')}
compact
sensitive={status.get('sensitive') && !status.get('spoiler_text')}
/>
);
}
visibilityName = status.get('limited_scope') || status.get('visibility_ex') || status.get('visibility');
const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status);
const expanded = !status.get('hidden') || status.get('spoiler_text').length === 0;
return (
<HotKeys handlers={handlers} tabIndex={unfocusable ? null : -1}>
<div className={classNames('status__wrapper', 'status__wrapper__compact', 'content-warning', 'content-warning--compacted-status', `status__wrapper-${status.get('visibility_ex')}`, { 'status__wrapper-reply': !!status.get('in_reply_to_id'), unread, focusable: !this.props.muted })} tabIndex={this.props.muted || unfocusable ? null : 0} data-featured={featured ? 'true' : null} aria-label={textForScreenReader(intl, status, rebloggedByText)} ref={this.handleRef} data-nosnippet={status.getIn(['account', 'noindex'], true) || undefined}>
{!skipPrepend && prepend}
<div className={classNames('status', `status-${status.get('visibility_ex')}`, { 'status-reply': !!status.get('in_reply_to_id'), 'status--in-thread': !!rootId, 'status--first-in-thread': previousId && (!connectUp || connectToRoot), muted: this.props.muted })} data-id={status.get('id')}>
{(connectReply || connectUp || connectToRoot) && <div className={classNames('status__line', { 'status__line--full': connectReply, 'status__line--first': !status.get('in_reply_to_id') && !connectToRoot })} />}
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
<div onClick={this.handleClick} className='status__info'>
<a href={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} className='status__relative-time' target='_blank' rel='noopener noreferrer'>
<span className='status__visibility-icon'><VisibilityIcon visibility={visibilityName} /></span>
<RelativeTimestamp timestamp={status.get('created_at')} />{status.get('edited_at') && <abbr title={intl.formatMessage(messages.edited, { date: intl.formatDate(status.get('edited_at'), { year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) })}> *</abbr>}
</a>
<a onClick={this.handleAccountClick} href={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} data-hover-card-account={status.getIn(['account', 'id'])} className='status__display-name' target='_blank' rel='noopener noreferrer'>
<div className='status__avatar__compact'>
<Avatar account={status.get('account')} size={32} inline />
</div>
<DisplayName account={status.get('account')} />
</a>
</div>
{status.get('spoiler_text').length > 0 && <ContentWarning text={status.getIn(['translation', 'spoilerHtml']) || status.get('spoilerHtml')} expanded={expanded} onClick={this.handleExpandedToggle} />}
{expanded && (
<>
<StatusContent
status={status}
onClick={this.handleClick}
onTranslate={this.handleTranslate}
collapsible
onCollapsedToggle={this.handleCollapsedToggle}
{...statusContentProps}
/>
{media}
{hashtagBar}
</>
)}
</div>
</div>
</HotKeys>
);
}
}
export default withOptionalRouter(injectIntl(CompactedStatus));

View file

@ -12,7 +12,6 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import { HotKeys } from 'react-hotkeys';
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react';
import QuoteIcon from '@/material-icons/400-24px/format_quote.svg?react';
import ReferenceIcon from '@/material-icons/400-24px/link.svg?react';
import PushPinIcon from '@/material-icons/400-24px/push_pin.svg?react';
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
@ -25,7 +24,6 @@ import { Icon } from 'mastodon/components/icon';
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
import { withOptionalRouter, WithOptionalRouterPropTypes } from 'mastodon/utils/react_router';
import CompactedStatusContainer from '../containers/compacted_status_container';
import Card from '../features/status/components/card';
// We use the component (and not the container) since we do not want
// to use the progress bar to show download progress
@ -136,7 +134,6 @@ class Status extends ImmutablePureComponent {
available: PropTypes.bool,
}),
withoutEmojiReactions: PropTypes.bool,
withoutQuote: PropTypes.bool,
...WithOptionalRouterPropTypes,
};
@ -382,7 +379,7 @@ class Status extends ImmutablePureComponent {
};
render () {
const { intl, hidden, featured, unfocusable, unread, showThread, scrollKey, pictureInPicture, previousId, rootId, withoutQuote, skipPrepend, avatarSize = 46 } = this.props;
const { intl, hidden, featured, unfocusable, unread, showThread, scrollKey, pictureInPicture, previousId, rootId, skipPrepend, avatarSize = 46 } = this.props;
let { status, account, ...other } = this.props;
@ -582,12 +579,9 @@ class Status extends ImmutablePureComponent {
const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status);
const withLimited = status.get('visibility_ex') === 'limited' && status.get('limited_scope') ? <span className='status__visibility-icon'><Icon id='get-pocket' icon={LimitedIcon} title={intl.formatMessage(messages.limited_short)} /></span> : null;
const withQuote = status.get('quote_id') ? <span className='status__visibility-icon'><Icon id='quote-right' icon={QuoteIcon} title='Quote' /></span> : null;
const withReference = (!withQuote && status.get('status_references_count') > 0) ? <span className='status__visibility-icon'><Icon id='link' icon={ReferenceIcon} title='Quiet quote' /></span> : null;
const withReference = status.get('status_references_count') > 0 ? <span className='status__visibility-icon'><Icon id='link' icon={ReferenceIcon} title='Link' /></span> : null;
const withExpiration = status.get('expires_at') ? <span className='status__visibility-icon'><Icon id='clock-o' icon={TimerIcon} title='Expiration' /></span> : null;
const quote = !this.props.muted && !withoutQuote && status.get('quote_id') && (['public', 'community'].includes(contextType) ? isShowItem('quote_in_public') : isShowItem('quote_in_home')) && <CompactedStatusContainer id={status.get('quote_id')} history={this.props.history} />;
return (
<HotKeys handlers={handlers} tabIndex={unfocusable ? null : -1}>
<div className={classNames('status__wrapper', `status__wrapper-${status.get('visibility_ex')}`, { 'status__wrapper-reply': !!status.get('in_reply_to_id'), unread, focusable: !this.props.muted })} tabIndex={this.props.muted || unfocusable ? null : 0} data-featured={featured ? 'true' : null} aria-label={textForScreenReader(intl, status, rebloggedByText)} ref={this.handleRef} data-nosnippet={status.getIn(['account', 'noindex'], true) || undefined}>
@ -598,7 +592,6 @@ class Status extends ImmutablePureComponent {
{(!matchedFilters || expanded || isShowItem('avatar_on_filter')) && (
<div onMouseUp={this.handleMouseUp} className='status__info'>
<Link to={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} className='status__relative-time'>
{withQuote}
{withReference}
{withExpiration}
{withLimited}
@ -633,7 +626,6 @@ class Status extends ImmutablePureComponent {
{media}
{hashtagBar}
{quote}
{emojiReactionsBar}
</>
)}

View file

@ -68,8 +68,7 @@ const messages = defineMessages({
admin_status: { id: 'status.admin_status', defaultMessage: 'Open this post in the moderation interface' },
admin_domain: { id: 'status.admin_domain', defaultMessage: 'Open moderation interface for {domain}' },
copy: { id: 'status.copy', defaultMessage: 'Copy link to post' },
reference: { id: 'status.reference', defaultMessage: 'Quiet quote' },
quote: { id: 'status.quote', defaultMessage: 'Quote' },
reference: { id: 'status.reference', defaultMessage: 'Link' },
blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' },
unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' },
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
@ -110,7 +109,6 @@ class StatusActionBar extends ImmutablePureComponent {
onFilter: PropTypes.func,
onAddFilter: PropTypes.func,
onReference: PropTypes.func,
onQuote: PropTypes.func,
onInteractionModal: PropTypes.func,
withDismiss: PropTypes.bool,
withCounters: PropTypes.bool,
@ -288,10 +286,6 @@ class StatusActionBar extends ImmutablePureComponent {
this.props.onReference(this.props.status, this.props.history);
};
handleQuote = () => {
this.props.onQuote(this.props.status, this.props.history);
};
render () {
const { status, relationship, intl, withDismiss, withCounters, scrollKey } = this.props;
const { signedIn, permissions } = this.props.identity;
@ -303,7 +297,6 @@ class StatusActionBar extends ImmutablePureComponent {
const account = status.get('account');
const writtenByMe = status.getIn(['account', 'id']) === me;
const isRemote = status.getIn(['account', 'username']) !== status.getIn(['account', 'acct']);
const allowQuote = status.getIn(['account', 'other_settings', 'allow_quote']);
let menu = [];
@ -335,10 +328,6 @@ class StatusActionBar extends ImmutablePureComponent {
}
if (!boostMenu) {
if (publicStatus && allowQuote && (account.getIn(['server_features', 'quote']) || !isHideItem('quote_unavailable_server'))) {
menu.push({ text: intl.formatMessage(messages.quote), action: this.handleQuote, tag: 'reblog' });
}
if (account.getIn(['server_features', 'status_reference']) || !isHideItem('status_reference_unavailable_server')) {
menu.push({ text: intl.formatMessage(messages.reference), action: this.handleReference, tag: 'reblog' });
}
@ -423,10 +412,6 @@ class StatusActionBar extends ImmutablePureComponent {
}
if (publicStatus) {
if (allowQuote && (account.getIn(['server_features', 'quote']) || !isHideItem('quote_unavailable_server'))) {
reblogMenu.push({ text: intl.formatMessage(messages.quote), action: this.handleQuote });
}
if (account.getIn(['server_features', 'status_reference']) || !isHideItem('status_reference_unavailable_server')) {
reblogMenu.push({ text: intl.formatMessage(messages.reference), action: this.handleReference });
}

View file

@ -1,78 +0,0 @@
import { injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import { openModal } from '../actions/modal';
import {
hideStatus,
revealStatus,
toggleStatusCollapse,
translateStatus,
undoStatusTranslation,
} from '../actions/statuses';
import CompactedStatus from '../components/compacted_status';
import { makeGetStatus, makeGetPictureInPicture } from '../selectors';
const makeMapStateToProps = () => {
const getStatus = makeGetStatus();
const getPictureInPicture = makeGetPictureInPicture();
const mapStateToProps = (state, props) => ({
status: getStatus(state, props),
nextInReplyToId: props.nextId ? state.getIn(['statuses', props.nextId, 'in_reply_to_id']) : null,
pictureInPicture: getPictureInPicture(state, props),
});
return mapStateToProps;
};
const mapDispatchToProps = (dispatch) => ({
onTranslate (status) {
if (status.get('translation')) {
dispatch(undoStatusTranslation(status.get('id'), status.get('poll')));
} else {
dispatch(translateStatus(status.get('id')));
}
},
onOpenMedia (statusId, media, index, lang) {
dispatch(openModal({
modalType: 'MEDIA',
modalProps: { statusId, media, index, lang },
}));
},
onOpenVideo (statusId, media, lang, options) {
dispatch(openModal({
modalType: 'VIDEO',
modalProps: { statusId, media, lang, options },
}));
},
onToggleHidden (status) {
if (status.get('hidden')) {
dispatch(revealStatus(status.get('id')));
} else {
dispatch(hideStatus(status.get('id')));
}
},
onToggleCollapsed (status, isCollapsed) {
dispatch(toggleStatusCollapse(status.get('id'), isCollapsed));
},
onInteractionModal (type, status) {
dispatch(openModal({
modalType: 'INTERACTION',
modalProps: {
type,
accountId: status.getIn(['account', 'id']),
url: status.get('uri'),
},
}));
},
});
export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(CompactedStatus));

View file

@ -152,10 +152,6 @@ const mapDispatchToProps = (dispatch, { contextType }) => ({
dispatch(insertReferenceCompose(0, status.get('url'), 'BT', router));
},
onQuote (status, router) {
dispatch(insertReferenceCompose(0, status.get('url'), 'QT', router));
},
onTranslate (status) {
if (status.get('translation')) {
dispatch(undoStatusTranslation(status.get('id'), status.get('poll')));

View file

@ -164,7 +164,7 @@ class ColumnSettings extends PureComponent {
<section>
<div role='group' aria-labelledby='notifications-status_reference'>
<h3 id='notifications-status_reference'><FormattedMessage id='notifications.column_settings.status_reference' defaultMessage='Quotes:' /></h3>
<h3 id='notifications-status_reference'><FormattedMessage id='notifications.column_settings.status_reference' defaultMessage='Links:' /></h3>
<div className='column-settings__row'>
<SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'status_reference']} onChange={onChange} label={alertStr} />

View file

@ -42,7 +42,7 @@ const messages = defineMessages({
reblog: { id: 'notification.reblog', defaultMessage: '{name} boosted your post' },
status: { id: 'notification.status', defaultMessage: '{name} just posted' },
listStatus: { id: 'notification.list_status', defaultMessage: '{name} post is added to {listName}' },
statusReference: { id: 'notification.status_reference', defaultMessage: '{name} quoted your post' },
statusReference: { id: 'notification.status_reference', defaultMessage: '{name} linked your post' },
update: { id: 'notification.update', defaultMessage: '{name} edited a post' },
adminSignUp: { id: 'notification.admin.sign_up', defaultMessage: '{name} signed up' },
adminReport: { id: 'notification.admin.report', defaultMessage: '{name} reported {target}' },
@ -305,7 +305,7 @@ class Notification extends ImmutablePureComponent {
</div>
<span title={notification.get('created_at')}>
<FormattedMessage id='notification.status_reference' defaultMessage='{name} quoted your post' values={{ name: link }} />
<FormattedMessage id='notification.status_reference' defaultMessage='{name} linked your post' values={{ name: link }} />
</span>
</div>

View file

@ -9,7 +9,7 @@ import { NotificationWithStatus } from './notification_with_status';
const labelRenderer: LabelRenderer = (displayedName) => (
<FormattedMessage
id='notification.status_reference'
defaultMessage='{name} quoted your post'
defaultMessage='{name} linked your post'
values={{ name: displayedName }}
/>
);

View file

@ -64,8 +64,7 @@ const messages = defineMessages({
admin_status: { id: 'status.admin_status', defaultMessage: 'Open this post in the moderation interface' },
admin_domain: { id: 'status.admin_domain', defaultMessage: 'Open moderation interface for {domain}' },
copy: { id: 'status.copy', defaultMessage: 'Copy link to post' },
reference: { id: 'status.reference', defaultMessage: 'Quiet quote' },
quote: { id: 'status.quote', defaultMessage: 'Quote' },
reference: { id: 'status.reference', defaultMessage: 'Link' },
blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' },
unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' },
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
@ -89,7 +88,6 @@ class ActionBar extends PureComponent {
onFavourite: PropTypes.func.isRequired,
onEmojiReact: PropTypes.func.isRequired,
onReference: PropTypes.func.isRequired,
onQuote: PropTypes.func.isRequired,
onBookmark: PropTypes.func.isRequired,
onBookmarkCategoryAdder: PropTypes.func.isRequired,
onDelete: PropTypes.func.isRequired,
@ -225,10 +223,6 @@ class ActionBar extends PureComponent {
this.props.onReference(this.props.status, this.props.history);
};
handleQuote = () => {
this.props.onQuote(this.props.status, this.props.history);
};
handleEmojiPick = (data) => {
this.props.onEmojiReact(this.props.status, data);
};
@ -244,7 +238,6 @@ class ActionBar extends PureComponent {
const account = status.get('account');
const writtenByMe = status.getIn(['account', 'id']) === me;
const isRemote = status.getIn(['account', 'username']) !== status.getIn(['account', 'acct']);
const allowQuote = status.getIn(['account', 'other_settings', 'allow_quote']);
let menu = [];
@ -269,10 +262,6 @@ class ActionBar extends PureComponent {
menu.push({ text: intl.formatMessage(status.get('reblogged') ? messages.cancel_reblog : messages.reblog), action: this.handleReblogForceModalClick, tag: 'reblog' });
if (publicStatus) {
if (allowQuote && (account.getIn(['server_features', 'quote']) || !isHideItem('quote_unavailable_server'))) {
menu.push({ text: intl.formatMessage(messages.quote), action: this.handleQuote, tag: 'reblog' });
}
if (account.getIn(['server_features', 'status_reference']) || !isHideItem('status_reference_unavailable_server')) {
menu.push({ text: intl.formatMessage(messages.reference), action: this.handleReference, tag: 'reblog' });
}
@ -350,10 +339,6 @@ class ActionBar extends PureComponent {
}
if (publicStatus) {
if (allowQuote && (account.getIn(['server_features', 'quote']) || !isHideItem('quote_unavailable_server'))) {
reblogMenu.push({ text: intl.formatMessage(messages.quote), action: this.handleQuote });
}
if (account.getIn(['server_features', 'status_reference']) || !isHideItem('status_reference_unavailable_server')) {
reblogMenu.push({ text: intl.formatMessage(messages.reference), action: this.handleReference });
}

View file

@ -32,7 +32,6 @@ import { DisplayName } from '../../../components/display_name';
import MediaGallery from '../../../components/media_gallery';
import StatusContent from '../../../components/status_content';
import StatusEmojiReactionsBar from '../../../components/status_emoji_reactions_bar';
import CompactedStatusContainer from '../../../containers/compacted_status_container';
import Audio from '../../audio';
import scheduleIdleTask from '../../ui/util/schedule_idle_task';
@ -77,7 +76,6 @@ export const DetailedStatus: React.FC<{
onToggleHidden,
onEmojiReact,
onUnEmojiReact,
muted,
}) => {
const properStatus = status?.get('reblog') ?? status;
const [height, setHeight] = useState(0);
@ -330,7 +328,7 @@ export const DetailedStatus: React.FC<{
<AnimatedNumber value={status.get('status_referred_by_count')} />
</span>
<FormattedMessage
id='status.quotes'
id='status.references'
defaultMessage='{count, plural, one {boost} other {boosts}}'
values={{ count: status.get('status_referred_by_count') }}
/>
@ -383,13 +381,6 @@ export const DetailedStatus: React.FC<{
(!matchedFilters || showDespiteFilter) &&
(!status.get('hidden') || status.get('spoiler_text').length === 0);
const quote = !muted && status.get('quote_id') && (
<>
{/* @ts-expect-error: CompactedStatusContainer class is not typescript still. */}
<CompactedStatusContainer id={status.get('quote_id')} history={history} />
</>
);
return (
<div style={outerStyle}>
<div ref={handleRef} className={classNames('detailed-status')}>
@ -459,7 +450,6 @@ export const DetailedStatus: React.FC<{
{media}
{hashtagBar}
{quote}
{emojiReactionsBar}
</>
)}

View file

@ -156,7 +156,7 @@ const makeMapStateToProps = () => {
if (status) {
ancestorsIds = getAncestorsIds(state, { id: status.get('in_reply_to_id') });
descendantsIds = getDescendantsIds(state, { id: status.get('id') });
referenceIds = getReferenceIds(state, { id: status.get('id') }).filter((id) => id !== status.get('quote_id'));
referenceIds = getReferenceIds(state, { id: status.get('id') });
}
return {
@ -341,10 +341,6 @@ class Status extends ImmutablePureComponent {
this.props.dispatch(insertReferenceCompose(0, status.get('url'), 'BT', router));
};
handleQuote = (status, router) => {
this.props.dispatch(insertReferenceCompose(0, status.get('url'), 'QT', router));
};
handleBookmarkClick = (status) => {
if (bookmarkCategoryNeeded) {
this.handleBookmarkCategoryAdderClick(status);
@ -774,7 +770,6 @@ class Status extends ImmutablePureComponent {
onReblog={this.handleReblogClick}
onReblogForceModal={this.handleReblogForceModalClick}
onReference={this.handleReference}
onQuote={this.handleQuote}
onBookmark={this.handleBookmarkClick}
onBookmarkCategoryAdder={this.handleBookmarkCategoryAdderClick}
onDelete={this.handleDeleteClick}

View file

@ -81,7 +81,7 @@ class StatusReferences extends ImmutablePureComponent {
bindToDocument={!multiColumn}
>
{accountIds.map(id =>
<StatusContainer key={id} id={id} withNote={false} withoutQuote />,
<StatusContainer key={id} id={id} withNote={false} />,
)}
</ScrollableList>

View file

@ -2,14 +2,10 @@
/**
* @typedef { 'blocking_quote'
* | 'emoji_reaction_on_timeline'
* @typedef { 'emoji_reaction_on_timeline'
* | 'emoji_reaction_unavailable_server'
* | 'emoji_reaction_count'
* | 'favourite_menu'
* | 'quote_in_home'
* | 'quote_in_public'
* | 'quote_unavailable_server'
* | 'recent_emojis'
* | 'relationships'
* | 'status_reference_unavailable_server'

View file

@ -462,7 +462,7 @@
"empty_column.notification_requests": "All clear! There is nothing here. When you receive new notifications, they will appear here according to your settings.",
"empty_column.notifications": "You don't have any notifications yet. When other people interact with you, you will see it here.",
"empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up",
"empty_column.status_references": "No one has quotes this post yet. When someone does, they will show up here.",
"empty_column.status_references": "No one has links this post yet. When someone does, they will show up here.",
"error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.",
"error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.",
"error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.",
@ -762,7 +762,7 @@
"notification.relationships_severance_event.learn_more": "Learn more",
"notification.relationships_severance_event.user_domain_block": "You have blocked {target}, removing {followersCount} of your followers and {followingCount, plural, one {# account} other {# accounts}} you follow.",
"notification.status": "{name} just posted",
"notification.status_reference": "{name} quoted your post",
"notification.status_reference": "{name} linked your post",
"notification.update": "{name} edited a post",
"notification_requests.accept": "Accept",
"notification_requests.accept_multiple": "{count, plural, one {Accept # request…} other {Accept # requests…}}",
@ -804,7 +804,7 @@
"notifications.column_settings.show": "Show in column",
"notifications.column_settings.sound": "Play sound",
"notifications.column_settings.status": "New posts:",
"notifications.column_settings.status_reference": "Quotes:",
"notifications.column_settings.status_reference": "Links:",
"notifications.column_settings.unread_notifications.category": "Unread notifications",
"notifications.column_settings.unread_notifications.highlight": "Highlight unread notifications",
"notifications.column_settings.update": "Edits:",
@ -815,7 +815,7 @@
"notifications.filter.follows": "Follows",
"notifications.filter.mentions": "Mentions",
"notifications.filter.polls": "Poll results",
"notifications.filter.status_references": "Quotes",
"notifications.filter.status_references": "Links",
"notifications.filter.statuses": "Updates from people you follow",
"notifications.grant_permission": "Grant permission.",
"notifications.group": "{count} notifications",
@ -1061,8 +1061,6 @@
"status.open": "Expand this post",
"status.pin": "Pin on profile",
"status.pinned": "Pinned post",
"status.quote": "Quote",
"status.quotes": "{count, plural, one {quote} other {quotes}}",
"status.read_more": "Read more",
"status.reblog": "Boost",
"status.reblog_private": "Boost with original visibility",
@ -1071,7 +1069,8 @@
"status.reblogs": "{count, plural, one {boost} other {boosts}}",
"status.reblogs.empty": "No one has boosted this post yet. When someone does, they will show up here.",
"status.redraft": "Delete & re-draft",
"status.reference": "Quiet quote",
"status.reference": "Link",
"status.references": "{count, plural, one {link} other {links}}",
"status.remove_bookmark": "Remove bookmark",
"status.remove_favourite": "Remove from favorites",
"status.replied_in_thread": "Replied in thread",

View file

@ -438,7 +438,7 @@
"empty_column.notification_requests": "ここに表示するものはありません。新しい通知を受け取ったとき、フィルタリング設定で通知がブロックされたアカウントがある場合はここに表示されます。",
"empty_column.notifications": "まだ通知がありません。他の人とふれ合って会話を始めましょう。",
"empty_column.public": "ここにはまだ何もありません! 公開で何かを投稿したり、他のサーバーのユーザーをフォローしたりしていっぱいにしましょう",
"empty_column.status_references": "まだ誰も引用していません。引用されるとここに表示されます。",
"empty_column.status_references": "まだ誰もリンクしていません。リンクされるとここに表示されます。",
"error.unexpected_crash.explanation": "不具合かブラウザの互換性問題のため、このページを正しく表示できませんでした。",
"error.unexpected_crash.explanation_addons": "このページは正しく表示できませんでした。このエラーはブラウザのアドオンや自動翻訳ツールによって引き起こされることがあります。",
"error.unexpected_crash.next_steps": "ページの再読み込みをお試しください。それでも解決しない場合、別のブラウザかアプリを使えば使用できることがあります。",
@ -733,7 +733,7 @@
"notification.relationships_severance_event.learn_more": "詳細を確認",
"notification.relationships_severance_event.user_domain_block": "{target} のブロックにより{followersCount}フォロワーと{followingCount, plural, other {#フォロー}}が解除されました。",
"notification.status": "{name}さんが投稿しました",
"notification.status_reference": "{name}さんがあなたの投稿を引用しました",
"notification.status_reference": "{name}さんがあなたの投稿をリンクしました",
"notification.update": "{name}さんが投稿を編集しました",
"notification_requests.accept": "受け入れる",
"notification_requests.accept_multiple": "{count, plural, other {選択中の#件を受け入れる}}",
@ -774,7 +774,7 @@
"notifications.column_settings.show": "カラムに表示",
"notifications.column_settings.sound": "通知音を再生",
"notifications.column_settings.status": "新しい投稿:",
"notifications.column_settings.status_reference": "引用",
"notifications.column_settings.status_reference": "リンク",
"notifications.column_settings.unread_notifications.category": "未読の通知:",
"notifications.column_settings.unread_notifications.highlight": "未読の通知を強調表示",
"notifications.column_settings.update": "編集:",
@ -786,7 +786,7 @@
"notifications.filter.mentions": "返信",
"notifications.filter.polls": "アンケート結果",
"notifications.filter.statuses": "フォローしている人の新着情報",
"notifications.filter.status_references": "引用",
"notifications.filter.status_references": "リンク",
"notifications.grant_permission": "権限の付与",
"notifications.group": "{count}件の通知",
"notifications.mark_as_read": "すべて既読にする",
@ -1031,8 +1031,7 @@
"status.open": "詳細を表示",
"status.pin": "プロフィールに固定表示",
"status.pinned": "固定された投稿",
"status.quote": "引用",
"status.quotes": "{count, plural, one {引用} other {引用}}",
"status.quote": "リンク",
"status.read_more": "もっと見る",
"status.reblog": "ブースト",
"status.reblog_private": "ブースト",
@ -1041,7 +1040,8 @@
"status.reblogs": "{count, plural, one {ブースト} other {ブースト}}",
"status.reblogs.empty": "まだ誰もブーストしていません。ブーストされるとここに表示されます。",
"status.redraft": "削除して下書きに戻す",
"status.reference": "ひかえめな引用",
"status.reference": "リンク",
"status.references": "{count, plural, one {リンク} other {リンク}}",
"status.remove_bookmark": "ブックマークを削除",
"status.remove_favourite": "お気に入りから削除",
"status.replied_in_thread": "ほかのユーザーへ",

View file

@ -56,7 +56,6 @@ const AccountOtherSettingsFactory = ImmutableRecord<AccountOtherSettingsShape>({
hide_statuses_count: false,
translatable_private: false,
link_preview: true,
allow_quote: true,
emoji_reaction_policy: 'allow',
subscription_policy: 'allow',
});
@ -69,7 +68,6 @@ const AccountServerFeaturesFactory =
ImmutableRecord<AccountServerFeaturesShape>({
circle: false,
emoji_reaction: false,
quote: false,
status_reference: false,
});

View file

@ -11,7 +11,6 @@ const normalizeFilter = (state, filter) => {
filter_action: filter.filter_action,
keywords: filter.keywords,
expires_at: filter.expires_at ? Date.parse(filter.expires_at) : null,
with_quote: filter.with_quote,
});
if (is(state.get(filter.id), normalizedFilter)) {

View file

@ -13,41 +13,27 @@ 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(['statuses', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), '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'])]),
getFilters,
(_, { contextType }) => ['detailed', 'bookmarks', 'favourites'].includes(contextType),
],
(statusBase, statusReblog, statusQuote, statusReblogQuote, accountBase, accountReblog, filters, warnInsteadOfHide) => {
(statusBase, statusReblog, accountBase, accountReblog, filters, warnInsteadOfHide) => {
if (!statusBase || statusBase.get('isLoading')) {
return null;
}
if (statusReblog) {
statusReblog = statusReblog.set('account', accountReblog);
statusQuote = statusReblogQuote;
} else {
statusReblog = null;
}
if (isHideItem('blocking_quote') && (statusReblog || statusBase).getIn(['quote', 'quote_muted'])) {
return null;
}
let filtered = false;
let mediaFiltered = false;
if ((accountReblog || accountBase).get('id') !== me && filters) {
let filterResults = statusReblog?.get('filtered') || statusBase.get('filtered') || ImmutableList();
const quoteFilterResults = statusQuote?.get('filtered');
if (quoteFilterResults) {
const filterWithQuote = quoteFilterResults.some((result) => filters.getIn([result.get('filter'), 'with_quote']));
if (filterWithQuote) {
filterResults = filterResults.concat(quoteFilterResults);
}
}
if (!warnInsteadOfHide && filterResults.some((result) => filters.getIn([result.get('filter'), 'filter_action']) === 'hide')) {
return null;
@ -66,7 +52,6 @@ export const makeGetStatus = () => {
return statusBase.withMutations(map => {
map.set('reblog', statusReblog);
map.set('quote', statusQuote);
map.set('account', accountBase);
map.set('matched_filters', filtered);
map.set('matched_media_filters', mediaFiltered);

View file

@ -555,7 +555,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
def related_to_local_activity?
fetch? || followed_by_local_accounts? || requested_through_relay? ||
responds_to_followed_account? || addresses_local_accounts? || quote_local? || free_friend_domain?
responds_to_followed_account? || addresses_local_accounts? || free_friend_domain?
end
def responds_to_followed_account?
@ -621,16 +621,6 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
ProcessReferencesService.call_service_without_error(@status, [], reference_uris, [quote].compact)
end
def quote_local?
url = quote
if url.present?
ActivityPub::TagManager.instance.uri_to_resource(url, Status)&.local?
else
false
end
end
def free_friend_domain?
FriendDomain.free_receivings.exists?(domain: @account.domain)
end
@ -640,15 +630,6 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
end
def quote
@quote ||= quote_from_tags || @object['quote'] || @object['quoteUrl'] || @object['quoteURL'] || @object['_misskey_quote']
end
def quote_from_tags
return @quote_from_tags if defined?(@quote_from_tags)
hit_tag = as_array(@object['tag']).detect do |tag|
equals_or_includes?(tag['type'], 'Link') && LINK_MEDIA_TYPES.include?(tag['mediaType']) && tag['href'].present?
end
@quote_from_tags = hit_tag && hit_tag['href']
@quote ||= nil # TODO: quote
end
end

View file

@ -5,7 +5,6 @@ module ActivityPub::CaseTransform
NO_CONVERT_VALUES = %w(
_misskey_content
_misskey_license
_misskey_quote
).freeze
def camel_lower_cache

View file

@ -78,7 +78,6 @@ class StatusReachFinder
reblogs_account_ids,
favourites_account_ids,
replies_account_ids,
quoted_account_id,
].tap do |arr|
arr.flatten!
arr.compact!
@ -114,10 +113,6 @@ class StatusReachFinder
@status.replies.pluck(:account_id) if distributable? || unsafe?
end
def quoted_account_id
@status.quote.account_id if @status.quote?
end
def followers_inboxes
scope = followers_scope
inboxes_without_suspended_for(scope)

View file

@ -15,13 +15,6 @@ module Account::OtherSettings
false
end
def allow_quote?
return user.setting_allow_quote if local? && user.present?
return settings['allow_quote'] if settings.present? && settings.key?('allow_quote')
true
end
def hide_statuses_count?
return user&.setting_hide_statuses_count if local? && user.present?
return settings['hide_statuses_count'] if settings.present? && settings.key?('hide_statuses_count')
@ -88,7 +81,6 @@ module Account::OtherSettings
'hide_following_count' => hide_following_count?,
'hide_followers_count' => hide_followers_count?,
'translatable_private' => translatable_private?,
'allow_quote' => allow_quote?,
'emoji_reaction_policy' => Setting.enable_emoji_reaction ? emoji_reaction_policy.to_s : 'block',
}
end

View file

@ -107,18 +107,6 @@ module User::HasSettings
settings['web.content_font_size']
end
def setting_show_quote_in_home
settings['web.show_quote_in_home']
end
def setting_show_quote_in_public
settings['web.show_quote_in_public']
end
def setting_hide_blocking_quote
settings['web.hide_blocking_quote']
end
def setting_show_relationships
settings['web.show_relationships']
end
@ -127,10 +115,6 @@ module User::HasSettings
settings['web.show_avatar_on_filter']
end
def setting_allow_quote
settings['allow_quote']
end
def setting_reject_send_limited_to_suspects
settings['reject_send_limited_to_suspects']
end
@ -259,10 +243,6 @@ module User::HasSettings
settings['use_public_index']
end
def setting_reverse_search_quote
settings['reverse_search_quote']
end
def setting_disallow_unlisted_public_searchability
settings['disallow_unlisted_public_searchability']
end
@ -275,10 +255,6 @@ module User::HasSettings
settings['web.hide_emoji_reaction_unavailable_server']
end
def setting_hide_quote_unavailable_server
settings['web.hide_quote_unavailable_server']
end
def setting_hide_status_reference_unavailable_server
settings['web.hide_status_reference_unavailable_server']
end

View file

@ -12,7 +12,6 @@
# expires_at :datetime
# phrase :text default(""), not null
# with_profile :boolean default(FALSE), not null
# with_quote :boolean default(TRUE), not null
# created_at :datetime not null
# updated_at :datetime not null
# account_id :bigint(8) not null
@ -69,14 +68,6 @@ class CustomFilter < ApplicationRecord
hide_action?
end
def exclude_quote=(value)
self.with_quote = !ActiveModel::Type::Boolean.new.cast(value)
end
def exclude_quote
!with_quote
end
def exclude_profile=(value)
self.with_profile = !ActiveModel::Type::Boolean.new.cast(value)
end
@ -111,9 +102,6 @@ class CustomFilter < ApplicationRecord
end
def self.apply_cached_filters(cached_filters, status, following: false)
references_text_cache = nil
references_spoiler_text_cache = nil
cached_filters.filter_map do |filter, rules|
next if filter.exclude_follows && following
next if filter.exclude_localusers && status.account.local?
@ -121,17 +109,10 @@ class CustomFilter < ApplicationRecord
if rules[:keywords].present?
match = rules[:keywords].match(status.proper.searchable_text)
match = rules[:keywords].match([status.account.display_name, status.account.note].join("\n\n")) if !match && filter.with_profile
if match.nil? && filter.with_quote && status.proper.reference_objects.exists?
references_text_cache = status.proper.references.pluck(:text).join("\n\n") if references_text_cache.nil?
references_spoiler_text_cache = status.proper.references.pluck(:spoiler_text).join("\n\n") if references_spoiler_text_cache.nil?
match = rules[:keywords].match(references_text_cache)
match = rules[:keywords].match(references_spoiler_text_cache) if match.nil?
end
end
keyword_matches = [match.to_s] unless match.nil?
reference_ids = filter.with_quote ? status.proper.reference_objects.pluck(:target_status_id) : []
status_matches = ([status.id, status.reblog_of_id] + reference_ids).compact & rules[:status_ids] if rules[:status_ids].present?
status_matches = [status.id, status.reblog_of_id].compact & rules[:status_ids] if rules[:status_ids].present?
next if keyword_matches.blank? && status_matches.blank?

View file

@ -35,8 +35,6 @@ class InstanceInfo < ApplicationRecord
yojo-art
).freeze
QUOTE_AVAILABLE_SOFTWARES = EMOJI_REACTION_AVAILABLE_SOFTWARES + %w(bridgy-fed).freeze
STATUS_REFERENCE_AVAILABLE_SOFTWARES = %w(fedibird).freeze
CIRCLE_AVAILABLE_SOFTWARES = %w(fedibird).freeze
@ -87,7 +85,6 @@ class InstanceInfo < ApplicationRecord
{
emoji_reaction: feature_available?(info, EMOJI_REACTION_AVAILABLE_SOFTWARES, 'emoji_reaction'),
quote: feature_available?(info, QUOTE_AVAILABLE_SOFTWARES, 'quote'),
status_reference: feature_available?(info, STATUS_REFERENCE_AVAILABLE_SOFTWARES, 'status_reference'),
circle: feature_available?(info, CIRCLE_AVAILABLE_SOFTWARES, 'circle'),
}
@ -96,7 +93,6 @@ class InstanceInfo < ApplicationRecord
def local_features
{
emoji_reaction: Setting.enable_emoji_reaction,
quote: true,
status_reference: true,
circle: true,
}

View file

@ -205,19 +205,6 @@ class Status < ApplicationRecord
account: [:account_stat, user: :role],
active_mentions: { account: :account_stat },
],
quote: [
:application,
:tags,
:media_attachments,
:conversation,
:status_stat,
:preloadable_poll,
:reference_objects,
:scheduled_expiration_status,
preview_cards_status: { preview_card: { author_account: [:account_stat, user: :role] } },
account: [:account_stat, user: :role],
active_mentions: :account,
],
thread: :account
delegate :domain, to: :account, prefix: true
@ -252,10 +239,6 @@ class Status < ApplicationRecord
!reblog_of_id.nil?
end
def quote?
!quote_of_id.nil? && !quote.nil?
end
def expires?
scheduled_expiration_status.present?
end

View file

@ -5,12 +5,11 @@
# Table name: status_references
#
# id :bigint(8) not null, primary key
# status_id :bigint(8) not null
# target_status_id :bigint(8) not null
# attribute_type :string
# created_at :datetime not null
# updated_at :datetime not null
# attribute_type :string
# quote :boolean default(FALSE), not null
# status_id :bigint(8) not null
# target_status_id :bigint(8) not null
#
class StatusReference < ApplicationRecord
@ -22,8 +21,6 @@ class StatusReference < ApplicationRecord
has_one :notification, as: :activity, dependent: :destroy
after_commit :reset_parent_cache
after_create_commit :set_quote
after_destroy_commit :remove_quote
private
@ -31,18 +28,4 @@ class StatusReference < ApplicationRecord
Rails.cache.delete("statuses/#{status_id}")
Rails.cache.delete("statuses/#{target_status_id}")
end
def set_quote
return unless quote
return if status.quote_of_id.present?
status.quote_of_id = target_status_id
end
def remove_quote
return unless quote
return unless status.quote_of_id == target_status_id
status.quote_of_id = nil
end
end

View file

@ -27,7 +27,6 @@ class UserSettings
setting :default_searchability, default: :direct, in: %w(public private direct limited public_unlisted)
setting :default_searchability_of_search, default: :public, in: %w(public private direct limited)
setting :use_public_index, default: true
setting :reverse_search_quote, default: false
setting :disallow_unlisted_public_searchability, default: false
setting :public_post_to_unlisted, default: false
setting :reject_public_unlisted_subscription, default: false
@ -40,7 +39,6 @@ class UserSettings
setting :dtl_force_visibility, default: :unchange, in: %w(unchange public public_unlisted unlisted)
setting :dtl_force_searchability, default: :unchange, in: %w(unchange public public_unlisted)
setting :lock_follow_from_bot, default: false
setting :allow_quote, default: true
setting :reject_send_limited_to_suspects, default: false
setting_inverse_alias :indexable, :noindex
@ -75,18 +73,12 @@ class UserSettings
setting :auto_play, default: true
setting :simple_timeline_menu, default: false
setting :boost_menu, default: false
setting :show_quote_in_home, default: true
setting :show_quote_in_public, default: false
setting :show_relationships, default: true
setting :hide_blocking_quote, default: true
setting :hide_emoji_reaction_unavailable_server, default: false
setting :hide_quote_unavailable_server, default: false
setting :hide_status_reference_unavailable_server, default: false
setting :hide_favourite_menu, default: false
setting :hide_emoji_reaction_count, default: false
setting :show_avatar_on_filter, default: true
setting_inverse_alias :'web.show_blocking_quote', :'web.hide_blocking_quote'
setting_inverse_alias :'web.show_emoji_reaction_count', :'web.hide_emoji_reaction_count'
setting_inverse_alias :'web.show_favourite_menu', :'web.hide_favourite_menu'
setting_inverse_alias :'web.show_recent_emojis', :'web.hide_recent_emojis'

View file

@ -47,10 +47,6 @@ class StatusPolicy < ApplicationPolicy
show? && !blocking_author?
end
def quote?
%i(public public_unlisted unlisted).include?(record.visibility.to_sym) && show? && !blocking_author?
end
def destroy?
owned?
end

View file

@ -21,7 +21,6 @@ class StatusRelationshipsPresenter
@emoji_reaction_allows_map = nil
else
statuses = statuses.compact
statuses += statuses.filter_map(&:quote)
status_ids = statuses.flat_map { |s| [s.id, s.reblog_of_id] }.uniq.compact
conversation_ids = statuses.filter_map(&:conversation_id).uniq
pinnable_status_ids = statuses.map(&:proper).filter_map { |s| s.id if s.account_id == current_account_id && PINNABLE_VISIBILITIES.include?(s.visibility) }

View file

@ -3,7 +3,7 @@
class ActivityPub::NoteSerializer < ActivityPub::Serializer
include FormattingHelper
context_extensions :atom_uri, :conversation, :sensitive, :voters_count, :searchable_by, :references, :limited_scope, :quote_uri
context_extensions :atom_uri, :conversation, :sensitive, :voters_count, :searchable_by, :references, :limited_scope
attributes :id, :type, :summary,
:in_reply_to, :published, :url,
@ -16,9 +16,6 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
attribute :updated, if: :edited?
attribute :limited_scope, if: :limited_visibility?
attribute :quote_uri, if: :quote?
attribute :misskey_quote, key: :_misskey_quote, if: :quote?
has_many :virtual_attachments, key: :attachment
has_many :virtual_tags, key: :tag
@ -158,30 +155,7 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
end
def virtual_tags
object.active_mentions.to_a.sort_by(&:id) + object.tags + object.emojis + virtual_tags_of_quote
end
class NoteLink < ActiveModelSerializers::Model
attributes :href
end
class NoteLinkSerializer < ActivityPub::Serializer
attributes :type, :href
attribute :media_type, key: :mediaType
def type
'Link'
end
def media_type
'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
end
end
def virtual_tags_of_quote
return [] unless object.quote?
[NoteLink.new(href: quote_uri)]
object.active_mentions.to_a.sort_by(&:id) + object.tags + object.emojis
end
def atom_uri
@ -218,20 +192,6 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
object.account.local?
end
delegate :quote?, to: :object
def quote_post
@quote_post ||= object.quote
end
def quote_uri
ActivityPub::TagManager.instance.uri_for(quote_post)
end
def misskey_quote
quote_uri
end
def poll_options
object.preloadable_poll.loaded_options
end

View file

@ -40,14 +40,10 @@ class InitialStateSerializer < ActiveModel::Serializer
store[:hide_items] = [
object_account_user.setting_hide_favourite_menu ? 'favourite_menu' : nil,
object_account_user.setting_hide_recent_emojis ? 'recent_emojis' : nil,
object_account_user.setting_hide_blocking_quote ? 'blocking_quote' : nil,
object_account_user.setting_hide_emoji_reaction_unavailable_server ? 'emoji_reaction_unavailable_server' : nil,
object_account_user.setting_hide_quote_unavailable_server ? 'quote_unavailable_server' : nil,
object_account_user.setting_hide_status_reference_unavailable_server ? 'status_reference_unavailable_server' : nil,
object_account_user.setting_hide_emoji_reaction_count ? 'emoji_reaction_count' : nil,
object_account_user.setting_show_emoji_reaction_on_timeline ? nil : 'emoji_reaction_on_timeline',
object_account_user.setting_show_quote_in_home ? nil : 'quote_in_home',
object_account_user.setting_show_quote_in_public ? nil : 'quote_in_public',
object_account_user.setting_show_relationships ? nil : 'relationships',
object_account_user.setting_show_avatar_on_filter ? nil : 'avatar_on_filter',
].compact

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true
class REST::FilterSerializer < ActiveModel::Serializer
attributes :id, :title, :exclude_follows, :exclude_localusers, :with_quote, :with_profile, :context, :expires_at, :filter_action
attributes :id, :title, :exclude_follows, :exclude_localusers, :with_profile, :context, :expires_at, :filter_action
has_many :keywords, serializer: REST::FilterKeywordSerializer, if: :rules_requested?
has_many :statuses, serializer: REST::FilterStatusSerializer, if: :rules_requested?

View file

@ -18,7 +18,6 @@ class REST::StatusSerializer < ActiveModel::Serializer
attribute :pinned, if: :pinnable?
attribute :reactions, if: :reactions?
attribute :expires_at, if: :will_expire?
attribute :quote_id, if: :quote?
attribute :markdown_opt, key: :markdown
has_many :filtered, serializer: REST::FilterResultSerializer, if: :current_user?
@ -37,23 +36,6 @@ class REST::StatusSerializer < ActiveModel::Serializer
has_one :preview_card, key: :card, serializer: REST::PreviewCardSerializer
has_one :preloadable_poll, key: :poll, serializer: REST::PollSerializer
class QuotedStatusSerializer < REST::StatusSerializer
attribute :quote_muted, if: :current_user?
def quote
nil
end
def quote_muted
if relationships
muted || relationships.blocks_map[object.account_id] || relationships.domain_blocks_map[object.account.domain] || false
else
muted || current_user.account.blocking?(object.account_id) || current_user.account.domain_blocking?(object.account.domain)
end
end
end
belongs_to :quote, if: :quote?, serializer: QuotedStatusSerializer, relationships: -> { relationships }
def id
object.id.to_s
end
@ -182,12 +164,6 @@ class REST::StatusSerializer < ActiveModel::Serializer
end
end
def quote_id
object.quote_of_id.to_s
end
delegate :quote?, to: :object
def reblogged
if relationships
relationships.reblogs_map[object.id] || false

View file

@ -351,7 +351,8 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
end
def quote
@json['quote'] || @json['quoteUrl'] || @json['quoteURL'] || @json['_misskey_quote']
# TODO: quote
nil
end
def local_referred_accounts

View file

@ -115,7 +115,7 @@ class FanOutOnWriteService < BaseService
end
def notify_about_update!
@status.reblogged_by_accounts.or(@status.quoted_by_accounts).merge(Account.local).select(:id).reorder(nil).find_in_batches do |accounts|
@status.reblogged_by_accounts.merge(Account.local).select(:id).reorder(nil).find_in_batches do |accounts|
LocalNotificationWorker.push_bulk(accounts) do |account|
[account.id, @status.id, 'Status', 'update']
end

View file

@ -277,6 +277,7 @@ class PostStatusService < BaseService
def quote_url
ProcessReferencesService.extract_quote(@text)
# TODO: quote
end
def reference_urls

View file

@ -188,7 +188,8 @@ class ProcessReferencesService < BaseService
quote = quote_attribute?(attribute_type)
@added_objects << @status.reference_objects.new(target_status: status, attribute_type: attribute_type, quote: quote)
@status.update!(quote_of_id: status_id) if quote
# TODO: quote
# @status.update!(quote_of_id: status_id) if quote
status.increment_count!(:status_referred_by_count)
@references_count += 1
@ -214,7 +215,9 @@ class ProcessReferencesService < BaseService
@removed_objects = []
@status.reference_objects.where(target_status: @removed_items.keys).destroy_all
@status.update!(quote_of_id: nil) if @status.quote_of_id.present? && @removed_items.key?(@status.quote_of_id)
# TODO: quote
# @status.update!(quote_of_id: nil) if @status.quote_of_id.present? && @removed_items.key?(@status.quote_of_id)
statuses = Status.where(id: @added_items.keys).to_a
@removed_items.each_key do |status_id|
@ -240,11 +243,12 @@ class ProcessReferencesService < BaseService
next unless quote_change
if quote
ref.status.update!(quote_of_id: ref.target_status.id)
else
ref.status.update!(quote_of_id: nil)
end
# TODO: quote
# if quote
# ref.status.update!(quote_of_id: ref.target_status.id)
# else
# ref.status.update!(quote_of_id: nil)
# end
end
end

View file

@ -139,6 +139,7 @@ class UpdateStatusService < BaseService
def quote_url
ProcessReferencesService.extract_quote(text)
# TODO: quote
end
def reference_urls

View file

@ -38,7 +38,6 @@
= f.input :exclude_localusers, wrapper: :with_label, kmyblue: true, label: t('simple_form.labels.filters.options.exclude_localusers')
.fields-group
= f.input :exclude_quote, wrapper: :with_label, as: :boolean, kmyblue: true, label: t('simple_form.labels.filters.options.exclude_quote')
= f.input :exclude_profile, wrapper: :with_label, as: :boolean, kmyblue: true, label: t('simple_form.labels.filters.options.exclude_profile')
%hr.spacer/

View file

@ -86,7 +86,6 @@
.fields-group
- if Setting.enable_emoji_reaction
= ff.input :'web.hide_emoji_reaction_unavailable_server', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_hide_emoji_reaction_unavailable_server')
= ff.input :'web.hide_quote_unavailable_server', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_hide_quote_unavailable_server')
= ff.input :'web.hide_status_reference_unavailable_server', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_hide_status_reference_unavailable_server')
%h4= t 'appearance.saved_posts'
@ -95,13 +94,6 @@
= ff.input :'web.bookmark_category_needed', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_bookmark_category_needed'), hint: I18n.t('simple_form.hints.defaults.setting_bookmark_category_needed')
= ff.input :'web.show_favourite_menu', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_show_favourite_menu')
%h4= t 'appearance.quotes'
.fields-group
= ff.input :'web.show_quote_in_home', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_show_quote_in_home'), hint: false
= ff.input :'web.show_quote_in_public', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_show_quote_in_public'), hint: false
= ff.input :'web.show_blocking_quote', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_show_blocking_quote'), hint: false
%h4= t 'appearance.status_action_bar'
.fields-group

View file

@ -18,9 +18,6 @@
.fields-group
= ff.input :translatable_private, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_translatable_private')
.fields-group
= ff.input :allow_quote, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_allow_quote'), hint: I18n.t('simple_form.hints.defaults.setting_allow_quote')
- if Setting.enable_emoji_reaction
%h4= t 'preferences.emoji_reaction_permitting'