pl-fe: status visibility icons

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak
2024-09-06 13:24:46 +02:00
parent b29242d200
commit 11c4e69728
4 changed files with 59 additions and 12 deletions

View File

@ -9,6 +9,7 @@ import { openModal } from 'pl-fe/actions/modals';
import { toggleStatusMediaHidden, unfilterStatus } from 'pl-fe/actions/statuses';
import TranslateButton from 'pl-fe/components/translate-button';
import AccountContainer from 'pl-fe/containers/account-container';
import StatusTypeIcon from 'pl-fe/features/status/components/status-type-icon';
import QuotedStatus from 'pl-fe/features/status/containers/quoted-status-container';
import { HotKeys } from 'pl-fe/features/ui/components/hotkeys';
import { useAppDispatch, useAppSelector, useSettings } from 'pl-fe/hooks';
@ -408,7 +409,12 @@ const Status: React.FC<IStatus> = (props) => {
withLinkToProfile={hoverable}
approvalStatus={actualStatus.approval_status}
avatarSize={avatarSize}
items={<StatusLanguagePicker status={status} />}
items={(
<>
<StatusTypeIcon status={status} />
<StatusLanguagePicker status={status} />
</>
)}
/>
<div className='status__content-wrapper'>

View File

@ -22,13 +22,15 @@ interface IIcon extends Pick<React.SVGAttributes<SVGAElement>, 'strokeWidth'> {
size?: number;
/** Override the data-testid */
'data-testid'?: string;
title?: string;
}
/** Renders and SVG icon with optional counter. */
const Icon: React.FC<IIcon> = ({ src, alt, count, size, countMax, containerClassName, ...filteredProps }): JSX.Element => (
const Icon: React.FC<IIcon> = ({ src, alt, count, size, countMax, containerClassName, title, ...filteredProps }): JSX.Element => (
<div
className={clsx('relative flex shrink-0 flex-col', containerClassName)}
data-testid={filteredProps['data-testid'] || 'icon'}
title={title}
>
{count ? (
<span className='absolute -right-3 -top-2 flex h-5 min-w-[20px] shrink-0 items-center justify-center whitespace-nowrap break-words'>

View File

@ -14,6 +14,7 @@ import { HStack, Icon, Stack, Text } from 'pl-fe/components/ui';
import QuotedStatus from 'pl-fe/features/status/containers/quoted-status-container';
import StatusInteractionBar from './status-interaction-bar';
import StatusTypeIcon from './status-type-icon';
import type { SelectedStatus } from 'pl-fe/selectors';
@ -76,8 +77,6 @@ const DetailedStatus: React.FC<IDetailedStatus> = ({
const { account } = actualStatus;
if (!account || typeof account !== 'object') return null;
let statusTypeIcon = null;
let quote;
if (actualStatus.quote_id) {
@ -92,12 +91,6 @@ const DetailedStatus: React.FC<IDetailedStatus> = ({
}
}
if (actualStatus.visibility === 'direct') {
statusTypeIcon = <Icon className='h-4 w-4 text-gray-700 dark:text-gray-600' src={require('@tabler/icons/outline/mail.svg')} />;
} else if (actualStatus.visibility === 'private' || actualStatus.visibility === 'mutuals_only') {
statusTypeIcon = <Icon className='h-4 w-4 text-gray-700 dark:text-gray-600' src={require('@tabler/icons/outline/lock.svg')} />;
}
return (
<div className='border-box'>
<div ref={node} className='detailed-actualStatus' tabIndex={-1}>
@ -144,8 +137,6 @@ const DetailedStatus: React.FC<IDetailedStatus> = ({
<StatusInteractionBar status={actualStatus} />
<HStack space={1} alignItems='center'>
{statusTypeIcon}
<span>
<a href={actualStatus.url} target='_blank' rel='noopener' className='hover:underline'>
<Text tag='span' theme='muted' size='sm'>
@ -170,6 +161,8 @@ const DetailedStatus: React.FC<IDetailedStatus> = ({
)}
</span>
<StatusTypeIcon status={actualStatus} />
<StatusLanguagePicker status={status} showLabel />
</HStack>
</HStack>

View File

@ -0,0 +1,46 @@
import React from 'react';
import { defineMessages, MessageDescriptor, useIntl } from 'react-intl';
import { Icon, Text } from 'pl-fe/components/ui';
import type { Status } from 'pl-fe/normalizers';
interface IStatusTypeIcon {
status: Pick<Status, 'visibility'>;
}
const messages: Record<string, MessageDescriptor> = defineMessages({
direct: { id: 'status.visibility.direct', defaultMessage: 'The post is only visible to mentioned users' },
private: { id: 'status.visibility.private', defaultMessage: 'The post is only visible to followers of the author' },
mutuals_only: { id: 'status.visibility.mutuals_only', defaultMessage: 'The post is only visible to people who mutually follow the author' },
local: { id: 'status.visibility.local', defaultMessage: 'The post is only visible to users on your instance' },
list: { id: 'status.visibility.list', defaultMessage: 'The post is only visible to the members of a list' },
list_named: { id: 'status.visibility.list.named', defaultMessage: 'The post is only visible to the members of a {name} list' },
});
const STATUS_TYPE_ICONS: Record<string, string> = {
direct: require('@tabler/icons/outline/mail.svg'),
private: require('@tabler/icons/outline/lock.svg'),
mutuals_only: require('@tabler/icons/outline/users-group.svg'),
local: require('@tabler/icons/outline/affiliate.svg'),
list: require('@tabler/icons/outline/list.svg'),
};
const StatusTypeIcon: React.FC<IStatusTypeIcon> = ({ status }) => {
const intl = useIntl();
const icon = STATUS_TYPE_ICONS[status.visibility];
const message = messages[status.visibility];
if (!icon) return null;
return (
<>
<Text tag='span' theme='muted' size='sm'>&middot;</Text>
<Icon title={message ? intl.formatMessage(message) : undefined} className='h-5 w-5 text-gray-700 dark:text-gray-600' src={icon} />
</>
);
};
export { StatusTypeIcon as default };