Merge branch 'sensitive' into fork
This commit is contained in:
@ -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'>
|
||||
|
||||
@ -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} />
|
||||
|
||||
@ -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]);
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
|
||||
@ -33,8 +33,7 @@ const keyMap = {
|
||||
goToBlocked: 'g b',
|
||||
goToMuted: 'g m',
|
||||
goToRequests: 'g r',
|
||||
toggleHidden: 'x',
|
||||
toggleSensitive: 'h',
|
||||
toggleSensitive: ['h', 'x'],
|
||||
openMedia: 'a',
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user