Merge branch 'sensitive' into fork

This commit is contained in:
marcin mikołajczak
2024-04-28 15:27:15 +02:00
24 changed files with 81 additions and 355 deletions

View File

@ -49,7 +49,7 @@ const ReportStatus: React.FC<IReportStatus> = ({ status }) => {
<HStack space={2} alignItems='start'>
<Stack space={2} className='overflow-hidden' grow>
<StatusContent status={status} />
<StatusMedia status={status} />
<StatusMedia status={status} showMedia />
</Stack>
<div className='flex-none'>

View File

@ -9,9 +9,8 @@ import StatusMedia from 'soapbox/components/status-media';
import TranslateButton from 'soapbox/components/translate-button';
import { HStack, Icon, Stack, Text } from 'soapbox/components/ui';
import QuotedStatus from 'soapbox/features/status/containers/quoted-status-container';
import { useAppDispatch, useAppSelector, useSettings, useSoapboxConfig } from 'soapbox/hooks';
import { useAppDispatch, useAppSelector, useSoapboxConfig } from 'soapbox/hooks';
import { makeGetStatus } from 'soapbox/selectors';
import { defaultMediaVisibility } from 'soapbox/utils/status';
import type { Status as StatusEntity } from 'soapbox/types/entities';
@ -28,10 +27,8 @@ const EventInformation: React.FC<IEventInformation> = ({ params }) => {
const status = useAppSelector(state => getStatus(state, { id: params.statusId })) as StatusEntity;
const { tileServer } = useSoapboxConfig();
const { displayMedia } = useSettings();
const [isLoaded, setIsLoaded] = useState<boolean>(!!status);
const [showMedia, setShowMedia] = useState<boolean>(defaultMediaVisibility(status, displayMedia));
useEffect(() => {
dispatch(fetchStatus(params.statusId)).then(() => {
@ -39,14 +36,8 @@ const EventInformation: React.FC<IEventInformation> = ({ params }) => {
}).catch(() => {
setIsLoaded(true);
});
setShowMedia(defaultMediaVisibility(status, displayMedia));
}, [params.statusId]);
const handleToggleMediaVisibility = () => {
setShowMedia(!showMedia);
};
const handleShowMap: React.MouseEventHandler<HTMLAnchorElement> = (e) => {
e.preventDefault();
@ -195,11 +186,7 @@ const EventInformation: React.FC<IEventInformation> = ({ params }) => {
</Stack>
)}
<StatusMedia
status={status}
showMedia={showMedia}
onToggleVisibility={handleToggleMediaVisibility}
/>
<StatusMedia status={status} />
{status.quote && status.pleroma.get('quote_visible', true) && (
<QuotedStatus statusId={status.quote as string} />

View File

@ -6,7 +6,7 @@ import { mentionCompose } from 'soapbox/actions/compose';
import { reblog, favourite, unreblog, unfavourite } from 'soapbox/actions/interactions';
import { openModal } from 'soapbox/actions/modals';
import { getSettings } from 'soapbox/actions/settings';
import { hideStatus, revealStatus } from 'soapbox/actions/statuses';
import { toggleStatusHidden } from 'soapbox/actions/statuses';
import Icon from 'soapbox/components/icon';
import { HStack, Text, Emoji } from 'soapbox/components/ui';
import AccountContainer from 'soapbox/containers/account-container';
@ -182,7 +182,7 @@ const Notification: React.FC<INotification> = (props) => {
openProfile: handleOpenProfile,
moveUp: handleMoveUp,
moveDown: handleMoveDown,
toggleHidden: handleHotkeyToggleHidden,
toggleSensitive: handleHotkeyToggleSensitive,
});
const handleOpen = () => {
@ -236,13 +236,9 @@ const Notification: React.FC<INotification> = (props) => {
}
}, [status]);
const handleHotkeyToggleHidden = useCallback((e?: KeyboardEvent) => {
const handleHotkeyToggleSensitive = useCallback((e?: KeyboardEvent) => {
if (status && typeof status === 'object') {
if (status.hidden) {
dispatch(revealStatus(status.id));
} else {
dispatch(hideStatus(status.id));
}
dispatch(toggleStatusHidden(status));
}
}, [status]);

View File

@ -78,7 +78,7 @@ const languages = {
const messages = defineMessages({
heading: { id: 'column.preferences', defaultMessage: 'Preferences' },
displayPostsDefault: { id: 'preferences.fields.display_media.default', defaultMessage: 'Hide posts marked as sensitive' },
displayPostsHideAll: { id: 'preferences.fields.display_media.hide_all', defaultMessage: 'Always hide posts' },
displayPostsHideAll: { id: 'preferences.fields.display_media.hide_all', defaultMessage: 'Always hide media posts' },
displayPostsShowAll: { id: 'preferences.fields.display_media.show_all', defaultMessage: 'Always show posts' },
privacy_public: { id: 'preferences.options.privacy_public', defaultMessage: 'Public' },
privacy_unlisted: { id: 'preferences.options.privacy_unlisted', defaultMessage: 'Unlisted' },
@ -201,10 +201,6 @@ const Preferences = () => {
<SettingToggle settings={settings} settingPath={['autoPlayGif']} onChange={onToggleChange} />
</ListItem>
{features.spoilers && <ListItem label={<FormattedMessage id='preferences.fields.expand_spoilers_label' defaultMessage='Always expand posts marked with content warnings' />}>
<SettingToggle settings={settings} settingPath={['expandSpoilers']} onChange={onToggleChange} />
</ListItem>}
<ListItem label={<FormattedMessage id='preferences.fields.autoload_timelines_label' defaultMessage='Automatically load new posts when scrolled to the top of the page' />}>
<SettingToggle settings={settings} settingPath={['autoloadTimelines']} onChange={onToggleChange} />
</ListItem>

View File

@ -19,17 +19,13 @@ import type { Group, Status as StatusEntity } from 'soapbox/types/entities';
interface IDetailedStatus {
status: StatusEntity;
showMedia?: boolean;
withMedia?: boolean;
onOpenCompareHistoryModal: (status: StatusEntity) => void;
onToggleMediaVisibility: () => void;
}
const DetailedStatus: React.FC<IDetailedStatus> = ({
status,
onOpenCompareHistoryModal,
onToggleMediaVisibility,
showMedia,
withMedia = true,
}) => {
const intl = useIntl();
@ -89,9 +85,6 @@ const DetailedStatus: React.FC<IDetailedStatus> = ({
const { account } = actualStatus;
if (!account || typeof account !== 'object') return null;
const isUnderReview = actualStatus.visibility === 'self';
const isSensitive = actualStatus.hidden;
let statusTypeIcon = null;
let quote;
@ -133,16 +126,12 @@ const DetailedStatus: React.FC<IDetailedStatus> = ({
<Stack
className='relative z-0'
style={{ minHeight: isUnderReview || isSensitive ? Math.max(minHeight, 208) + 12 : undefined }}
style={{ minHeight: actualStatus.sensitive ? Math.max(minHeight, 208) + 12 : undefined }}
>
{(isUnderReview || isSensitive) && (
<SensitiveContentOverlay
status={status}
visible={showMedia}
onToggleVisibility={onToggleMediaVisibility}
ref={overlay}
/>
)}
<SensitiveContentOverlay
status={status}
ref={overlay}
/>
<Stack space={4}>
<StatusContent
@ -155,11 +144,7 @@ const DetailedStatus: React.FC<IDetailedStatus> = ({
{(withMedia && (quote || actualStatus.card || actualStatus.media_attachments.size > 0)) && (
<Stack space={4}>
<StatusMedia
status={actualStatus}
showMedia={showMedia}
onToggleVisibility={onToggleMediaVisibility}
/>
<StatusMedia status={actualStatus} />
{quote}
</Stack>

View File

@ -1,7 +1,7 @@
import { createSelector } from '@reduxjs/toolkit';
import clsx from 'clsx';
import { List as ImmutableList, OrderedSet as ImmutableOrderedSet } from 'immutable';
import React, { useEffect, useRef, useState } from 'react';
import React, { useEffect, useRef } from 'react';
import { useIntl } from 'react-intl';
import { useHistory } from 'react-router-dom';
import { type VirtuosoHandle } from 'react-virtuoso';
@ -10,7 +10,7 @@ import { mentionCompose, replyCompose } from 'soapbox/actions/compose';
import { favourite, reblog, unfavourite, unreblog } from 'soapbox/actions/interactions';
import { openModal } from 'soapbox/actions/modals';
import { getSettings } from 'soapbox/actions/settings';
import { hideStatus, revealStatus } from 'soapbox/actions/statuses';
import { toggleStatusHidden } from 'soapbox/actions/statuses';
import ScrollableList from 'soapbox/components/scrollable-list';
import StatusActionBar from 'soapbox/components/status-action-bar';
import Tombstone from 'soapbox/components/tombstone';
@ -18,10 +18,10 @@ import { Stack } from 'soapbox/components/ui';
import PlaceholderStatus from 'soapbox/features/placeholder/components/placeholder-status';
import { HotKeys } from 'soapbox/features/ui/components/hotkeys';
import PendingStatus from 'soapbox/features/ui/components/pending-status';
import { useAppDispatch, useAppSelector, useSettings } from 'soapbox/hooks';
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { RootState } from 'soapbox/store';
import { type Account, type Status } from 'soapbox/types/entities';
import { defaultMediaVisibility, textForScreenReader } from 'soapbox/utils/status';
import { textForScreenReader } from 'soapbox/utils/status';
import DetailedStatus from './detailed-status';
import ThreadStatus from './thread-status';
@ -90,9 +90,6 @@ const Thread = (props: IThread) => {
const dispatch = useAppDispatch();
const history = useHistory();
const intl = useIntl();
const { displayMedia } = useSettings();
const isUnderReview = status?.visibility === 'self';
const { ancestorsIds, descendantsIds } = useAppSelector((state) => {
let ancestorsIds = ImmutableOrderedSet<string>();
@ -116,16 +113,10 @@ const Thread = (props: IThread) => {
let initialTopMostItemIndex = ancestorsIds.size;
if (!useWindowScroll && initialTopMostItemIndex !== 0) initialTopMostItemIndex = ancestorsIds.size + 1;
const [showMedia, setShowMedia] = useState<boolean>(status?.visibility === 'self' ? false : defaultMediaVisibility(status, displayMedia));
const node = useRef<HTMLDivElement>(null);
const statusRef = useRef<HTMLDivElement>(null);
const scroller = useRef<VirtuosoHandle>(null);
const handleToggleMediaVisibility = () => {
setShowMedia(!showMedia);
};
const handleHotkeyReact = () => {
if (statusRef.current) {
const firstEmoji: HTMLButtonElement | null = statusRef.current.querySelector('.emoji-react-selector .emoji-react-selector__emoji');
@ -178,14 +169,6 @@ const Thread = (props: IThread) => {
}
};
const handleToggleHidden = (status: Status) => {
if (status.hidden) {
dispatch(revealStatus(status.id));
} else {
dispatch(hideStatus(status.id));
}
};
const handleHotkeyMoveUp = () => {
handleMoveUp(status!.id);
};
@ -218,12 +201,8 @@ const Thread = (props: IThread) => {
history.push(`/@${status!.getIn(['account', 'acct'])}`);
};
const handleHotkeyToggleHidden = () => {
handleToggleHidden(status!);
};
const handleHotkeyToggleSensitive = () => {
handleToggleMediaVisibility();
dispatch(toggleStatusHidden(status));
};
const handleMoveUp = (id: string) => {
@ -317,11 +296,6 @@ const Thread = (props: IThread) => {
});
};
// Reset media visibility if status changes.
useEffect(() => {
setShowMedia(status?.visibility === 'self' ? false : defaultMediaVisibility(status, displayMedia));
}, [status.id]);
// Scroll focused status into view when thread updates.
useEffect(() => {
scroller.current?.scrollToIndex({
@ -351,7 +325,6 @@ const Thread = (props: IThread) => {
boost: handleHotkeyBoost,
mention: handleHotkeyMention,
openProfile: handleHotkeyOpenProfile,
toggleHidden: handleHotkeyToggleHidden,
toggleSensitive: handleHotkeyToggleSensitive,
openMedia: handleHotkeyOpenMedia,
react: handleHotkeyReact,
@ -370,24 +343,18 @@ const Thread = (props: IThread) => {
<DetailedStatus
status={status}
showMedia={showMedia}
withMedia={withMedia}
onToggleMediaVisibility={handleToggleMediaVisibility}
onOpenCompareHistoryModal={handleOpenCompareHistoryModal}
/>
{!isUnderReview ? (
<>
<hr className='-mx-4 mb-2 max-w-[100vw] border-t-2 black:border-t dark:border-gray-800' />
<hr className='-mx-4 mb-2 max-w-[100vw] border-t-2 black:border-t dark:border-gray-800' />
<StatusActionBar
status={status}
expandable={false}
space='lg'
withLabels
/>
</>
) : null}
<StatusActionBar
status={status}
expandable={false}
space='lg'
withLabels
/>
</div>
</HotKeys>

View File

@ -33,8 +33,7 @@ const keyMap = {
goToBlocked: 'g b',
goToMuted: 'g m',
goToRequests: 'g r',
toggleHidden: 'x',
toggleSensitive: 'h',
toggleSensitive: ['h', 'x'],
openMedia: 'a',
};