pl-fe: support filters blur action
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
@ -10,7 +10,7 @@ import type { MediaAttachment } from 'pl-api';
|
||||
import type { Status } from 'pl-fe/normalizers/status';
|
||||
|
||||
interface IAttachmentThumbs {
|
||||
status: Pick<Status, 'media_attachments' | 'sensitive'>;
|
||||
status: Pick<Status, 'filtered' | 'media_attachments' | 'sensitive'>;
|
||||
onClick?(): void;
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ const AttachmentThumbs = ({ status, onClick }: IAttachmentThumbs) => {
|
||||
const fallback = <div className='media-gallery--compact' />;
|
||||
const onOpenMedia = (media: Array<MediaAttachment>, index: number) => openModal('MEDIA', { media, index });
|
||||
|
||||
const visible = useMediaVisible(status, displayMedia);
|
||||
const [visible] = useMediaVisible(status, displayMedia);
|
||||
|
||||
return (
|
||||
<div className='relative'>
|
||||
|
||||
@ -14,7 +14,7 @@ import type { Status } from 'pl-fe/normalizers/status';
|
||||
|
||||
interface IStatusMedia {
|
||||
/** Status entity to render media for. */
|
||||
status: Pick<Status, 'id' | 'account' | 'card' | 'expectsCard' | 'media_attachments' | 'quote_id' | 'sensitive' | 'visibility'>;
|
||||
status: Pick<Status, 'id' | 'account' | 'card' | 'expectsCard' | 'filtered' | 'media_attachments' | 'quote_id' | 'sensitive' | 'visibility'>;
|
||||
/** Whether to display compact media. */
|
||||
muted?: boolean;
|
||||
/** Callback when compact media is clicked. */
|
||||
@ -30,7 +30,7 @@ const StatusMedia: React.FC<IStatusMedia> = ({
|
||||
const { openModal } = useModalsStore();
|
||||
const { displayMedia } = useSettings();
|
||||
|
||||
const visible = useMediaVisible(status, displayMedia);
|
||||
const [visible] = useMediaVisible(status, displayMedia);
|
||||
|
||||
const size = status.media_attachments.length;
|
||||
const firstAttachment = status.media_attachments[0];
|
||||
|
||||
@ -97,7 +97,8 @@ const Status: React.FC<IStatus> = (props) => {
|
||||
const statusUrl = `/@${actualStatus.account.acct}/posts/${actualStatus.id}`;
|
||||
const group = actualStatus.group;
|
||||
|
||||
const filtered = (status.filtered?.length || actualStatus.filtered?.length) > 0;
|
||||
const filterResults = useMemo(() => [...status.filtered, ...actualStatus.filtered].filter(({ filter }) => filter.filter_action === 'warn'), [status.filtered, actualStatus.filtered]);
|
||||
const filtered = filterResults.length > 0;
|
||||
|
||||
// Track height changes we know about to compensate scrolling.
|
||||
useEffect(() => {
|
||||
@ -336,7 +337,7 @@ const Status: React.FC<IStatus> = (props) => {
|
||||
<HotKeys handlers={minHandlers} attachRef={node}>
|
||||
<div className={clsx('status__wrapper text-center', { focusable })} tabIndex={focusable ? 0 : undefined} ref={node}>
|
||||
<Text theme='muted'>
|
||||
<FormattedMessage id='status.filtered' defaultMessage='Filtered' />: {status.filtered.join(', ')}.
|
||||
<FormattedMessage id='status.filtered' defaultMessage='Filtered' />: {filterResults.map(({ filter }) => filter.title).join(', ')}.
|
||||
{' '}
|
||||
<button className='text-primary-600 hover:underline dark:text-accent-blue' onClick={handleUnfilter}>
|
||||
<FormattedMessage id='status.show_filter_reason' defaultMessage='Show anyway' />
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import Button from 'pl-fe/components/ui/button';
|
||||
@ -8,23 +8,30 @@ import Text from 'pl-fe/components/ui/text';
|
||||
import { useSettings } from 'pl-fe/hooks/use-settings';
|
||||
import { useStatusMetaStore } from 'pl-fe/stores/status-meta';
|
||||
|
||||
import type { FilterResult } from 'pl-api';
|
||||
import type { Status } from 'pl-fe/normalizers/status';
|
||||
|
||||
const useMediaVisible = (status: Pick<Status, 'media_attachments' | 'sensitive'> & { id?: string }, displayMedia: 'default' | 'show_all' | 'hide_all') => {
|
||||
let visible = !status.sensitive;
|
||||
|
||||
const useMediaVisible = (status: Pick<Status, 'filtered' | 'media_attachments' | 'sensitive'> & { id?: string }, displayMedia: 'default' | 'show_all' | 'hide_all'): [boolean, Array<FilterResult>] => {
|
||||
const statusesMeta = useStatusMetaStore().statuses;
|
||||
const mediaVisible = status.id ? statusesMeta[status.id]?.mediaVisible : undefined;
|
||||
|
||||
if (mediaVisible !== undefined) visible = mediaVisible;
|
||||
else if (displayMedia === 'show_all') visible = true;
|
||||
else if (displayMedia === 'hide_all' && status.media_attachments.length) visible = false;
|
||||
return useMemo(() => {
|
||||
let visible = !status.sensitive;
|
||||
|
||||
return visible;
|
||||
const filterResults = status.filtered.filter(({ filter }) => filter.filter_action === 'blur');
|
||||
|
||||
if (filterResults.length) return [mediaVisible !== undefined ? mediaVisible : false, filterResults];
|
||||
|
||||
if (mediaVisible !== undefined) visible = mediaVisible;
|
||||
else if (displayMedia === 'show_all') visible = true;
|
||||
else if (displayMedia === 'hide_all' && status.media_attachments.length) visible = false;
|
||||
|
||||
return [visible, []];
|
||||
}, [status.sensitive, status.filtered, mediaVisible]);
|
||||
};
|
||||
|
||||
const useShowOverlay = (status: Pick<Status, 'id' | 'media_attachments' | 'sensitive'>, displayMedia: 'default' | 'show_all' | 'hide_all') => {
|
||||
const visible = useMediaVisible(status, displayMedia);
|
||||
const useShowOverlay = (status: Pick<Status, 'id' | 'filtered' | 'media_attachments' | 'sensitive'>, displayMedia: 'default' | 'show_all' | 'hide_all') => {
|
||||
const [visible] = useMediaVisible(status, displayMedia);
|
||||
|
||||
const showHideButton = status.sensitive || (status.media_attachments.length && displayMedia === 'hide_all');
|
||||
|
||||
@ -40,10 +47,11 @@ const messages = defineMessages({
|
||||
sensitiveTitle: { id: 'status.sensitive_warning', defaultMessage: 'Sensitive content' },
|
||||
sensitiveSubtitle: { id: 'status.sensitive_warning.subtitle', defaultMessage: 'This content may not be suitable for all audiences.' },
|
||||
show: { id: 'moderation_overlay.show', defaultMessage: 'Show content' },
|
||||
matchesFilter: { id: 'status.sensitive_warning.matches_filter', defaultMessage: 'Matches filter “<span>{title}</span>”' },
|
||||
});
|
||||
|
||||
interface ISensitiveContentOverlay {
|
||||
status: Pick<Status, 'id' | 'sensitive' | 'media_attachments'>;
|
||||
status: Pick<Status, 'id' | 'filtered' | 'sensitive' | 'media_attachments'>;
|
||||
}
|
||||
|
||||
const SensitiveContentOverlay = React.forwardRef<HTMLDivElement, ISensitiveContentOverlay>((props, ref) => {
|
||||
@ -52,7 +60,9 @@ const SensitiveContentOverlay = React.forwardRef<HTMLDivElement, ISensitiveConte
|
||||
const intl = useIntl();
|
||||
const { displayMedia } = useSettings();
|
||||
|
||||
const visible = useMediaVisible(status, displayMedia);
|
||||
const [visible, filters] = useMediaVisible(status, displayMedia);
|
||||
|
||||
const matchedFilters = useMemo(() => filters.map(({ filter }) => filter.title), [filters]);
|
||||
|
||||
const { hideStatusMedia, revealStatusMedia } = useStatusMetaStore();
|
||||
|
||||
@ -91,7 +101,10 @@ const SensitiveContentOverlay = React.forwardRef<HTMLDivElement, ISensitiveConte
|
||||
</Text>
|
||||
|
||||
<Text theme='white' size='sm' weight='medium'>
|
||||
{intl.formatMessage(messages.sensitiveSubtitle)}
|
||||
{filters.length ? intl.formatMessage(messages.matchesFilter, {
|
||||
title: matchedFilters.join(', '),
|
||||
span: (chunks) => <span className='filter-name'>{chunks}</span>,
|
||||
}) : intl.formatMessage(messages.sensitiveSubtitle)}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user