Remove this sensitive content overlay fuckery
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
f648a68edf
commit
5d17752231
12 changed files with 45 additions and 102 deletions
|
@ -13,7 +13,7 @@ interface IAttachmentThumbs {
|
|||
}
|
||||
|
||||
const AttachmentThumbs = (props: IAttachmentThumbs) => {
|
||||
const { media, onClick, sensitive } = props;
|
||||
const { media, onClick } = props;
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const fallback = <div className='media-gallery--compact' />;
|
||||
|
@ -27,8 +27,6 @@ const AttachmentThumbs = (props: IAttachmentThumbs) => {
|
|||
onOpenMedia={onOpenMedia}
|
||||
height={50}
|
||||
compact
|
||||
sensitive={sensitive}
|
||||
visible
|
||||
/>
|
||||
</Suspense>
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@ interface IItem {
|
|||
size: number;
|
||||
onClick: (index: number) => void;
|
||||
displayWidth?: number;
|
||||
visible: boolean;
|
||||
dimensions: Dimensions;
|
||||
last?: boolean;
|
||||
total: number;
|
||||
|
@ -66,7 +65,6 @@ const Item: React.FC<IItem> = ({
|
|||
index,
|
||||
onClick,
|
||||
standalone = false,
|
||||
visible,
|
||||
dimensions,
|
||||
last,
|
||||
total,
|
||||
|
@ -266,19 +264,17 @@ const Item: React.FC<IItem> = ({
|
|||
hash={attachment.blurhash}
|
||||
className='media-gallery__preview'
|
||||
/>
|
||||
{visible && thumbnail}
|
||||
{thumbnail}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface IMediaGallery {
|
||||
sensitive?: boolean;
|
||||
media: Array<MediaAttachment>;
|
||||
height?: number;
|
||||
onOpenMedia: (media: Array<MediaAttachment>, index: number) => void;
|
||||
defaultWidth?: number;
|
||||
cacheWidth?: (width: number) => void;
|
||||
visible?: boolean;
|
||||
displayMedia?: string;
|
||||
compact?: boolean;
|
||||
className?: string;
|
||||
|
@ -538,7 +534,6 @@ const MediaGallery: React.FC<IMediaGallery> = (props) => {
|
|||
index={i}
|
||||
size={sizeData.size}
|
||||
displayWidth={sizeData.width}
|
||||
visible={!!props.visible}
|
||||
dimensions={sizeData.itemsDimensions[i]}
|
||||
last={i === ATTACHMENT_LIMIT - 1}
|
||||
total={media.length}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import clsx from 'clsx';
|
||||
import React, { MouseEventHandler, useEffect, useRef, useState } from 'react';
|
||||
import React, { MouseEventHandler } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
|
@ -34,16 +34,6 @@ const QuotedStatus: React.FC<IQuotedStatus> = ({ status, onCancel, compose }) =>
|
|||
const intl = useIntl();
|
||||
const history = useHistory();
|
||||
|
||||
const overlay = useRef<HTMLDivElement>(null);
|
||||
|
||||
const [minHeight, setMinHeight] = useState(208);
|
||||
|
||||
useEffect(() => {
|
||||
if (overlay.current) {
|
||||
setMinHeight(overlay.current.getBoundingClientRect().height);
|
||||
}
|
||||
}, [overlay.current]);
|
||||
|
||||
const handleExpandClick: MouseEventHandler<HTMLDivElement> = (e) => {
|
||||
if (!status) return;
|
||||
const account = status.account;
|
||||
|
@ -105,15 +95,7 @@ const QuotedStatus: React.FC<IQuotedStatus> = ({ status, onCancel, compose }) =>
|
|||
<StatusReplyMentions status={status} hoverable={false} />
|
||||
|
||||
{status.event ? <EventPreview status={status} hideAction /> : (
|
||||
<Stack
|
||||
className='relative z-0'
|
||||
style={{ minHeight: status.sensitive ? Math.max(minHeight, 208) + 12 : undefined }}
|
||||
>
|
||||
<SensitiveContentOverlay
|
||||
status={status}
|
||||
ref={overlay}
|
||||
/>
|
||||
|
||||
<Stack className='relative z-0'>
|
||||
<Stack space={4}>
|
||||
<StatusContent
|
||||
status={status}
|
||||
|
@ -122,9 +104,14 @@ const QuotedStatus: React.FC<IQuotedStatus> = ({ status, onCancel, compose }) =>
|
|||
|
||||
{status.quote_id && <QuotedStatusIndicator statusId={status.quote_id} />}
|
||||
|
||||
{status.media_attachments.length > 0 && (
|
||||
<StatusMedia status={status} muted={compose} />
|
||||
)}
|
||||
<div className='relative'>
|
||||
<SensitiveContentOverlay
|
||||
status={status}
|
||||
/>
|
||||
{status.media_attachments.length > 0 && (
|
||||
<StatusMedia status={status} muted={compose} />
|
||||
)}
|
||||
</div>
|
||||
</Stack>
|
||||
</Stack>
|
||||
)}
|
||||
|
|
|
@ -5,6 +5,7 @@ import { FormattedMessage } from 'react-intl';
|
|||
import { Link } from 'react-router-dom';
|
||||
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import { Text } from 'soapbox/components/ui';
|
||||
import { onlyEmoji as isOnlyEmoji } from 'soapbox/utils/rich-content';
|
||||
|
||||
import { getTextDirection } from '../utils/rtl';
|
||||
|
@ -15,7 +16,6 @@ import Markup from './markup';
|
|||
import Poll from './polls/poll';
|
||||
|
||||
import type { Sizes } from 'soapbox/components/ui/text/text';
|
||||
// import type { Status } from 'soapbox/normalizers';
|
||||
import type { MinifiedStatus } from 'soapbox/reducers/statuses';
|
||||
|
||||
const MAX_HEIGHT = 642; // 20px * 32 (+ 2px padding at the top)
|
||||
|
@ -156,8 +156,22 @@ const StatusContent: React.FC<IStatusContent> = React.memo(({
|
|||
'leading-normal big-emoji': onlyEmoji,
|
||||
});
|
||||
|
||||
const spoilerText = status.spoilerMapHtml && status.currentLanguage
|
||||
? status.spoilerMapHtml[status.currentLanguage] || status.spoilerHtml
|
||||
: status.spoilerHtml;
|
||||
|
||||
const output = [];
|
||||
|
||||
if (spoilerText) {
|
||||
output.push(
|
||||
<Text className='mb-2' size='2xl' weight='medium'>
|
||||
<span dangerouslySetInnerHTML={{ __html: spoilerText }} />
|
||||
</Text>,
|
||||
);
|
||||
}
|
||||
|
||||
if (onClick) {
|
||||
const output = [
|
||||
output.push(
|
||||
<Markup
|
||||
ref={node}
|
||||
tabIndex={0}
|
||||
|
@ -169,7 +183,7 @@ const StatusContent: React.FC<IStatusContent> = React.memo(({
|
|||
>
|
||||
{content}
|
||||
</Markup>,
|
||||
];
|
||||
);
|
||||
|
||||
if (collapsed) {
|
||||
output.push(<ReadMoreButton onClick={onClick} key='read-more' />);
|
||||
|
@ -184,7 +198,7 @@ const StatusContent: React.FC<IStatusContent> = React.memo(({
|
|||
|
||||
return <div className={clsx({ 'bg-gray-100 dark:bg-primary-800 rounded-md p-4': hasPoll })}>{output}</div>;
|
||||
} else {
|
||||
const output = [
|
||||
output.push(
|
||||
<Markup
|
||||
ref={node}
|
||||
tabIndex={0}
|
||||
|
@ -198,7 +212,7 @@ const StatusContent: React.FC<IStatusContent> = React.memo(({
|
|||
>
|
||||
{content}
|
||||
</Markup>,
|
||||
];
|
||||
);
|
||||
|
||||
if (status.poll_id) {
|
||||
output.push(<Poll id={status.poll_id} key='poll' status={status} />);
|
||||
|
|
|
@ -59,7 +59,6 @@ const StatusMedia: React.FC<IStatusMedia> = ({
|
|||
<AttachmentThumbs
|
||||
media={status.media_attachments}
|
||||
onClick={onClick}
|
||||
sensitive={status.sensitive}
|
||||
/>
|
||||
);
|
||||
} else if (size === 1 && firstAttachment.type === 'video') {
|
||||
|
@ -101,10 +100,8 @@ const StatusMedia: React.FC<IStatusMedia> = ({
|
|||
<Suspense fallback={renderLoadingMediaGallery()}>
|
||||
<MediaGallery
|
||||
media={status.media_attachments}
|
||||
sensitive={status.sensitive}
|
||||
height={285}
|
||||
onOpenMedia={openMedia}
|
||||
visible={visible}
|
||||
/>
|
||||
</Suspense>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import clsx from 'clsx';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useRef } from 'react';
|
||||
import { defineMessages, useIntl, FormattedList, FormattedMessage } from 'react-intl';
|
||||
import { Link, useHistory } from 'react-router-dom';
|
||||
|
||||
|
@ -79,9 +79,6 @@ const Status: React.FC<IStatus> = (props) => {
|
|||
const { boostModal } = useSettings();
|
||||
const didShowCard = useRef(false);
|
||||
const node = useRef<HTMLDivElement>(null);
|
||||
const overlay = useRef<HTMLDivElement>(null);
|
||||
|
||||
const [minHeight, setMinHeight] = useState(208);
|
||||
|
||||
const getStatus = useCallback(makeGetStatus(), []);
|
||||
const actualStatus = useAppSelector(state => status.reblog_id && getStatus(state, { id: status.reblog_id }) || status)!;
|
||||
|
@ -97,12 +94,6 @@ const Status: React.FC<IStatus> = (props) => {
|
|||
didShowCard.current = Boolean(!muted && !hidden && status?.card);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (overlay.current) {
|
||||
setMinHeight(overlay.current.getBoundingClientRect().height);
|
||||
}
|
||||
}, [overlay.current]);
|
||||
|
||||
const handleClick = (e?: React.MouseEvent): void => {
|
||||
e?.stopPropagation();
|
||||
|
||||
|
@ -426,15 +417,7 @@ const Status: React.FC<IStatus> = (props) => {
|
|||
<div className='status__content-wrapper'>
|
||||
<StatusReplyMentions status={actualStatus} hoverable={hoverable} />
|
||||
|
||||
<Stack
|
||||
className='relative z-0'
|
||||
style={{ minHeight: actualStatus.sensitive ? Math.max(minHeight, 208) + 12 : undefined }}
|
||||
>
|
||||
<SensitiveContentOverlay
|
||||
status={actualStatus}
|
||||
ref={overlay}
|
||||
/>
|
||||
|
||||
<Stack className='relative z-0'>
|
||||
{actualStatus.event ? <EventPreview className='shadow-xl' status={actualStatus} /> : (
|
||||
<Stack space={4}>
|
||||
<StatusContent
|
||||
|
@ -447,7 +430,8 @@ const Status: React.FC<IStatus> = (props) => {
|
|||
<TranslateButton status={actualStatus} />
|
||||
|
||||
{(quote || actualStatus.card || actualStatus.media_attachments.length > 0) && (
|
||||
<Stack space={4}>
|
||||
<Stack space={4} className='relative'>
|
||||
<SensitiveContentOverlay status={actualStatus} />
|
||||
<StatusMedia
|
||||
status={actualStatus}
|
||||
muted={muted}
|
||||
|
|
|
@ -21,7 +21,7 @@ const messages = defineMessages({
|
|||
});
|
||||
|
||||
interface ISensitiveContentOverlay {
|
||||
status: Pick<Status, 'id' | 'sensitive' | 'hidden' | 'media_attachments' | 'currentLanguage' | 'spoilerHtml' | 'spoilerMapHtml' | 'spoiler_text'>;
|
||||
status: Pick<Status, 'id' | 'sensitive' | 'hidden' | 'media_attachments' | 'currentLanguage'>;
|
||||
}
|
||||
|
||||
const SensitiveContentOverlay = React.forwardRef<HTMLDivElement, ISensitiveContentOverlay>((props, ref) => {
|
||||
|
@ -47,10 +47,6 @@ const SensitiveContentOverlay = React.forwardRef<HTMLDivElement, ISensitiveConte
|
|||
|
||||
if (visible && !showHideButton) return null;
|
||||
|
||||
const spoilerText = status.currentLanguage
|
||||
? status.spoilerMapHtml![status.currentLanguage] || status.spoilerHtml
|
||||
: status.spoilerHtml;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx('absolute z-40', {
|
||||
|
@ -79,14 +75,6 @@ const SensitiveContentOverlay = React.forwardRef<HTMLDivElement, ISensitiveConte
|
|||
<Text theme='white' size='sm' weight='medium'>
|
||||
{intl.formatMessage(messages.sensitiveSubtitle)}
|
||||
</Text>
|
||||
|
||||
{status.spoiler_text && (
|
||||
<div className='py-4 italic'>
|
||||
<Text className='line-clamp-6' theme='white' size='md' weight='medium'>
|
||||
“<span dangerouslySetInnerHTML={{ __html: spoilerText }} />”
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<HStack alignItems='center' justifyContent='center' space={2}>
|
||||
|
|
|
@ -40,8 +40,8 @@ const AccountGallery = () => {
|
|||
} = useAccountLookup(username, { withRelationship: true });
|
||||
|
||||
const attachments: ImmutableList<AccountGalleryAttachment> = useAppSelector((state) => account ? getAccountGallery(state, account.id) : ImmutableList());
|
||||
const isLoading = useAppSelector((state) => state.timelines.get(`account:${account?.id}:media`)?.isLoading);
|
||||
const hasMore = useAppSelector((state) => state.timelines.get(`account:${account?.id}:media`)?.hasMore);
|
||||
const isLoading = useAppSelector((state) => state.timelines.get(`account:${account?.id}:with_replies:media`)?.isLoading);
|
||||
const hasMore = useAppSelector((state) => state.timelines.get(`account:${account?.id}:with_replies:media`)?.hasMore);
|
||||
|
||||
const node = useRef<HTMLDivElement>(null);
|
||||
|
||||
|
|
|
@ -61,7 +61,6 @@ const StatusCheckBox: React.FC<IStatusCheckBox> = ({ id, disabled }) => {
|
|||
media = (
|
||||
<MediaGallery
|
||||
media={status.media_attachments}
|
||||
sensitive={status.sensitive}
|
||||
height={110}
|
||||
onOpenMedia={noop}
|
||||
visible
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import React, { useRef } from 'react';
|
||||
import { FormattedDate, FormattedMessage, useIntl } from 'react-intl';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
|
@ -31,15 +31,6 @@ const DetailedStatus: React.FC<IDetailedStatus> = ({
|
|||
const intl = useIntl();
|
||||
|
||||
const node = useRef<HTMLDivElement>(null);
|
||||
const overlay = useRef<HTMLDivElement>(null);
|
||||
|
||||
const [minHeight, setMinHeight] = useState(208);
|
||||
|
||||
useEffect(() => {
|
||||
if (overlay.current) {
|
||||
setMinHeight(overlay.current.getBoundingClientRect().height);
|
||||
}
|
||||
}, [overlay.current]);
|
||||
|
||||
const handleOpenCompareHistoryModal = () => {
|
||||
onOpenCompareHistoryModal(status);
|
||||
|
@ -124,15 +115,7 @@ const DetailedStatus: React.FC<IDetailedStatus> = ({
|
|||
|
||||
<StatusReplyMentions status={actualStatus} />
|
||||
|
||||
<Stack
|
||||
className='relative z-0'
|
||||
style={{ minHeight: actualStatus.sensitive ? Math.max(minHeight, 208) + 12 : undefined }}
|
||||
>
|
||||
<SensitiveContentOverlay
|
||||
status={status}
|
||||
ref={overlay}
|
||||
/>
|
||||
|
||||
<Stack className='relative z-0'>
|
||||
<Stack space={4}>
|
||||
<StatusContent
|
||||
status={actualStatus}
|
||||
|
@ -143,7 +126,9 @@ const DetailedStatus: React.FC<IDetailedStatus> = ({
|
|||
<TranslateButton status={actualStatus} />
|
||||
|
||||
{(withMedia && (quote || actualStatus.card || actualStatus.media_attachments.length > 0)) && (
|
||||
<Stack space={4}>
|
||||
<Stack space={4} className='relative'>
|
||||
<SensitiveContentOverlay status={status} />
|
||||
|
||||
<StatusMedia status={actualStatus} />
|
||||
|
||||
{quote}
|
||||
|
|
|
@ -114,9 +114,6 @@ const normalizeStatus = (status: BaseStatus & {
|
|||
mentions = [selfMention, ...mentions];
|
||||
}
|
||||
|
||||
// If the status contains spoiler text, treat it as sensitive.
|
||||
const sensitive = !!status.spoiler_text || status.sensitive;
|
||||
|
||||
// Normalize event
|
||||
let event: BaseStatus['event'] & ({
|
||||
banner: MediaAttachment | null;
|
||||
|
@ -162,8 +159,7 @@ const normalizeStatus = (status: BaseStatus & {
|
|||
account: normalizeAccount(status.account),
|
||||
accounts: status.accounts?.map(normalizeAccount),
|
||||
mentions,
|
||||
sensitive,
|
||||
hidden: sensitive,
|
||||
hidden: status.sensitive,
|
||||
/** Rewrite `<p></p>` to empty string. */
|
||||
content: status.content === '<p></p>' ? '' : status.content,
|
||||
filtered: status.filtered?.map(result => result.filter.title),
|
||||
|
|
|
@ -206,7 +206,7 @@ type AccountGalleryAttachment = MediaAttachment & {
|
|||
}
|
||||
|
||||
const getAccountGallery = createSelector([
|
||||
(state: RootState, id: string) => state.timelines.get(`account:${id}:media`)?.items || ImmutableOrderedSet<string>(),
|
||||
(state: RootState, id: string) => state.timelines.get(`account:${id}:with_replies:media`)?.items || ImmutableOrderedSet<string>(),
|
||||
(state: RootState) => state.statuses,
|
||||
], (statusIds, statuses) =>
|
||||
statusIds.reduce((medias: ImmutableList<AccountGalleryAttachment>, statusId: string) => {
|
||||
|
|
Loading…
Reference in a new issue